From fe8e1403f04db652abf9c86590232827502266a1 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Thu, 20 Apr 2023 11:21:50 +0200 Subject: [PATCH] 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 `[]` (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 `[]` 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 `*`) 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` --- .github/workflows/d.yml | 103 ++++++ branding/logo.png | Bin 0 -> 13666 bytes branding/logo.xcf | Bin 0 -> 72349 bytes source/tlang/compiler/codegen/emit/dgen.d | 264 ++++++++++++- source/tlang/compiler/codegen/instruction.d | 138 +++++++ source/tlang/compiler/parsing/core.d | 216 +++++++++-- source/tlang/compiler/symbols/check.d | 12 + source/tlang/compiler/symbols/data.d | 42 +++ source/tlang/compiler/symbols/expressions.d | 30 ++ .../tlang/compiler/symbols/typing/builtins.d | 109 ++++-- source/tlang/compiler/symbols/typing/core.d | 31 +- source/tlang/compiler/typecheck/core.d | 350 ++++++++++++++++++ .../compiler/typecheck/dependency/core.d | 95 +++++ .../testing/complex_stack_array_coerce.t | 21 ++ .../testing/complex_stack_array_coerce_bad1.t | 17 + .../testing/complex_stack_array_coerce_bad2.t | 17 + .../testing/complex_stack_array_coerce_bad3.t | 17 + ...plex_stack_array_coerce_permutation_good.t | 23 ++ source/tlang/testing/complex_stack_arrays1.t | 9 + source/tlang/testing/simple_arrays.t | 6 + source/tlang/testing/simple_arrays2.t | 12 + source/tlang/testing/simple_arrays4.t | 8 + .../testing/simple_pointer_array_syntax.t | 17 + .../tlang/testing/simple_stack_array_coerce.t | 15 + .../simple_stack_array_coerce_ptr_syntax.t | 15 + .../testing/simple_stack_array_coerce_wrong.t | 15 + source/tlang/testing/simple_stack_arrays2.t | 9 + source/tlang/testing/simple_stack_arrays3.t | 11 + source/tlang/testing/simple_stack_arrays4.t | 12 + wip.txt | 10 + 30 files changed, 1558 insertions(+), 66 deletions(-) create mode 100644 branding/logo.png create mode 100644 branding/logo.xcf create mode 100644 source/tlang/testing/complex_stack_array_coerce.t create mode 100644 source/tlang/testing/complex_stack_array_coerce_bad1.t create mode 100644 source/tlang/testing/complex_stack_array_coerce_bad2.t create mode 100644 source/tlang/testing/complex_stack_array_coerce_bad3.t create mode 100644 source/tlang/testing/complex_stack_array_coerce_permutation_good.t create mode 100644 source/tlang/testing/complex_stack_arrays1.t create mode 100644 source/tlang/testing/simple_arrays.t create mode 100644 source/tlang/testing/simple_arrays2.t create mode 100644 source/tlang/testing/simple_arrays4.t create mode 100644 source/tlang/testing/simple_pointer_array_syntax.t create mode 100644 source/tlang/testing/simple_stack_array_coerce.t create mode 100644 source/tlang/testing/simple_stack_array_coerce_ptr_syntax.t create mode 100644 source/tlang/testing/simple_stack_array_coerce_wrong.t create mode 100644 source/tlang/testing/simple_stack_arrays2.t create mode 100644 source/tlang/testing/simple_stack_arrays3.t create mode 100644 source/tlang/testing/simple_stack_arrays4.t create mode 100644 wip.txt diff --git a/.github/workflows/d.yml b/.github/workflows/d.yml index 9638613..3cbd14b 100644 --- a/.github/workflows/d.yml +++ b/.github/workflows/d.yml @@ -129,6 +129,62 @@ jobs: exit 1 fi + # Array support + - name: Simple array + run: ./tlang typecheck source/tlang/testing/simple_arrays.t + - name: Simple array 2 + run: ./tlang typecheck source/tlang/testing/simple_arrays2.t + - name: Simple array 4 + run: ./tlang typecheck source/tlang/testing/simple_arrays4.t + + - name: Stack-based array coercion + run: ./tlang typecheck source/tlang/testing/simple_stack_array_coerce.t + - name: Complex stack-based arrays + run: ./tlang typecheck source/tlang/testing/complex_stack_arrays1.t + - name: Stack-based array coercion (type mismatch) + run: | + set +e + ./tlang compile source/tlang/testing/simple_stack_array_coerce_wrong.t + if [ $? = 255 ] + then + exit 0 + else + exit 1 + fi + + - name: Stack-based array coercion (good permutations)) + run: | + ./tlang typecheck source/tlang/testing/complex_stack_array_coerce_permutation_good.t + - name: Stack-based array coercion (type mismatch - bad permutation 1) + run: | + set +e + ./tlang compile source/tlang/testing/complex_stack_array_coerce_bad1.t + if [ $? = 255 ] + then + exit 0 + else + exit 1 + fi + - name: Stack-based array coercion (type mismatch - bad permutation 2) + run: | + set +e + ./tlang compile source/tlang/testing/complex_stack_array_coerce_bad2.t + if [ $? = 255 ] + then + exit 0 + else + exit 1 + fi + - name: Stack-based array coercion (type mismatch - bad permutation 3) + run: | + set +e + ./tlang compile source/tlang/testing/complex_stack_array_coerce_bad3.t + if [ $? = 255 ] + then + exit 0 + else + exit 1 + fi - name: Collide container module1 run: | @@ -313,10 +369,57 @@ jobs: run: | chmod +x extern_test.sh ./extern_test.sh + + + # Array support + - name: Stack-based arrays simple + run: | + ./tlang compile source/tlang/testing/simple_stack_arrays4.t + ./tlang.out + - name: Stack-based array coercion (array syntax) + run: | + ./tlang compile source/tlang/testing/simple_stack_array_coerce.t + ./tlang.out + - name: Stack-based array coercion (pointer syntax) + run: | + ./tlang compile source/tlang/testing/simple_stack_array_coerce_ptr_syntax.t + ./tlang.out + - name: Stack-based array with normal array coercion (complex) + run: | + ./tlang compile source/tlang/testing/complex_stack_array_coerce.t + ./tlang.out + + + # TODO: Actually add semantic tests for these + - name: Complex stack-based arrays + run: | + ./tlang compile source/tlang/testing/complex_stack_arrays1.t + ./tlang.out + - name: Simple array + run: | + ./tlang compile source/tlang/testing/simple_arrays.t + ./tlang.out + - name: Simple array 2 + run: | + ./tlang compile source/tlang/testing/simple_arrays2.t + ./tlang.out + - name: Simple array 4 + run: | + ./tlang compile source/tlang/testing/simple_arrays4.t + ./tlang.out + + - name: Simple pointer (malloc and free) run: | chmod +x malloc_test.sh ./malloc_test.sh + - name: Simple pointer (array syntax) + run: | + ./tlang compile source/tlang/testing/simple_pointer_array_syntax.t + ./tlang.out + + + ################################## ####### Deployment section ####### ################################## diff --git a/branding/logo.png b/branding/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0ed63c5633c844a8dd0383b9a5d48979d78577ac GIT binary patch literal 13666 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 WmOB;fOU0LiM1#Vk!*&nQrTiat0*TB3 literal 0 HcmV?d00001 diff --git a/branding/logo.xcf b/branding/logo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..90771cca3cb1a94f50778e2a2c464b7918a99d93 GIT binary patch literal 72349 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 jJ&wTcV$#sJ$ [] + // ... hence this must be performed in avriable declaration + StackArray stackArray = cast(StackArray)typeIn; + + return typeTransform(stackArray.getComponentType()); + // return "KAK TODO"; + } gprintln("Type transform unimplemented"); assert(false); @@ -166,6 +178,14 @@ public final class DCodeEmitter : CodeEmitter string renamedSymbol = mapper.symbolLookup(typedEntityVariable); + // Check if the type is a stack-based array + // ... if so then take make symbolName := `[]` + if(cast(StackArray)varDecInstr.varType) + { + StackArray stackArray = cast(StackArray)varDecInstr.varType; + renamedSymbol~="["~to!(string)(stackArray.getAllocatedSize())~"]"; + } + // Check to see if this declaration has an assignment attached if(typedEntityVariable.getAssignment()) { @@ -505,6 +525,176 @@ public final class DCodeEmitter : CodeEmitter + return emit; + } + /** + * Array indexing (pointer-based arrays) + * + * Handles `myArray[]` 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 *(+) + */ + 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[] = ` 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 *(+) = ; + */ + 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[]` where `myArray` is + * of type `int[]` (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 [] + */ + 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[] = ` where `myArray` + * is of type `int[]` (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 [] = ; + */ + string emit = arrayNameMapped; + emit ~= "["; + emit ~= transform(indexInstr); + emit ~= "]"; + + emit ~= " = "; + emit ~= transform(assignmentInstr); + emit ~= ";"; + + + // return "(StackArrAssignmentInstr: TODO)"; + return emit; } // TODO: MAAAAN we don't even have this yet @@ -815,6 +1005,20 @@ int main() assert(t_87bc875d0b65f741b69fb100a0edebc7 == 4); assert(retValue == 6); + return 0; +}`); + } + else if(cmp(typeChecker.getModule().getName(), "simple_pointer_array_syntax") == 0) + { + file.writeln(` +#include +#include +int main() +{ + int retValue = thing(); + assert(t_9d01d71b858651e520c9b503122a1b7a == 4); + assert(retValue == 6); + return 0; }`); } @@ -857,6 +1061,64 @@ int main() + return 0; +}`); + } + else if(cmp(typeChecker.getModule().getName(), "simple_stack_array_coerce") == 0) + { + file.writeln(` +#include +#include +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 +#include +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 +#include +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 +#include +int main() +{ + int result = function(); + assert(result == 61); + return 0; }`); } diff --git a/source/tlang/compiler/codegen/instruction.d b/source/tlang/compiler/codegen/instruction.d index 5864c41..208da01 100644 --- a/source/tlang/compiler/codegen/instruction.d +++ b/source/tlang/compiler/codegen/instruction.d @@ -511,4 +511,142 @@ public final class CastedValueInstruction : Value { return type; } +} + +public final class ArrayIndexInstruction : Value +{ + /* Index-to instruction */ + private Value indexTo; + + /* The index */ + private Value index; + + this(Value indexTo, Value index) + { + this.indexTo = indexTo; + this.index = index; + } + + public Value getIndexInstr() + { + return index; + } + + public Value getIndexedToInstr() + { + return indexTo; + } + + public override string toString() + { + return "ArrayIndexInstr [IndexTo: "~indexTo.toString()~", Index: "~index.toString()~"]"; + } +} + +//TODO: ArrayIndexAssignmentInstruction +public final class ArrayIndexAssignmentInstruction : Instruction +{ + // TODO: We then need the left hand side array evaluation instruction (a pointer value basically) + // private Value arrayPtrEval; + + // TODO: We then also need a `Value` field for the index expression instruction + // private Value index; + + // NOTE: We now to the above to using an ArrayIndexInstruction + private ArrayIndexInstruction arrayPtrEval; + + // TODO: We then also need another `Value` field for the expression instruction + // ... being assigned into the pointer-array + private Value assignment; + + this(ArrayIndexInstruction arrayPtrEval, Value assignment) + { + this.arrayPtrEval = arrayPtrEval; + // this.index = index; + this.assignment = assignment; + } + + public ArrayIndexInstruction getArrayPtrEval() + { + return arrayPtrEval; + } + + public Value getAssignmentInstr() + { + return assignment; + } +} + +// TODO: StackArrayIndexInstruction +public final class StackArrayIndexInstruction : Value +{ + /* Index-to instruction */ + private Value indexTo; + + /* The index */ + private Value index; + + this(Value indexTo, Value index) + { + this.indexTo = indexTo; + this.index = index; + } + + public Value getIndexInstr() + { + return index; + } + + public Value getIndexedToInstr() + { + return indexTo; + } + + public override string toString() + { + return "StackArrayIndexInstr [IndexTo: "~indexTo.toString()~", Index: "~index.toString()~"]"; + } +} + +// TODO: StackArrayIndexAssignmentInstruction +public final class StackArrayIndexAssignmentInstruction : Instruction +{ + // TODO: We need a `string` field here which is looked up with the + // ... associated context of this instruction and refers to the + // ... stack-array being index-assigned into + private string arrayName; + + // TODO: We then also need a `Value` field for the index expression instruction + private Value index; + + // TODO: We then also need another `Value` field for the expression instruction + // ... being assigned into the stack-array at said index + private Value assignment; + + this(string arrayName, Value index, Value assignment) + { + this.arrayName = arrayName; + this.index = index; + this.assignment = assignment; + } + + public string getArrayName() + { + return arrayName; + } + + public Value getIndexInstr() + { + return index; + } + + public Value getAssignedValue() + { + return assignment; + } + + public override string toString() + { + return "StackArrayASSIGN [name: "~arrayName~", index: "~index.toString()~", Assignment: "~assignment.toString()~"]"; + } } \ No newline at end of file diff --git a/source/tlang/compiler/parsing/core.d b/source/tlang/compiler/parsing/core.d index 134ad62..abc082e 100644 --- a/source/tlang/compiler/parsing/core.d +++ b/source/tlang/compiler/parsing/core.d @@ -455,9 +455,10 @@ public final class Parser * * 1. `int ptr` (and we looked ahead to `ptr`) * 2. `int* ptr` (and we looked ahead to `*`) + * 3. `int[] thing` (and we looked ahead to `[`) */ /* If we have an identifier/type then declaration */ - else if(type == SymbolType.IDENT_TYPE || type == SymbolType.STAR) + else if(type == SymbolType.IDENT_TYPE || type == SymbolType.STAR || type == SymbolType.OBRACKET) { previousToken(); ret = parseTypedDeclaration(); @@ -474,6 +475,13 @@ public final class Parser expect(SymbolType.SEMICOLON, getCurrentToken()); nextToken(); } + /* If it is an arrau assignment */ + else if(cast(ArrayAssignment)ret) + { + /* Expect a semicolon and consume it */ + expect(SymbolType.SEMICOLON, getCurrentToken()); + nextToken(); + } /* This should never happen */ else { @@ -907,7 +915,7 @@ public final class Parser if(getSymbolType(getCurrentToken()) == SymbolType.IDENT_TYPE) { /* Get the type */ - TypedEntity bogusEntity = parseTypedDeclaration(false, false, false, true); + TypedEntity bogusEntity = cast(TypedEntity)parseTypedDeclaration(false, false, false, true); string type = bogusEntity.getType(); /* Get the identifier (This CAN NOT be dotted) */ @@ -1041,7 +1049,8 @@ public final class Parser * which means we can call `getType()` and extract * the type string */ - TypedEntity bogusEntity = parseTypedDeclaration(false, false, false, true); + TypedEntity bogusEntity = cast(TypedEntity)parseTypedDeclaration(false, false, false, true); + assert(bogusEntity); string toType = bogusEntity.getType(); /* Expect a `)` closing brace */ @@ -1057,7 +1066,6 @@ public final class Parser return castedExpression; } - /** * Parses an expression * @@ -1315,6 +1323,23 @@ public final class Parser /* Get the next token */ nextToken(); } + /* If we have a `[` (array index/access) */ + else if(symbol == SymbolType.OBRACKET) + { + // Pop off an expression which will be `indexTo` + Expression indexTo = removeExp(); + gprintln("indexTo: "~indexTo.toString()); + + /* Get the index expression */ + nextToken(); + Expression index = parseExpression(); + nextToken(); + gprintln("IndexExpr: "~index.toString()); + // gprintln(getCurrentToken()); + + ArrayIndex arrayIndexExpr = new ArrayIndex(indexTo, index); + addRetExp(arrayIndexExpr); + } /* If it is an identifier */ else if (symbol == SymbolType.IDENT_TYPE) { @@ -1348,7 +1373,9 @@ public final class Parser addRetExp(toAdd); } /* Detect if this expression is coming to an end, then return */ - else if (symbol == SymbolType.SEMICOLON || symbol == SymbolType.RBRACE || symbol == SymbolType.COMMA || symbol == SymbolType.ASSIGN) + else if (symbol == SymbolType.SEMICOLON || symbol == SymbolType.RBRACE || + symbol == SymbolType.COMMA || symbol == SymbolType.ASSIGN || + symbol == SymbolType.CBRACKET) { break; } @@ -1436,29 +1463,93 @@ public final class Parser return retExpression[0]; } - private TypedEntity parseTypedDeclaration(bool wantsBody = true, bool allowVarDec = true, bool allowFuncDef = true, bool onlyType = false) + + + // TODO: Update to `Statement` as this can return an ArrayAssignment now + private Statement parseTypedDeclaration(bool wantsBody = true, bool allowVarDec = true, bool allowFuncDef = true, bool onlyType = false) { gprintln("parseTypedDeclaration(): Enter", DebugType.WARNING); /* Generated object */ - TypedEntity generated; + Statement generated; /* TODO: Save type */ string type = getCurrentToken().getToken(); string identifier; - - - // TODO: Insert pointer `*`-handling code here nextToken(); - ulong derefCount = 0; - /* If we have a star */ - while(getSymbolType(getCurrentToken()) == SymbolType.STAR) + + + /* Potential array index expressions (assignment) */ + // Think myArray[i][1] -> [`i`, `1`] + Expression[] arrayIndexExprs; + + // We are currently 1 past the "type" (the identifier) so go back one + ulong arrayAssignTokenBeginPos = getCursor()-1; + + /* Potential stack-array type size (declaration) */ + string potentialStackSize; + + /* Handling of pointer and array types */ + while(getSymbolType(getCurrentToken()) == SymbolType.STAR || getSymbolType(getCurrentToken()) == SymbolType.OBRACKET) { - derefCount+=1; - type=type~"*"; + /* If we have `[` then expect a number and/or a `]` */ + if(getSymbolType(getCurrentToken()) == SymbolType.OBRACKET) + { + nextToken(); + SymbolType nextType = getSymbolType(getCurrentToken()); + + + /* Check if the next symbol is NOT a `]` */ + if(nextType != SymbolType.CBRACKET) + { + + + arrayIndexExprs ~= parseExpression(); + + /** + * If it is the case it is a number literal then save it + * anyways just for the case whereby we may be declaring + * a stack-array type + * + * TODO: Double check any error checking here which should be deferred to later + */ + if(nextType == SymbolType.NUMBER_LITERAL) + { + // TODO: Ensure the returned thing is a number + // TODO: Ensure said number is non-negative + // TODO: May as well now start adding `]` as a seperator or stopper or something + IntegerLiteral stackArraySize = cast(IntegerLiteral)arrayIndexExprs[$-1]; + + // If the expression is an integer (which it should be) + if(stackArraySize) + { + gprintln("StackArraySize: "~stackArraySize.toString()); + potentialStackSize = stackArraySize.getNumber(); + } + // If not, then error + else + { + gprintln("Expected an integer as stack-array size but got iets ander", DebugType.ERROR); + // TODO: Rather throw a parsing error + assert(false); + } + } + } + + + + expect(SymbolType.CBRACKET, getCurrentToken()); + type=type~"["~potentialStackSize~"]"; + } + /* If we have `*` */ + else + { + type=type~"*"; + } + nextToken(); } @@ -1470,17 +1561,39 @@ public final class Parser return generated; } - - /* Expect an identifier (CAN NOT be dotted) */ - expect(SymbolType.IDENT_TYPE, getCurrentToken()); - if(!isIdentifier_NoDot(getCurrentToken())) - { - expect("Identifier cannot be dotted"); - } - identifier = getCurrentToken().getToken(); - nextToken(); - gprintln("ParseTypedDec: DecisionBtwn FuncDef/VarDef: " ~ getCurrentToken().getToken()); + /* If we are going to be assigning into an array (indexed) */ + bool arrayIndexing = false; + + + /* If the current token is ASSIGN then array indexing is occuring */ + if(getSymbolType(getCurrentToken()) == SymbolType.ASSIGN) + { + // Then we are doing an array-indexed assignment + arrayIndexing = true; + } + /* If we have an identifier the a declaration is occuring */ + else if(getSymbolType(getCurrentToken()) == SymbolType.IDENT_TYPE) + { + /* Expect an identifier (CAN NOT be dotted) */ + expect(SymbolType.IDENT_TYPE, getCurrentToken()); + if(!isIdentifier_NoDot(getCurrentToken())) + { + expect("Identifier cannot be dotted"); + } + identifier = getCurrentToken().getToken(); + + nextToken(); + gprintln("ParseTypedDec: DecisionBtwn FuncDef/VarDef: " ~ getCurrentToken().getToken()); + } + /* Anything else is an error */ + else + { + expect("Either a identity or an assignment symbol is expected"); + } + + + /* Check if it is `(` (func dec) */ SymbolType symbolType = getSymbolType(getCurrentToken()); @@ -1528,7 +1641,7 @@ public final class Parser } } /* Check for `=` (var dec) */ - else if (symbolType == SymbolType.ASSIGN) + else if (symbolType == SymbolType.ASSIGN && (arrayIndexing == false)) { // Only continue if variable declarations are allowed if(allowVarDec) @@ -1564,6 +1677,47 @@ public final class Parser expect("Variables declarations are not allowed."); } } + /* Check for `=` (array indexed assignment) */ + else if (symbolType == SymbolType.ASSIGN && (arrayIndexing == true)) + { + // Set the token pointer back to the beginning + setCursor(arrayAssignTokenBeginPos); + gprintln("Looking at: "~to!(string)(getCurrentToken())); + + // TODO: Move all below code to the branch below that handles this case + gprintln("We have an array assignment, here is the indexers: "~to!(string)(arrayIndexExprs), DebugType.WARNING); + + // Our identifier will be some weird malformed-looking `mrArray[][1]` (because os atck array size declarations no-number literal) + // ... expressions don't make it in (we have arrayIndexExprs for that). Therefore what we must do is actually + // strip the array bracket syntax away to get the name + import std.string : indexOf; + long firstBracket = indexOf(type, "["); + assert(firstBracket > -1); + identifier = type[0..firstBracket]; + gprintln("Then identifier is type actually: "~identifier); + + + gprintln("We are still implenenting array assignments", DebugType.ERROR); + + ArrayIndex muhIndex = cast(ArrayIndex)parseExpression(); + gprintln("Expback: "~muhIndex.toString()); + + /* Expect a `=` and consume it */ + gprintln(getCurrentToken()); + expect(SymbolType.ASSIGN, getCurrentToken()); + nextToken(); + + /* Parse the expression being assigned followed by a semi-colon `;` */ + Expression expressionBeingAssigned = parseExpression(); + expect(SymbolType.SEMICOLON, getCurrentToken()); + + // TODO: Get the expression after the `=` + ArrayAssignment arrayAssignment = new ArrayAssignment(muhIndex, expressionBeingAssigned); + gprintln("Created array assignment: "~arrayAssignment.toString()); + // assert(false); + + generated = arrayAssignment; + } else { expect("Expected one of the following: (, ; or ="); @@ -1964,14 +2118,20 @@ public final class Parser // We now parse function definition but with `wantsBody` set to false // indicating no body should be allowed. - pseudoEntity = parseTypedDeclaration(false, false, true); + pseudoEntity = cast(TypedEntity)parseTypedDeclaration(false, false, true); + + // TODO: Add a check for this cast (AND parse wise if it is evan possible) + assert(pseudoEntity); } /* External variable symbol */ else if(externType == SymbolType.EXTERN_EVAR) { // We now parse a variable declaration but with the `wantsBody` set to false // indicating no assignment should be allowed. - pseudoEntity = parseTypedDeclaration(false, true, false); + pseudoEntity = cast(TypedEntity)parseTypedDeclaration(false, true, false); + + // TODO: Add a check for this cast (AND parse wise if it is evan possible) + assert(pseudoEntity); } /* Anything else is invalid */ else diff --git a/source/tlang/compiler/symbols/check.d b/source/tlang/compiler/symbols/check.d index 2fa77e7..d18c50c 100644 --- a/source/tlang/compiler/symbols/check.d +++ b/source/tlang/compiler/symbols/check.d @@ -58,6 +58,8 @@ public enum SymbolType SMALLER_THAN, GREATER_THAN_OR_EQUALS, SMALLER_THAN_OR_EQUALS, + OBRACKET, + CBRACKET, CAST, EXTERN, EXTERN_EFUNC, @@ -418,6 +420,16 @@ public SymbolType getSymbolType(Token tokenIn) { return SymbolType.CCURLY; } + /* Left-bracket checl */ + else if(token[0] == '[') + { + return SymbolType.OBRACKET; + } + /* Right-bracket check */ + else if(token[0] == ']') + { + return SymbolType.CBRACKET; + } /* Comma check */ else if (token[0] == ',') { diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index c2ef9da..a11d37b 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -458,6 +458,48 @@ public class VariableAssignmentStdAlone : Statement } } +// TODO: Add an ArrayAssignment thing here, would be similiar to PointerDeference +// mmmh, we would also need to ensure during typechecking/codegen/emit that we don't +// do pointer arithmetic. Makes sense we would have a ArrayAssign and expression for indexers +// but during codegen we check WHO was being assigned to and their type and based on that +// generate the correct INSTRUCTION +public final class ArrayAssignment : Statement +{ + private Expression assignmentExpression; + + /** + * The left hand side of: + * e.g. myArray[i][1] = 2; + * + * Therefore the `myArray[i][1]` part + */ + private ArrayIndex leftHandExpression; + + this(ArrayIndex leftHandExpression, Expression assignmentExpression) + { + this.leftHandExpression = leftHandExpression; + this.assignmentExpression = assignmentExpression; + + /* Weighted as 2 */ + weight = 2; + } + + public ArrayIndex getArrayLeft() + { + return leftHandExpression; + } + + public Expression getAssignmentExpression() + { + return assignmentExpression; + } + + public override string toString() + { + return "ArrayAssignment [leftHand: "~leftHandExpression.toString()~", assignmentExpr: "~assignmentExpression.toString()~"]"; + } +} + public class PointerDereferenceAssignment : Statement { diff --git a/source/tlang/compiler/symbols/expressions.d b/source/tlang/compiler/symbols/expressions.d index 2d62764..9e9ba2b 100644 --- a/source/tlang/compiler/symbols/expressions.d +++ b/source/tlang/compiler/symbols/expressions.d @@ -199,4 +199,34 @@ public final class CastedExpression : Expression { return uncastedExpression; } +} + +public final class ArrayIndex : Expression +{ + /* The expression to index of */ + private Expression indexInto; + + /* The expression used as the index */ + private Expression index; + + this(Expression indexInto, Expression index) + { + this.indexInto = indexInto; + this.index = index; + } + + public Expression getIndexed() + { + return indexInto; + } + + public Expression getIndex() + { + return index; + } + + public override string toString() + { + return "ArrayIndex [to: "~indexInto.toString()~", idx: "~index.toString()~"]"; + } } \ No newline at end of file diff --git a/source/tlang/compiler/symbols/typing/builtins.d b/source/tlang/compiler/symbols/typing/builtins.d index 271f576..85672a7 100644 --- a/source/tlang/compiler/symbols/typing/builtins.d +++ b/source/tlang/compiler/symbols/typing/builtins.d @@ -4,6 +4,7 @@ import tlang.compiler.symbols.typing.core; import std.string : cmp, indexOf, lastIndexOf; import gogga; import tlang.compiler.typecheck.core; +import std.conv : to; /** * TODO: We should write spec here like I want int and stuff of proper size so imma hard code em @@ -12,6 +13,8 @@ import tlang.compiler.typecheck.core; */ public Type getBuiltInType(TypeChecker tc, string typeString) { + gprintln("getBuiltInType("~typeString~")"); + /* `int`, signed (2-complement) */ if(cmp(typeString, "int") == 0) { @@ -75,36 +78,62 @@ public Type getBuiltInType(TypeChecker tc, string typeString) { return new Integer("ubyte", 1, false); } - - - /** - * FIXME: For the below we need to find which is the RIGHT-MOST and THEN - * go from there - * - * This is so that we can support things such as: - * - * `char*[]` - */ - - - /* Pointer handling `*` */ - else if(lastIndexOf(typeString, "*") > -1) + /* Stack-based array handling `[]` */ + else if(isStackArray(typeString)) { - long ptrTypePos = lastIndexOf(typeString, "*"); + // TODO: Construct this by dissecting `typeString` + StackArray stackArray; + + // Find the last occuring `[` + long lastOBracketPos = lastIndexOf(typeString, "["); + assert(lastOBracketPos > -1); + + // Find the component type (everything before `lastOBracketPos`) + string componentTypeString = typeString[0..lastOBracketPos]; + gprintln("StackArray (component type): "~componentTypeString); + + // Determine the size of the array (from `pos('[')+1` to typeString.length-2) + string arraySizeString = typeString[lastOBracketPos+1..$-1]; + ulong arraySize = to!(ulong)(arraySizeString); + gprintln("StackArray (stack size): "~to!(string)(arraySize)); + + + gprintln("typeString: "~typeString); + + stackArray = new StackArray(tc.getType(tc.getModule(), componentTypeString), arraySize); + + gprintln("Stack-based array types are still being implemented", DebugType.ERROR); + // assert(false); + return stackArray; + } + /* Pointer handling `*` and Array handling `*` */ + else if((lastIndexOf(typeString, "*") > -1) || (lastIndexOf(typeString, "[]") > -1)) + { + // Find the `*` (if any) + long starPos = lastIndexOf(typeString, "*"); + + // Find the `[]` (if any) + long brackPos = lastIndexOf(typeString, "[]"); + + // Determine which one is the rightmost + long rightmostTypePos; + if(starPos > brackPos) + { + rightmostTypePos = starPos; + } + else + { + rightmostTypePos = brackPos; + } + + long ptrTypePos = rightmostTypePos; string ptrType = typeString[0..(ptrTypePos)]; - gprintln("Pointer to '"~ptrType~"'"); + gprintln("TypeStr: "~typeString); + gprintln("Pointer to '"~ptrType~"'", DebugType.ERROR); return new Pointer(tc.getType(tc.getModule(), ptrType)); } - /* Array handling `[]` */ - else if(lastIndexOf(typeString, "[]") > -1) - { - long arrayTypePos = lastIndexOf(typeString, "[]"); - string arrayType = typeString[0..(arrayTypePos)]; - gprintln("Array of '"~arrayType~"'"); - - return new Array(tc.getType(tc.getModule(), arrayType)); - } + /* TODO: Add all remaining types, BUGS probabloy occur on failed looks ups when hitting this */ @@ -113,8 +142,36 @@ public Type getBuiltInType(TypeChecker tc, string typeString) { - + gprintln("getBuiltInType("~typeString~"): Failed to map to a built-in type", DebugType.ERROR); return null; } +} + +/** + * Given a type string this returns true if the provided + * type string is infact a stack array type + * + * Params: + * typeString = the type string to check + * Returns: a true if it is s atck array, false + * otherwise. + */ +private bool isStackArray(string typeString) +{ + // FIXME: THis below will be picked up by `int[]` before us + // e.g. int[][222] (a stack array of size 222 of `int[]` (a.k.a. `int*`)) + + // TODO: Also how will we fix: int[222][] which is int[222]*, ak..a a pojnter to a stack array of size 222 which + // ... is simply not a thing it would just be int[][] (int[]*) - irrespective of where the array is (on stack or heap) + + // TODO: Length check? Or parser would have caught? + + // Ensure `<...>[ ]` + if(typeString[$-1] == ']' && typeString[$-2] != '[') + { + return true; + } + + return false; } \ No newline at end of file diff --git a/source/tlang/compiler/symbols/typing/core.d b/source/tlang/compiler/symbols/typing/core.d index 188edfb..1ae7aa8 100644 --- a/source/tlang/compiler/symbols/typing/core.d +++ b/source/tlang/compiler/symbols/typing/core.d @@ -116,23 +116,32 @@ public class Pointer : Integer } /** -* Array type -* -* TODO: Might need investigation +* Stack-based Array type */ -public class Array : Type +public class StackArray : Type { + /* Size of the stack array to allocate */ + private ulong arraySize; + + /* Component type */ private Type elementType; - this(Type elementType) + this(Type elementType, ulong arraySize) { - /* The name should be `elementType[]` */ - - // super(name, ) - - /* TODO: Differentiate between stack arrays and heap */ - super(to!(string)(elementType)~"[]"); + /* The name should be `elementType[arraySize]` */ + super(to!(string)(elementType)~"["~to!(string)(arraySize)~"]"); this.elementType = elementType; + this.arraySize = arraySize; + } + + public Type getComponentType() + { + return elementType; + } + + public ulong getAllocatedSize() + { + return arraySize; } } \ No newline at end of file diff --git a/source/tlang/compiler/typecheck/core.d b/source/tlang/compiler/typecheck/core.d index e78863d..4519ac4 100644 --- a/source/tlang/compiler/typecheck/core.d +++ b/source/tlang/compiler/typecheck/core.d @@ -691,6 +691,95 @@ public final class TypeChecker } /** + * Determines whether the provided Value-instruction refers + * to a StackArray. This is used for array indexing checks, + * to disambiguate between pointer-arrays and stack-based + * arrays. + * + * Params: + * valInstr = the Value-based instruction to inspect + * Returns: true if the FetchValInstr refers to a stack-array, + * false otherwise + */ + private bool isStackArrayIndex(Value valInstr) + { + // TODO: Rename + Value indexToInstr = valInstr; + + /* We need a `FetchValueInstruction` as the first condition */ + FetchValueVar potFVV = cast(FetchValueVar)indexToInstr; + if(potFVV) + { + /** + * Obtain the array variable being referred to + * and obtain it's declared type + */ + Context potFVVCtx = potFVV.getContext(); + Variable potStackArrVar = cast(Variable)resolver.resolveBest(potFVVCtx.getContainer(), potFVV.varName); + Type variableDeclaredType = getType(potFVVCtx.getContainer(), potStackArrVar.getType()); + + /** + * If the type is `StackArray` + */ + if(cast(StackArray)variableDeclaredType) + { + return true; + } + } + + return false; + } + + /** + * Used to check if the type of the argument being passed into + * a function call is a stack array and if the function's parameter + * type is a pointer then this will check if the component type + * of the stack array is the same as that of the pointer + * + * Params: + * parameterType = the function's parameter typoe + * argumentType = the argument's type + * outputType = variable to place updated type into + * + * Returns: true if the so, false otherwise + */ + private bool canCoerceStackArray(Type parameterType, Type argumentType, ref Type outputType) + { + // If the argument being passed in is a stack array + if(cast(StackArray)argumentType) + { + StackArray stackArrayType = cast(StackArray)argumentType; + + // Get the component type of the stack array + Type stackArrCompType = stackArrayType.getComponentType(); + + // Now check if the parameter is a pointer type + if(cast(Pointer)parameterType) + { + Pointer parameterPointerCompType = cast(Pointer)parameterType; + + // Now create a new type for the stack array which is + // effectively * + Type stackArrayTypeCoerced = new Pointer(stackArrCompType); + outputType = stackArrayTypeCoerced; + + // If the coerced stack array's component type is the same as the pointer's component type + return isSameType(parameterPointerCompType, stackArrayTypeCoerced); + } + // If not, then return false immedtaiely + else + { + return false; + } + } + // If not, then immediately return false + else + { + return false; + } + } + + /** * Given two Value-based instructions this will firstly check if * at least one of the two is of type Pointer, then checks if the * remaining instruction is an of type Integer - the remaining instruction @@ -1112,6 +1201,9 @@ public final class TypeChecker // gprintln("FuncCall(Formal): "~parmType.getName()); // gprintln("FuncCall(Actual): "~valueInstr.toString()); + /* Scratch type used only for stack-array coercion */ + Type coercionScratchType; + /* Match up types */ //if(argType == parmType) @@ -1123,6 +1215,22 @@ public final class TypeChecker funcCallInstr.setEvalInstr(parmCount, valueInstr); gprintln(funcCallInstr.getEvaluationInstructions()); } + /* Stack-array argument to pointer parameter coercion check */ + else if(canCoerceStackArray(parmType, argType, coercionScratchType)) + { + // TODO: Add stack coercion check here + gprintln("Stack-based array has been coerced for function call"); + + // Update the fetch-var instruction's type to the coerced + // TODO: Should we have applied this technically earlier then fallen through to + // ... the branch above? That would have worked and been neater - we should do + // ... that to avoid duplicating any code + valueInstr.setInstrType(coercionScratchType); + + /* Add the instruction into the FunctionCallInstr */ + funcCallInstr.setEvalInstr(parmCount, valueInstr); + gprintln(funcCallInstr.getEvaluationInstructions()); + } else { printCodeQueue(); @@ -1203,6 +1311,125 @@ public final class TypeChecker /* The type of the cats expression is that of the type it casts to */ castedValueInstruction.setInstrType(castToType); } + /* ArrayIndex */ + else if(cast(ArrayIndex)statement) + { + ArrayIndex arrayIndex = cast(ArrayIndex)statement; + Type accessType; + + /* Pop the thing being indexed (the indexTo expression) */ + Value indexToInstr = cast(Value)popInstr(); + Type indexToType = indexToInstr.getInstrType(); + assert(indexToType); + gprintln("ArrayIndex: Type of `indexToInstr`: "~indexToType.toString()); + + /* Pop the index instruction (the index expression) */ + Value indexInstr = cast(Value)popInstr(); + Type indexType = indexInstr.getInstrType(); + assert(indexType); + + + // TODO: Type check here the `indexToInstr` ensure that it is an array + // TODO: Type check the indexInstr and ensure it is an integral type (index can not be anything else) + + // TODO: We need iets different for stack-arrays here + + + + /* Final Instruction generated */ + Instruction generatedInstruction; + + + // // TODO: We need to add a check here for if the `arrayRefInstruction` is a name + // // ... and if so if its type is `StackArray`, else we will enter the wrong thing below + + // TODO: Look up based on the name of the `FetchValueInstruction` (so if it is) + // ... AND if it refers to a stack array + bool isStackArray = isStackArrayIndex(indexToInstr); + gprintln("isStackArray (being indexed-on)?: "~to!(string)(isStackArray), DebugType.ERROR); + + + + // /* The type of what is being indexed on */ + // Type indexingOnType = arrayRefInstruction.getInstrType(); + // gprintln("Indexing-on type: "~indexingOnType.toString(), DebugType.WARNING); + + + /* Stack-array type `[]` */ + if(isStackArray) + { + StackArray stackArray = cast(StackArray)indexToType; + accessType = stackArray.getComponentType(); + gprintln("ArrayIndex: Stack-array access"); + + + gprintln("<<<<<<<< STCK ARRAY INDEX CODE GEN >>>>>>>>", DebugType.ERROR); + + + + /** + * Codegen and type checking + * + * 1. Set the type (TODO) + * 2. Set the context (TODO) + */ + StackArrayIndexInstruction stackArrayIndexInstr = new StackArrayIndexInstruction(indexToInstr, indexInstr); + stackArrayIndexInstr.setInstrType(accessType); + stackArrayIndexInstr.setContext(arrayIndex.context); + + gprintln("IndexTo: "~indexToInstr.toString(), DebugType.ERROR); + gprintln("Index: "~indexInstr.toString(), DebugType.ERROR); + gprintln("Stack ARray type: "~stackArray.getComponentType().toString(), DebugType.ERROR); + + + + // assert(false); + generatedInstruction = stackArrayIndexInstr; + } + /* Array type `[]` */ + else if(cast(Pointer)indexToType) + { + gprintln("ArrayIndex: Pointer access"); + + Pointer pointer = cast(Pointer)indexToType; + accessType = pointer.getReferredType(); + + /** + * Codegen and type checking + * + * 1. Embed the index instruction and indexed-to instruction + * 2. Set the type of this instruction to the type of the array's component type + * 3. (TODO) Set the context + */ + ArrayIndexInstruction arrayIndexInstr = new ArrayIndexInstruction(indexToInstr, indexInstr); + arrayIndexInstr.setInstrType(accessType); + + generatedInstruction = arrayIndexInstr; + } + else + { + // TODO: Throw an error here + // throw new TypeMismatchException() + gprintln("Indexing to an entity other than a stack array or pointer!", DebugType.ERROR); + assert(false); + } + + + + // TODO: context (arrayIndex) + + gprintln("ArrayIndex: [toInstr: "~indexToInstr.toString()~", indexInstr: "~indexInstr.toString()~"]"); + + gprintln("Array index not yet supported", DebugType.ERROR); + // assert(false); + + addInstr(generatedInstruction); + } + else + { + gprintln("This ain't it chief", DebugType.ERROR); + assert(false); + } } /* VariableAssigbmentDNode */ else if(cast(tlang.compiler.typecheck.dependency.variables.VariableAssignmentNode)dnode) @@ -1634,6 +1861,129 @@ public final class TypeChecker discardInstruction.setContext(discardStatement.context); addInstrB(discardInstruction); } + /** + * Array assignments (ArrayAssignment) + */ + else if(cast(ArrayAssignment)statement) + { + ArrayAssignment arrayAssignment = cast(ArrayAssignment)statement; + + gprintln("Note, dependency processing of ArrayAssignment is not yet implemented, recall seggy", DebugType.ERROR); + printCodeQueue(); + + // TODO: We need to implement this, what should we put here + // ... we also should be setting the correct types if need be + + /** + * At this point the code queue top of stack should look like this + * (as a requirement for Array assignments) (top-to-bottom) + * + * 1. Index instruction + * 2. Array name instruction + * 3. Assigment expression instruction + */ + Value indexInstruction = cast(Value)popInstr(); + + + // FIXME: Actually this may not always be the case, the name fetching makes sense + // ... for stack arrays but not pointer ones where the arrayRef may be generated + // ... from something else. + Value arrayRefInstruction = cast(Value)popInstr(); + Value assignmentInstr = cast(Value)popInstr(); + + gprintln("indexInstruction: "~indexInstruction.toString(), DebugType.WARNING); + gprintln("arrayRefInstruction: "~arrayRefInstruction.toString(), DebugType.WARNING); + gprintln("assignmentInstr: "~assignmentInstr.toString(), DebugType.WARNING); + + + /* Final Instruction generated */ + Instruction generatedInstruction; + + + // TODO: We need to add a check here for if the `arrayRefInstruction` is a name + // ... and if so if its type is `StackArray`, else we will enter the wrong thing below + bool isStackArray = isStackArrayIndex(arrayRefInstruction); + gprintln("isStackArray (being assigned to)?: "~to!(string)(isStackArray), DebugType.ERROR); + + + + /* The type of what is being indexed on */ + Type indexingOnType = arrayRefInstruction.getInstrType(); + gprintln("Indexing-on type: "~indexingOnType.toString(), DebugType.WARNING); + gprintln("Indexing-on type: "~indexingOnType.classinfo.toString(), DebugType.WARNING); + + + /* Stack-array type `[]` */ + if(isStackArray) + { + // TODO: Crashing here currently with `simple_stack_arrays2.t` + // gprint("arrayRefInstruction: "); + // gprintln(arrayRefInstruction); + + // StackArrayIndexInstruction stackArrayIndex = cast(StackArrayIndexInstruction)arrayRefInstruction; + + FetchValueVar arrayFetch = cast(FetchValueVar)arrayRefInstruction; + + /** + * Hoist out the declared stack array variable + */ + Context stackVarContext = arrayFetch.getContext(); + assert(stackVarContext); //TODO: We must set the Context when we make the `StackArrayIndexInstruction` + + Variable arrayVariable = cast(Variable)resolver.resolveBest(stackVarContext.container, arrayFetch.varName); + Type arrayVariableDeclarationType = getType(stackVarContext.container, arrayVariable.getType()); + + gprintln("TODO: We are still working on generating an assignment instruction for assigning to stack arrays", DebugType.ERROR); + gprintln("TODO: Implement instruction generation for stack-based arrays", DebugType.ERROR); + + // TODO: Use StackArrayIndexAssignmentInstruction + StackArrayIndexAssignmentInstruction stackAssignmentInstr = new StackArrayIndexAssignmentInstruction(arrayFetch.varName, indexInstruction, assignmentInstr); + + // TODO: See issue on `Stack-array support` for what to do next + // assert(false); + generatedInstruction = stackAssignmentInstr; + + // TODO: Set context + /* Set the context */ + stackAssignmentInstr.setContext(arrayAssignment.getContext()); + + + gprintln(">>>>> "~stackAssignmentInstr.toString()); + gprintln("Assigning into this array: "~to!(string)(assignmentInstr)); + // assert(false); + } + /* Array type `[]` */ + else if(cast(Pointer)indexingOnType) + { + // TODO: Update this and don't use pointer dereference assignment + /** + * Create a new pointer dereference assignment instruction + * + * 1. The deref is level 1 (as array index == one `*`) + * 2. The left-hand side is to be `new ArrayIndexInstruction(arrayRefInstruction, indexInstruction)` + * 3. Assignment expression is to be `assignmentInstr` + */ + // NOTE: We couple arrBasePtr+offset (index) using an ArrayIndexInstruction (optimization/code-reuse) + ArrayIndexInstruction arrIndex = new ArrayIndexInstruction(arrayRefInstruction, indexInstruction); + ArrayIndexAssignmentInstruction arrDerefAssInstr = new ArrayIndexAssignmentInstruction(arrIndex, assignmentInstr); + + gprintln("TODO: Implement instruction generation for pointer-based arrays", DebugType.ERROR); + generatedInstruction = arrDerefAssInstr; + // assert(false); + + // TODO: Set context + } + // TODO: handle this error (if even possible?) + else + { + assert(false); + } + + assert(generatedInstruction !is null); + + /* Add the instruction */ + addInstrB(generatedInstruction); + } /* Case of no matches */ else { diff --git a/source/tlang/compiler/typecheck/dependency/core.d b/source/tlang/compiler/typecheck/dependency/core.d index 9182fdf..ddca33f 100644 --- a/source/tlang/compiler/typecheck/dependency/core.d +++ b/source/tlang/compiler/typecheck/dependency/core.d @@ -1156,6 +1156,31 @@ public class DNodeGenerator dnode.needs(uncastedExpressionDNode); } + /** + * Array indexing (ArrayIndex) + */ + else if(cast(ArrayIndex)exp) + { + gprintln("Working on expressionPass'ing of ArrayIndex", DebugType.ERROR); + + ArrayIndex arrayIndex = cast(ArrayIndex)exp; + + // Set the context as we need to grab it later in the typechecker + arrayIndex.context = context; + + /* The index's expression */ + Expression indexExp = arrayIndex.getIndex(); + DNode indexExpDNode = expressionPass(indexExp, context); + dnode.needs(indexExpDNode); + + /* The thing being indexeds' expression */ + Expression indexedExp = arrayIndex.getIndexed(); + DNode indexedExpDNode = expressionPass(indexedExp, context); + dnode.needs(indexedExpDNode); + + + // assert(false); + } else { // dnode = new DNode(this, exp); @@ -1266,11 +1291,41 @@ public class DNodeGenerator else if(cast(Struct)variableType) { + } + /* Stack-based array-type */ + else if(cast(StackArray)variableType) + { + // TODO: For array support not all too sure what I shoudl put here, perhap nothing? + StackArray arrayType = cast(StackArray)variableType; + + // TODO: We might need to do pointer magic + + // (TODO) Check component type + Type componentType = arrayType.getComponentType(); + + // If the component type is a primitive type + if(cast(Primitive)componentType) + { + /* Do nothing (I presume?) */ + } + // If not + else + { + // TODO: Add more advanced handling here + gprintln("Advanced component types l;ike arrays of arrays or arrays of classes etc not yet supported", DebugType.ERROR); + assert(false); + } + + gprintln("Arrays (and these are stack arrays) are not yet supported", DebugType.ERROR); + // assert(false); } /* Anything else */ else { /* This should never happen */ + gprintln(variableType); + gprintln(variableType.classinfo); + gprintln("#ThisShouldNeverHappen Fault: A variable declaration with a kind-of type we don't know", DebugType.ERROR); assert(false); } @@ -1341,6 +1396,46 @@ public class DNodeGenerator } } /** + * Array assignments + */ + else if(cast(ArrayAssignment)entity) + { + ArrayAssignment arrayAssignment = cast(ArrayAssignment)entity; + arrayAssignment.setContext(context); + DNode arrayAssDerefDNode = pool(arrayAssignment); + + /* Pass the expression to be assigned */ + Expression assignedExpression = arrayAssignment.getAssignmentExpression(); + DNode assignmentExpressionDNode = expressionPass(assignedExpression, context); + arrayAssDerefDNode.needs(assignmentExpressionDNode); + + /** + * Extract the ArrayIndex expression + * + * This consists of two parts (e.g. `myArray[i]`): + * + * 1. The indexTo `myArray` + * 2. The index `i` + */ + ArrayIndex arrayIndexExpression = arrayAssignment.getArrayLeft(); + Expression indexTo = arrayIndexExpression.getIndexed(); + Expression index = arrayIndexExpression.getIndex(); + + DNode indexToExpression = expressionPass(indexTo, context); + arrayAssDerefDNode.needs(indexToExpression); + + DNode indexExpression = expressionPass(index, context); + arrayAssDerefDNode.needs(indexExpression); + + + + + gprintln("Please implement array assignment dependency generation", DebugType.ERROR); + // assert(false); + + return arrayAssDerefDNode; + } + /** * Function definitions */ else if(cast(Function)entity) diff --git a/source/tlang/testing/complex_stack_array_coerce.t b/source/tlang/testing/complex_stack_array_coerce.t new file mode 100644 index 0000000..01ad4ff --- /dev/null +++ b/source/tlang/testing/complex_stack_array_coerce.t @@ -0,0 +1,21 @@ +module complex_stack_array_coerce; + +int val1; +int val2; + +void coerce(int** in) +{ + in[0][0] = 69; + in[1][0] = 420; +} + +int function() +{ + int[][2] stackArr; + stackArr[0] = &val1; + stackArr[1] = &val2; + + discard coerce(stackArr); + + return val1+val2; +} \ No newline at end of file diff --git a/source/tlang/testing/complex_stack_array_coerce_bad1.t b/source/tlang/testing/complex_stack_array_coerce_bad1.t new file mode 100644 index 0000000..2583d0e --- /dev/null +++ b/source/tlang/testing/complex_stack_array_coerce_bad1.t @@ -0,0 +1,17 @@ +module complex_stack_array_coerce_bad1; + +int val1; +int val2; + +void coerce_bad1(int* in) {} + +int function() +{ + int[][2] stackArr; + stackArr[0] = &val1; + stackArr[1] = &val2; + + discard coerce_bad1(stackArr); + + return val1+val2; +} \ No newline at end of file diff --git a/source/tlang/testing/complex_stack_array_coerce_bad2.t b/source/tlang/testing/complex_stack_array_coerce_bad2.t new file mode 100644 index 0000000..1107e18 --- /dev/null +++ b/source/tlang/testing/complex_stack_array_coerce_bad2.t @@ -0,0 +1,17 @@ +module complex_stack_array_coerce_bad2; + +int val1; +int val2; + +void coerce_bad2(int*** in) {} + +int function() +{ + int[][2] stackArr; + stackArr[0] = &val1; + stackArr[1] = &val2; + + discard coerce_bad2(stackArr); + + return val1+val2; +} \ No newline at end of file diff --git a/source/tlang/testing/complex_stack_array_coerce_bad3.t b/source/tlang/testing/complex_stack_array_coerce_bad3.t new file mode 100644 index 0000000..252e542 --- /dev/null +++ b/source/tlang/testing/complex_stack_array_coerce_bad3.t @@ -0,0 +1,17 @@ +module complex_stack_array_coerce_bad3; + +int val1; +int val2; + +void coerce_bad3(int in) {} + +int function() +{ + int[][2] stackArr; + stackArr[0] = &val1; + stackArr[1] = &val2; + + discard coerce_bad3(stackArr); + + return val1+val2; +} \ No newline at end of file diff --git a/source/tlang/testing/complex_stack_array_coerce_permutation_good.t b/source/tlang/testing/complex_stack_array_coerce_permutation_good.t new file mode 100644 index 0000000..77dc2e4 --- /dev/null +++ b/source/tlang/testing/complex_stack_array_coerce_permutation_good.t @@ -0,0 +1,23 @@ +module complex_stack_array_coerce_permutation_good; + +int val1; +int val2; + +void coerce_good1(int** in) {} +void coerce_good2(int[][] in) {} +void coerce_good3(int[]* in) {} +void coerce_good4(int*[] in) {} + +int function() +{ + int[][2] stackArr; + stackArr[0] = &val1; + stackArr[1] = &val2; + + discard coerce_good1(stackArr); + discard coerce_good2(stackArr); + discard coerce_good3(stackArr); + discard coerce_good4(stackArr); + + return val1+val2; +} \ No newline at end of file diff --git a/source/tlang/testing/complex_stack_arrays1.t b/source/tlang/testing/complex_stack_arrays1.t new file mode 100644 index 0000000..063fa42 --- /dev/null +++ b/source/tlang/testing/complex_stack_arrays1.t @@ -0,0 +1,9 @@ +module complex_stack_arrays1; + +void function() +{ + int[][22222] myArray; + + int i = 2; + myArray[2][i] = 1 + myArray[2][i]; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_arrays.t b/source/tlang/testing/simple_arrays.t new file mode 100644 index 0000000..e0d23e0 --- /dev/null +++ b/source/tlang/testing/simple_arrays.t @@ -0,0 +1,6 @@ +module simple_arrays; + +void function() +{ + int[][22222] myArray; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_arrays2.t b/source/tlang/testing/simple_arrays2.t new file mode 100644 index 0000000..c249f94 --- /dev/null +++ b/source/tlang/testing/simple_arrays2.t @@ -0,0 +1,12 @@ +module simple_arrays2; + +void function() +{ + int*[] myArray1; + int[]* myArray2; + + myArray2 = cast(int[]*)myArray2; + myArray2 = cast(int[][])myArray2; + myArray2 = cast(int**)myArray2; + myArray2 = cast(int*[])myArray2; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_arrays4.t b/source/tlang/testing/simple_arrays4.t new file mode 100644 index 0000000..b4e9a24 --- /dev/null +++ b/source/tlang/testing/simple_arrays4.t @@ -0,0 +1,8 @@ +module simple_arrays4; + +void function() +{ + int[] myArray; + int i = 2; + myArray[i] = myArray[1]+2; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_pointer_array_syntax.t b/source/tlang/testing/simple_pointer_array_syntax.t new file mode 100644 index 0000000..a2b1c95 --- /dev/null +++ b/source/tlang/testing/simple_pointer_array_syntax.t @@ -0,0 +1,17 @@ +module simple_pointer_array_syntax; + +int j; + +int function(int[] ptr) +{ + *(ptr+0) = 2+2; + return (*ptr)+1*2; +} + +int thing() +{ + int discardExpr = function(&j); + int** l; + + return discardExpr; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_stack_array_coerce.t b/source/tlang/testing/simple_stack_array_coerce.t new file mode 100644 index 0000000..7b896bf --- /dev/null +++ b/source/tlang/testing/simple_stack_array_coerce.t @@ -0,0 +1,15 @@ +module simple_stack_array_coerce; + +void coerce(int* in) +{ + in[0] = 69; + in[1] = 420; +} + +int function() +{ + int[2] stackArr; + discard coerce(stackArr); + + return stackArr[0]+stackArr[1]; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_stack_array_coerce_ptr_syntax.t b/source/tlang/testing/simple_stack_array_coerce_ptr_syntax.t new file mode 100644 index 0000000..c17c990 --- /dev/null +++ b/source/tlang/testing/simple_stack_array_coerce_ptr_syntax.t @@ -0,0 +1,15 @@ +module simple_stack_array_coerce_ptr_syntax; + +void coerce(int* in) +{ + *(in+0) = 69; + *(in+1) = 420; +} + +int function() +{ + int[2] stackArr; + discard coerce(stackArr); + + return stackArr[0]+stackArr[1]; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_stack_array_coerce_wrong.t b/source/tlang/testing/simple_stack_array_coerce_wrong.t new file mode 100644 index 0000000..554f2ed --- /dev/null +++ b/source/tlang/testing/simple_stack_array_coerce_wrong.t @@ -0,0 +1,15 @@ +module simple_stack_array_coerce_wrong; + +void coerce(int** in) +{ + in[0] = 69; + in[1] = 420; +} + +int function() +{ + int[2] stackArr; + discard coerce(stackArr); + + return stackArr[0]+stackArr[1]; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_stack_arrays2.t b/source/tlang/testing/simple_stack_arrays2.t new file mode 100644 index 0000000..4591f8c --- /dev/null +++ b/source/tlang/testing/simple_stack_arrays2.t @@ -0,0 +1,9 @@ +module simple_stack_arrays2; + +void function() +{ + int[22222] myArray; + + int i = 2; + myArray[i] = 1; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_stack_arrays3.t b/source/tlang/testing/simple_stack_arrays3.t new file mode 100644 index 0000000..aedc221 --- /dev/null +++ b/source/tlang/testing/simple_stack_arrays3.t @@ -0,0 +1,11 @@ +module simple_stack_arrays3; + +void function() +{ + int[][22222] myArray; + + int[2][2] myArray2; + + int i = 2; + myArray[i][i] = 69; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_stack_arrays4.t b/source/tlang/testing/simple_stack_arrays4.t new file mode 100644 index 0000000..d3810d2 --- /dev/null +++ b/source/tlang/testing/simple_stack_arrays4.t @@ -0,0 +1,12 @@ +module simple_stack_arrays4; + +int function() +{ + int[22222] myArray; + + int i = 2; + myArray[i] = 60; + myArray[2] = myArray[i]+1; + + return myArray[2]; +} \ No newline at end of file diff --git a/wip.txt b/wip.txt new file mode 100644 index 0000000..ea211f7 --- /dev/null +++ b/wip.txt @@ -0,0 +1,10 @@ +Arrays support + +1. Todo: Add expression support for int k = `myArray[1+1]`; (for example) +2. COntinue working on indexer support +3. How would we process: + ``` + myArray[i][1] + + We should take the [`i`, `1`] and produce a nested assignment expression + ``` \ No newline at end of file