You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tlang/source/tlang/compiler/codegen/instruction.d

713 lines
16 KiB
D

module tlang.compiler.codegen.instruction;
3 years ago
import std.conv : to;
import tlang.compiler.typecheck.dependency.core : Context;
import std.string : cmp;
import tlang.compiler.symbols.data : SymbolType;
import tlang.compiler.symbols.check : getCharacter;
import gogga;
import tlang.compiler.symbols.typing.core : Type;
3 years ago
public class Instruction
{
3 years ago
/* Context for the Instruction (used in emitter for name resolution) */
private Context context; //TODO: Make this private and add a setCOntext
3 years ago
3 years ago
protected string addInfo;
public override string toString()
{
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
}
private final string produceToStrEnclose(string addInfo)
3 years ago
{
return "[Instruction: "~this.classinfo.name~":"~addInfo~"]";
}
public final Context getContext()
{
return context;
}
public final void setContext(Context context)
{
this.context = context;
}
3 years ago
}
public class FetchInst : Instruction
{
}
public class Value : Instruction
{
/* The type of the Value this instruction produces */
private Type type;
public final void setInstrType(Type type)
{
this.type = type;
}
public final Type getInstrType()
{
return type;
}
3 years ago
}
public class StorageDeclaration : Instruction
3 years ago
{
}
public class ClassStaticInitAllocate : Instruction
{
this(string className)
{
addInfo = "classStaticInitAllocate: "~className;
}
}
public class VariableAssignmentInstr : Instruction
{
/* Name of variable being declared */
public string varName; /*TODO: Might not be needed */
public Value data;
this(string varName, Value data)
{
this.varName = varName;
this.data = data;
addInfo = "assignTo: "~varName~", valInstr: "~data.toString();
}
}
public final class VariableDeclaration : StorageDeclaration
3 years ago
{
/* Name of variable being declared */
public const string varName;
3 years ago
/* Length */
public const byte length;
3 years ago
/* Type of the variable being declared */
public const Type varType;
/* Value-instruction to be assigned */
private Value varAssInstr;
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2 years ago
//TODO: This must take in type information
this(string varName, byte len, Type varType, Value varAssInstr)
3 years ago
{
this.varName = varName;
this.length = len;
this.varType = varType;
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2 years ago
this.varAssInstr = varAssInstr;
addInfo = "varName: "~varName;
3 years ago
}
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2 years ago
public Value getAssignmentInstr()
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2 years ago
{
return varAssInstr;
}
3 years ago
}
public final class FetchValueVar : Value
{
/* Name of variable to fetch from */
public string varName;
/* Length */
public byte length;
this(string varName, byte len)
{
this.varName = varName;
this.length = len;
addInfo = "fetchVarValName: "~varName~", VarLen: "~to!(string)(length);
3 years ago
}
}
/* Used for integers */
3 years ago
public final class LiteralValue : Value
{
/* Data */
private string data;
3 years ago
this(string data, Type type)
3 years ago
{
this.data = data;
this.type = type;
3 years ago
addInfo = "Data: "~to!(string)(data)~", Type: "~to!(string)(type);
}
public string getLiteralValue()
{
return data;
}
public override string toString()
{
return produceToStrEnclose("Data: "~to!(string)(data)~", Type: "~to!(string)(type));
}
}
public final class LiteralValueFloat : Value
{
/* Data */
private string data;
this(string data, Type type)
{
this.data = data;
this.type = type;
addInfo = "Data: "~to!(string)(data)~", Type: "~to!(string)(type);
3 years ago
}
public string getLiteralValue()
{
return data;
}
public override string toString()
{
return produceToStrEnclose("Data: "~to!(string)(data)~", Type: "~to!(string)(type));
}
3 years ago
}
/* FIXME: Implement this */
/**
* TODO: This should take in:
*
* 1. The string literal
* 2. It should assign it to an interning pool and get the ID (associate one with the string literal if equal/in-the-pool)
*/
public final class StringLiteral : Value
{
/* String interning pool */
private static int[string] internmentCamp;
private static int rollCount = 0;
private string stringLiteral;
this(string stringLiteral)
{
this.stringLiteral = stringLiteral;
/* Intern the string */
intern(stringLiteral);
addInfo = "StrLit: `"~stringLiteral~"`, InternID: "~to!(string)(intern(stringLiteral));
}
public static int intern(string strLit)
{
/* Search for the string (if it exists return it's pool ID) */
foreach(string curStrLit; internmentCamp.keys())
{
if(cmp(strLit, curStrLit) == 0)
{
return internmentCamp[strLit];
}
}
/* If not, create a new entry (pool it) and return */
internmentCamp[strLit] = rollCount;
rollCount++; /* TODO: Overflow check */
return rollCount-1;
}
public string getStringLiteral()
{
return stringLiteral;
}
}
3 years ago
/**
* BinOpInstr instruction
3 years ago
*
* Any sort of Binary Operator
3 years ago
*/
public class BinOpInstr : Value
3 years ago
{
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
public const Value lhs;
public const Value rhs;
public const SymbolType operator;
3 years ago
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
this(Value lhs, Value rhs, SymbolType operator)
3 years ago
{
this.lhs = lhs;
this.rhs = rhs;
this.operator = operator;
addInfo = "BinOpType: "~to!(string)(operator)~", LhsValInstr: "~lhs.toString()~", RhsValInstr: "~rhs.toString();
3 years ago
}
}
/**
* UnaryOpInstr instruction
*
* Any sort of Unary Operator
*/
public class UnaryOpInstr : Value
{
private Value exp;
private SymbolType operator;
this(Value exp, SymbolType operator)
{
this.exp = exp;
this.operator = operator;
addInfo = "UnaryOpType: "~to!(string)(operator)~", Instr: "~exp.toString();
}
Instruction - Added `getOperator()` and `getOperand()` methods to `UnaryOpInstr` - Added new instruction `PointerDereferenceAssignmentInstruction` for pointer support DGen - Updated `transform()` to emit code for instruction type `UnaryOpInstr` - Updated `transform()` to emit code for instruction type `PointerDereferenceAssignmentInstruction` - Added testing emit code in `emitEntryPoint()` for pointer testing Parser - Updated `parseName()` to trigger `parseTypedDeclaration()` on occurene of `SymbolType.STAR` (for pointer type declarations) - Added pointer-type support for function parameters (so far only single) in `parseFuncDef()` - `parseExpression()` terminates on occurence of a single `=` (ASSIGN) operator - Declaring of pointers of any depth implemented in `parseTypedDeclaration()` - Added support for pointer dereferncing assignments with the addition of `parseDerefAssignment()` - `parseStatement()` will now call `parseDerefAssignment()` on occurence of a `SymbolType.STAR` - Added a unittest for testing pointers - Finished unittest for for loops Check - Added backmapping for `SymbolType.ASSIGN` -> `&` Data - Added new parser node type `PointerDereferenceAssignment` for pointer support in the parser TypeChecker - Because function parameters are type che cked upon function call I had to add typechecking code for pointer support in the `UnaryOperatorExpression` case - Added code generation support for `PointerDereferenceAssignment` type Dependency - Added support for `PointerDereferenceAssignment` type (pointer support) to `generalStatement()` Tests - Added pointer test `simple_pointer.t`
1 year ago
public SymbolType getOperator()
{
return operator;
}
public Value getOperand()
Instruction - Added `getOperator()` and `getOperand()` methods to `UnaryOpInstr` - Added new instruction `PointerDereferenceAssignmentInstruction` for pointer support DGen - Updated `transform()` to emit code for instruction type `UnaryOpInstr` - Updated `transform()` to emit code for instruction type `PointerDereferenceAssignmentInstruction` - Added testing emit code in `emitEntryPoint()` for pointer testing Parser - Updated `parseName()` to trigger `parseTypedDeclaration()` on occurene of `SymbolType.STAR` (for pointer type declarations) - Added pointer-type support for function parameters (so far only single) in `parseFuncDef()` - `parseExpression()` terminates on occurence of a single `=` (ASSIGN) operator - Declaring of pointers of any depth implemented in `parseTypedDeclaration()` - Added support for pointer dereferncing assignments with the addition of `parseDerefAssignment()` - `parseStatement()` will now call `parseDerefAssignment()` on occurence of a `SymbolType.STAR` - Added a unittest for testing pointers - Finished unittest for for loops Check - Added backmapping for `SymbolType.ASSIGN` -> `&` Data - Added new parser node type `PointerDereferenceAssignment` for pointer support in the parser TypeChecker - Because function parameters are type che cked upon function call I had to add typechecking code for pointer support in the `UnaryOperatorExpression` case - Added code generation support for `PointerDereferenceAssignment` type Dependency - Added support for `PointerDereferenceAssignment` type (pointer support) to `generalStatement()` Tests - Added pointer test `simple_pointer.t`
1 year ago
{
return exp;
}
}
/**
* 2022 New things
*
*/
//public class CallInstr : Instruction
public class CallInstr : Value
{
}
public class FuncCallInstr : CallInstr
{
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
/**
* This is described in the corresponding AST node
* `FunctionCall`. See that. For short, function calls
* from within expressions and those as appearing as statements
* require a tiny different code gen but for Instructions
* their emit also needs a tiny difference
*/
private bool statementLevel = false;
/* Per-argument instrructions */
private Value[] evaluationInstructions;
public const string functionName;
this(string functionName, ulong argEvalInstrsSize)
{
this.functionName = functionName;
evaluationInstructions.length = argEvalInstrsSize;
updateAddInfo();
}
/**
* FuncCallInstr is built-bit-by-bit so toString information will change
*/
private void updateAddInfo()
{
addInfo = "FunctionName: "~functionName ~" EvalInstrs: "~ to!(string)(getEvaluationInstructions());
}
public void setEvalInstr(ulong argPos, Value instr)
{
evaluationInstructions[argPos] = instr;
updateAddInfo();
}
public Value[] getEvaluationInstructions()
{
return evaluationInstructions;
}
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
/**
* Determines whether this function call instruction
* is within an expression or a statement itself
*
* Returns: true if statement-level, false otherwise
*/
public bool isStatementLevel()
{
return statementLevel;
}
/**
* Marks this function call instruction as statement
* level
*/
public void markStatementLevel()
{
statementLevel = true;
}
}
public final class ReturnInstruction : Instruction
{
private Value returnExprInstr;
this(Value returnExprInstr)
{
this.returnExprInstr = returnExprInstr;
}
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
this()
{
}
public Value getReturnExpInstr()
{
return returnExprInstr;
}
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
public bool hasReturnExpInstr()
{
return returnExprInstr !is null;
}
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2 years ago
}
public final class IfStatementInstruction : Instruction
{
private BranchInstruction[] branchInstructions;
this(BranchInstruction[] branchInstructions)
{
this.branchInstructions = branchInstructions;
addInfo = "Branches: "~to!(string)(branchInstructions);
}
public BranchInstruction[] getBranchInstructions()
{
return branchInstructions;
}
}
public final class WhileLoopInstruction : Instruction
{
private BranchInstruction branchInstruction;
this(BranchInstruction branchInstruction)
{
this.branchInstruction = branchInstruction;
addInfo = "Branch: "~to!(string)(branchInstruction);
}
public BranchInstruction getBranchInstruction()
{
return branchInstruction;
}
}
Instruction - Added a new instruction, `ForLoop`, which contains a pre-run Instruction and a `Branch` instruction, coupled with some flags DGen - Added a TODO for WhileLoops (we need to implement do-while loops) - Implemented C code emitting in `emit()` for `ForLoop` instruction Check - Added missing back-mapping for `SymbolType.SMALLER_THAN` Data - Added new parser node type `ForLoop` Parser - Fixed typo in `parseWhile()` - Implemented `parseDoWhile()` for do-while loops - Implemented `parseFor()` for for-loops - Implemented `parseStatement()` for singular statement parsing - `parseStatement()` can now have the terminating symbol specified, defaults to `SymbolType.SEMICOLON` - `parseName()` and `parseAssignment()` now also accept a terminating symbol parameter as per `parseStatement()`'s behavior - `parseBody()` now makes multiple calls to `parseStatement()` for singular Statement parsing (dead code below still to be removed) - Removed commented-out unittests - Unittests that read from files now have the file source code embedded - Added unit test for while loops, for-loops (unfinished) and some other smaller language constructs (roughly 70% coverage) TypeChecker (CodeGen) - Do-while loops will fail if used (for now) - Added for-loop code generation Dependency - Implemented `generalStatement()` for statement processing - `generalPass()` now makes calls to `generalStatement()` Tests - Added `simple_for_loops.t` to test for-loops - Added `simple_do_while.t` to test do-while loops
1 year ago
public final class ForLoopInstruction : Instruction
{
private Instruction preRunInstruction;
private BranchInstruction branchInstruction;
private bool hasPostIterate;
this(BranchInstruction branchInstruction, Instruction preRunInstruction = null, bool hasPostIterate = false)
{
this.branchInstruction = branchInstruction;
this.preRunInstruction = preRunInstruction;
addInfo = (hasPreRunInstruction() ? "PreRun: "~to!(string)(preRunInstruction)~", " : "")~"Branch: "~to!(string)(branchInstruction);
this.hasPostIterate = hasPostIterate;
}
public bool hasPostIterationInstruction()
{
return hasPostIterate;
}
public Instruction getPreRunInstruction()
{
return preRunInstruction;
}
public bool hasPreRunInstruction()
{
return !(preRunInstruction is null);
}
public BranchInstruction getBranchInstruction()
{
return branchInstruction;
}
}
Lexer - Fixed missing flushing for issue #65 (see "Flushing fix ✅") - Added unit test for flushing fix VariableDeclaration (Instruction) - Added support for the embedding of a VariableAssignmentInstr inside (added a getter too) (a part of issue #66) - Conditional support for if statements: Added two new instructions (IfStatementInstruction and BranchInstruction). See issue #64 DGen - Added depth increment/decrement on enter/leave scope of `transform()` - Correct tabbing for nested if-statements using new method `genTabs(ulong)` (which uses the above mechanism). Makes code emitted for if statements (issue #64) look nicer. - Updated VariableDeclarations (with assignments) handling in `transform()` in the manner similar to BinOpInstr (see issue #66) - Added a TODO for formatting BinOpInstr's `transform()` a little more aesthetically nicer - Added code emitting support for if statements (the `IfStatementInstruction` instruction) (see issue #64) - Updated `emitEntryPoint()` to only emit testing C code for the correct input test file Parser - `parseIf()` now returns an instance of IfStatement which couples multiple `Branch` objects consisting of `Statement[]` and `Expression` - Ensured that each `Statement` of the generated `Statement[]` from `parseBody()` for a given `Branch` is parented to said Branch using `parentToContainer()` - Ensured each generated `Branch` in `Branch[]` is parented to the generated `IfStatement` using `parentToContainer()` - `parseBody()` now adds to its `Statement[]` build-up array the generated `IfStatement` from the call to `parseIf()` Check - Added support for back-mapping `SymbolType.EQUALS` to `getCharacter(SymbolType)` Data - Added `Branch` parser node which is a Container for body statements (`Statement[]`) - Added `IfStatement` parser node which is a Container of `Statement[]` which are actually `Branch[]` TypeChecker - Moved import for `reverse` to top of module - Implemented `tailPopInstr()` method which will pop from the back of the `codeQueue` "scratchpad" - Fixes handling of `StaticVariableDeclaration` and `VariableAssignmentNode` (fixes issue #66) - Added handling for IfStatement entities (if statement support #64) Resolution - Added a debug statement to `resolveUp(Container, string)` to print out the container to lookup from and the name being looked up Dependency - Added a default `toString()` to the DNode class which prints `[DNode: <entity toString()]` - Added a TODO and debug print related to issues #9 - Disabled InitScope.STATIC check for now as it caused issues with if statement parsing (probably due to VIRTUAL being default and therefore skipping if statment processing) - issue #69 - Cleaned up handling of Entity type `Variable` (variable declarations) - removed repeated code - Undid the VarAss->(depends on)->VarDec, reverted back to VarDec->(depends on)->VarAss, fixed by #66 (and closes it and #11) - Added support for `IfStatement` (if statements) in `generalPass(Container, Context)` Test cases - Added new test case testing nested if statements (`nested_conditions.t`) - Added another test case for if statements, `simple_conditions.t`
2 years ago
public final class BranchInstruction : Instruction
{
private Value branchConditionInstr;
private Instruction[] bodyInstructions;
this(Value conditionInstr, Instruction[] bodyInstructions)
{
this.branchConditionInstr = conditionInstr;
this.bodyInstructions = bodyInstructions;
addInfo = "CondInstr: "~to!(string)(branchConditionInstr)~", BBodyInstrs: "~to!(string)(bodyInstructions);
}
public bool hasConditionInstr()
{
return !(branchConditionInstr is null);
}
public Value getConditionInstr()
{
return branchConditionInstr;
}
public Instruction[] getBodyInstructions()
{
return bodyInstructions;
}
Instruction - Added `getOperator()` and `getOperand()` methods to `UnaryOpInstr` - Added new instruction `PointerDereferenceAssignmentInstruction` for pointer support DGen - Updated `transform()` to emit code for instruction type `UnaryOpInstr` - Updated `transform()` to emit code for instruction type `PointerDereferenceAssignmentInstruction` - Added testing emit code in `emitEntryPoint()` for pointer testing Parser - Updated `parseName()` to trigger `parseTypedDeclaration()` on occurene of `SymbolType.STAR` (for pointer type declarations) - Added pointer-type support for function parameters (so far only single) in `parseFuncDef()` - `parseExpression()` terminates on occurence of a single `=` (ASSIGN) operator - Declaring of pointers of any depth implemented in `parseTypedDeclaration()` - Added support for pointer dereferncing assignments with the addition of `parseDerefAssignment()` - `parseStatement()` will now call `parseDerefAssignment()` on occurence of a `SymbolType.STAR` - Added a unittest for testing pointers - Finished unittest for for loops Check - Added backmapping for `SymbolType.ASSIGN` -> `&` Data - Added new parser node type `PointerDereferenceAssignment` for pointer support in the parser TypeChecker - Because function parameters are type che cked upon function call I had to add typechecking code for pointer support in the `UnaryOperatorExpression` case - Added code generation support for `PointerDereferenceAssignment` type Dependency - Added support for `PointerDereferenceAssignment` type (pointer support) to `generalStatement()` Tests - Added pointer test `simple_pointer.t`
1 year ago
}
public final class PointerDereferenceAssignmentInstruction : Instruction
{
private Value pointerEvalInstr;
private Value assigmnetExprInstr;
private ulong derefCount;
this(Value pointerEvalInstr, Value assigmnetExprInstr, ulong derefCount)
{
this.pointerEvalInstr = pointerEvalInstr;
this.assigmnetExprInstr = assigmnetExprInstr;
this.derefCount = derefCount;
}
public Value getPointerEvalInstr()
{
return pointerEvalInstr;
}
public Value getAssExprInstr()
{
return assigmnetExprInstr;
}
public ulong getDerefCount()
{
return derefCount;
}
}
public final class DiscardInstruction : Instruction
{
private Value exprInstr;
this(Value exprInstr)
{
this.exprInstr = exprInstr;
}
public Value getExpressionInstruction()
{
return exprInstr;
}
}
public final class CastedValueInstruction : Value
{
/* The uncasted original instruction that must be executed-then-trimmed (casted) */
private Value uncastedValue;
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
/**
* Used in code emitting, this is related to
* #140. Really just a C+DGen thing.
*
* Signals that we shouldn't emit any special
* casting syntax in the underlying emitter.
*/
private bool relax;
this(Value uncastedValue, Type castToType)
{
this.uncastedValue = uncastedValue;
this.type = castToType;
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
// Relaxing is disabled by default
this.relax = false;
}
public Value getEmbeddedInstruction()
{
return uncastedValue;
}
public Type getCastToType()
{
return type;
}
Hotfix/jcli upgrade fix (#24) * 🐞️ isSameType: Add a base case (#8) * Core - Added a TODO where we are meant to insert the fallback check in `isSameType(Type t1, Type t2)` * TypeChecker - Added backported `isSameType(Type 1, Type t2)` fix for #114 * 🐞️ Functions: Return position enforcement (#6) * Parser - Added a TODO in `wantsBody == true` case in `parseFuncDef()` to check for the return keyword's position * Parser - Added a check in `parseFuncDef()` which, is a `ReturnStmt` is found, then crash the parser if it is found anywhere besides the last statement * Test cases - Added test cases to test the `return` statement position enforcement * 🧠 Feature: Direct function calls (#11) * Test cases - Added `simple_direct_func_call.t` to test direct function calls * Test cases - Removed tabs which broke lexing * AST nodes - `FunctionCall` now has the ability to be marked as statement-level by calling `makeStatementLevel()`, this can then be queried later via `isStatementLevelFuncCall()` * Parser - Statement-level function calls were never actually returned, resulting in `null` being returned by `parseName()` - this has now been fixed. - Along with this we now "mark" this `FunctionCall` AST node as statement-level when it occurs in `parseName()` * Instruction - Allow `FuncCallInstr` to be makred as statement-level and queired much in the same manner as its corresponding AST-node/parser-node `FunctionCall` * Dependency - Added support for `DNode` generation in `generalPass()` for `FunctionCall` AST nodes * TypeChecker - Handle `FunctionCall`s differently in terms of code generation dependent on whether or not rhe call is within an expression of statement-level * DGen - Handle statement-level function calls (`FuncCallInstr`s) differently by tacking on an additional `";"` to the emit string * - Added `simple_direct_func_call.t` to GitHub pipeline * DGen - Added instrumentation for semantic code generation for `simple_function_recursion_factorial.t` - Added TODO for future `simple_func_call_direct.t` Test cases - Added `simple_function_recursion_factorial.t` to test recursion Pipelines - Added `simple_function_recursion_factorial.t` to `emit` stage * DGen - Made `if` an `else if` - this wouldn't of affected anything but just to be correct * DGen - Added semantic code generation instrumentation for test case `simple_direct_func_call.t` Test cases - Updated test case `simple_direct_func_call.t` * 🧠 Feature: Meta-programming engine (#10) * Parser - Added new interface `Cloneable` * Symbols - Added new `Statement`-based type: `Macro` to support `Macro`(s) * MetaProcessor - Added the `MetaProcessor` TypeChecker - Added the `MetaProcessor` instance to the `TypeChecker`, it will be instantiated upon the `TypeChecker`'s construction and later have its `.process()` method called as the first call in `beginCheck()` * TypedEntity - Added a `setType(string)` method to update the internal `type` field * MetaProcessor - Added a type-re-writing facility via `typeRewrite(TypedEntity)` which will re-write the types such as `size_t`, `ssize_t` and so forth Test cases - Added a test case `meta/types.t` which tests this * MetaProcessor - Updated the constructor to only take in an instance of the `TypeChecker` - Updated the `process()` method to take in a `Container` such that it can be used recursively - Commented code - Added a recursive call to `process(Container)` when `curStmt` is a kind-of `Container` (this ensures that we reach the `VariableParameter`s of `Function` (die to them making up the `Statement[]` of `Function` type) - Removed unused `cmp` import `std.string` - Added type-rewrite for `ssize_t` -> `long` TypeChecker - Updated the constructor call to `MetaProcessor` to use its new API - Updated call to `process()` to now be `process(modulle)` Test cases - Updated `types.t` to test re-writing of the `Function`'s parameters * MetaProcessor - Added another FIXME * Mcro - Added interface `MTypeRewritable` to represent any AST node which has a `setType(string)` and `string getType()` method for rewriting- Added `Sizeof` which is a kind-of `IntegerLiteral` Data - Made `TypedEntity` implement the `MTypeRewritable` interface Expressions - Made `IntegerLiteral` non-final such that we can inherit from it - Added a final `setNumber(string)` method to `NumberLiteral` to update the literal MetaProcessor - The type rewriting mechanism now operates on `MTypeRewritable` AST nodes - Work has begun on `sizeOf_Literalize(Sizeof)` which is to determine the `Type` of the `Sizeof` statement and then calculate the memory width and update its literal (as it is a kind-of `NunberLiteral`) to said size Test cases - Added `meta/sizeof.t` to test `sizeof` functionality * Mcro - Added interface type `MStatementSearchable` * Mcro - Redefined `MStatementSearchable` - Added `MStatementReplaceable` - Added `Repr` (a kind-of `Expression`) which will be used as an example to test out the aforementioned two interfaces * MStatementSearchable - Added method `search(TypeInfo_Class clazzType)` which uses a `TypeInfo_Class` to search for all types matching that (and which are sub-types of `Statement` and then adds these to a list and returns it in the form of `Statement[]` * MStatementReplaceable - Implemented `replace(Statement thiz, Statement that)` which replaces the `Statement` in the first argument with that of the `Statement` in the second argument * MStatementSearchable - Added documentation for `search(TypeInfo_Class)` method * Mcro - Made `Repr` implement `MStatementSearchable` - Added new interface `MCloneable` to represent PNode's which are deeply-cloneable * Data - Made `DiscardStatement` searchabe via implementing `MStatementSearchable` - Added a stub override for implementing `MStatementReplaceable` in `DiscardStatement` * Mcro - Updated `MStatementReplaceable` to have its `replace(Statement, Statement)` method return a boolean `true` if the replacement was successful, else `false` * Parsing - Added the ability to parse a `Repr` statement Check - Added `GENERIC_TYPE_DECLARE` and `REPR` as new `SymbolType`(s) Data - `DiscardStatement` now implements the `bool replace(Statement, Statement)` method MetaProcessor - Added the ability to replace statements that occur within any _other_ statements which implement `MStatementSearchable` and `MStatementReplaceable` Test cases - Added `meta/simple_meta_replace.t` to test all of this Diagrams - Added diagram on how the meta system works * MetaProcessor - Removed unused `replace` method * MetaProcessor - Accept a new argument to the `MetaProcessor(TypeChecker)` constructor indicating whether or not the `MetaProcessor` is enabled or not TypeChecker - Enable the `MetaProcessor` * Mcro - Removed `Sizeof`, we will let it be parsed as a normal `FunctionCall` and then inspect in `MetaProcessor` * MetaProcessor - Disabled `sizeOf_Literalize` for now - Search for all `FunctionCall` statements in `process(Container)` * MetaProcessor - Removed old code for testing `MStatementSearchable` and `MStatementReplaceable` - Added note that we will have to investigate a recursive `MTypeRewritable` to be able to support things like `sizeof(size_t)` - Implemented module-level `sizeof(<ident_type>)` support - Added `Number`-kind of types support to `sizeOf_Literalize`(string)` Containers (`Module`) - Added `MStatementSearchable` and `MStatementReplaceable` support to `Module` container type Data - Added `MStatementSearchable` and `MStatementReplaceable` support to `Variable` - Added `MStatementSearchable` and `MStatementReplaceable` support to `VariableAssignment` - Work-in-progress for adding `MStatementSearchable` and `MStatementReplaceable` support to `FunctionCall` - Added a note to return `false` in `DiscardStatement` if the statement to be replaced is us (the `DiscardSTatement`) ourselves Test cases - Updated the `meta/sizeof.t` test case * Containers - Inherit from `MStatementSearchable` and `MStatementReplaceable` - Removed direct interface inheritance of `MStatementSearchable, MStatementReplaceable` and `MStatementReplaceable`, rely on `Container` now * Struct - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Clazz - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` BinaryOperatorExpression - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Function - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Variable - Fixed the `replace` method implementation which had a bug that would never replace the node `VariableAssignment` inside of it VariableAssignmentStdAlone - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` IfStatement - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` WhileLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` ForLoop - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` Branch - Implemented the `search` method for `MStatementSearchable` - Implemented the `replace` method for `MStatementReplaceable` * MetaProcessor - Added a future TODO for occurence of certain types that are alises (i.e. `size_t` appearing in a expression context like `sizeof(size_t)` - Now that all `Container`-based types are `MStatementReplaceable` we no longer need this check * MetaProcessor - Removed `break` which caused only one `sizeof()` function call to be replaced, we should have been looping over each `FunctionCall` found with `search` and then replacing ech that had a name of `sizeof` with a `NumberLiteral` expression - Moved all type alias replacement code into a new method; `doTypeAlias(Container, Statement)` - Added some rudiementary support for replacing any `IdentExpression` containing `size_t` with `uint` IdentExpression - Made it `MStatementSearchable` and `MStatementReplaceable` Test cases - Updated test case `meta/sizeof.t` to test the `sizeof(<expr>)` AST node in the `MetaProcessor` Documentation - Added diagram showing the `MStatementSearchable` and `MStatementReplaceable` in action * Compiler - If the T compiler was built on `X86` then set the maximum width to 4 bytes - If the T compiler was built on `X86_64` then set the maximum width to 8 bytes - Pass in the `Compiler` instance to the `TypeChecker` in `doTypeCheck()` TypeChecker - Added `Compiler` field and now accept it in constructor - If just single parameter constructor then pass in `null` as the `Compiler` instance - Added `getCompiler()` to get the instance MetaProcessor - Extract the `CompilerConfiguration` via the `TypeChecker`'s `getCompiler()` - Implemented `getSystemType(string)` which will map `size_t`/`ssize_t` to the correct maximum width'd type your system supports via the `types:max_width` config entry * CompilerConfiguration - Added `defaultConfig()` * Compiler - Removed `defaultConfig()` - During construction call `CompilerConfiguration.defaultConfig()` in order to generate the default config - Pass the config into `TypeChecker` in `doTypeCheck()` * TypeChecker - No longer store a field for the `Compiler` but rather store a field for the `CompilerConfiguration` - Removed single parameter constructor for `TypeChecker` - Constructor now uses the default `CompilerConfiguration` if not specified; therefore fixing the issue with unit tests failing MetaProcessor - Extract the compiler configuration via `tc.getConfig()` - Updated `typeRewrite(MTypeRewritable)` to use `getSystemType(string)` to lookup concrete types for `size_t`/`ssize_t` - `doTypeAlias(Container, Statement)` now uses `getSsstemType(string)` to lookup the concrete types for alises such as `size_t`/`ssize_t` * MetaProcessor - Implemented `isSystemType(string)` which returns `true` if the provided type is a system type alias (such as `size_t` or `ssize_t`), `false` otherwise * MetaProcessor - Implemented `isTypeAlias(string)` which determines if the given type is a type alias. - Implemented `getConcreteType(string typeAlias)` which transforms the type alias into its concrete type; this method incorporates defensive programming in that it will only apply the transformation IF the provided type alias is infact a type alias, otherwise it performs an identity transformation and returns the "alias" untouched. * TypeChecker - Clean up * MetaProcessor - `doTypeAlias(Container, Statement)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * - `typeRewrite(MTypeRewritable)` now makes use of `isTypeAlias(string)` and `getConcreteType(string)` * MetaProcessor - Cleaned up * MetaProcessor - Removed unused import * MetaProcessor - Removed now-completed TODO * MetaProcessor - Updated comment before call to `doTypeAlias(Container, Statement)` * Containers - `Module` now applies re-parenting in its `replace()` - `Struct` now applies re-parenting in its `replace()` - `Clazz` now applies re-parenting in its `replace()` Data - `Function` now applies re-parenting in its `replace()` * Test cases - Added `simple_template_type_def.t` for future test cases * - Updated `.gitignore` * Check - Removed `SymbolType.REPR` which was used for testing early versions of the `MetaProcessor` * Mcro - Removed `Repr` which was used for testing in the early stages of `MetaProcessor` * Check - Removed reference to `SymbolType.REPR` in checker * Parser - Removed reference to `SymbolType.REPR` and `Repr` which was used for testing the `MetaProcessor` in early stages * 🧹️🧼️ Cleanup: Clean up series 1 (#16) * ⚡️ Feature: Lexer Interface cleanup (#14) * LexerInterface Defined the lexer interface * Parser - Fixed import for `Token` class - Removed the token management fields such as `tokens`, `currentToken` and `tokenPtr` as these are now replaced by our `LexerInterface`, `lexer` field which manages this all for us - Removed constructor which accepts a `Token[]`, now onyl accept a `LexerInterface` - Removed `nextToken()`, `hasTokens()`, `getCurrentToken()`, `previousToken()`, `setCursor(ulong)` and `getCursor()`. - The above now are called via the `lexer` instance Parser (unit tests) - Migrated to new `LexerInterface`+`BasicLexer` system - Hoisted out common imports for unit tests into a `version(unittest)` TypeChecker (unittests) - Hoisted out common imports for unit tests into a `version(unittest)` - Migrated to new `LexerInterface`+`BasicLexer` system LexerInterface - Moved to new `lexer.core` package - Documented module and class Commands - Fixed imports for the (now) `BasicLexer` - Fixed imports for the (now) `lexer.core` package Compiler - Fixed imports for the (now) `BasicLexer` - Use `LexerInterface` instead of `Lexer` - The `doLex()` method now uses an instance of `BasicLexer` and then downcasts to quickly call `performLex()` in order to tokenize and make them available - The `doParse()` method now takes in an instance of `LexerInterface` rather than `Token[]` BasicLexer (previously Lexer) - Moved to the `lexer.kinds` package - Now implements `LexerInterface` - Documented module and class - Documented the `LexerInterface` methods Exceptions - Moved to the `lexer.core` package - Fixed import of `Token` class - Now uses `LexerInterface` Core.Lexer.Package - Documented package module Tokens - Moved to the `lexer.core` package - Documented module and class Check - Fixed import for `Token` - Fixed import for `BasicLexer` * `core.lexer` (package) - Documented all public imports * Exceptions - Documented the module - Documented `LexerError` and its members - Documented `LexerException`, its members too * Tokens - Documented the fields (using proper syntax) - Documented constructor and methods * BasicLexer - Removed now-completed TODO - Added (for clarity) `override` keywords to the `getLine()` and `getColumn()` methods - Moved `getLine()`, `getColumn()` and `getTokens()` altoghether - Made `getTokens()` override-marked - Documented `getTokens()` * Check - Removed weird TODO that makes no sense - Documented some of the members of `SymbolType` * Check - Documented a few more enum members of `SymbolType` - Fixed documentation (and added a TODO) for the `SymbolType.LE_SYMBOL` * Check - Documented a few more enum members of `SymbolType` * Check - Documented `isType(string)` - Added a TODO for `isTYpe(string)` to "Check if below is even used - Documented `isPathIdentifier(string)` * Check - Updated description of `isPathIdentifier(string)` to note it can contain underscores - Documented isIdentifier(string)` - Updated `SymbolType.IDENT_TYPE` to acknowledge underscores - Documented `isAccessor(Token token)` and `isModifier(Token)` * Check - Documented `isIdentifier_NoDot(Token tokenIn)`, `isIdentifier_Dot(Token tokenIn)`, `isNumericLiteral(string token)` - Removed uneeded import of `BasicLexer` - Moved import to the top of file * Check - Documented `getSymbolType(Token tokenIn)`, `isMathOp(Token token)`, `isBinaryOp(Token token)` * Check - Documented the `symbols.check` module * Builtins - Properly documented `getBuiltInType(TypeChecker, string)` * Builtins - Documented module * Typing (core) - Documented module - Documented all members * Exceptions (lexer) - Fixed documentation missing parameters * Check - Make comments docs/ddox compatible * BasicLexer - Fixed parameter name in documentation * BasixLexer - Fixed formatting in documentation for class * Typing (core) - Documented all remaining class members and fields * - Update `.gitignore` * Commands - Handle `Exception` as well, I know DGen emits this on CC error so we should DO this to make tests more accurate * Commands - Fixed variable usage * Instructions - Made `BinOpInstr`'s left-hand side instruction of type `Value` and right-hand side instruction of type `Value` too - Doesn't make sense to use anything but `Value`-based instructions for it * Containers - Removed redundant import that causes compilation failure on `ldc2` * 🐞️ Functions: Expressionless return and enforcing requirement (#7) * Parser - Added a TODO in `parseReturn()` for issue #113 * Data - The `ReturnStmt` now has a default constructor which is for cases where one doesn't want to provide an expression (for expressionless returns) Parser - `parseReturn()` now supports expressionless returns Test cases - Added `simple_return_expressionless.t` to test expressionless return statement * Data - Added a method `hasReturnExpression()` to `ReturnStmt` which returns `true` if the return statement has an expression attached, `false` otherwise * Dependency - When processing a `ReturnStmt` only run do dependency generation for the return statement's expression IF it has one * Instruction - Made `ReturnInstruction` have a constructor which takes in no `Value` instruction (intended for return expression) - Added a `hasReturnExpInstr()` to `ReturnInstruction`such that during typechecking/codegen we can check for it * TypeChecker - Added a TODO regarding the missing typechecking for `ReturnStmt` typechecking. Added notes on how we'd go about this. - Fixed crash due to assuming there was always an expression on the stack that could be popped off for generating a `ReturnInstruction` (this is not the case when the return statement is expressionless) * Tests - Added a typecheck test for `simple_return_expressionless.t` * TypeChecker - Update `isSameType(Type t1, Type t2)` to check if the actual types of both `Type` objects are the same as a last resort - Added a `NOTE` comment on how `isSameType(Type t1, Type t2)` is implemented - Added typechecking code for `ReturnStmt` and updated the code generation with it. We now do the following: 1. We extract the container of the `ReturnStmt` and cast it to a `Function`; if it is not a `Function` we throw an error because you cannot have a `ReturnStmt` appear in a non-`Function` container 2. We extract the function's name relative to it container (the function's container) for use of it in error messages 3. Next, we get the return type of the function and do the following: a. If the return type is `void` i. If the return has an expression we throw an error ii. If the return has NO expression we pass typechecking and generate the `ReturnInstr` b. If the return type is non-`void` i. If the return has an expression we ensure that its type matches that of the function's return type and generate the `ReturnInstr` ii. If the return has NO expression we raise an exception as one is expected 4. If we pass and got here then we set the `ReturnInstr`'s context and `addInstrB(returnInstr)` * Test cases - Added test case `simple_return_type.t` which is here to test our return type checking * - Updated `.gitignore` * Parser - Use `lexer` for all `Token`-based operations * Resolution - Implemented `findContainerOfType(TypeInfo_Class, Statement)` which, given a type-of `Container` and a starting `Statement` (AST node) this will swim upwards to try and find the first matching parent of which is of the given type (exactly, not kind-of). * TypeChecker - Fixed the `Function` `Container` resolution for the `ReturnStmt` to now find the nearest `parent` in its parenthood tree which is a `Function`, extract the `Function`'s name and then use that where needed * 🐞 Bugfix: Ensure that typed functions contain a return statement (#17) * Parser - Added TODO for checking for non-`void` function's return statements * Parser - If a `ReturnStmt` is not found after calling `parseFuncDef()` * Parser - Added a FIXME comment that needs to be completed soon * Parser - Only check that a `ReturnStmt` is present in a function definition when `wantsBody` is true ELSE we'd expect it for `efunc` `extern`'d statements - Fixed a unit test which had a missing `return <expr>` - Added a unit test which tests for a function definition with a body with a non-void return type that it DOES fail - Removed two now-completed TODOs and FIXMEs Test cases - Fixed test case in `typecheck/simple_function_call.t` to now include the required `return <expr>` statements * 🐞 Bugfix: Recursively check for return statemen tprescence (#19) * Parsing - Added a TODO for where the fix needs to be * Parser - Implemented `findOfType(TypeInfo_Class statementType, Container from)` which given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. it will return an array of `Statement` (`Statement[]`) of the matches. - Implemented `existsWithin(TypeInfo_Class statementType, Container from)` given a type of `Statement` to look for and a `Container` of which to search with in. This method will recursively search down the given container and look for any statements which are a kind-of (`isBaseOf`) the requested type. It will return `true` if any matches are found. - We now will recursively explore the `Function`'s body statements in search of a `ReturnStmt` * Parser (unit tests) - Updated unit test which was meant to check for a greater number of body statements of the `Function` at question * Parser (unit tests) - Because this causes `expect(string)` to be called (this unit test) we must catch `TError` as that is what `expect(string)` throws - We should update this (see https://deavmi.assigned.network/git/tlang/tlang/issues/147) * Tets cases - Added missing `return` to function `banana` in `simple_functions.t` test case * Test cases - Fixed `simple_function_decls.t` to include the required (but missing) `return` statement * 🐞 Bugfix: expect(string) should throw ParserException atleast (#20) * Parser - Removed commented-out code * Parser - Removed `isUnitTest` variable and how `expect(string)` relies on it * Parser - Now throw a new `ParserException` instead of a `TError` when calling `expect(string)` * Parser - Made `expect(string)` not static * TypeChecker - Implemented `expect(string)` which throws a `TypeCheckerException` in a similar fashion to `Parser`'s `expect(string)` * Dependency - Implemented `expect(string)` which throws a `DependencyException` in a similar fashion to `Parser`'s `expect(string)` Exceptions (dependency) - Added enum member `GENERAL_ERROR` to `DependencyError` * Parser (unit tests) - Made more specific * Parser - Removed now-completed TODO * Data - Removed unused type `ArgumentList` * Expressions - Made the `Expression` class abstract - Removed irrelevant TODOs and method - Removed uneeded constructor VariableExpression - Removed unused junk * 🧠 Feature/Meta: Cloneable (round 1) (#21) * Data - Moved AST manipulation imports to the top - Made `VariableAssignment` cloneable - Made `Variable` cloneable * Data - When trying to `clone()` an `Expression`, do a runtime type check to check if we can (else `null` is used) * Expressions - Moved AST-manipulation related import to the top * Expressions - `BinaryOperatorExpression` now overrides `clone()` from `MCloneable` * Expressions - `IntegerLiteral` now implements `MCloneable` * Expressions - `CastedExpression` now implements `clone()` for `MCloneable` * Containers - Moved all AST maniuplation-related imports to the top * Containers - Made `Struct` support `MCloneable`'s `clone()` method * Data - Only clone the `VariableAssignment` if the `Variable` has one * Containers (unit test) - Added test which tests the `clone()` on a `Struct` * DGen - If `typeTransform(Type)` fails then the debug text should be in the error coloring * DGen - If `typeTransform(Type)` is called on an unknown type then print out the type in the error message asx well * Mcro - Made `MCloneable`'s `clone()` require a `Container` argument of which the final cloned `Statement` must parent-itself to * Expressions - `BinaryOperatorExpression`, `CastedExpression` and `IntegerLiteral` now implements the new `MCloneable` API * Expressions - Added notes about where parenting must manually be done * Data - `Variable` and `VariableAssignment` now uses the new `MCloneable` API * Containers - `Struct`'s `MCloenable` API adhered to * Containers - Fixed `clone(Container)` implementation for `Struct` whereby it would not parent the newly created copy * TypeChecker - Added a TODO regarding the `ClassStaticNode` handling * TypeCheck - Undo incorrect FIXME * CodeEmitter - Added a new parameter to `transform(Instruction)` (now `transform(Instruction, Object)`. `customRules` is an `Object` to be interpreted by the underlying emitter which can change how certain transformations are done when it is in a certain state DGen - Uses new `CodeEmitter` API * Revert "CodeEmitter" This reverts commit 75372ee13252737304dde5473384b6e47d30b056. * DGen - Added ability to flag whether symbol mapping should occur or not - By default enable symbol mapping * Variable - When calling `replace(Statement, Statement)`, if we hit the `variableAssignment` replacement check, first check and ensure it is not null`, try * 🧠️ Feature: Universal coercion and type enforcer (#9) * TypeChecker - Added `bool isSameType2(Value v1, Value v2, bool attemptCoercion = false)` for future implementation of universal coercion as per #115 * TypeChecker - Renamed `isSameType2` to `typeEnforce` - Updated `typeEnforce`'s default parameter documentation from `false` to `attemptCoercion` (as it should have been in the beginning) * TypeCheckerException - Save the `TypecheckError` coming in as `errType` and make it available via `getError()` TypemMismatchException - Save the original (expected) and attempted types and make them available via `getExpectedType()` and `getATtemptedType()` respectively * TypeChecker - Updated `typeEnforce` from taking in `Value v1, Value v2, bool` to `Type t1, Value v2, bool`. - `typeEnforce()` will now extract the `Type` of `Value v2` and call `isSameType(t1, t2)`, if that fails and coercion is allowed then it is attempted, however if that fails then it causes an exception to be thrown. In the case coercion is not allowed, then a `TypeMismatchException` is thrown Unit tests - Tested the new `typeEnforce(Type t1, Value v2, bool)` and it seems to work, both a case of failing matching (coercion disallowed) and working coercion (coercion allowed) * TypeChecker - Documented existing unittest for `typeEnforce(Type, Value, bool)` - Added new unit test for `typeEnforce(Type, Value, bool)` which tests when the types ARE the same * TypeChecker - Cleaned up `typeEnforce(Type, Value, bool)` * TypeChecker - Added a work-in-progress unit test to test how I would use `typeEnforce(Type t1, Value v2, bool coercion = false)` in practice - Added TODOs in `attemptCoercion(Type, Type)` where I must add support * TypeChecker - Finished the unit test testing out the usage for `typeEnforce(Type, Value, bool coerce = false)` - Added TODOs to `attemptCoercion(Type, Value)` for the changes required to it * TypeChecker - Removed incorrect TODOs from `attemptCoerce(Type, Value)` and updated the message when the coercion fails Unit tests - Updated first unit test for `typeEnforce()` to test failing coercion on a non-`LiteralValue` instruction - Added a unit test where `typeEnforce()` WILL pass as it coerces a `LiteralValue` instruction * Exceptions (`typechecker`) - Added new exception type `CoercionException` to be thrown whenever a coercion cannot take place. * TypeChecker - Ensure that `attemptCoercion(Type, Value)` only throws instances of `CoercionException` * Unit tests - Fixed failing-coercion check by catching the correct exception when it fails `CoercionException` instead of `TypeMismatchException`) * TypeChecker - Added documentation for `isSameType(Type t1, Type t2)` * TypeChecker - Updated documentation for `isCoercibleRange(Type, Value)` - Updated `attemptCoercion(Type, Value)` with new documentation and renamed parameters * Unit tests (typechecker) - Added comments * TypeChecker - Removed now-completed TODO in `typeEnforce(Type t1, Value v2, bool allowCoercion = false)` * TypeChecker - Removed unused `typeStatus` variable in `typeEnforce(Type, Value, bool)` * TypeChecker - Variable declarations (with assignments) now use the `typeEnforce()` method with coercion allowed in order to do the type checking and coercion changes - Added a comment explaining a certain branch of `attemptCoercion(Type, Value)` * TypeChecker - If the to-type and provided-type are both numerical then use a size-based test Test cases - Added two test cases which test `typeEnforce()` on incoming `Value`-based instructions as part of variable declarations * Test cases - Fixed negative test case - it MUST have an error and that should be seen as a pass * TypeChecker (unit tests) - Disabled invalid unit test (marked for re-writing) - I should re-write the below. It is now incorrect as I DO ALLOW coercion of non literal-based instructions now - so it fails because it is using an older specification of TLang * TypeChecker - Migrated the type checking of standalone variable assignments to using `typeEnforce()` Test cases - Added positive and negative test cases * - Updated `.gitignore` * Feature/type enforcer cast instr emit (#13) * TypeChecker - `typeEnforce()` now will not change the type of `Value`-based instruction `v2` but rather return, on successful coercion set a `ref`-based argument to a new instance of a `CastedValueInstruction`, if coercion fails or was disabled and types mismatched then an exeption is thrown as normal. - If the types are an exact same match, a-la `isSameType(Type, Type)`, then this `ref` value is set to `v2` (makes programming easy) else we would have no way to know - `attemptCoerce()` now, to go with the above changes to `typeEnforce()`, returns a `CatsedValueInstruction` to the to-type on successful coercion, else an exception is thrown as usual - Updated two cases of `typeEnforce()` usage to the new method signature, also now add a sanity check assertion that the types now DO match as they should * TypeChecker - We need not set it again, look the value we use when we CALL `typeEnforce()` is that of the `fromInstruction` and if no changes occur we still have it, it is fine - if it changes via the call to `typeEnforce()` via the `ref` based argument thne same old - No need for us to set it here in the event of no changes, we are writing back the exact same Instruction/object-reference * TypeChecker (unit tests) - Upgraded to the new `typeEnforcer()` method signature * TypeChecker - Improved documentation for `typeEnforce()` * TypeChecker - Added TODO regarding pointer coercion with integers in `Pointer + Integer` case (for pointer airthmetic) * TypeChecker - Added a new branch which currently throws an exception as it is unimplememted - This branch (above) is in `attemptCoercion()` and is to handle the coercion of `Integer` to `Pointer` for pointer arithmetic - When doing the typechecking/codegen for `BinaryOp`, disable the pointer coercion call to `attemptPointerAriehmeticCoercion()`, instead now make calls in those cases they apply, to `typeEnforce()` - The above stuff is still broken, not yet implemented. * TypeChecker - Cannot use cast as that can return false positives for an all pointer case as all `Pointer`s are `Integer`s - Added `isPointerType(Type)` to check the above - Added then also `isIntegralTypeButNotPointer(Type)` which checks for an `Integer` type but excluding if it is a `Pointer` - Updated the checks in the `BinaryOperator` branch of `typeCheckThing(DNode)` to do this * TypeChecker - Need to do the `Pointer` checks first in `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` now returns a `CastedValueInstruction` to cast the `Integer` type to the `Pointer` type * TypeCHecker - Catch mis use of type enforcement by using `isIntegralTypeButNotPointer(Type)` and isPointerType`(Type)` for the previous commit * TypeChecker - Refresh the types after the potential calls to `typeEnforce(..., ..., ..., ...)` * Pipeline - Use `set -e` for `simple_pointer.t` test in emit stage * Pipelines (emit stage) - Previous compilation may have succeeded, meaning ./tlang.out never gets updated and exits fine with 0, but we only use the last commands exit status to check for a pass for a test. - By setting this if COMPILATION fails then we exit with its code and the test status is set via that * Pipelines - Removed the `set -e` code as the correct `Exception` now causes a non-zero exit code from the changes made in `varass_vardec_dependency` * DGen - Added notice for issue #140 * TypeChecker - Made `isIntegralTypeButNotPointer(Type)` public - Made `isPointerType(Type)` public * Instructions - `CastedValueInstruction` now is unrelaxed by default but can be set (tis aids in how it can be emitted later for issue #140) * DGen - Added some checks for certain conditions whereby pointer coercion requires relaxing the casted operands (coerced operands) * DGen - Relax `CastedValueInstruction`(s) when appropriate in `BinaryOpInstr` handling code - Removed panics * DGen - Added relaxation support to the code emitting code for `CastedValueInstruction` * DGen - make debug messages for when relaxation occurs for `CastedValueInstruction` emitting more clear * TypeChecker - Implemented `biggerOfTheTwo(Integer, Integer)` which determines the biggest of the two `Integer`-based types and returns that one. * TypeChecker - Fixed incorrect variable name in `biggerOfTheTwo(Integer, Integer)` * TypeChecker - Throw an error in the case where a `BinaryOperatorExpression` occurs with non-`Integer`-based instructions (at least for now) * TypeChecker - If both types are `Integral` (but not `Pointer`) then smaller coerces to bigger, if they however are equal then signed coerces to unsigned * TypeChecker - Removed now irrelevant comment * TypeChecker - Don't throw exception here, rather let the `isSameType(Type, Type)` check handle that - We still keep the warning we print about missing cases implementation-wise * TypeChecker - Fixed explanation * TypeChecker - Marked related issue * TypeChecker - Implemented ` isStackArrayType(Type typeIn)` - WIP: Added a check for handling `StackArray -> Pointer` coercion to `attemptCoercion(Type, Value)` * TypeChecker - `attemptCoercion(Type, Value)` will now ensure firstly that the `StackArray`'s component type matches that of the `Pointer`'s referred type, if not throw an exception, if so, then return a `CastedValueInstruction` * TypeChecker - Print out a debug message when attempting to coerce a `StackArray` to a `Pointer` - Fixed the error message thrown when a `StackArray` could not be coerced to a `Pointer` due to the component type != ptr's referred type - `FunctionCall` handling now has the `canCoerceStackArray()` code disabled and uses the `typeEnforce()` method * TypeChecker - Type checking code for `FunctionCall` * TypeCheck - Completed TODO comment * TypeChecker - Added a TODO * TypeChecker - Added FIXME where the `typeEnforce()` call need to be made for the `ReturnStmt`'s return expression's type to match or be checked-against the containing `Function`'s * TypeChecker - `ReturnStmt` now uses `typeEnforce()` * Test cases - Added two new checks for checking the return type of a function and matching a `ReturnStmt`'s expression's type to it * TypeChecker - Removed assertion check, rather let the exception thrown handle the error - Only after we know the finally-parenting `Container` is a `Function` (should we reference `funcContainer` * Test cases - Removed explicit cast from `simple_function_recursion_factorial.t` * TypeChecker - If we have a `LiteralValue` and a non-`LiteralValue` then coerce the `LiteralValue` towards the non`-LiteralValue` via `typeEnforce()` - This should allow the correct range checking of literal values within the range of the to-type and not require annoying explicit casts * Test cases - Removed now-unneeded explicit casts on literal values in `simple_function_recursion_factorial.t` * TypeChecker - Added comment describing the process used - Removed now-completed TODO * TypeChecker - Removed some dead code - Removed now-completed FIXME/TODO * TypeChecker - Removed old type checking code for variable declarations with assignments - Removed old type checking code for standalone variable assignments * Dub - Upgraded `jcli` to version `0.25.0-beta.2` * Dub - Upgtraded package `jcli` to version `0.25.0-beta.3` * - Try using latest version of `dmd`
10 months ago
public bool isRelaxed()
{
return relax;
}
public void setRelax(bool relax)
{
this.relax = relax;
}
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`
1 year ago
}
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()~"]";
}
3 years ago
}