2023-02-05 18:21:26 +00:00
|
|
|
module tlang.compiler.symbols.data;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
2023-02-05 18:21:26 +00:00
|
|
|
public import tlang.compiler.symbols.check;
|
2021-03-30 16:35:16 +01:00
|
|
|
import std.conv : to;
|
2023-02-05 18:21:26 +00:00
|
|
|
import tlang.compiler.typecheck.dependency.core : Context;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO: Implement the blow and use them
|
|
|
|
*
|
|
|
|
* These are just to use for keeping track of what
|
|
|
|
* valid identifiers are.
|
|
|
|
*
|
|
|
|
* Actually it might be, yeah it will
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class Program
|
|
|
|
{
|
|
|
|
private string moduleName;
|
|
|
|
private Program[] importedModules;
|
|
|
|
|
|
|
|
private Statement[] statements;
|
|
|
|
|
|
|
|
this(string moduleName)
|
|
|
|
{
|
|
|
|
this.moduleName = moduleName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addStatement(Statement statement)
|
|
|
|
{
|
|
|
|
statements ~= statement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static StatementType[] getAllOf(StatementType)(StatementType, Statement[] statements)
|
|
|
|
{
|
|
|
|
StatementType[] statementsMatched;
|
|
|
|
|
|
|
|
foreach(Statement statement; statements)
|
|
|
|
{
|
|
|
|
/* TODO: Remove null, this is for unimpemented */
|
|
|
|
if(statement !is null && cast(StatementType)statement)
|
|
|
|
{
|
|
|
|
statementsMatched ~= cast(StatementType)statement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return statementsMatched;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Variable[] getGlobals()
|
|
|
|
{
|
|
|
|
Variable[] variables;
|
|
|
|
|
|
|
|
foreach(Statement statement; statements)
|
|
|
|
{
|
|
|
|
if(typeid(statement) == typeid(Variable))
|
|
|
|
{
|
|
|
|
variables ~= cast(Variable)statement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return variables;
|
|
|
|
}
|
|
|
|
|
2021-10-27 14:52:43 +01:00
|
|
|
/* TODO: Make this use weights */
|
2021-03-30 16:35:16 +01:00
|
|
|
public Statement[] getStatements()
|
|
|
|
{
|
2021-10-27 19:57:30 +01:00
|
|
|
/* Re-ordered by lowest wieght first */
|
|
|
|
Statement[] stmntsRed;
|
|
|
|
|
|
|
|
bool wCmp(Statement lhs, Statement rhs)
|
|
|
|
{
|
|
|
|
return lhs.weight < rhs.weight;
|
|
|
|
}
|
|
|
|
import std.algorithm.sorting;
|
|
|
|
stmntsRed = sort!(wCmp)(statements).release;
|
|
|
|
|
|
|
|
|
|
|
|
return stmntsRed;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class Statement
|
|
|
|
{
|
2021-10-25 21:31:07 +01:00
|
|
|
|
2021-10-27 14:52:43 +01:00
|
|
|
public byte weight = 0;
|
|
|
|
|
2021-10-25 21:31:07 +01:00
|
|
|
/* !!!! BEGIN TYPE CHECK ROUTINES AND DATA !!!! */
|
|
|
|
/* TODO: Used for type checking */
|
2021-11-09 17:00:23 +00:00
|
|
|
|
|
|
|
public Context context;
|
|
|
|
public void setContext(Context context)
|
2021-10-25 21:31:07 +01:00
|
|
|
{
|
|
|
|
this.context = context;
|
|
|
|
}
|
|
|
|
|
2021-11-09 17:00:23 +00:00
|
|
|
public Context getContext()
|
2021-10-25 21:31:07 +01:00
|
|
|
{
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
/* !!!! END TYPE CHECK ROUTINES AND DATA !!!! */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-06-15 10:10:58 +01:00
|
|
|
private static ulong rollingCount = 0;
|
|
|
|
|
2021-03-30 16:35:16 +01:00
|
|
|
private Container container;
|
2021-11-01 16:28:19 +00:00
|
|
|
|
2021-03-30 16:35:16 +01:00
|
|
|
|
|
|
|
public final void parentTo(Container container)
|
|
|
|
{
|
|
|
|
this.container = container;
|
|
|
|
}
|
2021-03-30 19:05:16 +01:00
|
|
|
|
|
|
|
public final Container parentOf()
|
|
|
|
{
|
|
|
|
return container;
|
|
|
|
}
|
2021-06-04 10:36:58 +01:00
|
|
|
|
2021-06-15 10:10:58 +01:00
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return to!(string)(rollingCount++);
|
|
|
|
}
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public enum AccessorType
|
|
|
|
{
|
|
|
|
PUBLIC, PRIVATE, PROTECTED, UNKNOWN
|
|
|
|
}
|
|
|
|
|
2021-06-04 20:28:30 +01:00
|
|
|
public enum InitScope
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
2021-06-06 19:06:27 +01:00
|
|
|
VIRTUAL, STATIC, UNKNOWN
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
2021-04-01 14:49:02 +01:00
|
|
|
public class Assignment : Statement
|
|
|
|
{
|
|
|
|
private string identifier;
|
|
|
|
private Expression assignmentExpression;
|
|
|
|
|
|
|
|
this(string identifier, Expression assignmentExpression)
|
|
|
|
{
|
|
|
|
this.identifier = identifier;
|
|
|
|
this.assignmentExpression = assignmentExpression;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
/**
|
|
|
|
* Entity
|
|
|
|
*
|
|
|
|
* Declared variables, defined classes and functions
|
|
|
|
*/
|
2021-03-30 16:35:16 +01:00
|
|
|
public class Entity : Statement
|
|
|
|
{
|
2023-01-04 10:03:50 +00:00
|
|
|
/* Accessor type */
|
2021-03-30 16:35:16 +01:00
|
|
|
private AccessorType accessorType = AccessorType.PUBLIC;
|
|
|
|
|
|
|
|
/* Function/Modifier type */
|
2021-06-04 20:28:30 +01:00
|
|
|
private InitScope initScope;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
|
|
|
/* Name of the entity (class's name, function's name, variable's name) */
|
2021-04-16 21:32:01 +01:00
|
|
|
protected string name;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
2023-01-15 18:48:40 +00:00
|
|
|
/* If this entity is extern'd */
|
|
|
|
private bool isExternalEntity;
|
|
|
|
|
|
|
|
this(string name, bool isExternalEntity = false)
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
|
|
|
this.name = name;
|
2023-01-15 18:48:40 +00:00
|
|
|
this.isExternalEntity = isExternalEntity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool isExternal()
|
|
|
|
{
|
|
|
|
return isExternalEntity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void makeExternal()
|
|
|
|
{
|
|
|
|
isExternalEntity = true;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setAccessorType(AccessorType accessorType)
|
|
|
|
{
|
|
|
|
this.accessorType = accessorType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public AccessorType getAccessorType()
|
|
|
|
{
|
|
|
|
return accessorType;
|
|
|
|
}
|
|
|
|
|
2021-06-04 20:28:30 +01:00
|
|
|
public void setModifierType(InitScope initScope)
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
2021-06-04 20:28:30 +01:00
|
|
|
this.initScope = initScope;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
2021-06-04 20:28:30 +01:00
|
|
|
public InitScope getModifierType()
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
2021-06-04 20:28:30 +01:00
|
|
|
return initScope;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public string getName()
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: DO we need intermediary class, TypedEntity */
|
|
|
|
public class TypedEntity : Entity
|
|
|
|
{
|
|
|
|
private string type;
|
|
|
|
|
|
|
|
/* TODO: Return type/variable type in here (do what we did for ENtity with `name/identifier`) */
|
|
|
|
this(string name, string type)
|
|
|
|
{
|
|
|
|
super(name);
|
|
|
|
this.type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
public string getType()
|
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-05 18:21:26 +00:00
|
|
|
public import tlang.compiler.symbols.containers;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
|
|
|
public class ArgumentList
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-17 12:00:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* VariableParameter
|
|
|
|
*
|
|
|
|
* Represents a kindof-Variable which is used to indicate
|
|
|
|
* it is a function's parameter - to differentiate between
|
|
|
|
* those and other variables like local/global definitions
|
|
|
|
* and so on
|
|
|
|
*
|
|
|
|
* These are only to be used in the `Function` class (below)
|
|
|
|
*/
|
|
|
|
public final class VariableParameter : Variable
|
|
|
|
{
|
|
|
|
this(string type, string identifier)
|
|
|
|
{
|
|
|
|
super(type, identifier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-23 13:14:09 +01:00
|
|
|
/* TODO: Don't make this a Container, or maybe (make sure I don't rely on COntainer casting for other shit
|
|
|
|
* though, also the recent changes) */
|
2022-10-01 19:54:50 +01:00
|
|
|
public class Function : TypedEntity, Container
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
2022-12-17 12:00:16 +00:00
|
|
|
private VariableParameter[] params;
|
2021-03-30 16:35:16 +01:00
|
|
|
private Statement[] bodyStatements;
|
|
|
|
|
2022-12-17 12:00:16 +00:00
|
|
|
this(string name, string returnType, Statement[] bodyStatements, VariableParameter[] params)
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
|
|
|
super(name, returnType);
|
2022-12-17 12:00:16 +00:00
|
|
|
|
|
|
|
// Add the parameters first THEN the function's body statements
|
|
|
|
// because they must be available before other statements
|
|
|
|
// which may reference them, Secondly they must be added (the VariableParameter(s))
|
|
|
|
// such that they are lookup-able.
|
|
|
|
addStatements(cast(Statement[])params);
|
|
|
|
|
|
|
|
// Add the funciton's body
|
|
|
|
addStatements(bodyStatements);
|
|
|
|
|
|
|
|
// Save a seperate copy of the parameters (to seperate them from the
|
|
|
|
// other body stetements)
|
|
|
|
this.params = params;
|
2021-10-27 14:52:43 +01:00
|
|
|
|
|
|
|
/* Weighted as 1 */
|
|
|
|
weight = 1;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
2022-12-17 12:00:16 +00:00
|
|
|
public VariableParameter[] getParams()
|
2022-02-18 12:32:45 +00:00
|
|
|
{
|
|
|
|
return params;
|
|
|
|
}
|
|
|
|
|
2022-12-14 17:49:08 +00:00
|
|
|
public bool hasParams()
|
|
|
|
{
|
|
|
|
return params.length != 0;
|
|
|
|
}
|
|
|
|
|
2022-10-01 19:54:50 +01:00
|
|
|
public void addStatement(Statement statement)
|
|
|
|
{
|
|
|
|
this.bodyStatements~=statement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addStatements(Statement[] statements)
|
|
|
|
{
|
|
|
|
this.bodyStatements~=statements;
|
|
|
|
}
|
|
|
|
|
2021-11-09 16:26:30 +00:00
|
|
|
public Statement[] getStatements()
|
|
|
|
{
|
2023-02-05 18:21:26 +00:00
|
|
|
import tlang.compiler.symbols.containers : weightReorder;
|
2021-11-09 16:26:30 +00:00
|
|
|
return weightReorder(bodyStatements);
|
|
|
|
}
|
|
|
|
|
2021-03-30 16:35:16 +01:00
|
|
|
/**
|
|
|
|
* This will sift through all the `Statement[]`'s in held
|
|
|
|
* within this Function and will find those which are Variable
|
|
|
|
*/
|
|
|
|
public Variable[] getVariables()
|
|
|
|
{
|
|
|
|
Variable[] variables;
|
|
|
|
|
|
|
|
foreach(Statement statement; bodyStatements)
|
|
|
|
{
|
|
|
|
|
|
|
|
if(statement !is null && cast(Variable)statement)
|
|
|
|
{
|
|
|
|
variables ~= cast(Variable)statement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return variables;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
string argTypes;
|
|
|
|
|
|
|
|
for(ulong i = 0; i < params.length; i++)
|
|
|
|
{
|
|
|
|
Variable variable = params[i];
|
|
|
|
|
|
|
|
if(i == params.length-1)
|
|
|
|
{
|
|
|
|
argTypes ~= variable.getType();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
argTypes ~= variable.getType() ~ ", ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Function (Name: "~name~", ReturnType: "~type~", Args: "~argTypes~")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-02 08:38:09 +00:00
|
|
|
public class Variable : TypedEntity
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
|
|
|
/* TODO: Just make this an Expression */
|
|
|
|
private VariableAssignment assignment;
|
|
|
|
|
|
|
|
this(string type, string identifier)
|
|
|
|
{
|
|
|
|
super(identifier, type);
|
2021-10-27 19:57:30 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* Weighted as 2 */
|
|
|
|
weight = 2;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addAssignment(VariableAssignment assignment)
|
|
|
|
{
|
|
|
|
this.assignment = assignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
public VariableAssignment getAssignment()
|
|
|
|
{
|
|
|
|
return assignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "Variable (Ident: "~name~", Type: "~type~")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-02-05 18:21:26 +00:00
|
|
|
public import tlang.compiler.symbols.expressions;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-10-27 14:52:43 +01:00
|
|
|
/**
|
|
|
|
* TODO: Rename to `VariableDeclarationAssignment`
|
|
|
|
*/
|
2021-06-15 10:10:58 +01:00
|
|
|
public class VariableAssignment : Statement
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
|
|
|
private Expression expression;
|
2021-06-15 10:10:58 +01:00
|
|
|
private Variable variable;
|
2021-03-30 16:35:16 +01:00
|
|
|
|
|
|
|
this(Expression expression)
|
|
|
|
{
|
|
|
|
this.expression = expression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getExpression()
|
|
|
|
{
|
|
|
|
return expression;
|
|
|
|
}
|
2021-06-15 10:10:58 +01:00
|
|
|
|
|
|
|
public Variable getVariable()
|
|
|
|
{
|
|
|
|
return variable;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setVariable(Variable variable)
|
|
|
|
{
|
|
|
|
this.variable = variable;
|
|
|
|
}
|
2021-10-27 14:33:24 +01:00
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
2021-10-27 14:52:43 +01:00
|
|
|
return "[varAssignDec'd: To: "~variable.toString()~"]";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO: Rename to ``
|
|
|
|
*/
|
|
|
|
public class VariableAssignmentStdAlone : Statement
|
|
|
|
{
|
|
|
|
private Expression expression;
|
|
|
|
private string varName;
|
|
|
|
|
|
|
|
this(string varName, Expression expression)
|
|
|
|
{
|
|
|
|
this.varName = varName;
|
|
|
|
this.expression = expression;
|
2021-10-27 19:57:30 +01:00
|
|
|
|
|
|
|
/* Weighted as 2 */
|
|
|
|
weight = 2;
|
2021-10-27 14:52:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getExpression()
|
|
|
|
{
|
|
|
|
return expression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public string getVariableName()
|
|
|
|
{
|
|
|
|
return varName;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "[varAssignStdAlone: To: "~varName~"]";
|
2021-10-27 14:33:24 +01:00
|
|
|
}
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
Array support (#1)
* Parser
- Added ability for `parseName()` to recognize array types
- Added array type handling to `parseTypedDeclaration()`
- Removed unneeded `derefCount` and comment in `parseTypedDeclaration()`
Check
- Added new symbol types `OBRACKET` and `CBRACKET`
* Tets cases
- We will now be using `simple_arrays2.t` as our testing bench for array support
* Dependency
- When a variable declaration has a kind-of type we are unaware of then print out an error message before asserting `false`
* Builtins
- `getBuiltInType(TypeChecker, string)` will now return a `Pointer` object for arrays of which the type was `<componentType>[]` (non-stack bound) as effectively they are pointers with a different syntax -doing it here means that it is transparent and typechecking, code gen and emit will just see a pointer type which makes life a lot easier
* Builtins
- Added information about the current bug faced in issue #81 (third sub-issue)
* Test cases
- Updated test case `simple_arrays2.t` to show case bug sub-issue 3 in issue #81
* Builtins
- Removed seperate handling of `<componentType>[]` and incorporated it into the pointer check, now we have fixed sub-issue 3 of issue #81
Test cases
- Updated test case `simple_arrays2.t` to showcase the aforementioned fix
* Builtins
- Updated TODO
* Builtins
- Removed comment as now fixed
* Array
- Added `getComponentType()` method which will return the array's element type
* Dependency
- When processing the `Array` type which is now to be seen as a stack-based array (fixed size), error out in processing it during variable declarations
* Builtins
- Added `bool isStackArray(string)` in order to check if a given type string is designated as a stack-array type or not
- `Type getBuiltInType(TypeChecker, string)` now can generate the `StackArray` type including the component type and the size of the stack allocation
Parser
- Added support to`parseTypedDeclaration` to be able to parse stack-based array types
- Added terminator `]` to `parseExpression()`
DGen
- Added stack-based array type transformation support to `string typeTransform(Type)`
- Added transformation support for stack-based arrays for the `VariableDeclaration` instruction
StackArray
- Renamed `Array` type to `StackArray`
` The `StackArray` type now has an `arraySize` field and is included in the constructor's paremeters
- Added a `getAllocatedSize()` method to retrieve the `arraySize` field
Dependency
- Temporarily enabled the `StackArray` type in dependency processing for `VariableDeclarations` such that we can continue through the pipeline
Test cases
- Updated `simple_arrays.t` to test stack-based array types
* Tets cases
- Added new test case for testing (later) multi-dimensional stack-arrays
* Parser
- Working on adding array index assignment support
Test cases
- Added test case to test array assignments with
* Parser
- We can now detect when infact we are doing an array-indexed assignment and when not, we then flip` arrayIndexing` to `true` if that is the case and ensure that `=` SymbolType.ASSIGN is not triggering the varaible-declaration-with-assignment but rather eters a different branch based on this boolean
- Set the identifier being assigned to (in the array indexing case) to the `type` with the `[]...` stripped
Notes
- Added a TODO file `wip.txt` with notes about what is to be done for adding full array support
* Parser
- Handle the case whereby `SymbolType.ASSIGN` or `SymbolType.IDENT_TYPE` is not found by throwing an error
* Parser
- Moved logic for array assignments into the branch for it (deferred it)
* Data
- Added new work-in-progress parser node type `ArrayAssignment`
Parser
- Added TODO about the type of returned parse node needing to be updated down the line
Notes
- Updated `wip.txt` with more thoughts
* Expressions
- Added new parse node (a sub-type of `Expression`) for representing array indexing; `ArrayIndex`
Data
- Fixed compilation error caused by missing semi-colon
* Parser
- Added support for array accesses/indexing in `parseExpression()`
- Added a token-rerun mechanism that lets us replay the needed tokens which needed to be looked ahead in order to determine an array access was about to occur
* Parser
- Removed now-completed TODO relating to array accesses in `parseExpression()`
* Parser
- Added right-hand side expression parsing for array assignments
Test cases
- Updated test case to test both array expressions on the left-hand side of an assignment and as a free-standing expression on the right hand side
Data
- Implemeneted `ArrayAssignment` which is to be used for assigning into arrays
* Instruction
- Added new instruction for indexing into arrays, a new `Value`-type instruction called `ArrayIndexInstruction`
* DGen
- Handle `ArrayIndexInstruction` which is for whenever you index into a point-based array (an expression like `myArray[i]` is now being supported in emit (first steps))
* Instructions
- Added a new instruction type, `StackArrayINdexInstruction`, which is used to know when we are indexing into a stack-based array rather than a pointer-based array (just to be able to disambiguate between the two)
- Added a work-in-progress type `StackArrayIndexAssignmentInstruction` which will be used for assigning to stack arrays at a given index
* Instructions
- Added implementation for `StackArrayIndexAssignmentInstruction` which represents the assignment of some `Value` instruction to a stack-based array (indicated by the `arrayName` string field) at the index indicated by the provided `Value` instruction
* DGen
- Added a stub emitter for `ArrayIndexInstruction` (pointer-based array indexing)
- Added a stub emitter for `StackArrayINdexInstruction` (stack-array based array indexing)
* INstructions
- Added `getArrayName()`, `getIndexInstr()` and `getAssignedValue()` to `StackArrayIndexAssignmentInstruction`
* Instructions
- Added `ArrayIndexAssignmentInstruction` which is intended to be used for when one wants to assign into a pointer-based array
- It embeds a `Value` instruction which is what is to be assigned and then an `ArrayIndexInstruction` representing the base of the poiinter-based array (base address) coupled with an "index" (offset)
- Added a `toString()` override for `StackArrayIndexAssignmentInstruction`
* Test cases
- Added `complex_stack_arrays1.t`
- This tests a stack array of a fixed size of `int[]` (basically `int*`) and assigneing into it
* Test cases
- Added `simple_arrays4.t` which makes an `int[]` (which is an `int*`) and then assignes into it at `i` whilst referring to itself at `i` and doing a binary operation
* Test cases
- Added `simple_stack_arrays2.t` which tests a stack array of a fixed size and then assigns into it a value
* Test cases
- Added `simple_stack_arrays4.t` which just tests assigning to a stack array of a fixed size BUT referring to said stack array itself as part of the assignment expression
* DGen
- Removed TODO comment for `ArrayIndexInstruction` transformation branch
- Added a description for when the `ArrayIndexInstruction` branch is activated for a transformation
- Implemented transformation for `ArrayIndexInstruction`
- Added comment on when `ArrayIndexAssignmentInstruction` activates
- Implemented transformation for `ArrayIndexAssignmentInstruction`
- Added comment for when the `StackArrayIndexInstruction` branch activates
- Implemented transformation for `StackArrayIndexInstruction`
- Added comment for when `StackArrayIndexAssignmentInstruction` branch activates
- Implemented transformation for `StackArrayIndexAssignmentInstruction`
* Dependency
- Added dependency node generation for the `ArrayIndex`
- This will pool the `ArrayIndex` parser-node
- This will then set the context of the parser-node to the current context
- The index expression will be depended upon
- The indexed expression (the entity being indexed) will be depended upon
---
- Added dependency generation for `ArrayAssignment`
- The `ArrayAssignment` parser node will be pooled
- The `ArrayAssignment` will have its context set to the current context
- The assigned expression will be depended upon
- The entity being indexed will be depended upon
- The index expression will be depended upon
* Parser
- Added a branch to `parseName()` which handles array assignments's semicolon consumption and token cursor movement to the next token
- Updated `parseTypedDeclaration()` to return an object of type `Statement` rather than `TypedEntity`
- Disabled the intentional `assert(false)` when handling array assignments
- Assign the generated `ArrayAssignment` to the `generated` variable
- Updated `parseExtern()` to cast to `TypedEntity` to ensure that the `Statement` returned is of that sub-type (added an assertion to then check this fact)
* Typechecker/Codegen
- Implemented `isStackArray(Value)` which checks if the given `Value` instruction is a `FetchValueVar`, then extracts the `Variable` being referred to in said instruction and checks if its declared type is that of `StackArray`
- Implemented code generation for `ArrayAssignment`
- Implemented code generation for `ArrayIndex`
* Test cases
- WIP: Added `simple_stack_array_coerce.t` as we want to add coercion for this now
* Typecheck
- Added rudimentary check for checking if an argument is a stack array, and if the parameter (to a function call) is a pointer and if so then returns whether they have matching component types in a new function named `canCoerceStackArray(Type, Type)`
* Typecheck
- Fixed `canCoerceStackArray(Type, Type)` to actually coerce the first type first into a pointer type (coercing the stack array's component type to `<compType>*`) and THEN apply the `isSameType(Type, Type)` check
* Typecheck
- Hoisted up `canCoerceStackArray(Type, Type)` to the class-level of `TypeChecker`
- Removed debug prints from `canCoerceStackArray(Type, Type)`
- Added a TODO where the check should be done in the `FunctionCall` branch of the `DNode` processor
* TypeChecker
- Added a seperate check for function call `DNode` processing which now checks if we can coerce the stack-array-based argument to the pointer-based type parameter
Notes
- Emit now fails as we haven't implement an emit for this case, so we need to do that.
- Also, should we change the type of what is being passed in - perhaps that actually makes sense here - we haven't fully coerced it actually
* TypeChecker
- Updated `canCoerceStackArray(Type, Type)` to now take in `canCoerceStackArray(Type, Type, ref Type)` to set the newly created coerced type
- Fixed bug whereby if the coercion succeeded we didn't actually add to the list of evaluation-instructions in the `FuncCallInstr` object, hence there would be a `null` Instruction object appearing in the code emit phase.
- Added some NOTEs which we can clean up this code using
* TypeChecker
- Cleaned up commented-out code
* Added CI/CD test for 'simple_stack_array_coerce.t'
* Added CI/CD test for 'complex_stack_arrays1.t'
* Added CI/CD semantic tests (WIP) for 'simple_stack_array_coerce.t' and 'complex_stack_arrays1.t'
* Added CI/CD semantic tests (WIP) for 'simple_arrays2.t' and 'simple_arrays4.t'
* Added CI/CD semantic tests (WIP) for 'simple_arrays2.t' and 'simple_arrays4.t'
* Added CI/CD semantic tests (WIP) for 'simple_arrays2.t' and 'simple_arrays4.t'
* Fixed filepath for test 'simple_arrays.t'
* Fixed typechecking tests for arrays
* DGen
- Added instrumentation for `simple_stack_array_coerce.t`
Test cases
- Updated `simple_stack_array_coerce.t` to update the array passed in a manner such that we can sum the two elements later, return it and assert to ensure it is set correctly
* Parser
- Had to ensure the old identifier code was removed too, was too early; therefore this now-dead code was removed
* Test cases
- Added this test (even though it is a bad test, the syntax ie wrong)
* Test cases
- Update `simple_stack_arrsys4.t` to return an `int` such that we can verify it works.
- Also added more tests to it.
DGen
- Added semantic test code generation for `simple_stack_arrays4.t`
CI
- Re-organised tests for semantics in emit for arrays into those "Which have semantic tests" and "those which don't (yet)"
- Added semantic/emit test for `simple_stack_arrays4.t`
* Test cases
- Updated `simple_arrays2.t` to test casting of complex array types
* Test cases
- Updated `complex_stack_arrays1.t`
* Test cases
- Added new test for testing pointer syntax; `simple_stack_array_coerce_ptr_syntax.t`
- FIXME: It is broken as we don't have the latest pointer code - that must still be finished
* Test cases
- Added test case `simple_stack_array_ceorce_wrong.t` where coercion must fail
* Test cases
- Added `simple_pointer_array_syntax.t` which should test the `int[] == int*` stuff
* DGen
- Made semantic test for `simple_pointer_array_syntax.t`
Test cases
- Added a test for `simple_pointer_array_syntax.t.t`
* Branding
- Added logo here
* Test cases
- Addes semantic code emit instrucmentation for `simple_stack_array_coerce_ptr_syntax.t`
* Pipelines
- Added test case for `source/tlang/testing/simple_stack_array_coerce_wrong.t` for typechecking phase
* Test cases
- Added test case `complex_stack_array_coerce.t`
* Test cases
- Added extensive positive test case `complex_stack_array_coerce_permutation_good.t` which has a lot of different ways to write `int**` (think `int*[]` etc)
- Added negative test cases `complex_stack_array_coerce_bad1.t`, `complex_stack_array_coerce_bad2.t` and `complex_stack_array_coerce_bad3.t`
2023-04-20 10:21:50 +01:00
|
|
|
// TODO: Add an ArrayAssignment thing here, would be similiar to PointerDeference
|
|
|
|
// mmmh, we would also need to ensure during typechecking/codegen/emit that we don't
|
|
|
|
// do pointer arithmetic. Makes sense we would have a ArrayAssign and expression for indexers
|
|
|
|
// but during codegen we check WHO was being assigned to and their type and based on that
|
|
|
|
// generate the correct INSTRUCTION
|
|
|
|
public final class ArrayAssignment : Statement
|
|
|
|
{
|
|
|
|
private Expression assignmentExpression;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The left hand side of:
|
|
|
|
* e.g. myArray[i][1] = 2;
|
|
|
|
*
|
|
|
|
* Therefore the `myArray[i][1]` part
|
|
|
|
*/
|
|
|
|
private ArrayIndex leftHandExpression;
|
|
|
|
|
|
|
|
this(ArrayIndex leftHandExpression, Expression assignmentExpression)
|
|
|
|
{
|
|
|
|
this.leftHandExpression = leftHandExpression;
|
|
|
|
this.assignmentExpression = assignmentExpression;
|
|
|
|
|
|
|
|
/* Weighted as 2 */
|
|
|
|
weight = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArrayIndex getArrayLeft()
|
|
|
|
{
|
|
|
|
return leftHandExpression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getAssignmentExpression()
|
|
|
|
{
|
|
|
|
return assignmentExpression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "ArrayAssignment [leftHand: "~leftHandExpression.toString()~", assignmentExpr: "~assignmentExpression.toString()~"]";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-27 14:52:43 +01:00
|
|
|
|
2023-01-12 08:53:48 +00:00
|
|
|
public class PointerDereferenceAssignment : Statement
|
|
|
|
{
|
|
|
|
private Expression assignmentExpression;
|
|
|
|
private Expression pointerExpression;
|
|
|
|
private ulong derefCount;
|
|
|
|
|
|
|
|
this(Expression pointerExpression, Expression assignmentExpression, ulong derefCount = 1)
|
|
|
|
{
|
|
|
|
this.pointerExpression = pointerExpression;
|
|
|
|
this.assignmentExpression = assignmentExpression;
|
|
|
|
this.derefCount = derefCount;
|
|
|
|
|
|
|
|
/* Weighted as 2 */
|
|
|
|
weight = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getExpression()
|
|
|
|
{
|
|
|
|
return assignmentExpression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getPointerExpression()
|
|
|
|
{
|
|
|
|
return pointerExpression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ulong getDerefCount()
|
|
|
|
{
|
|
|
|
return derefCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "[pointerDeref: From: "~pointerExpression.toString()~"]";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-27 14:52:43 +01:00
|
|
|
|
2021-06-07 15:47:57 +01:00
|
|
|
public class IdentExpression : Expression
|
2021-03-30 16:35:16 +01:00
|
|
|
{
|
2021-10-25 21:31:07 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-03-30 16:35:16 +01:00
|
|
|
/* name */
|
|
|
|
private string name;
|
|
|
|
|
|
|
|
this(string name)
|
|
|
|
{
|
|
|
|
this.name = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
public string getName()
|
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
2021-10-25 21:31:07 +01:00
|
|
|
|
|
|
|
public void updateName(string newName)
|
|
|
|
{
|
|
|
|
name = newName;
|
|
|
|
}
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public class VariableExpression : IdentExpression
|
|
|
|
{
|
|
|
|
|
|
|
|
this(string identifier)
|
|
|
|
{
|
|
|
|
super(identifier);
|
|
|
|
}
|
|
|
|
|
2021-10-25 21:31:07 +01:00
|
|
|
|
|
|
|
|
2023-02-05 18:21:26 +00:00
|
|
|
import tlang.compiler.typecheck.core;
|
2021-03-30 16:35:16 +01:00
|
|
|
public override string evaluateType(TypeChecker typeChecker, Container c)
|
|
|
|
{
|
|
|
|
string type;
|
|
|
|
|
|
|
|
|
2021-04-01 13:09:30 +01:00
|
|
|
return null;
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
2021-08-12 14:41:56 +01:00
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "[varExp: "~getName()~"]";
|
|
|
|
}
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public class Call : IdentExpression
|
|
|
|
{
|
|
|
|
this(string ident)
|
|
|
|
{
|
|
|
|
super(ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public final class FunctionCall : Call
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
/* Argument list */
|
|
|
|
private Expression[] arguments;
|
|
|
|
|
|
|
|
this(string functionName, Expression[] arguments)
|
|
|
|
{
|
|
|
|
super(functionName);
|
|
|
|
this.arguments = arguments;
|
|
|
|
}
|
2022-02-16 05:31:22 +00:00
|
|
|
|
2022-04-08 00:08:57 +01:00
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return super.toString()~" "~name~"()";
|
|
|
|
}
|
|
|
|
|
2022-02-16 05:31:22 +00:00
|
|
|
public Expression[] getCallArguments()
|
|
|
|
{
|
|
|
|
return arguments;
|
|
|
|
}
|
2022-12-13 12:17:40 +00:00
|
|
|
}
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
/**
|
|
|
|
* ReturnStmt
|
|
|
|
*
|
|
|
|
* Represents a return statement with an expression
|
|
|
|
* to be returned
|
|
|
|
*/
|
2022-12-13 12:17:40 +00:00
|
|
|
public final class ReturnStmt : Statement
|
|
|
|
{
|
|
|
|
// The Expression being returned
|
|
|
|
private Expression returnExpression;
|
|
|
|
|
|
|
|
this(Expression returnExpression)
|
|
|
|
{
|
|
|
|
this.returnExpression = returnExpression;
|
2022-12-17 17:02:14 +00:00
|
|
|
|
|
|
|
/* Statement level weighting is 2 */
|
|
|
|
weight = 2;
|
2022-12-13 12:17:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getReturnExpression()
|
|
|
|
{
|
|
|
|
return returnExpression;
|
|
|
|
}
|
2022-12-19 13:37:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* IfStatement
|
2023-01-04 10:03:50 +00:00
|
|
|
*
|
|
|
|
* Represents an if statement with branches of code
|
|
|
|
* and conditions per each
|
2022-12-19 13:37:55 +00:00
|
|
|
*/
|
|
|
|
public final class IfStatement : Entity, Container
|
|
|
|
{
|
|
|
|
private Branch[] branches;
|
|
|
|
|
|
|
|
private static ulong ifStmtContainerRollingNameCounter = 0;
|
|
|
|
|
|
|
|
this(Branch[] branches)
|
|
|
|
{
|
|
|
|
ifStmtContainerRollingNameCounter++;
|
|
|
|
super("ifStmt_"~to!(string)(ifStmtContainerRollingNameCounter));
|
|
|
|
|
|
|
|
this.branches = branches;
|
|
|
|
|
|
|
|
weight = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Branch[] getBranches()
|
|
|
|
{
|
|
|
|
return branches;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatement(Statement statement)
|
|
|
|
{
|
|
|
|
branches ~= cast(Branch)statement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatements(Statement[] statements)
|
|
|
|
{
|
|
|
|
branches ~= cast(Branch[])statements;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override Statement[] getStatements()
|
|
|
|
{
|
|
|
|
return cast(Statement[])branches;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "IfStmt";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
/**
|
|
|
|
* WhileLoop
|
|
|
|
*
|
|
|
|
* Represents a while loop with conditional code
|
|
|
|
*/
|
|
|
|
public final class WhileLoop : Entity, Container
|
|
|
|
{
|
|
|
|
private Branch branch;
|
|
|
|
private static ulong whileStmtContainerRollingNameCounter = 0;
|
|
|
|
public const bool isDoWhile;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new While Loop parser node, optionally specifying
|
|
|
|
* if this is to be interpreted (in-post) as a while-loop
|
|
|
|
* or do-while loop
|
|
|
|
*
|
|
|
|
* Params:
|
|
|
|
* branch = The <code>Branch</code> that makes up this while
|
|
|
|
* loop
|
|
|
|
* isDoWhile = If <code>true</code> then interpret this as a
|
|
|
|
* do-while loop, however if <code>false</code>
|
|
|
|
* then a while-loop (default optional value)
|
|
|
|
*/
|
|
|
|
this(Branch branch, bool isDoWhile = false)
|
|
|
|
{
|
|
|
|
whileStmtContainerRollingNameCounter++;
|
|
|
|
super("whileStmt_"~to!(string)(whileStmtContainerRollingNameCounter));
|
|
|
|
|
|
|
|
this.branch = branch;
|
|
|
|
this.isDoWhile = isDoWhile;
|
|
|
|
|
|
|
|
weight = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Branch getBranch()
|
|
|
|
{
|
|
|
|
return branch;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatement(Statement statement)
|
|
|
|
{
|
|
|
|
// You should only be adding one branch to a while loop
|
|
|
|
assert(branch is null);
|
|
|
|
branch = cast(Branch)statement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatements(Statement[] statements)
|
|
|
|
{
|
|
|
|
// Only one Branch in the given input list
|
|
|
|
assert(statements.length == 1);
|
|
|
|
|
|
|
|
// You should only be adding one branch to a while loop
|
|
|
|
assert(branch is null);
|
|
|
|
|
|
|
|
branch = (cast(Branch[])statements)[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
public override Statement[] getStatements()
|
|
|
|
{
|
|
|
|
return cast(Statement[])[branch];
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "WhileLoop";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-11 08:43:29 +00:00
|
|
|
public final class ForLoop : Entity, Container
|
|
|
|
{
|
|
|
|
private Statement preLoopStatement;
|
|
|
|
private Branch branch;
|
|
|
|
private bool hasPostIterate;
|
|
|
|
private static ulong forStmtContainerRollingNameCounter = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new For Loop parser node
|
|
|
|
*
|
|
|
|
* Params:
|
|
|
|
*
|
|
|
|
* preLoopStatement = The <code>Statement</code> to run before
|
|
|
|
* beginning the first iteration
|
|
|
|
* branch = The <code>Branch</code> that makes up this for
|
|
|
|
* loop
|
|
|
|
*/
|
|
|
|
this(Branch branch, Statement preLoopStatement = null, bool hasPostIterate = false)
|
|
|
|
{
|
|
|
|
forStmtContainerRollingNameCounter++;
|
|
|
|
super("forStmt_"~to!(string)(forStmtContainerRollingNameCounter));
|
|
|
|
|
|
|
|
this.preLoopStatement = preLoopStatement;
|
|
|
|
this.branch = branch;
|
|
|
|
this.hasPostIterate = hasPostIterate;
|
|
|
|
|
|
|
|
weight = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool hasPostIterateStatement()
|
|
|
|
{
|
|
|
|
return hasPostIterate;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool hasPreRunStatement()
|
|
|
|
{
|
|
|
|
return !(preLoopStatement is null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Branch getBranch()
|
|
|
|
{
|
|
|
|
return branch;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Statement getPreRunStatement()
|
|
|
|
{
|
|
|
|
return preLoopStatement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatement(Statement statement)
|
|
|
|
{
|
|
|
|
// You should only be adding one branch to a for loop
|
|
|
|
assert(branch is null);
|
|
|
|
branch = cast(Branch)statement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatements(Statement[] statements)
|
|
|
|
{
|
|
|
|
// Only one Branch in the given input list
|
|
|
|
assert(statements.length == 1);
|
|
|
|
|
|
|
|
// You should only be adding one branch to a for loop
|
|
|
|
assert(branch is null);
|
|
|
|
|
|
|
|
branch = (cast(Branch[])statements)[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
public override Statement[] getStatements()
|
|
|
|
{
|
|
|
|
// If there is a pre-run statement then prepend it
|
|
|
|
if(hasPreRunStatement())
|
|
|
|
{
|
|
|
|
return cast(Statement[])[preLoopStatement, branch];
|
|
|
|
}
|
|
|
|
// If not, then just the Branch container
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return cast(Statement[])[branch];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "ForLoop";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-19 13:37:55 +00:00
|
|
|
/**
|
|
|
|
* Branch
|
|
|
|
*
|
|
|
|
* Represents a condition and code attached to
|
|
|
|
* run on said condition
|
|
|
|
*
|
|
|
|
* NOTE: I feel as though this should be a container
|
|
|
|
* with a `generalPass` applied to it in `dependency/core.d`
|
|
|
|
*/
|
|
|
|
public final class Branch : Entity, Container
|
|
|
|
{
|
|
|
|
private Expression branchCondition;
|
|
|
|
private Statement[] branchBody;
|
|
|
|
|
|
|
|
private static ulong branchContainerRollingNameCounter = 0;
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
/**
|
|
|
|
* Creates a new Branch which will couple a condition
|
|
|
|
* as an instance of <code>Expression</code> and a body
|
|
|
|
* of <code>Statement</code>(s) apart of it
|
|
|
|
*
|
|
|
|
* Params:
|
|
|
|
* condition = The condition as an <code>Expression</code>
|
|
|
|
* branch = The body of <code>Statement</code>(s) making up the branch
|
|
|
|
*/
|
2022-12-19 13:37:55 +00:00
|
|
|
this(Expression condition, Statement[] branch)
|
|
|
|
{
|
|
|
|
branchContainerRollingNameCounter++;
|
|
|
|
super("branch_"~to!(string)(branchContainerRollingNameCounter));
|
|
|
|
|
|
|
|
this.branchCondition = condition;
|
|
|
|
this.branchBody = branch;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Effectively checks if this branch is an 'else' branch
|
|
|
|
*
|
|
|
|
* Returns: <code>true</code> if so, <code>false</code>
|
|
|
|
* otherwise
|
|
|
|
*/
|
|
|
|
public bool hasCondition()
|
|
|
|
{
|
|
|
|
return !(branchCondition is null);
|
|
|
|
}
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
/**
|
|
|
|
* Returns the condition of the branch
|
|
|
|
*
|
|
|
|
* Returns: The condition as an instance of <code>Expression</code>
|
|
|
|
*/
|
2022-12-19 13:37:55 +00:00
|
|
|
public Expression getCondition()
|
|
|
|
{
|
|
|
|
return branchCondition;
|
|
|
|
}
|
|
|
|
|
2023-01-04 10:03:50 +00:00
|
|
|
|
2022-12-19 13:37:55 +00:00
|
|
|
public Statement[] getBody()
|
|
|
|
{
|
|
|
|
return branchBody;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatement(Statement statement)
|
|
|
|
{
|
|
|
|
branchBody ~= statement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void addStatements(Statement[] statements)
|
|
|
|
{
|
|
|
|
branchBody ~= statements;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override Statement[] getStatements()
|
|
|
|
{
|
|
|
|
return branchBody;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "Branch";
|
|
|
|
}
|
2023-01-13 08:49:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public final class DiscardStatement : Statement
|
|
|
|
{
|
|
|
|
private Expression expression;
|
|
|
|
|
|
|
|
this(Expression expression)
|
|
|
|
{
|
|
|
|
this.expression = expression;
|
|
|
|
|
|
|
|
/* Weighted as 2 */
|
|
|
|
weight = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Expression getExpression()
|
|
|
|
{
|
|
|
|
return expression;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "[DiscardStatement: (Exp: "~expression.toString()~")]";
|
|
|
|
}
|
2023-01-15 18:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public final class ExternStmt : Statement
|
|
|
|
{
|
|
|
|
// Pseudo entity created
|
|
|
|
private Entity pseudoEntity;
|
|
|
|
|
|
|
|
private SymbolType externType;
|
|
|
|
|
|
|
|
this(Entity pseudoEntity, SymbolType externType)
|
|
|
|
{
|
|
|
|
// External symbols are either external functions or external variables
|
|
|
|
assert(externType == SymbolType.EXTERN_EFUNC || externType == SymbolType.EXTERN_EVAR);
|
|
|
|
|
|
|
|
this.pseudoEntity = pseudoEntity;
|
|
|
|
this.externType = externType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public string getExternalName()
|
|
|
|
{
|
|
|
|
return pseudoEntity.getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
public SymbolType getExternType()
|
|
|
|
{
|
|
|
|
return externType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Entity getPseudoEntity()
|
|
|
|
{
|
|
|
|
return pseudoEntity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string toString()
|
|
|
|
{
|
|
|
|
return "[ExternStatement: (Symbol name: "~getExternalName()~")]";
|
|
|
|
}
|
2021-03-30 16:35:16 +01:00
|
|
|
}
|