tlang/source/tlang/compiler/symbols/data.d

991 lines
21 KiB
D
Raw Normal View History

module tlang.compiler.symbols.data;
2021-03-30 16:35:16 +01:00
public import tlang.compiler.symbols.check;
2021-03-30 16:35:16 +01:00
import std.conv : to;
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()
{
/* 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
{
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;
}
}
/**
* Entity
*
* Declared variables, defined classes and functions
*/
2021-03-30 16:35:16 +01:00
public class Entity : Statement
{
/* 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
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
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;
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
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;
}
}
public import tlang.compiler.symbols.containers;
2021-03-30 16:35:16 +01:00
public class ArgumentList
{
}
/**
* 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);
}
}
/* 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) */
public class Function : TypedEntity, Container
2021-03-30 16:35:16 +01:00
{
private VariableParameter[] params;
2021-03-30 16:35:16 +01:00
private Statement[] bodyStatements;
this(string name, string returnType, Statement[] bodyStatements, VariableParameter[] params)
2021-03-30 16:35:16 +01:00
{
super(name, returnType);
// 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
}
public VariableParameter[] getParams()
{
return params;
}
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
public bool hasParams()
{
return params.length != 0;
}
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()
{
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);
/* 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~")";
}
}
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;
/* 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
Instruction - Added `getOperator()` and `getOperand()` methods to `UnaryOpInstr` - Added new instruction `PointerDereferenceAssignmentInstruction` for pointer support DGen - Updated `transform()` to emit code for instruction type `UnaryOpInstr` - Updated `transform()` to emit code for instruction type `PointerDereferenceAssignmentInstruction` - Added testing emit code in `emitEntryPoint()` for pointer testing Parser - Updated `parseName()` to trigger `parseTypedDeclaration()` on occurene of `SymbolType.STAR` (for pointer type declarations) - Added pointer-type support for function parameters (so far only single) in `parseFuncDef()` - `parseExpression()` terminates on occurence of a single `=` (ASSIGN) operator - Declaring of pointers of any depth implemented in `parseTypedDeclaration()` - Added support for pointer dereferncing assignments with the addition of `parseDerefAssignment()` - `parseStatement()` will now call `parseDerefAssignment()` on occurence of a `SymbolType.STAR` - Added a unittest for testing pointers - Finished unittest for for loops Check - Added backmapping for `SymbolType.ASSIGN` -> `&` Data - Added new parser node type `PointerDereferenceAssignment` for pointer support in the parser TypeChecker - Because function parameters are type che cked upon function call I had to add typechecking code for pointer support in the `UnaryOperatorExpression` case - Added code generation support for `PointerDereferenceAssignment` type Dependency - Added support for `PointerDereferenceAssignment` type (pointer support) to `generalStatement()` Tests - Added pointer test `simple_pointer.t`
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
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
}
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;
}
public override string toString()
{
return super.toString()~" "~name~"()";
}
public Expression[] getCallArguments()
{
return arguments;
}
}
/**
* ReturnStmt
*
* Represents a return statement with an expression
* to be returned
*/
public final class ReturnStmt : Statement
{
// The Expression being returned
private Expression returnExpression;
this(Expression returnExpression)
{
this.returnExpression = returnExpression;
/* Statement level weighting is 2 */
weight = 2;
}
public Expression getReturnExpression()
{
return returnExpression;
}
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2022-12-19 13:37:55 +00:00
}
/**
* IfStatement
*
* Represents an if statement with branches of code
* and conditions per each
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
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";
}
}
/**
* 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";
}
}
Instruction - Added a new instruction, `ForLoop`, which contains a pre-run Instruction and a `Branch` instruction, coupled with some flags DGen - Added a TODO for WhileLoops (we need to implement do-while loops) - Implemented C code emitting in `emit()` for `ForLoop` instruction Check - Added missing back-mapping for `SymbolType.SMALLER_THAN` Data - Added new parser node type `ForLoop` Parser - Fixed typo in `parseWhile()` - Implemented `parseDoWhile()` for do-while loops - Implemented `parseFor()` for for-loops - Implemented `parseStatement()` for singular statement parsing - `parseStatement()` can now have the terminating symbol specified, defaults to `SymbolType.SEMICOLON` - `parseName()` and `parseAssignment()` now also accept a terminating symbol parameter as per `parseStatement()`'s behavior - `parseBody()` now makes multiple calls to `parseStatement()` for singular Statement parsing (dead code below still to be removed) - Removed commented-out unittests - Unittests that read from files now have the file source code embedded - Added unit test for while loops, for-loops (unfinished) and some other smaller language constructs (roughly 70% coverage) TypeChecker (CodeGen) - Do-while loops will fail if used (for now) - Added for-loop code generation Dependency - Implemented `generalStatement()` for statement processing - `generalPass()` now makes calls to `generalStatement()` Tests - Added `simple_for_loops.t` to test for-loops - Added `simple_do_while.t` to test do-while loops
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";
}
}
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
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;
/**
* 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
*/
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
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);
}
/**
* Returns the condition of the branch
*
* Returns: The condition as an instance of <code>Expression</code>
*/
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2022-12-19 13:37:55 +00:00
public Expression getCondition()
{
return branchCondition;
}
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
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";
}
}
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()~")]";
}
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
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
}