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:
Tristan B. Velloza Kildaire 2023-04-20 11:21:50 +02:00 committed by GitHub
parent 493da1a4e7
commit fe8e1403f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1558 additions and 66 deletions

View File

@ -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 #######
##################################

BIN
branding/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
branding/logo.xcf Normal file

Binary file not shown.

View File

@ -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;
}`);
}

View File

@ -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()~"]";
}
}

View File

@ -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

View File

@ -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] == ',')
{

View File

@ -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
{

View File

@ -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()~"]";
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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
{

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,9 @@
module complex_stack_arrays1;
void function()
{
int[][22222] myArray;
int i = 2;
myArray[2][i] = 1 + myArray[2][i];
}

View File

@ -0,0 +1,6 @@
module simple_arrays;
void function()
{
int[][22222] myArray;
}

View File

@ -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;
}

View File

@ -0,0 +1,8 @@
module simple_arrays4;
void function()
{
int[] myArray;
int i = 2;
myArray[i] = myArray[1]+2;
}

View File

@ -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;
}

View File

@ -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];
}

View File

@ -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];
}

View File

@ -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];
}

View File

@ -0,0 +1,9 @@
module simple_stack_arrays2;
void function()
{
int[22222] myArray;
int i = 2;
myArray[i] = 1;
}

View File

@ -0,0 +1,11 @@
module simple_stack_arrays3;
void function()
{
int[][22222] myArray;
int[2][2] myArray2;
int i = 2;
myArray[i][i] = 69;
}

View File

@ -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];
}

10
wip.txt Normal file
View File

@ -0,0 +1,10 @@
Arrays support
1. Todo: Add expression support for int k = `myArray[1+1]`; (for example)
2. COntinue working on indexer support
3. How would we process:
```
myArray[i][1]
We should take the [`i`, `1`] and produce a nested assignment expression
```