2023-02-05 18:21:26 +00:00
module tlang.compiler.codegen.emit.dgen ;
2021-11-02 08:41:03 +00:00
2023-02-05 18:21:26 +00:00
import tlang.compiler.codegen.emit.core : CodeEmitter ;
import tlang.compiler.typecheck.core ;
2021-11-02 13:13:44 +00:00
import std.container.slist : SList ;
2023-02-05 18:21:26 +00:00
import tlang.compiler.codegen.instruction ;
2021-11-02 13:13:44 +00:00
import std.stdio ;
import std.file ;
2021-11-02 15:03:38 +00:00
import std.conv : to ;
import std.string : cmp ;
2021-11-02 15:24:08 +00:00
import gogga ;
2022-12-11 15:52:36 +00:00
import std.range : walkLength ;
2022-12-11 19:00:48 +00:00
import std.string : wrap ;
2022-12-11 19:41:15 +00:00
import std.process : spawnProcess , Pid , ProcessException , wait ;
2023-02-05 18:21:26 +00:00
import tlang.compiler.typecheck.dependency.core : Context , FunctionData , DNode ;
import tlang.compiler.codegen.mapper.core : SymbolMapper ;
import tlang.compiler.symbols.data : SymbolType , Variable , Function , VariableParameter ;
import tlang.compiler.symbols.check : getCharacter ;
2022-12-12 14:40:45 +00:00
import misc.utils : Stack ;
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
import tlang.compiler.symbols.typing.core ;
2023-02-05 18:21:26 +00:00
import tlang.compiler.configuration : CompilerConfiguration ;
2021-11-02 13:27:17 +00:00
2021-11-02 08:41:03 +00:00
public final class DCodeEmitter : CodeEmitter
2023-02-04 10:41:30 +00:00
{
2023-01-23 18:44:35 +00:00
// NOTE: In future store the mapper in the config please
this ( TypeChecker typeChecker , File file , CompilerConfiguration config , SymbolMapper mapper )
2021-11-02 13:13:44 +00:00
{
2023-01-23 18:44:35 +00:00
super ( typeChecker , file , config , mapper ) ;
2021-11-09 13:30:37 +00:00
}
2022-12-19 13:37:55 +00:00
private ulong transformDepth = 0 ;
private string genTabs ( ulong count )
{
string tabStr ;
2023-01-19 19:06:20 +00:00
/* Only generate tabs if enabled in compiler config */
2023-01-28 16:12:49 +00:00
if ( config . getConfig ( "dgen:pretty_code" ) . getBoolean ( ) )
2022-12-19 13:37:55 +00:00
{
2023-01-19 19:06:20 +00:00
for ( ulong i = 0 ; i < count ; i + + )
{
tabStr ~ = "\t" ;
}
2022-12-19 13:37:55 +00:00
}
2023-01-19 19:06:20 +00:00
2022-12-19 13:37:55 +00:00
return tabStr ;
}
2023-01-15 10:36:54 +00:00
/ * *
* Given an instance of a Type this will transform it to a string
*
* Params :
* typeIn = The Type to transform
*
* Returns : The string representation of the transformed type
* /
public string typeTransform ( Type typeIn )
{
string stringRepr ;
// TODO: Some types will ident transform
2023-01-15 10:49:28 +00:00
/* Pointer types */
if ( cast ( Pointer ) typeIn )
{
/* Extract type being pointed to */
Pointer pointerType = cast ( Pointer ) typeIn ;
2023-01-15 10:59:41 +00:00
Type referType = pointerType . getReferredType ( ) ;
2023-01-15 10:49:28 +00:00
/* The type is then `transform(<refertype>)*` */
return typeTransform ( referType ) ~ "*" ;
}
2023-01-15 10:36:54 +00:00
/* Integral types transformation */
2023-01-15 10:49:28 +00:00
else if ( cast ( Integer ) typeIn )
2023-01-15 10:36:54 +00:00
{
Integer integralType = cast ( Integer ) typeIn ;
/* u<>_t or <>_t (Determine signedness) */
string typeString = integralType . isSigned ( ) ? "int" : "uint" ;
/* Width of integer */
typeString ~ = to ! ( string ) ( integralType . getSize ( ) * 8 ) ;
/* Trailing `_t` */
typeString ~ = "_t" ;
return typeString ;
}
/* Void type */
else if ( cast ( Void ) typeIn )
{
return "void" ;
}
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
/* Stack-based array type */
else if ( cast ( StackArray ) typeIn )
{
// TODO: Still implement stakc-based arrays
// we won't be able to tyoe transform just here
// ... as we need <componentType> <varName>[<arraySize>]
// ... hence this must be performed in avriable declaration
StackArray stackArray = cast ( StackArray ) typeIn ;
return typeTransform ( stackArray . getComponentType ( ) ) ;
// return "KAK TODO";
}
2023-01-15 10:36:54 +00:00
gprintln ( "Type transform unimplemented" ) ;
assert ( false ) ;
// return stringRepr;
}
2022-12-12 13:36:07 +00:00
public override string transform ( const Instruction instruction )
2022-12-11 19:41:15 +00:00
{
2022-12-16 12:53:33 +00:00
writeln ( "\n" ) ;
2022-12-14 17:49:08 +00:00
gprintln ( "transform(): " ~ to ! ( string ) ( instruction ) ) ;
2022-12-19 13:37:55 +00:00
transformDepth + + ;
// At any return decrement the depth
scope ( exit )
{
transformDepth - - ;
}
2022-12-14 17:49:08 +00:00
2022-12-12 13:36:07 +00:00
/* VariableAssignmentInstr */
if ( cast ( VariableAssignmentInstr ) instruction )
2022-12-11 19:41:15 +00:00
{
2022-12-16 12:53:33 +00:00
gprintln ( "type: VariableAssignmentInstr" ) ;
2022-12-12 13:36:07 +00:00
VariableAssignmentInstr varAs = cast ( VariableAssignmentInstr ) instruction ;
Context context = varAs . getContext ( ) ;
2022-12-11 19:41:15 +00:00
2022-12-12 13:36:07 +00:00
gprintln ( "Is ContextNull?: " ~ to ! ( string ) ( context is null ) ) ;
2022-12-16 12:53:33 +00:00
gprintln ( "Wazza contect: " ~ to ! ( string ) ( context . container ) ) ;
2023-01-23 18:44:35 +00:00
auto typedEntityVariable = typeChecker . getResolver ( ) . resolveBest ( context . getContainer ( ) , varAs . varName ) ; //TODO: Remove `auto`
2023-01-30 17:08:48 +00:00
gprintln ( "Hi" ~ to ! ( string ) ( varAs ) ) ;
gprintln ( "Hi" ~ to ! ( string ) ( varAs . data ) ) ;
2023-02-01 12:55:23 +00:00
gprintln ( "Hi" ~ to ! ( string ) ( varAs . data . getInstrType ( ) ) ) ;
2023-01-30 17:08:48 +00:00
// NOTE: For tetsing issue #94 coercion (remove when done)
2023-02-01 12:55:23 +00:00
string typeName = ( cast ( Type ) varAs . data . getInstrType ( ) ) . getName ( ) ;
2023-01-30 17:08:48 +00:00
gprintln ( "VariableAssignmentInstr: The data to assign's type is: " ~ typeName ) ;
2022-12-11 19:41:15 +00:00
2022-12-12 13:36:07 +00:00
2023-01-19 07:03:19 +00:00
/* If it is not external */
if ( ! typedEntityVariable . isExternal ( ) )
2022-12-12 14:56:54 +00:00
{
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper . symbolLookup ( typedEntityVariable ) ;
2022-12-12 17:12:39 +00:00
2023-01-19 07:03:19 +00:00
return renamedSymbol ~ " = " ~ transform ( varAs . data ) ~ ";" ;
}
/* If it is external */
else
{
return typedEntityVariable . getName ( ) ~ " = " ~ transform ( varAs . data ) ~ ";" ;
}
2022-12-11 19:41:15 +00:00
}
2022-12-12 13:36:07 +00:00
/* VariableDeclaration */
else if ( cast ( VariableDeclaration ) instruction )
2022-12-11 19:41:15 +00:00
{
2022-12-16 12:53:33 +00:00
gprintln ( "type: VariableDeclaration" ) ;
2022-12-12 13:36:07 +00:00
VariableDeclaration varDecInstr = cast ( VariableDeclaration ) instruction ;
Context context = varDecInstr . getContext ( ) ;
2023-01-23 18:44:35 +00:00
Variable typedEntityVariable = cast ( Variable ) typeChecker . getResolver ( ) . resolveBest ( context . getContainer ( ) , varDecInstr . varName ) ; //TODO: Remove `auto`
2022-12-12 13:36:07 +00:00
2023-01-19 07:03:19 +00:00
/* If the variable is not external */
if ( ! typedEntityVariable . isExternal ( ) )
2022-12-12 17:12:39 +00:00
{
2023-01-19 07:03:19 +00:00
//NOTE: We should remove all dots from generated symbol names as it won't be valid C (I don't want to say C because
// a custom CodeEmitter should be allowed, so let's call it a general rule)
//
//simple_variables.x -> simple_variables_x
//NOTE: We may need to create a symbol table actually and add to that and use that as these names
//could get out of hand (too long)
// NOTE: Best would be identity-mapping Entity's to a name
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper . symbolLookup ( typedEntityVariable ) ;
2022-12-19 13:37:55 +00:00
2022-12-12 17:12:39 +00: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
// Check if the type is a stack-based array
// ... if so then take make symbolName := `<symbolName>[<stackArraySize>]`
if ( cast ( StackArray ) varDecInstr . varType )
{
StackArray stackArray = cast ( StackArray ) varDecInstr . varType ;
renamedSymbol ~ = "[" ~ to ! ( string ) ( stackArray . getAllocatedSize ( ) ) ~ "]" ;
}
2023-01-19 07:03:19 +00:00
// Check to see if this declaration has an assignment attached
if ( typedEntityVariable . getAssignment ( ) )
{
2023-02-04 10:41:30 +00:00
Value varAssInstr = varDecInstr . getAssignmentInstr ( ) ;
2023-02-04 12:25:39 +00:00
gprintln ( "VarDec(with assignment): My assignment type is: " ~ varAssInstr . getInstrType ( ) . getName ( ) ) ;
2023-01-19 07:03:19 +00:00
// Generate the code to emit
return typeTransform ( cast ( Type ) varDecInstr . varType ) ~ " " ~ renamedSymbol ~ " = " ~ transform ( varAssInstr ) ~ ";" ;
}
2022-12-12 14:40:45 +00:00
2023-01-19 07:03:19 +00:00
return typeTransform ( cast ( Type ) varDecInstr . varType ) ~ " " ~ renamedSymbol ~ ";" ;
}
/* If the variable is external */
else
{
return "extern " ~ typeTransform ( cast ( Type ) varDecInstr . varType ) ~ " " ~ typedEntityVariable . getName ( ) ~ ";" ;
2022-12-12 17:12:39 +00:00
}
2022-12-12 14:40:45 +00:00
2022-12-12 13:36:07 +00:00
}
/* LiteralValue */
else if ( cast ( LiteralValue ) instruction )
{
2022-12-16 12:53:33 +00:00
gprintln ( "type: LiteralValue" ) ;
2022-12-12 13:36:07 +00:00
LiteralValue literalValueInstr = cast ( LiteralValue ) instruction ;
2023-02-04 12:25:39 +00:00
return to ! ( string ) ( literalValueInstr . getLiteralValue ( ) ) ;
2022-12-13 09:46:40 +00:00
}
/* FetchValueVar */
else if ( cast ( FetchValueVar ) instruction )
{
2022-12-16 12:53:33 +00:00
gprintln ( "type: FetchValueVar" ) ;
2022-12-13 09:51:44 +00:00
FetchValueVar fetchValueVarInstr = cast ( FetchValueVar ) instruction ;
Context context = fetchValueVarInstr . getContext ( ) ;
2022-12-13 09:46:40 +00:00
2023-01-23 18:44:35 +00:00
Variable typedEntityVariable = cast ( Variable ) typeChecker . getResolver ( ) . resolveBest ( context . getContainer ( ) , fetchValueVarInstr . varName ) ; //TODO: Remove `auto`
2022-12-13 09:51:44 +00:00
2023-01-19 07:03:19 +00:00
/* If it is not external */
if ( ! typedEntityVariable . isExternal ( ) )
{
//TODO: THis is giving me kak (see issue #54), it's generating name but trying to do it for the given container, relative to it
//TODO: We might need a version of generateName that is like generatenamebest (currently it acts like generatename, within)
2022-12-17 11:41:00 +00:00
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper . symbolLookup ( typedEntityVariable ) ;
2022-12-13 09:51:44 +00:00
2023-01-19 07:03:19 +00:00
return renamedSymbol ;
}
/* If it is external */
else
{
return typedEntityVariable . getName ( ) ;
}
2022-12-12 13:36:07 +00:00
}
/* BinOpInstr */
else if ( cast ( BinOpInstr ) instruction )
{
2022-12-16 12:53:33 +00:00
gprintln ( "type: BinOpInstr" ) ;
2022-12-12 13:36:07 +00:00
BinOpInstr binOpInstr = cast ( BinOpInstr ) instruction ;
2022-12-11 19:41:15 +00:00
2022-12-19 13:37:55 +00:00
// TODO: I like having `lhs == rhs` for `==` or comparators but not spaces for `lhs+rhs`
2022-12-12 13:36:07 +00:00
return transform ( binOpInstr . lhs ) ~ to ! ( string ) ( getCharacter ( binOpInstr . operator ) ) ~ transform ( binOpInstr . rhs ) ;
2022-12-11 19:41:15 +00:00
}
2022-12-16 12:53:33 +00:00
/* FuncCallInstr */
else if ( cast ( FuncCallInstr ) instruction )
{
gprintln ( "type: FuncCallInstr" ) ;
FuncCallInstr funcCallInstr = cast ( FuncCallInstr ) instruction ;
Context context = funcCallInstr . getContext ( ) ;
assert ( context ) ;
2023-01-23 18:44:35 +00:00
Function functionToCall = cast ( Function ) typeChecker . getResolver ( ) . resolveBest ( context . getContainer ( ) , funcCallInstr . functionName ) ; //TODO: Remove `auto`
2022-12-16 12:53:33 +00:00
// TODO: SymbolLookup?
string emit = functionToCall . getName ( ) ~ "(" ;
//TODO: Insert argument passimng code here
//NOTE: Typechecker must have checked for passing arguments to a function that doesn't take any, for example
//NOTE (Behaviour): We may want to actually have an preinliner for these arguments
//such to enforce a certain ordering. I believe this should be done in the emitter stage,
//so it is best placed here
if ( functionToCall . hasParams ( ) )
{
Value [ ] argumentInstructions = funcCallInstr . getEvaluationInstructions ( ) ;
string argumentString ;
for ( ulong argIdx = 0 ; argIdx < argumentInstructions . length ; argIdx + + )
{
Value currentArgumentInstr = argumentInstructions [ argIdx ] ;
argumentString ~ = transform ( currentArgumentInstr ) ;
if ( argIdx ! = ( argumentInstructions . length - 1 ) )
{
argumentString ~ = ", " ;
}
}
emit ~ = argumentString ;
}
emit ~ = ")" ;
return emit ;
}
2022-12-17 17:02:14 +00:00
/* ReturnInstruction */
else if ( cast ( ReturnInstruction ) instruction )
{
gprintln ( "type: ReturnInstruction" ) ;
ReturnInstruction returnInstruction = cast ( ReturnInstruction ) instruction ;
Context context = returnInstruction . getContext ( ) ;
assert ( context ) ;
/* Get the return expression instruction */
Value returnExpressionInstr = returnInstruction . getReturnExpInstr ( ) ;
return "return " ~ transform ( returnExpressionInstr ) ~ ";" ;
}
2022-12-19 13:37:55 +00:00
/ * *
* If statements ( IfStatementInstruction )
* /
else if ( cast ( IfStatementInstruction ) instruction )
{
IfStatementInstruction ifStatementInstruction = cast ( IfStatementInstruction ) instruction ;
BranchInstruction [ ] branchInstructions = ifStatementInstruction . getBranchInstructions ( ) ;
gprintln ( "Holla" ~ to ! ( string ) ( branchInstructions ) ) ;
string emit ;
for ( ulong i = 0 ; i < branchInstructions . length ; i + + )
{
BranchInstruction curBranchInstr = branchInstructions [ i ] ;
if ( curBranchInstr . hasConditionInstr ( ) )
{
Value conditionInstr = cast ( Value ) curBranchInstr . getConditionInstr ( ) ;
string hStr = ( i = = 0 ) ? "if" : genTabs ( transformDepth ) ~ "else if" ;
emit ~ = hStr ~ "(" ~ transform ( conditionInstr ) ~ ")\n" ;
emit ~ = genTabs ( transformDepth ) ~ "{\n" ;
foreach ( Instruction branchBodyInstr ; curBranchInstr . getBodyInstructions ( ) )
{
emit ~ = genTabs ( transformDepth ) ~ "\t" ~ transform ( branchBodyInstr ) ~ "\n" ;
}
emit ~ = genTabs ( transformDepth ) ~ "}\n" ;
}
else
{
emit ~ = genTabs ( transformDepth ) ~ "else\n" ;
emit ~ = genTabs ( transformDepth ) ~ "{\n" ;
foreach ( Instruction branchBodyInstr ; curBranchInstr . getBodyInstructions ( ) )
{
emit ~ = genTabs ( transformDepth ) ~ "\t" ~ transform ( branchBodyInstr ) ~ "\n" ;
}
emit ~ = genTabs ( transformDepth ) ~ "}\n" ;
}
}
return emit ;
}
2023-01-04 10:03:50 +00:00
/ * *
* While loops ( WhileLoopInstruction )
2023-01-11 08:43:29 +00:00
*
* TODO : Add do - while check
2023-01-04 10:03:50 +00:00
* /
else if ( cast ( WhileLoopInstruction ) instruction )
{
WhileLoopInstruction whileLoopInstr = cast ( WhileLoopInstruction ) instruction ;
BranchInstruction branchInstr = whileLoopInstr . getBranchInstruction ( ) ;
Value conditionInstr = branchInstr . getConditionInstr ( ) ;
Instruction [ ] bodyInstructions = branchInstr . getBodyInstructions ( ) ;
string emit ;
/* Generate the `while(<expr>)` and opening curly brace */
emit = "while(" ~ transform ( conditionInstr ) ~ ")\n" ;
emit ~ = genTabs ( transformDepth ) ~ "{\n" ;
/* Transform each body statement */
foreach ( Instruction curBodyInstr ; bodyInstructions )
{
emit ~ = genTabs ( transformDepth ) ~ "\t" ~ transform ( curBodyInstr ) ~ "\n" ;
}
/* Closing curly brace */
emit ~ = genTabs ( transformDepth ) ~ "}" ;
return emit ;
}
2023-01-11 08:43:29 +00:00
/ * *
* For loops ( ForLoopInstruction )
* /
else if ( cast ( ForLoopInstruction ) instruction )
{
ForLoopInstruction forLoopInstr = cast ( ForLoopInstruction ) instruction ;
BranchInstruction branchInstruction = forLoopInstr . getBranchInstruction ( ) ;
Value conditionInstr = branchInstruction . getConditionInstr ( ) ;
Instruction [ ] bodyInstructions = branchInstruction . getBodyInstructions ( ) ;
string emit = "for(" ;
// Emit potential pre-run instruction
emit ~ = forLoopInstr . hasPreRunInstruction ( ) ? transform ( forLoopInstr . getPreRunInstruction ( ) ) : ";" ;
// Condition
emit ~ = transform ( conditionInstr ) ~ ";" ;
// NOTE: We are leaving the post-iteration blank due to us including it in the body
// TODO: We can hoist bodyInstructions[$] maybe if we want to generate it as C-for-loops
// if(forLoopInstr.hasPostIterationInstruction())
emit ~ = ")\n" ;
// Open curly (begin body)
emit ~ = genTabs ( transformDepth ) ~ "{\n" ;
/* Transform each body statement */
foreach ( Instruction curBodyInstr ; bodyInstructions )
{
emit ~ = genTabs ( transformDepth ) ~ "\t" ~ transform ( curBodyInstr ) ~ "\n" ;
}
// Close curly (body end)
emit ~ = genTabs ( transformDepth ) ~ "}" ;
2023-01-12 08:53:48 +00:00
return emit ;
}
/ * *
* Unary operators ( UnaryOpInstr )
* /
else if ( cast ( UnaryOpInstr ) instruction )
{
UnaryOpInstr unaryOpInstr = cast ( UnaryOpInstr ) instruction ;
Value operandInstruction = cast ( Value ) unaryOpInstr . getOperand ( ) ;
assert ( operandInstruction ) ;
string emit ;
/* The operator's symbol */
emit ~ = getCharacter ( unaryOpInstr . getOperator ( ) ) ;
/* Transform the operand */
emit ~ = transform ( operandInstruction ) ;
return emit ;
}
/ * *
* Pointer dereference assignment ( PointerDereferenceAssignmentInstruction )
* /
else if ( cast ( PointerDereferenceAssignmentInstruction ) instruction )
{
PointerDereferenceAssignmentInstruction pointerDereferenceAssignmentInstruction = cast ( PointerDereferenceAssignmentInstruction ) instruction ;
Value lhsPtrAddrExprInstr = pointerDereferenceAssignmentInstruction . getPointerEvalInstr ( ) ;
assert ( lhsPtrAddrExprInstr ) ;
Value rhsAssExprInstr = pointerDereferenceAssignmentInstruction . getAssExprInstr ( ) ;
assert ( rhsAssExprInstr ) ;
string emit ;
/* Star followed by transformation of the pointer address expression */
string starsOfLiberty ;
for ( ulong i = 0 ; i < pointerDereferenceAssignmentInstruction . getDerefCount ( ) ; i + + )
{
starsOfLiberty ~ = "*" ;
}
2023-04-17 15:50:11 +01:00
emit ~ = starsOfLiberty ~ "(" ~ transform ( lhsPtrAddrExprInstr ) ~ ")" ;
2023-01-12 08:53:48 +00:00
/* Assignment operator follows */
emit ~ = " = " ;
/* Expression to be assigned on the right hand side */
emit ~ = transform ( rhsAssExprInstr ) ~ ";" ;
2023-01-13 08:49:47 +00:00
return emit ;
}
/ * *
* Discard instruction ( DiscardInstruction )
* /
else if ( cast ( DiscardInstruction ) instruction )
{
DiscardInstruction discardInstruction = cast ( DiscardInstruction ) instruction ;
Value valueInstruction = discardInstruction . getExpressionInstruction ( ) ;
string emit ;
/* Transform the expression */
emit ~ = transform ( valueInstruction ) ~ ";" ;
2023-01-14 16:40:08 +00:00
return emit ;
}
/ * *
* Type casting instruction ( CastedValueInstruction )
* /
else if ( cast ( CastedValueInstruction ) instruction )
{
CastedValueInstruction castedValueInstruction = cast ( CastedValueInstruction ) instruction ;
Type castingTo = castedValueInstruction . getCastToType ( ) ;
// TODO: Dependent on type being casted one must handle different types, well differently (as is case for atleast OOP)
Value uncastedInstruction = castedValueInstruction . getEmbeddedInstruction ( ) ;
string emit ;
/* Handling of primitive types */
if ( cast ( Primitive ) castingTo )
{
/* Add the actual cast */
2023-01-15 10:36:54 +00:00
emit ~ = "(" ~ typeTransform ( castingTo ) ~ ")" ;
2023-01-14 16:40:08 +00:00
/* The expression being casted */
emit ~ = transform ( uncastedInstruction ) ;
}
else
{
// TODO: Implement this
gprintln ( "Non-primitive type casting not yet implemented" , DebugType . ERROR ) ;
assert ( false ) ;
}
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
return emit ;
}
/ * *
* Array indexing ( pointer - based arrays )
*
* Handles `myArray[<index>]` where `myArray` is
* of type `int[]` ( i . e . `int*` )
* /
else if ( cast ( ArrayIndexInstruction ) instruction )
{
ArrayIndexInstruction arrAssInstr = cast ( ArrayIndexInstruction ) instruction ;
gprintln ( "TODO: Implement Pointer-array index emit" , DebugType . ERROR ) ;
gprintln ( "ArrayInstr: " ~ arrAssInstr . getIndexedToInstr ( ) . toString ( ) ) ;
gprintln ( "ArrayIndexInstr: " ~ to ! ( string ) ( arrAssInstr . getIndexInstr ( ) ) ) ;
/* Obtain the entity being indexed */
Value indexed = arrAssInstr . getIndexedToInstr ( ) ;
/* Obtain the index */
Value index = arrAssInstr . getIndexInstr ( ) ;
/ * *
* Emit * ( < indexedEval > + < index > )
* /
string emit ;
emit ~ = "*(" ;
emit ~ = transform ( indexed ) ;
emit ~ = "+" ;
emit ~ = transform ( index ) ;
emit ~ = ")" ;
// return "*("~transform(indexed)~"+"~transform(index)~")";
return emit ;
}
/ * *
* Array assignments ( pointer - based arrays )
*
* Handles `myArray[<index>] = <expression>` where `myArray`
* is of type `int[]` ( i . e . `int*` )
* /
else if ( cast ( ArrayIndexAssignmentInstruction ) instruction )
{
ArrayIndexAssignmentInstruction arrayAssignmentInstr = cast ( ArrayIndexAssignmentInstruction ) instruction ;
/ * *
* Obtain the array pointer evaluation
* /
ArrayIndexInstruction arrayPtrEval = arrayAssignmentInstr . getArrayPtrEval ( ) ;
// NOTE: See above
// /**
// * Obtain the index being assigned at
// */
// Value index = arrayAssignmentInstr.getIndexInstr();
/ * *
* Obtain the expression being assigned
* /
Value assignmentInstr = arrayAssignmentInstr . getAssignmentInstr ( ) ;
/ * *
* Emit * ( < arrayPtrVal > + < indexInstr > ) = < assignmentInstr > ;
* /
string emit ;
// NOTE: Below is done by ArrayIndexInstruction
// emit ~= "*(";
// emit ~= transform(arrayPtrEval);
// emit ~= "+";
// emit ~= transform(index);
// emit ~= ")";
emit ~ = transform ( arrayPtrEval ) ;
emit ~ = " = " ;
emit ~ = transform ( assignmentInstr ) ;
emit ~ = ";" ;
return emit ;
}
/ * *
* Array indexing ( stack - based arrays )
*
* Handles `myArray[<index>]` where `myArray` is
* of type `int[<size>]` ( i . e . a stack - array )
* /
else if ( cast ( StackArrayIndexInstruction ) instruction )
{
StackArrayIndexInstruction stackArrInstr = cast ( StackArrayIndexInstruction ) instruction ;
Context context = stackArrInstr . getContext ( ) ;
/* Obtain the stack array variable being indexed */
// TODO: Investigate, nroamlly we do a `FetchValueVar` as like the instr which is fine actually
FetchValueVar array = cast ( FetchValueVar ) stackArrInstr . getIndexedToInstr ( ) ;
assert ( array ) ;
Variable arrayVariable = cast ( Variable ) typeChecker . getResolver ( ) . resolveBest ( context . getContainer ( ) , array . varName ) ;
/* Perform symbol mapping */
string arrayName = mapper . symbolLookup ( arrayVariable ) ;
/* Obtain the index expression */
Value indexInstr = stackArrInstr . getIndexInstr ( ) ;
/ * *
* Emit < arrayName > [ < index > ]
* /
string emit = arrayName ;
emit ~ = "[" ;
emit ~ = transform ( indexInstr ) ;
emit ~ = "]" ;
gprintln ( "TODO: Implement Stack-array index emit" , DebugType . ERROR ) ;
// return "(TODO: Stack-array index emit)";
return emit ;
}
/ * *
* Array assignments ( stack - based arrays )
*
* Handles `myArray[<index>] = <expression>` where `myArray`
* is of type `int[<size>]` ( i . e . a stack - array )
* /
else if ( cast ( StackArrayIndexAssignmentInstruction ) instruction )
{
StackArrayIndexAssignmentInstruction stackArrAssInstr = cast ( StackArrayIndexAssignmentInstruction ) instruction ;
Context context = stackArrAssInstr . getContext ( ) ;
assert ( context ) ;
/ * *
* Obtain the stack array being assigned to
* /
string arrayName = stackArrAssInstr . getArrayName ( ) ;
Variable arrayVariable = cast ( Variable ) typeChecker . getResolver ( ) . resolveBest ( context . getContainer ( ) , arrayName ) ;
/* Perform symbol mapping */
string arrayNameMapped = mapper . symbolLookup ( arrayVariable ) ;
/* Obtain the index expression */
Value indexInstr = stackArrAssInstr . getIndexInstr ( ) ;
/* Obtain the expresison being assigned */
Value assignmentInstr = stackArrAssInstr . getAssignedValue ( ) ;
/ * *
* Emit < arrayName > [ < index > ] = < expression > ;
* /
string emit = arrayNameMapped ;
emit ~ = "[" ;
emit ~ = transform ( indexInstr ) ;
emit ~ = "]" ;
emit ~ = " = " ;
emit ~ = transform ( assignmentInstr ) ;
emit ~ = ";" ;
// return "(StackArrAssignmentInstr: TODO)";
2023-01-11 08:43:29 +00:00
return emit ;
}
2023-01-15 18:48:40 +00:00
// TODO: MAAAAN we don't even have this yet
// else if(cast(StringExpression))
2022-12-13 09:45:45 +00:00
2022-12-13 09:46:40 +00:00
return "<TODO: Base emit: " ~ to ! ( string ) ( instruction ) ~ ">" ;
2022-12-11 19:41:15 +00:00
}
2022-12-12 13:36:07 +00:00
2021-11-02 08:41:03 +00:00
public override void emit ( )
{
2022-12-11 19:00:48 +00:00
// Emit header comment (NOTE: Change this to a useful piece of text)
emitHeaderComment ( "Place any extra information by code generator here" ) ; // NOTE: We can pass a string with extra information to it if we want to
2022-12-11 15:52:36 +00:00
2023-01-15 10:36:54 +00:00
// Emit standard integer header import
emitStdint ( ) ;
2022-12-17 12:31:03 +00:00
// Emit static allocation code
2022-12-12 17:12:39 +00:00
emitStaticAllocations ( ) ;
2022-12-11 15:52:36 +00:00
2022-12-17 12:31:03 +00:00
// Emit globals
2022-12-16 12:53:33 +00:00
emitCodeQueue ( ) ;
2022-12-17 12:31:03 +00:00
// Emit function definitions
2023-01-13 09:22:47 +00:00
emitFunctionPrototypes ( ) ;
2022-12-14 17:49:08 +00:00
emitFunctionDefinitions ( ) ;
2023-01-19 19:06:20 +00:00
// If enabled (default: yes) then emit entry point (TODO: change later)
2023-01-28 16:12:49 +00:00
if ( config . getConfig ( "dgen:emit_entrypoint_test" ) . getBoolean ( ) )
2023-01-19 19:06:20 +00:00
{
//TODO: Emit main (entry point)
emitEntryPoint ( ) ;
}
2022-12-11 15:52:36 +00:00
}
2022-12-11 15:58:33 +00:00
/ * *
* Emits the header comment which contains information about the source
* file and the generated code file
*
* Params :
* headerPhrase = Optional additional string information to add to the header comment
* /
2022-12-11 15:52:36 +00:00
private void emitHeaderComment ( string headerPhrase = "" )
{
2022-12-11 16:01:54 +00:00
// NOTE: We could maybe fetch input fiel info too? Although it would have to be named similiarly in any case
// so perhaps just appending a `.t` to the module name below would be fine
2022-12-11 15:57:16 +00:00
string moduleName = typeChecker . getResolver ( ) . generateName ( typeChecker . getModule ( ) , typeChecker . getModule ( ) ) ; //TODO: Lookup actual module name (I was lazy)
2022-12-11 15:52:36 +00:00
string outputCFilename = file . name ( ) ;
2022-12-11 16:09:56 +00:00
file . write ( ` / * *
2022-12-11 15:52:36 +00:00
* TLP compiler generated code
*
* Module name : ` ) ;
file . writeln ( moduleName ) ;
file . write ( " * Output C file: " ) ;
file . writeln ( outputCFilename ) ;
2022-12-11 15:55:18 +00:00
if ( headerPhrase . length )
{
2022-12-11 19:00:48 +00:00
file . write ( wrap ( headerPhrase , 40 , " *\n * " , " * " ) ) ;
2022-12-11 15:55:18 +00:00
}
2022-12-11 15:52:36 +00:00
2022-12-11 19:00:48 +00:00
file . write ( " */\n" ) ;
2022-12-11 15:52:36 +00:00
}
/ * *
* Emits the static allocations provided
*
* Params :
* initQueue = The allocation queue to emit static allocations from
* /
2022-12-12 17:12:39 +00:00
private void emitStaticAllocations ( )
2022-12-11 15:52:36 +00:00
{
2022-12-14 17:49:08 +00:00
selectQueue ( QueueType . ALLOC_QUEUE ) ;
gprintln ( "Static allocations needed: " ~ to ! ( string ) ( getQueueLength ( ) ) ) ;
2022-12-16 12:53:33 +00:00
file . writeln ( ) ;
2022-12-14 17:49:08 +00:00
}
/ * *
2023-01-13 09:22:47 +00:00
* Emits the function prototypes
* /
private void emitFunctionPrototypes ( )
{
gprintln ( "Function definitions needed: " ~ to ! ( string ) ( getFunctionDefinitionsCount ( ) ) ) ;
Instruction [ ] [ string ] functionBodyInstrs = typeChecker . getFunctionBodyCodeQueues ( ) ;
string [ ] functionNames = getFunctionDefinitionNames ( ) ;
gprintln ( "WOAH: " ~ to ! ( string ) ( functionNames ) ) ;
foreach ( string currentFunctioName ; functionNames )
{
emitFunctionPrototype ( currentFunctioName ) ;
file . writeln ( ) ;
}
}
/ * *
* Emits the function definitions
2022-12-14 17:49:08 +00:00
* /
private void emitFunctionDefinitions ( )
{
2022-12-16 12:53:33 +00:00
gprintln ( "Function definitions needed: " ~ to ! ( string ) ( getFunctionDefinitionsCount ( ) ) ) ;
2022-12-14 17:49:08 +00:00
Instruction [ ] [ string ] functionBodyInstrs = typeChecker . getFunctionBodyCodeQueues ( ) ;
string [ ] functionNames = getFunctionDefinitionNames ( ) ;
gprintln ( "WOAH: " ~ to ! ( string ) ( functionNames ) ) ;
foreach ( string currentFunctioName ; functionNames )
{
emitFunctionDefinition ( currentFunctioName ) ;
2022-12-16 12:53:33 +00:00
file . writeln ( ) ;
2023-01-13 09:22:47 +00:00
}
2022-12-14 17:49:08 +00:00
}
private string generateSignature ( Function func )
{
string signature ;
2023-01-15 10:40:42 +00:00
// Extract the Function's return Type
2023-01-15 10:36:54 +00:00
Type returnType = typeChecker . getType ( func . context . container , func . getType ( ) ) ;
2022-12-14 17:49:08 +00:00
// <type> <functionName> (
2023-01-15 10:36:54 +00:00
signature = typeTransform ( returnType ) ~ " " ~ func . getName ( ) ~ "(" ;
2022-12-14 17:49:08 +00:00
// Generate parameter list
if ( func . hasParams ( ) )
{
2022-12-17 12:00:16 +00:00
VariableParameter [ ] parameters = func . getParams ( ) ;
2022-12-14 17:49:08 +00:00
string parameterString ;
for ( ulong parIdx = 0 ; parIdx < parameters . length ; parIdx + + )
{
Variable currentParameter = parameters [ parIdx ] ;
2022-12-17 12:00:16 +00:00
2023-01-15 10:40:42 +00:00
// Extract the variable's type
Type parameterType = typeChecker . getType ( currentParameter . context . container , currentParameter . getType ( ) ) ;
2022-12-17 12:00:16 +00:00
// Generate the symbol-mapped names for the parameters
Variable typedEntityVariable = cast ( Variable ) typeChecker . getResolver ( ) . resolveBest ( func , currentParameter . getName ( ) ) ; //TODO: Remove `auto`
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper . symbolLookup ( typedEntityVariable ) ;
2022-12-17 12:00:16 +00:00
// Generate <type> <parameter-name (symbol mapped)>
2023-01-15 10:40:42 +00:00
parameterString ~ = typeTransform ( parameterType ) ~ " " ~ renamedSymbol ;
2022-12-14 17:49:08 +00:00
if ( parIdx ! = ( parameters . length - 1 ) )
{
parameterString ~ = ", " ;
}
}
signature ~ = parameterString ;
}
// )
signature ~ = ")" ;
2023-01-15 18:48:40 +00:00
// If the function is marked as external then place `extern` infront
if ( func . isExternal ( ) )
{
signature = "extern " ~ signature ;
}
2022-12-14 17:49:08 +00:00
return signature ;
}
2023-01-13 09:22:47 +00:00
private void emitFunctionPrototype ( string functionName )
{
selectQueue ( QueueType . FUNCTION_DEF_QUEUE , functionName ) ;
gprintln ( "emotFunctionDefinition(): Function: " ~ functionName ~ ", with " ~ to ! ( string ) ( getSelectedQueueLength ( ) ) ~ " many instructions" ) ;
//TODO: Look at nested definitions or nah? (Context!!)
//TODO: And what about methods defined in classes? Those should technically be here too
Function functionEntity = cast ( Function ) typeChecker . getResolver ( ) . resolveBest ( typeChecker . getModule ( ) , functionName ) ; //TODO: Remove `auto`
// Emit the function signature
file . writeln ( generateSignature ( functionEntity ) ~ ";" ) ;
}
2022-12-14 17:49:08 +00:00
private void emitFunctionDefinition ( string functionName )
{
selectQueue ( QueueType . FUNCTION_DEF_QUEUE , functionName ) ;
2022-12-16 12:53:33 +00:00
gprintln ( "emotFunctionDefinition(): Function: " ~ functionName ~ ", with " ~ to ! ( string ) ( getSelectedQueueLength ( ) ) ~ " many instructions" ) ;
2022-12-14 17:49:08 +00:00
//TODO: Look at nested definitions or nah? (Context!!)
//TODO: And what about methods defined in classes? Those should technically be here too
Function functionEntity = cast ( Function ) typeChecker . getResolver ( ) . resolveBest ( typeChecker . getModule ( ) , functionName ) ; //TODO: Remove `auto`
2023-01-15 18:48:40 +00:00
// If the Entity is NOT external then emit the signature+body
if ( ! functionEntity . isExternal ( ) )
{
// Emit the function signature
file . writeln ( generateSignature ( functionEntity ) ) ;
2022-12-14 17:49:08 +00:00
2023-01-15 18:48:40 +00:00
// Emit opening curly brace
file . writeln ( getCharacter ( SymbolType . OCURLY ) ) ;
2022-12-11 15:52:36 +00:00
2023-01-15 18:48:40 +00:00
// Emit body
while ( hasInstructions ( ) )
{
Instruction curFuncBodyInstr = getCurrentInstruction ( ) ;
2022-12-14 17:49:08 +00:00
2023-01-15 18:48:40 +00:00
string emit = transform ( curFuncBodyInstr ) ;
gprintln ( "emitFunctionDefinition(" ~ functionName ~ "): Emit: " ~ emit ) ;
file . writeln ( "\t" ~ emit ) ;
nextInstruction ( ) ;
}
2022-12-14 17:49:08 +00:00
2023-01-15 18:48:40 +00:00
// Emit closing curly brace
file . writeln ( getCharacter ( SymbolType . CCURLY ) ) ;
}
// If the Entity IS external then don't emit anything as the signature would have been emitted via a prorotype earlier with `emitPrototypes()`
else
{
// Do nothing
}
2021-11-02 08:41:03 +00:00
}
2022-12-11 16:04:53 +00:00
2022-12-12 17:12:39 +00:00
private void emitCodeQueue ( )
2022-12-11 16:04:53 +00:00
{
2022-12-14 17:49:08 +00:00
selectQueue ( QueueType . GLOBALS_QUEUE ) ;
gprintln ( "Code emittings needed: " ~ to ! ( string ) ( getQueueLength ( ) ) ) ;
while ( hasInstructions ( ) )
2022-12-11 16:06:10 +00:00
{
2022-12-14 17:49:08 +00:00
Instruction currentInstruction = getCurrentInstruction ( ) ;
2022-12-12 13:36:07 +00:00
file . writeln ( transform ( currentInstruction ) ) ;
2022-12-12 17:12:39 +00:00
2022-12-14 17:49:08 +00:00
nextInstruction ( ) ;
2022-12-11 16:06:10 +00:00
}
2022-12-16 12:53:33 +00:00
file . writeln ( ) ;
2022-12-11 16:04:53 +00:00
}
2022-12-11 19:41:15 +00:00
2023-01-15 10:36:54 +00:00
private void emitStdint ( )
{
file . writeln ( "#include<stdint.h>" ) ;
}
2022-12-11 19:41:15 +00:00
private void emitEntryPoint ( )
{
2023-01-24 17:57:27 +00:00
// TODO: Implement me
2022-12-11 19:41:15 +00:00
2023-01-04 10:03:50 +00:00
// Test for `simple_functions.t` (function call testing)
2022-12-19 13:37:55 +00:00
if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_functions" ) = = 0 )
{
2023-01-04 10:03:50 +00:00
file . writeln ( `
2022-12-16 12:53:33 +00:00
# include < stdio . h >
2023-01-04 10:03:50 +00:00
# include < assert . h >
2022-12-11 19:41:15 +00:00
int main ( )
{
2023-01-04 10:03:50 +00:00
assert ( t_7b6d477c5859059f16bc9da72fc8cc3b = = 22 ) ;
2022-12-17 12:31:03 +00:00
printf ( "k: %u\n" , t_7b6d477c5859059f16bc9da72fc8cc3b ) ;
2023-01-04 10:03:50 +00:00
2022-12-16 12:53:33 +00:00
banana ( 1 ) ;
2023-01-04 10:03:50 +00:00
assert ( t_7b6d477c5859059f16bc9da72fc8cc3b = = 72 ) ;
2022-12-17 12:31:03 +00:00
printf ( "k: %u\n" , t_7b6d477c5859059f16bc9da72fc8cc3b ) ;
2023-01-04 10:03:50 +00:00
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_while" ) = = 0 )
{
file . writeln ( `
2023-01-11 08:43:29 +00:00
# include < stdio . h >
# include < assert . h >
int main ( )
{
int result = function ( 3 ) ;
printf ( "result: %d\n" , result ) ;
assert ( result = = 3 ) ;
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_for_loops" ) = = 0 )
{
file . writeln ( `
2023-01-04 10:03:50 +00:00
# include < stdio . h >
# include < assert . h >
int main ( )
{
int result = function ( 3 ) ;
printf ( "result: %d\n" , result ) ;
assert ( result = = 3 ) ;
2023-01-12 08:53:48 +00:00
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_pointer" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
2023-01-14 10:39:37 +00:00
int retValue = thing ( ) ;
2023-01-12 08:53:48 +00:00
assert ( t_87bc875d0b65f741b69fb100a0edebc7 = = 4 ) ;
2023-01-14 10:39:37 +00:00
assert ( retValue = = 6 ) ;
2023-01-12 08:53:48 +00: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
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_pointer_array_syntax" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
int retValue = thing ( ) ;
assert ( t_9d01d71b858651e520c9b503122a1b7a = = 4 ) ;
assert ( retValue = = 6 ) ;
2023-04-17 15:50:11 +01:00
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_pointer_cast_le" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
int retValue = thing ( ) ;
assert ( t_e159019f766be1a175186a13f16bcfb7 = = 256 + 4 ) ;
assert ( retValue = = 256 + 4 + 2 ) ;
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_pointer_malloc" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
test ( ) ;
// TODO: Test the value
2023-01-15 18:48:40 +00:00
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_extern" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
test ( ) ;
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
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_stack_array_coerce" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
int result = function ( ) ;
assert ( result = = 420 + 69 ) ;
printf ( "stackArr sum: %d\n" , result ) ;
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "complex_stack_array_coerce" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
int result = function ( ) ;
assert ( result = = 69 + 420 ) ;
printf ( "val1: %d\n" , t_596f49b2a2784a3c1b073ccfe174caa0 ) ;
printf ( "val2: %d\n" , t_4233b83329676d70ab4afaa00b504564 ) ;
printf ( "stackArr sum: %d\n" , result ) ;
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_stack_array_coerce_ptr_syntax" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
int result = function ( ) ;
assert ( result = = 420 + 69 ) ;
printf ( "stackArr sum: %d\n" , result ) ;
return 0 ;
} ` ) ;
}
else if ( cmp ( typeChecker . getModule ( ) . getName ( ) , "simple_stack_arrays4" ) = = 0 )
{
file . writeln ( `
# include < stdio . h >
# include < assert . h >
int main ( )
{
int result = function ( ) ;
assert ( result = = 61 ) ;
2022-12-11 19:41:15 +00:00
return 0 ;
} ` ) ;
2022-12-19 13:37:55 +00:00
}
else
{
file . writeln ( `
int main ( )
{
return 0 ;
}
` ) ;
}
2022-12-11 19:41:15 +00:00
}
2022-12-12 13:36:07 +00:00
public override void finalize ( )
{
try
{
//NOTE: Change to system compiler (maybe, we need to choose a good C compiler)
2023-01-28 16:12:49 +00:00
string [ ] compileArgs = [ "clang" , "-o" , "tlang.out" , file . name ( ) ] ;
// Check for object files to be linked in
string [ ] objectFilesLink ;
if ( config . hasConfig ( "linker:link_files" ) )
{
objectFilesLink = config . getConfig ( "linker:link_files" ) . getArray ( ) ;
gprintln ( "Object files to be linked in: " ~ to ! ( string ) ( objectFilesLink ) ) ;
}
else
{
gprintln ( "No files to link in" ) ;
}
Pid ccPID = spawnProcess ( compileArgs ~ objectFilesLink ) ;
2022-12-12 13:36:07 +00:00
int code = wait ( ccPID ) ;
if ( code )
{
//NOTE: Make this a TLang exception
2022-12-16 12:53:33 +00:00
throw new Exception ( "The CC exited with a non-zero exit code (" ~ to ! ( string ) ( code ) ~ ")" ) ;
2022-12-12 13:36:07 +00:00
}
}
catch ( ProcessException e )
{
gprintln ( "NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?" , DebugType . ERROR ) ;
assert ( false ) ;
}
}
2021-11-02 08:41:03 +00:00
}