365 lines
9.8 KiB
D
365 lines
9.8 KiB
D
module tlang.compiler.symbols.containers;
|
|
|
|
import tlang.compiler.symbols.data;
|
|
import std.conv : to;
|
|
import tlang.compiler.symbols.typing.core;
|
|
|
|
/**
|
|
* Used so often that we may as well
|
|
* declare it once
|
|
*
|
|
* TODO: Check if we could do it with interfaces?
|
|
*/
|
|
public Statement[] weightReorder(Statement[] statements)
|
|
{
|
|
import std.algorithm.sorting : sort;
|
|
import std.algorithm.mutation : SwapStrategy;
|
|
|
|
/* Re-ordered by lowest wieght first */
|
|
Statement[] stmntsRed;
|
|
|
|
/* Comparator for Statement objects */
|
|
bool wCmp(Statement lhs, Statement rhs)
|
|
{
|
|
return lhs.weight < rhs.weight;
|
|
}
|
|
|
|
stmntsRed = sort!(wCmp, SwapStrategy.stable)(statements).release;
|
|
|
|
return stmntsRed;
|
|
}
|
|
|
|
// TODO: Honestly all contains should be a kind-of `MStatementSearchable` and `MStatementReplaceable`
|
|
import tlang.compiler.symbols.mcro : MStatementSearchable, MStatementReplaceable;
|
|
public interface Container : MStatementSearchable, MStatementReplaceable
|
|
{
|
|
public void addStatement(Statement statement);
|
|
|
|
public void addStatements(Statement[] statements);
|
|
|
|
public Statement[] getStatements();
|
|
}
|
|
|
|
|
|
public class Module : Entity, Container
|
|
{
|
|
this(string moduleName)
|
|
{
|
|
super(moduleName);
|
|
}
|
|
|
|
private Statement[] statements;
|
|
|
|
|
|
public void addStatement(Statement statement)
|
|
{
|
|
this.statements ~= statement;
|
|
}
|
|
|
|
public void addStatements(Statement[] statements)
|
|
{
|
|
this.statements ~= statements;
|
|
}
|
|
|
|
public Statement[] getStatements()
|
|
{
|
|
return weightReorder(statements);
|
|
}
|
|
|
|
public override Statement[] search(TypeInfo_Class clazzType)
|
|
{
|
|
/* List of returned matches */
|
|
Statement[] matches;
|
|
|
|
/* Are we (ourselves) of this type? */
|
|
if(clazzType.isBaseOf(this.classinfo))
|
|
{
|
|
matches ~= [this];
|
|
}
|
|
|
|
/* Recurse on each `Statement` making up our body */
|
|
// NOTE: Using weight-reordered? Is that fine?
|
|
foreach(Statement curStmt; getStatements())
|
|
{
|
|
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
|
if(curStmtCasted)
|
|
{
|
|
matches ~= curStmtCasted.search(clazzType);
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
public override bool replace(Statement thiz, Statement that)
|
|
{
|
|
/* If we (`this`) are `thiz`, then we cannot replace */
|
|
if(this == thiz)
|
|
{
|
|
return false;
|
|
}
|
|
/* If not ourself, then check the body statements */
|
|
else
|
|
{
|
|
/**
|
|
* First check each `Statement` that make sup our
|
|
* body and see if we can replace that, else see
|
|
* if we can recurse on each of the body statements
|
|
* and apply replacement therein
|
|
*/
|
|
// NOTE: Using weight-reordered? Is that fine?
|
|
Statement[] bodyStmts = getStatements();
|
|
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
|
{
|
|
Statement curBodyStmt = bodyStmts[idx];
|
|
|
|
/* Should we directly replace the Statement in the body? */
|
|
if(curBodyStmt == thiz)
|
|
{
|
|
// Replace the statement in the body
|
|
statements[idx] = that;
|
|
|
|
// Re-parent `that` to us
|
|
that.parentTo(this);
|
|
|
|
return true;
|
|
}
|
|
/* If we cannot, then recurse (try) on it */
|
|
else if(cast(MStatementReplaceable)curBodyStmt)
|
|
{
|
|
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
|
if(curBodyStmtRepl.replace(thiz, that))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Struct
|
|
*
|
|
* A Struct can only contain Entity's
|
|
* that are Variables (TODO: Enforce in parser)
|
|
* TODO: Possibly enforce here too
|
|
*/
|
|
public class Struct : Type, Container
|
|
{
|
|
private Statement[] statements;
|
|
|
|
public void addStatement(Statement statement)
|
|
{
|
|
this.statements ~= statement;
|
|
}
|
|
|
|
public void addStatements(Statement[] statements)
|
|
{
|
|
this.statements ~= statements;
|
|
}
|
|
|
|
public Statement[] getStatements()
|
|
{
|
|
return weightReorder(statements);
|
|
}
|
|
|
|
this(string name)
|
|
{
|
|
super(name);
|
|
}
|
|
|
|
public override Statement[] search(TypeInfo_Class clazzType)
|
|
{
|
|
/* List of returned matches */
|
|
Statement[] matches;
|
|
|
|
/* Are we (ourselves) of this type? */
|
|
if(clazzType.isBaseOf(this.classinfo))
|
|
{
|
|
matches ~= [this];
|
|
}
|
|
|
|
/* Recurse on each `Statement` making up our body */
|
|
// NOTE: Using weight-reordered? Is that fine?
|
|
foreach(Statement curStmt; getStatements())
|
|
{
|
|
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
|
if(curStmtCasted)
|
|
{
|
|
matches ~= curStmtCasted.search(clazzType);
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
public override bool replace(Statement thiz, Statement that)
|
|
{
|
|
/* If we (`this`) are `thiz`, then we cannot replace */
|
|
if(this == thiz)
|
|
{
|
|
return false;
|
|
}
|
|
/* If not ourself, then check the body statements */
|
|
else
|
|
{
|
|
/**
|
|
* First check each `Statement` that make sup our
|
|
* body and see if we can replace that, else see
|
|
* if we can recurse on each of the body statements
|
|
* and apply replacement therein
|
|
*/
|
|
// NOTE: Using weight-reordered? Is that fine?
|
|
Statement[] bodyStmts = getStatements();
|
|
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
|
{
|
|
Statement curBodyStmt = bodyStmts[idx];
|
|
|
|
/* Should we directly replace the Statement in the body? */
|
|
if(curBodyStmt == thiz)
|
|
{
|
|
// Replace the statement in the body
|
|
statements[idx] = that;
|
|
|
|
// Re-parent `that` to us
|
|
that.parentTo(this);
|
|
|
|
return true;
|
|
}
|
|
/* If we cannot, then recurse (try) on it */
|
|
else if(cast(MStatementReplaceable)curBodyStmt)
|
|
{
|
|
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
|
if(curBodyStmtRepl.replace(thiz, that))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public class Clazz : Type, Container
|
|
{
|
|
private Statement[] statements;
|
|
|
|
private string[] interfacesClasses;
|
|
|
|
this(string name)
|
|
{
|
|
super(name);
|
|
|
|
/* Weighted as 0 */
|
|
weight = 0;
|
|
}
|
|
|
|
public void addInherit(string[] l)
|
|
{
|
|
interfacesClasses ~= l;
|
|
}
|
|
|
|
public string[] getInherit()
|
|
{
|
|
return interfacesClasses;
|
|
}
|
|
|
|
public override string toString()
|
|
{
|
|
return "Class (Name: "~name~", Parents (Class/Interfaces): "~to!(string)(interfacesClasses)~")";
|
|
}
|
|
|
|
public void addStatement(Statement statement)
|
|
{
|
|
this.statements ~= statement;
|
|
}
|
|
|
|
public void addStatements(Statement[] statements)
|
|
{
|
|
this.statements ~= statements;
|
|
}
|
|
|
|
public Statement[] getStatements()
|
|
{
|
|
return weightReorder(statements);
|
|
}
|
|
|
|
public override Statement[] search(TypeInfo_Class clazzType)
|
|
{
|
|
/* List of returned matches */
|
|
Statement[] matches;
|
|
|
|
/* Are we (ourselves) of this type? */
|
|
if(clazzType.isBaseOf(this.classinfo))
|
|
{
|
|
matches ~= [this];
|
|
}
|
|
|
|
/* Recurse on each `Statement` making up our body */
|
|
// NOTE: Using weight-reordered? Is that fine?
|
|
foreach(Statement curStmt; getStatements())
|
|
{
|
|
MStatementSearchable curStmtCasted = cast(MStatementSearchable)curStmt;
|
|
if(curStmtCasted)
|
|
{
|
|
matches ~= curStmtCasted.search(clazzType);
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
}
|
|
|
|
public override bool replace(Statement thiz, Statement that)
|
|
{
|
|
/* If we (`this`) are `thiz`, then we cannot replace */
|
|
if(this == thiz)
|
|
{
|
|
return false;
|
|
}
|
|
/* If not ourself, then check the body statements */
|
|
else
|
|
{
|
|
/**
|
|
* First check each `Statement` that make sup our
|
|
* body and see if we can replace that, else see
|
|
* if we can recurse on each of the body statements
|
|
* and apply replacement therein
|
|
*/
|
|
// NOTE: Using weight-reordered? Is that fine?
|
|
Statement[] bodyStmts = getStatements();
|
|
for(ulong idx = 0; idx < bodyStmts.length; idx++)
|
|
{
|
|
Statement curBodyStmt = bodyStmts[idx];
|
|
|
|
/* Should we directly replace the Statement in the body? */
|
|
if(curBodyStmt == thiz)
|
|
{
|
|
// Replace the statement in the body
|
|
statements[idx] = that;
|
|
|
|
// Re-parent `that` to us
|
|
that.parentTo(this);
|
|
|
|
return true;
|
|
}
|
|
/* If we cannot, then recurse (try) on it */
|
|
else if(cast(MStatementReplaceable)curBodyStmt)
|
|
{
|
|
MStatementReplaceable curBodyStmtRepl = cast(MStatementReplaceable)curBodyStmt;
|
|
if(curBodyStmtRepl.replace(thiz, that))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
} |