mirror of https://github.com/tbklang/tlang.git
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`
This commit is contained in:
parent
493da1a4e7
commit
fe8e1403f0
|
@ -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 #######
|
||||
##################################
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
@ -17,7 +17,7 @@ import tlang.compiler.codegen.mapper.core : SymbolMapper;
|
|||
import tlang.compiler.symbols.data : SymbolType, Variable, Function, VariableParameter;
|
||||
import tlang.compiler.symbols.check : getCharacter;
|
||||
import misc.utils : Stack;
|
||||
import tlang.compiler.symbols.typing.core : Type, Primitive, Integer, Void, Pointer;
|
||||
import tlang.compiler.symbols.typing.core;
|
||||
import tlang.compiler.configuration : CompilerConfiguration;
|
||||
|
||||
public final class DCodeEmitter : CodeEmitter
|
||||
|
@ -91,6 +91,18 @@ public final class DCodeEmitter : CodeEmitter
|
|||
{
|
||||
return "void";
|
||||
}
|
||||
/* 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";
|
||||
}
|
||||
|
||||
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 := `<symbolName>[<stackArraySize>]`
|
||||
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[<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)";
|
||||
|
||||
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<stdio.h>
|
||||
#include<assert.h>
|
||||
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<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);
|
||||
|
||||
return 0;
|
||||
}`);
|
||||
}
|
||||
|
|
|
@ -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()~"]";
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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] == ',')
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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()~"]";
|
||||
}
|
||||
}
|
|
@ -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 `<type>*` */
|
||||
else if(lastIndexOf(typeString, "*") > -1)
|
||||
/* Stack-based array handling `<componentType>[<number>]` */
|
||||
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 `<type>*` and Array handling `<type>*` */
|
||||
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 `<type>[]` */
|
||||
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 `<...>[ <something> ]`
|
||||
if(typeString[$-1] == ']' && typeString[$-2] != '[')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 <stackArrayType>*
|
||||
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 `<compnentType>[<size>]` */
|
||||
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 `<componentType>[]` */
|
||||
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 `<compnentType>[<size>]` */
|
||||
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 `<componentType>[]` */
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module complex_stack_arrays1;
|
||||
|
||||
void function()
|
||||
{
|
||||
int[][22222] myArray;
|
||||
|
||||
int i = 2;
|
||||
myArray[2][i] = 1 + myArray[2][i];
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
module simple_arrays;
|
||||
|
||||
void function()
|
||||
{
|
||||
int[][22222] myArray;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
module simple_arrays4;
|
||||
|
||||
void function()
|
||||
{
|
||||
int[] myArray;
|
||||
int i = 2;
|
||||
myArray[i] = myArray[1]+2;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module simple_stack_arrays2;
|
||||
|
||||
void function()
|
||||
{
|
||||
int[22222] myArray;
|
||||
|
||||
int i = 2;
|
||||
myArray[i] = 1;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
module simple_stack_arrays3;
|
||||
|
||||
void function()
|
||||
{
|
||||
int[][22222] myArray;
|
||||
|
||||
int[2][2] myArray2;
|
||||
|
||||
int i = 2;
|
||||
myArray[i][i] = 69;
|
||||
}
|
|
@ -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];
|
||||
}
|
Loading…
Reference in New Issue