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
|
exit 1
|
||||||
fi
|
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
|
- name: Collide container module1
|
||||||
run: |
|
run: |
|
||||||
|
@ -313,10 +369,57 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
chmod +x extern_test.sh
|
chmod +x extern_test.sh
|
||||||
./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)
|
- name: Simple pointer (malloc and free)
|
||||||
run: |
|
run: |
|
||||||
chmod +x malloc_test.sh
|
chmod +x malloc_test.sh
|
||||||
./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 #######
|
####### 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.data : SymbolType, Variable, Function, VariableParameter;
|
||||||
import tlang.compiler.symbols.check : getCharacter;
|
import tlang.compiler.symbols.check : getCharacter;
|
||||||
import misc.utils : Stack;
|
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;
|
import tlang.compiler.configuration : CompilerConfiguration;
|
||||||
|
|
||||||
public final class DCodeEmitter : CodeEmitter
|
public final class DCodeEmitter : CodeEmitter
|
||||||
|
@ -91,6 +91,18 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
{
|
{
|
||||||
return "void";
|
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");
|
gprintln("Type transform unimplemented");
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -166,6 +178,14 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
|
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
|
// Check to see if this declaration has an assignment attached
|
||||||
if(typedEntityVariable.getAssignment())
|
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;
|
return emit;
|
||||||
}
|
}
|
||||||
// TODO: MAAAAN we don't even have this yet
|
// TODO: MAAAAN we don't even have this yet
|
||||||
|
@ -815,6 +1005,20 @@ int main()
|
||||||
assert(t_87bc875d0b65f741b69fb100a0edebc7 == 4);
|
assert(t_87bc875d0b65f741b69fb100a0edebc7 == 4);
|
||||||
assert(retValue == 6);
|
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;
|
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;
|
return 0;
|
||||||
}`);
|
}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -511,4 +511,142 @@ public final class CastedValueInstruction : Value
|
||||||
{
|
{
|
||||||
return type;
|
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`)
|
* 1. `int ptr` (and we looked ahead to `ptr`)
|
||||||
* 2. `int* ptr` (and we looked ahead to `*`)
|
* 2. `int* ptr` (and we looked ahead to `*`)
|
||||||
|
* 3. `int[] thing` (and we looked ahead to `[`)
|
||||||
*/
|
*/
|
||||||
/* If we have an identifier/type then declaration */
|
/* 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();
|
previousToken();
|
||||||
ret = parseTypedDeclaration();
|
ret = parseTypedDeclaration();
|
||||||
|
@ -474,6 +475,13 @@ public final class Parser
|
||||||
expect(SymbolType.SEMICOLON, getCurrentToken());
|
expect(SymbolType.SEMICOLON, getCurrentToken());
|
||||||
nextToken();
|
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 */
|
/* This should never happen */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -907,7 +915,7 @@ public final class Parser
|
||||||
if(getSymbolType(getCurrentToken()) == SymbolType.IDENT_TYPE)
|
if(getSymbolType(getCurrentToken()) == SymbolType.IDENT_TYPE)
|
||||||
{
|
{
|
||||||
/* Get the type */
|
/* Get the type */
|
||||||
TypedEntity bogusEntity = parseTypedDeclaration(false, false, false, true);
|
TypedEntity bogusEntity = cast(TypedEntity)parseTypedDeclaration(false, false, false, true);
|
||||||
string type = bogusEntity.getType();
|
string type = bogusEntity.getType();
|
||||||
|
|
||||||
/* Get the identifier (This CAN NOT be dotted) */
|
/* Get the identifier (This CAN NOT be dotted) */
|
||||||
|
@ -1041,7 +1049,8 @@ public final class Parser
|
||||||
* which means we can call `getType()` and extract
|
* which means we can call `getType()` and extract
|
||||||
* the type string
|
* 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();
|
string toType = bogusEntity.getType();
|
||||||
|
|
||||||
/* Expect a `)` closing brace */
|
/* Expect a `)` closing brace */
|
||||||
|
@ -1057,7 +1066,6 @@ public final class Parser
|
||||||
return castedExpression;
|
return castedExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an expression
|
* Parses an expression
|
||||||
*
|
*
|
||||||
|
@ -1315,6 +1323,23 @@ public final class Parser
|
||||||
/* Get the next token */
|
/* Get the next token */
|
||||||
nextToken();
|
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 */
|
/* If it is an identifier */
|
||||||
else if (symbol == SymbolType.IDENT_TYPE)
|
else if (symbol == SymbolType.IDENT_TYPE)
|
||||||
{
|
{
|
||||||
|
@ -1348,7 +1373,9 @@ public final class Parser
|
||||||
addRetExp(toAdd);
|
addRetExp(toAdd);
|
||||||
}
|
}
|
||||||
/* Detect if this expression is coming to an end, then return */
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1436,29 +1463,93 @@ public final class Parser
|
||||||
return retExpression[0];
|
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);
|
gprintln("parseTypedDeclaration(): Enter", DebugType.WARNING);
|
||||||
|
|
||||||
|
|
||||||
/* Generated object */
|
/* Generated object */
|
||||||
TypedEntity generated;
|
Statement generated;
|
||||||
|
|
||||||
|
|
||||||
/* TODO: Save type */
|
/* TODO: Save type */
|
||||||
string type = getCurrentToken().getToken();
|
string type = getCurrentToken().getToken();
|
||||||
string identifier;
|
string identifier;
|
||||||
|
|
||||||
|
|
||||||
// TODO: Insert pointer `*`-handling code here
|
|
||||||
nextToken();
|
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;
|
/* If we have `[` then expect a number and/or a `]` */
|
||||||
type=type~"*";
|
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();
|
nextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1470,17 +1561,39 @@ public final class Parser
|
||||||
|
|
||||||
return generated;
|
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();
|
/* If we are going to be assigning into an array (indexed) */
|
||||||
gprintln("ParseTypedDec: DecisionBtwn FuncDef/VarDef: " ~ getCurrentToken().getToken());
|
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) */
|
/* Check if it is `(` (func dec) */
|
||||||
SymbolType symbolType = getSymbolType(getCurrentToken());
|
SymbolType symbolType = getSymbolType(getCurrentToken());
|
||||||
|
@ -1528,7 +1641,7 @@ public final class Parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Check for `=` (var dec) */
|
/* Check for `=` (var dec) */
|
||||||
else if (symbolType == SymbolType.ASSIGN)
|
else if (symbolType == SymbolType.ASSIGN && (arrayIndexing == false))
|
||||||
{
|
{
|
||||||
// Only continue if variable declarations are allowed
|
// Only continue if variable declarations are allowed
|
||||||
if(allowVarDec)
|
if(allowVarDec)
|
||||||
|
@ -1564,6 +1677,47 @@ public final class Parser
|
||||||
expect("Variables declarations are not allowed.");
|
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
|
else
|
||||||
{
|
{
|
||||||
expect("Expected one of the following: (, ; or =");
|
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
|
// We now parse function definition but with `wantsBody` set to false
|
||||||
// indicating no body should be allowed.
|
// 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 */
|
/* External variable symbol */
|
||||||
else if(externType == SymbolType.EXTERN_EVAR)
|
else if(externType == SymbolType.EXTERN_EVAR)
|
||||||
{
|
{
|
||||||
// We now parse a variable declaration but with the `wantsBody` set to false
|
// We now parse a variable declaration but with the `wantsBody` set to false
|
||||||
// indicating no assignment should be allowed.
|
// 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 */
|
/* Anything else is invalid */
|
||||||
else
|
else
|
||||||
|
|
|
@ -58,6 +58,8 @@ public enum SymbolType
|
||||||
SMALLER_THAN,
|
SMALLER_THAN,
|
||||||
GREATER_THAN_OR_EQUALS,
|
GREATER_THAN_OR_EQUALS,
|
||||||
SMALLER_THAN_OR_EQUALS,
|
SMALLER_THAN_OR_EQUALS,
|
||||||
|
OBRACKET,
|
||||||
|
CBRACKET,
|
||||||
CAST,
|
CAST,
|
||||||
EXTERN,
|
EXTERN,
|
||||||
EXTERN_EFUNC,
|
EXTERN_EFUNC,
|
||||||
|
@ -418,6 +420,16 @@ public SymbolType getSymbolType(Token tokenIn)
|
||||||
{
|
{
|
||||||
return SymbolType.CCURLY;
|
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 */
|
/* Comma check */
|
||||||
else if (token[0] == ',')
|
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
|
public class PointerDereferenceAssignment : Statement
|
||||||
{
|
{
|
||||||
|
|
|
@ -199,4 +199,34 @@ public final class CastedExpression : Expression
|
||||||
{
|
{
|
||||||
return uncastedExpression;
|
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 std.string : cmp, indexOf, lastIndexOf;
|
||||||
import gogga;
|
import gogga;
|
||||||
import tlang.compiler.typecheck.core;
|
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
|
* 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)
|
public Type getBuiltInType(TypeChecker tc, string typeString)
|
||||||
{
|
{
|
||||||
|
gprintln("getBuiltInType("~typeString~")");
|
||||||
|
|
||||||
/* `int`, signed (2-complement) */
|
/* `int`, signed (2-complement) */
|
||||||
if(cmp(typeString, "int") == 0)
|
if(cmp(typeString, "int") == 0)
|
||||||
{
|
{
|
||||||
|
@ -75,36 +78,62 @@ public Type getBuiltInType(TypeChecker tc, string typeString)
|
||||||
{
|
{
|
||||||
return new Integer("ubyte", 1, false);
|
return new Integer("ubyte", 1, false);
|
||||||
}
|
}
|
||||||
|
/* Stack-based array handling `<componentType>[<number>]` */
|
||||||
|
else if(isStackArray(typeString))
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
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)];
|
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));
|
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 */
|
/* 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;
|
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
|
* Stack-based Array type
|
||||||
*
|
|
||||||
* TODO: Might need investigation
|
|
||||||
*/
|
*/
|
||||||
public class Array : Type
|
public class StackArray : Type
|
||||||
{
|
{
|
||||||
|
/* Size of the stack array to allocate */
|
||||||
|
private ulong arraySize;
|
||||||
|
|
||||||
|
/* Component type */
|
||||||
private Type elementType;
|
private Type elementType;
|
||||||
|
|
||||||
this(Type elementType)
|
this(Type elementType, ulong arraySize)
|
||||||
{
|
{
|
||||||
/* The name should be `elementType[]` */
|
/* The name should be `elementType[arraySize]` */
|
||||||
|
super(to!(string)(elementType)~"["~to!(string)(arraySize)~"]");
|
||||||
// super(name, )
|
|
||||||
|
|
||||||
/* TODO: Differentiate between stack arrays and heap */
|
|
||||||
super(to!(string)(elementType)~"[]");
|
|
||||||
|
|
||||||
this.elementType = elementType;
|
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
|
* Given two Value-based instructions this will firstly check if
|
||||||
* at least one of the two is of type Pointer, then checks if the
|
* at least one of the two is of type Pointer, then checks if the
|
||||||
* remaining instruction is an of type Integer - the remaining instruction
|
* 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(Formal): "~parmType.getName());
|
||||||
// gprintln("FuncCall(Actual): "~valueInstr.toString());
|
// gprintln("FuncCall(Actual): "~valueInstr.toString());
|
||||||
|
|
||||||
|
/* Scratch type used only for stack-array coercion */
|
||||||
|
Type coercionScratchType;
|
||||||
|
|
||||||
|
|
||||||
/* Match up types */
|
/* Match up types */
|
||||||
//if(argType == parmType)
|
//if(argType == parmType)
|
||||||
|
@ -1123,6 +1215,22 @@ public final class TypeChecker
|
||||||
funcCallInstr.setEvalInstr(parmCount, valueInstr);
|
funcCallInstr.setEvalInstr(parmCount, valueInstr);
|
||||||
gprintln(funcCallInstr.getEvaluationInstructions());
|
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
|
else
|
||||||
{
|
{
|
||||||
printCodeQueue();
|
printCodeQueue();
|
||||||
|
@ -1203,6 +1311,125 @@ public final class TypeChecker
|
||||||
/* The type of the cats expression is that of the type it casts to */
|
/* The type of the cats expression is that of the type it casts to */
|
||||||
castedValueInstruction.setInstrType(castToType);
|
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 */
|
/* VariableAssigbmentDNode */
|
||||||
else if(cast(tlang.compiler.typecheck.dependency.variables.VariableAssignmentNode)dnode)
|
else if(cast(tlang.compiler.typecheck.dependency.variables.VariableAssignmentNode)dnode)
|
||||||
|
@ -1634,6 +1861,129 @@ public final class TypeChecker
|
||||||
discardInstruction.setContext(discardStatement.context);
|
discardInstruction.setContext(discardStatement.context);
|
||||||
addInstrB(discardInstruction);
|
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 */
|
/* Case of no matches */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1156,6 +1156,31 @@ public class DNodeGenerator
|
||||||
|
|
||||||
dnode.needs(uncastedExpressionDNode);
|
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
|
else
|
||||||
{
|
{
|
||||||
// dnode = new DNode(this, exp);
|
// dnode = new DNode(this, exp);
|
||||||
|
@ -1266,11 +1291,41 @@ public class DNodeGenerator
|
||||||
else if(cast(Struct)variableType)
|
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 */
|
/* Anything else */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This should never happen */
|
/* 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);
|
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
|
* Function definitions
|
||||||
*/
|
*/
|
||||||
else if(cast(Function)entity)
|
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