tlang/source/tlang/compiler/symbols/containers.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;
}
}
}