tlang/source/tlang/compiler/codegen/emit/dgen.d

919 lines
30 KiB
D
Raw Normal View History

module tlang.compiler.codegen.emit.dgen;
2021-11-02 08:41:03 +00:00
import tlang.compiler.codegen.emit.core : CodeEmitter;
import tlang.compiler.typecheck.core;
import std.container.slist : SList;
import tlang.compiler.codegen.instruction;
import std.stdio;
import std.file;
2021-11-02 15:03:38 +00:00
import std.conv : to;
import std.string : cmp;
import gogga;
import std.range : walkLength;
import std.string : wrap;
import std.process : spawnProcess, Pid, ProcessException, wait;
import tlang.compiler.typecheck.dependency.core : Context, FunctionData, DNode;
import tlang.compiler.codegen.mapper.core : SymbolMapper;
import tlang.compiler.symbols.data : SymbolType, Variable, Function, VariableParameter;
import tlang.compiler.symbols.check : getCharacter;
import misc.utils : Stack;
import tlang.compiler.symbols.typing.core : Type, Primitive, Integer, Void, Pointer;
import tlang.compiler.configuration : CompilerConfiguration;
2021-11-02 08:41:03 +00:00
public final class DCodeEmitter : CodeEmitter
{
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
// NOTE: In future store the mapper in the config please
this(TypeChecker typeChecker, File file, CompilerConfiguration config, SymbolMapper mapper)
{
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
super(typeChecker, file, config, mapper);
}
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`
2022-12-19 13:37:55 +00:00
private ulong transformDepth = 0;
private string genTabs(ulong count)
{
string tabStr;
/* Only generate tabs if enabled in compiler config */
if(config.getConfig("dgen:pretty_code").getBoolean())
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`
2022-12-19 13:37:55 +00:00
{
for(ulong i = 0; i < count; i++)
{
tabStr~="\t";
}
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`
2022-12-19 13:37:55 +00:00
}
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`
2022-12-19 13:37:55 +00:00
return tabStr;
}
/**
* Given an instance of a Type this will transform it to a string
*
* Params:
* typeIn = The Type to transform
*
* Returns: The string representation of the transformed type
*/
public string typeTransform(Type typeIn)
{
string stringRepr;
// TODO: Some types will ident transform
/* Pointer types */
if(cast(Pointer)typeIn)
{
/* Extract type being pointed to */
Pointer pointerType = cast(Pointer)typeIn;
Type referType = pointerType.getReferredType();
/* The type is then `transform(<refertype>)*` */
return typeTransform(referType)~"*";
}
/* Integral types transformation */
else if(cast(Integer)typeIn)
{
Integer integralType = cast(Integer)typeIn;
/* u<>_t or <>_t (Determine signedness) */
string typeString = integralType.isSigned() ? "int" : "uint";
/* Width of integer */
typeString ~= to!(string)(integralType.getSize()*8);
/* Trailing `_t` */
typeString ~= "_t";
return typeString;
}
/* Void type */
else if(cast(Void)typeIn)
{
return "void";
}
gprintln("Type transform unimplemented");
assert(false);
// return stringRepr;
}
public override string transform(const Instruction instruction)
{
writeln("\n");
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
gprintln("transform(): "~to!(string)(instruction));
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`
2022-12-19 13:37:55 +00:00
transformDepth++;
// At any return decrement the depth
scope(exit)
{
transformDepth--;
}
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
/* VariableAssignmentInstr */
if(cast(VariableAssignmentInstr)instruction)
{
gprintln("type: VariableAssignmentInstr");
VariableAssignmentInstr varAs = cast(VariableAssignmentInstr)instruction;
Context context = varAs.getContext();
gprintln("Is ContextNull?: "~to!(string)(context is null));
gprintln("Wazza contect: "~to!(string)(context.container));
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
auto typedEntityVariable = typeChecker.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
gprintln("Hi"~to!(string)(varAs));
gprintln("Hi"~to!(string)(varAs.data));
gprintln("Hi"~to!(string)(varAs.data.getInstrType()));
// NOTE: For tetsing issue #94 coercion (remove when done)
string typeName = (cast(Type)varAs.data.getInstrType()).getName();
gprintln("VariableAssignmentInstr: The data to assign's type is: "~typeName);
/* If it is not external */
if(!typedEntityVariable.isExternal())
{
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
return renamedSymbol~" = "~transform(varAs.data)~";";
}
/* If it is external */
else
{
return typedEntityVariable.getName()~" = "~transform(varAs.data)~";";
}
}
/* VariableDeclaration */
else if(cast(VariableDeclaration)instruction)
{
gprintln("type: VariableDeclaration");
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
Context context = varDecInstr.getContext();
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
/* If the variable is not external */
if(!typedEntityVariable.isExternal())
{
//NOTE: We should remove all dots from generated symbol names as it won't be valid C (I don't want to say C because
// a custom CodeEmitter should be allowed, so let's call it a general rule)
//
//simple_variables.x -> simple_variables_x
//NOTE: We may need to create a symbol table actually and add to that and use that as these names
//could get out of hand (too long)
// NOTE: Best would be identity-mapping Entity's to a name
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
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`
2022-12-19 13:37:55 +00:00
// Check to see if this declaration has an assignment attached
if(typedEntityVariable.getAssignment())
{
Value varAssInstr = varDecInstr.getAssignmentInstr();
gprintln("VarDec(with assignment): My assignment type is: "~varAssInstr.getInstrType().getName());
// Generate the code to emit
return typeTransform(cast(Type)varDecInstr.varType)~" "~renamedSymbol~" = "~transform(varAssInstr)~";";
}
return typeTransform(cast(Type)varDecInstr.varType)~" "~renamedSymbol~";";
}
/* If the variable is external */
else
{
return "extern "~typeTransform(cast(Type)varDecInstr.varType)~" "~typedEntityVariable.getName()~";";
}
}
/* LiteralValue */
else if(cast(LiteralValue)instruction)
{
gprintln("type: LiteralValue");
LiteralValue literalValueInstr = cast(LiteralValue)instruction;
return to!(string)(literalValueInstr.getLiteralValue());
2022-12-13 09:46:40 +00:00
}
/* FetchValueVar */
else if(cast(FetchValueVar)instruction)
{
gprintln("type: FetchValueVar");
FetchValueVar fetchValueVarInstr = cast(FetchValueVar)instruction;
Context context = fetchValueVarInstr.getContext();
2022-12-13 09:46:40 +00:00
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(context.getContainer(), fetchValueVarInstr.varName); //TODO: Remove `auto`
/* If it is not external */
if(!typedEntityVariable.isExternal())
{
//TODO: THis is giving me kak (see issue #54), it's generating name but trying to do it for the given container, relative to it
//TODO: We might need a version of generateName that is like generatenamebest (currently it acts like generatename, within)
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
return renamedSymbol;
}
/* If it is external */
else
{
return typedEntityVariable.getName();
}
}
/* BinOpInstr */
else if(cast(BinOpInstr)instruction)
{
gprintln("type: BinOpInstr");
BinOpInstr binOpInstr = cast(BinOpInstr)instruction;
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`
2022-12-19 13:37:55 +00:00
// TODO: I like having `lhs == rhs` for `==` or comparators but not spaces for `lhs+rhs`
return transform(binOpInstr.lhs)~to!(string)(getCharacter(binOpInstr.operator))~transform(binOpInstr.rhs);
}
/* FuncCallInstr */
else if(cast(FuncCallInstr)instruction)
{
gprintln("type: FuncCallInstr");
FuncCallInstr funcCallInstr = cast(FuncCallInstr)instruction;
Context context = funcCallInstr.getContext();
assert(context);
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
Function functionToCall = cast(Function)typeChecker.getResolver().resolveBest(context.getContainer(), funcCallInstr.functionName); //TODO: Remove `auto`
// TODO: SymbolLookup?
string emit = functionToCall.getName()~"(";
//TODO: Insert argument passimng code here
//NOTE: Typechecker must have checked for passing arguments to a function that doesn't take any, for example
//NOTE (Behaviour): We may want to actually have an preinliner for these arguments
//such to enforce a certain ordering. I believe this should be done in the emitter stage,
//so it is best placed here
if(functionToCall.hasParams())
{
Value[] argumentInstructions = funcCallInstr.getEvaluationInstructions();
string argumentString;
for(ulong argIdx = 0; argIdx < argumentInstructions.length; argIdx++)
{
Value currentArgumentInstr = argumentInstructions[argIdx];
argumentString~=transform(currentArgumentInstr);
if(argIdx != (argumentInstructions.length-1))
{
argumentString~=", ";
}
}
emit~=argumentString;
}
emit ~= ")";
return emit;
}
/* ReturnInstruction */
else if(cast(ReturnInstruction)instruction)
{
gprintln("type: ReturnInstruction");
ReturnInstruction returnInstruction = cast(ReturnInstruction)instruction;
Context context = returnInstruction.getContext();
assert(context);
/* Get the return expression instruction */
Value returnExpressionInstr = returnInstruction.getReturnExpInstr();
return "return "~transform(returnExpressionInstr)~";";
}
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`
2022-12-19 13:37:55 +00:00
/**
* If statements (IfStatementInstruction)
*/
else if(cast(IfStatementInstruction)instruction)
{
IfStatementInstruction ifStatementInstruction = cast(IfStatementInstruction)instruction;
BranchInstruction[] branchInstructions = ifStatementInstruction.getBranchInstructions();
gprintln("Holla"~to!(string)(branchInstructions));
string emit;
for(ulong i = 0; i < branchInstructions.length; i++)
{
BranchInstruction curBranchInstr = branchInstructions[i];
if(curBranchInstr.hasConditionInstr())
{
Value conditionInstr = cast(Value)curBranchInstr.getConditionInstr();
string hStr = (i == 0) ? "if" : genTabs(transformDepth)~"else if";
emit~=hStr~"("~transform(conditionInstr)~")\n";
emit~=genTabs(transformDepth)~"{\n";
foreach(Instruction branchBodyInstr; curBranchInstr.getBodyInstructions())
{
emit~=genTabs(transformDepth)~"\t"~transform(branchBodyInstr)~"\n";
}
emit~=genTabs(transformDepth)~"}\n";
}
else
{
emit~=genTabs(transformDepth)~"else\n";
emit~=genTabs(transformDepth)~"{\n";
foreach(Instruction branchBodyInstr; curBranchInstr.getBodyInstructions())
{
emit~=genTabs(transformDepth)~"\t"~transform(branchBodyInstr)~"\n";
}
emit~=genTabs(transformDepth)~"}\n";
}
}
return emit;
}
/**
* While loops (WhileLoopInstruction)
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
2023-01-11 08:43:29 +00:00
*
* TODO: Add do-while check
*/
else if(cast(WhileLoopInstruction)instruction)
{
WhileLoopInstruction whileLoopInstr = cast(WhileLoopInstruction)instruction;
BranchInstruction branchInstr = whileLoopInstr.getBranchInstruction();
Value conditionInstr = branchInstr.getConditionInstr();
Instruction[] bodyInstructions = branchInstr.getBodyInstructions();
string emit;
/* Generate the `while(<expr>)` and opening curly brace */
emit = "while("~transform(conditionInstr)~")\n";
emit~=genTabs(transformDepth)~"{\n";
/* Transform each body statement */
foreach(Instruction curBodyInstr; bodyInstructions)
{
emit~=genTabs(transformDepth)~"\t"~transform(curBodyInstr)~"\n";
}
/* Closing curly brace */
emit~=genTabs(transformDepth)~"}";
return emit;
}
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
2023-01-11 08:43:29 +00:00
/**
* For loops (ForLoopInstruction)
*/
else if(cast(ForLoopInstruction)instruction)
{
ForLoopInstruction forLoopInstr = cast(ForLoopInstruction)instruction;
BranchInstruction branchInstruction = forLoopInstr.getBranchInstruction();
Value conditionInstr = branchInstruction.getConditionInstr();
Instruction[] bodyInstructions = branchInstruction.getBodyInstructions();
string emit = "for(";
// Emit potential pre-run instruction
emit ~= forLoopInstr.hasPreRunInstruction() ? transform(forLoopInstr.getPreRunInstruction()) : ";";
// Condition
emit ~= transform(conditionInstr)~";";
// NOTE: We are leaving the post-iteration blank due to us including it in the body
// TODO: We can hoist bodyInstructions[$] maybe if we want to generate it as C-for-loops
// if(forLoopInstr.hasPostIterationInstruction())
emit ~= ")\n";
// Open curly (begin body)
emit~=genTabs(transformDepth)~"{\n";
/* Transform each body statement */
foreach(Instruction curBodyInstr; bodyInstructions)
{
emit~=genTabs(transformDepth)~"\t"~transform(curBodyInstr)~"\n";
}
// Close curly (body end)
emit~=genTabs(transformDepth)~"}";
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`
2023-01-12 08:53:48 +00:00
return emit;
}
/**
* Unary operators (UnaryOpInstr)
*/
else if(cast(UnaryOpInstr)instruction)
{
UnaryOpInstr unaryOpInstr = cast(UnaryOpInstr)instruction;
Value operandInstruction = cast(Value)unaryOpInstr.getOperand();
assert(operandInstruction);
string emit;
/* The operator's symbol */
emit ~= getCharacter(unaryOpInstr.getOperator());
/* Transform the operand */
emit ~= transform(operandInstruction);
return emit;
}
/**
* Pointer dereference assignment (PointerDereferenceAssignmentInstruction)
*/
else if(cast(PointerDereferenceAssignmentInstruction)instruction)
{
PointerDereferenceAssignmentInstruction pointerDereferenceAssignmentInstruction = cast(PointerDereferenceAssignmentInstruction)instruction;
Value lhsPtrAddrExprInstr = pointerDereferenceAssignmentInstruction.getPointerEvalInstr();
assert(lhsPtrAddrExprInstr);
Value rhsAssExprInstr = pointerDereferenceAssignmentInstruction.getAssExprInstr();
assert(rhsAssExprInstr);
string emit;
/* Star followed by transformation of the pointer address expression */
string starsOfLiberty;
for(ulong i = 0; i < pointerDereferenceAssignmentInstruction.getDerefCount(); i++)
{
starsOfLiberty ~= "*";
}
Pointer support (#2) * Make branches not identical * Removed temporary file * Typecheck - Added `attemptPointerAriehmeticCoercion(Value, Value)` * Typechecker - Moved `attemptPointerAriehmeticCoercion(Value, Value)` to class-level and made privately accessible * Test cases - Added pointer arithmetic in the form of `*(ptr+0)` to `simple_pointer.t` to start testing it out * Typechecker - When handling `BinaryOperatorExpression` call `attemptPointerAriehmeticCoercion(Value, Value)` with both `(vLhsInstr, vRhsInstr)` before we call `vLhsInstr.getInstrType()` and `vRhsInstr.getInstrType()` before `isSameType(vLhsType, vRhsType)`. By doing so we attempt to coerce the types of both instructions if one is a pointer and another is an integer, else do nothing * DGen - When emitting for `PointerDereferenceAssignmentInstruction` we didn't wrap `<expr>` with `()`. So instead of `*(<expre>)` we got `*<expr>` which doesn't work if you're doing pointer arithmetic * Test cases - Added `simple_pointer_cast.t` to test casting (currently broken parsing-wise) DGen - Added a todo for semantic tests for the `simple_pointer_cast.t` test case * Parser - Added a TODO - we need a `parseType()` * Test cases - Removed `simple_cast_complex_type.t` as it is wrong, syntax wise * Test cases - Removed coercion usage, I am only testing the casting here (explicit) * Test cases - Removed `simple_pointer_cast.t` and replace it with `simple_pointer_cast_le.t` which casts the integer pointer to a byte pointer and sets the lowest significant byte (little endian hence at base of integer) to `2+2` DGen - Added semantic test for `simple_pointer_cast_le.t` * Test cases - Update `simple_pointer_cast_le.t` to do some pointer airthmetic at the byte-level of the 32-bit integer DGen - Updated the semantic test code generation for `simple_pointer_cast_le.t` to check for new values * Added 'simple_pointer_cast_le.t' to Emit tests * TypeChecker - Update `isSameType(Type t1, Type t2)` to now handle pointers explicitly and in a recursive manner based on their referred types - This check occurs before the `Integer` type check therefore following the rule of most specific types to least * Test cases - Added new test case `simple_pointer_malloc.t` - Added semantic code test generation for `simple_pointer_malloc.t` - Added `malloc_test.sh` to compile and generate `mem.o` from `mem.c` to link it then with `simple_pointer_malloc.t` - Added `mem.c` external C file to generate the required `mem.o` for linking against `simple_pointer_malloc.t` * Test cases - Updated `malloc_test.sh` to look for any `brk()` system calls and fixed its interpreter path
2023-04-17 15:50:11 +01:00
emit ~= starsOfLiberty~"("~transform(lhsPtrAddrExprInstr)~")";
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`
2023-01-12 08:53:48 +00:00
/* Assignment operator follows */
emit ~= " = ";
/* Expression to be assigned on the right hand side */
emit ~= transform(rhsAssExprInstr)~";";
return emit;
}
/**
* Discard instruction (DiscardInstruction)
*/
else if(cast(DiscardInstruction)instruction)
{
DiscardInstruction discardInstruction = cast(DiscardInstruction)instruction;
Value valueInstruction = discardInstruction.getExpressionInstruction();
string emit;
/* Transform the expression */
emit ~= transform(valueInstruction)~";";
return emit;
}
/**
* Type casting instruction (CastedValueInstruction)
*/
else if(cast(CastedValueInstruction)instruction)
{
CastedValueInstruction castedValueInstruction = cast(CastedValueInstruction)instruction;
Type castingTo = castedValueInstruction.getCastToType();
// TODO: Dependent on type being casted one must handle different types, well differently (as is case for atleast OOP)
Value uncastedInstruction = castedValueInstruction.getEmbeddedInstruction();
string emit;
/* Handling of primitive types */
if(cast(Primitive)castingTo)
{
/* Add the actual cast */
emit ~= "("~typeTransform(castingTo)~")";
/* The expression being casted */
emit ~= transform(uncastedInstruction);
}
else
{
// TODO: Implement this
gprintln("Non-primitive type casting not yet implemented", DebugType.ERROR);
assert(false);
}
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
2023-01-11 08:43:29 +00:00
return emit;
}
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
// TODO: MAAAAN we don't even have this yet
// else if(cast(StringExpression))
2022-12-13 09:46:40 +00:00
return "<TODO: Base emit: "~to!(string)(instruction)~">";
}
2021-11-02 08:41:03 +00:00
public override void emit()
{
// Emit header comment (NOTE: Change this to a useful piece of text)
emitHeaderComment("Place any extra information by code generator here"); // NOTE: We can pass a string with extra information to it if we want to
// Emit standard integer header import
emitStdint();
// Emit static allocation code
emitStaticAllocations();
// Emit globals
emitCodeQueue();
// Emit function definitions
2023-01-13 09:22:47 +00:00
emitFunctionPrototypes();
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
emitFunctionDefinitions();
// If enabled (default: yes) then emit entry point (TODO: change later)
if(config.getConfig("dgen:emit_entrypoint_test").getBoolean())
{
//TODO: Emit main (entry point)
emitEntryPoint();
}
}
/**
* Emits the header comment which contains information about the source
* file and the generated code file
*
* Params:
* headerPhrase = Optional additional string information to add to the header comment
*/
private void emitHeaderComment(string headerPhrase = "")
{
// NOTE: We could maybe fetch input fiel info too? Although it would have to be named similiarly in any case
// so perhaps just appending a `.t` to the module name below would be fine
string moduleName = typeChecker.getResolver().generateName(typeChecker.getModule(), typeChecker.getModule()); //TODO: Lookup actual module name (I was lazy)
string outputCFilename = file.name();
file.write(`/**
* TLP compiler generated code
*
* Module name: `);
file.writeln(moduleName);
file.write(" * Output C file: ");
file.writeln(outputCFilename);
if(headerPhrase.length)
{
file.write(wrap(headerPhrase, 40, " *\n * ", " * "));
}
file.write(" */\n");
}
/**
* Emits the static allocations provided
*
* Params:
* initQueue = The allocation queue to emit static allocations from
*/
private void emitStaticAllocations()
{
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
selectQueue(QueueType.ALLOC_QUEUE);
gprintln("Static allocations needed: "~to!(string)(getQueueLength()));
file.writeln();
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
}
/**
2023-01-13 09:22:47 +00:00
* Emits the function prototypes
*/
private void emitFunctionPrototypes()
{
gprintln("Function definitions needed: "~to!(string)(getFunctionDefinitionsCount()));
Instruction[][string] functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues();
string[] functionNames = getFunctionDefinitionNames();
gprintln("WOAH: "~to!(string)(functionNames));
foreach(string currentFunctioName; functionNames)
{
emitFunctionPrototype(currentFunctioName);
file.writeln();
}
}
/**
* Emits the function definitions
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
*/
private void emitFunctionDefinitions()
{
gprintln("Function definitions needed: "~to!(string)(getFunctionDefinitionsCount()));
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
Instruction[][string] functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues();
string[] functionNames = getFunctionDefinitionNames();
gprintln("WOAH: "~to!(string)(functionNames));
foreach(string currentFunctioName; functionNames)
{
emitFunctionDefinition(currentFunctioName);
file.writeln();
2023-01-13 09:22:47 +00:00
}
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
}
private string generateSignature(Function func)
{
string signature;
// Extract the Function's return Type
Type returnType = typeChecker.getType(func.context.container, func.getType());
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
// <type> <functionName> (
signature = typeTransform(returnType)~" "~func.getName()~"(";
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
// Generate parameter list
if(func.hasParams())
{
VariableParameter[] parameters = func.getParams();
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
string parameterString;
for(ulong parIdx = 0; parIdx < parameters.length; parIdx++)
{
Variable currentParameter = parameters[parIdx];
// Extract the variable's type
Type parameterType = typeChecker.getType(currentParameter.context.container, currentParameter.getType());
// Generate the symbol-mapped names for the parameters
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(func, currentParameter.getName()); //TODO: Remove `auto`
Command-line - All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
2023-01-23 18:44:35 +00:00
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
// Generate <type> <parameter-name (symbol mapped)>
parameterString~=typeTransform(parameterType)~" "~renamedSymbol;
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
if(parIdx != (parameters.length-1))
{
parameterString~=", ";
}
}
signature~=parameterString;
}
// )
signature~=")";
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
// If the function is marked as external then place `extern` infront
if(func.isExternal())
{
signature = "extern "~signature;
}
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
return signature;
}
2023-01-13 09:22:47 +00:00
private void emitFunctionPrototype(string functionName)
{
selectQueue(QueueType.FUNCTION_DEF_QUEUE, functionName);
gprintln("emotFunctionDefinition(): Function: "~functionName~", with "~to!(string)(getSelectedQueueLength())~" many instructions");
//TODO: Look at nested definitions or nah? (Context!!)
//TODO: And what about methods defined in classes? Those should technically be here too
Function functionEntity = cast(Function)typeChecker.getResolver().resolveBest(typeChecker.getModule(), functionName); //TODO: Remove `auto`
// Emit the function signature
file.writeln(generateSignature(functionEntity)~";");
}
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
private void emitFunctionDefinition(string functionName)
{
selectQueue(QueueType.FUNCTION_DEF_QUEUE, functionName);
gprintln("emotFunctionDefinition(): Function: "~functionName~", with "~to!(string)(getSelectedQueueLength())~" many instructions");
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
//TODO: Look at nested definitions or nah? (Context!!)
//TODO: And what about methods defined in classes? Those should technically be here too
Function functionEntity = cast(Function)typeChecker.getResolver().resolveBest(typeChecker.getModule(), functionName); //TODO: Remove `auto`
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
// If the Entity is NOT external then emit the signature+body
if(!functionEntity.isExternal())
{
// Emit the function signature
file.writeln(generateSignature(functionEntity));
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
// Emit opening curly brace
file.writeln(getCharacter(SymbolType.OCURLY));
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
// Emit body
while(hasInstructions())
{
Instruction curFuncBodyInstr = getCurrentInstruction();
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
string emit = transform(curFuncBodyInstr);
gprintln("emitFunctionDefinition("~functionName~"): Emit: "~emit);
file.writeln("\t"~emit);
nextInstruction();
}
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
// Emit closing curly brace
file.writeln(getCharacter(SymbolType.CCURLY));
}
// If the Entity IS external then don't emit anything as the signature would have been emitted via a prorotype earlier with `emitPrototypes()`
else
{
// Do nothing
}
2021-11-02 08:41:03 +00:00
}
private void emitCodeQueue()
{
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
selectQueue(QueueType.GLOBALS_QUEUE);
gprintln("Code emittings needed: "~to!(string)(getQueueLength()));
while(hasInstructions())
{
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
Instruction currentInstruction = getCurrentInstruction();
file.writeln(transform(currentInstruction));
App - Added newline to release info print - Fixed module docstring Commands - Added new command-line options: `syntaxcheck`, `typecheck` - Added todo to `help` command - Re-ordered commands for order of appearance in help text Compiler - Added docstring to `beginCompilation(string[])` function Mapper - Added debug print of the Container being used for the symbol lookup CodeEmitter - Re-worked CodeEmitter class to use a single so-called "selected queue" - Added methods to move back and forth between said "selected queue", get the length, etc. - Remove old queue-specific methods DGen - Use the new CodeEmitter "selected-queue" functionality - Emit function definitions now supported Exceptions - Added this keyword Check - Added support for SymbolTYpe.OCURLY and SymbolType.CCURLY to `getCharacter(SymbolType)` Data - Added a `hasParams()` method to the Function entity type TypeChecker - Added support for emitting function definitions (required DNode.poes = [] (cleaning), codeQueue cleaning etc.) - Added `getInitQueue()` method to make a copy of the current "scratchpad" `codeQueue` - Build up a copy of the global queue now (make a copy similiar to what we did for `getInitQueue()` but inline) - Added a debug print Dependency - Added a FIXME note for issue #46 - Added a TODO relating to `static DNode[] poes` Test cases - Added test case `simple_function_decls.t` to test function definition code emit - Updated test case `simple_variables.t` to note that the T code generates invalid C code README - Build instructions now generate coverage files (`.lst`s) - Updated link to documentation
2022-12-14 17:49:08 +00:00
nextInstruction();
}
file.writeln();
}
private void emitStdint()
{
file.writeln("#include<stdint.h>");
}
private void emitEntryPoint()
{
// TODO: Implement me
// Test for `simple_functions.t` (function call testing)
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`
2022-12-19 13:37:55 +00:00
if(cmp(typeChecker.getModule().getName(), "simple_functions") == 0)
{
file.writeln(`
#include<stdio.h>
#include<assert.h>
int main()
{
assert(t_7b6d477c5859059f16bc9da72fc8cc3b == 22);
printf("k: %u\n", t_7b6d477c5859059f16bc9da72fc8cc3b);
banana(1);
assert(t_7b6d477c5859059f16bc9da72fc8cc3b == 72);
printf("k: %u\n", t_7b6d477c5859059f16bc9da72fc8cc3b);
return 0;
}`);
}
else if(cmp(typeChecker.getModule().getName(), "simple_while") == 0)
{
file.writeln(`
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
2023-01-11 08:43:29 +00:00
#include<stdio.h>
#include<assert.h>
int main()
{
int result = function(3);
printf("result: %d\n", result);
assert(result == 3);
return 0;
}`);
}
else if(cmp(typeChecker.getModule().getName(), "simple_for_loops") == 0)
{
file.writeln(`
#include<stdio.h>
#include<assert.h>
int main()
{
int result = function(3);
printf("result: %d\n", result);
assert(result == 3);
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`
2023-01-12 08:53:48 +00:00
return 0;
}`);
}
else if(cmp(typeChecker.getModule().getName(), "simple_pointer") == 0)
{
file.writeln(`
#include<stdio.h>
#include<assert.h>
int main()
{
int retValue = thing();
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`
2023-01-12 08:53:48 +00:00
assert(t_87bc875d0b65f741b69fb100a0edebc7 == 4);
assert(retValue == 6);
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`
2023-01-12 08:53:48 +00:00
Pointer support (#2) * Make branches not identical * Removed temporary file * Typecheck - Added `attemptPointerAriehmeticCoercion(Value, Value)` * Typechecker - Moved `attemptPointerAriehmeticCoercion(Value, Value)` to class-level and made privately accessible * Test cases - Added pointer arithmetic in the form of `*(ptr+0)` to `simple_pointer.t` to start testing it out * Typechecker - When handling `BinaryOperatorExpression` call `attemptPointerAriehmeticCoercion(Value, Value)` with both `(vLhsInstr, vRhsInstr)` before we call `vLhsInstr.getInstrType()` and `vRhsInstr.getInstrType()` before `isSameType(vLhsType, vRhsType)`. By doing so we attempt to coerce the types of both instructions if one is a pointer and another is an integer, else do nothing * DGen - When emitting for `PointerDereferenceAssignmentInstruction` we didn't wrap `<expr>` with `()`. So instead of `*(<expre>)` we got `*<expr>` which doesn't work if you're doing pointer arithmetic * Test cases - Added `simple_pointer_cast.t` to test casting (currently broken parsing-wise) DGen - Added a todo for semantic tests for the `simple_pointer_cast.t` test case * Parser - Added a TODO - we need a `parseType()` * Test cases - Removed `simple_cast_complex_type.t` as it is wrong, syntax wise * Test cases - Removed coercion usage, I am only testing the casting here (explicit) * Test cases - Removed `simple_pointer_cast.t` and replace it with `simple_pointer_cast_le.t` which casts the integer pointer to a byte pointer and sets the lowest significant byte (little endian hence at base of integer) to `2+2` DGen - Added semantic test for `simple_pointer_cast_le.t` * Test cases - Update `simple_pointer_cast_le.t` to do some pointer airthmetic at the byte-level of the 32-bit integer DGen - Updated the semantic test code generation for `simple_pointer_cast_le.t` to check for new values * Added 'simple_pointer_cast_le.t' to Emit tests * TypeChecker - Update `isSameType(Type t1, Type t2)` to now handle pointers explicitly and in a recursive manner based on their referred types - This check occurs before the `Integer` type check therefore following the rule of most specific types to least * Test cases - Added new test case `simple_pointer_malloc.t` - Added semantic code test generation for `simple_pointer_malloc.t` - Added `malloc_test.sh` to compile and generate `mem.o` from `mem.c` to link it then with `simple_pointer_malloc.t` - Added `mem.c` external C file to generate the required `mem.o` for linking against `simple_pointer_malloc.t` * Test cases - Updated `malloc_test.sh` to look for any `brk()` system calls and fixed its interpreter path
2023-04-17 15:50:11 +01:00
return 0;
}`);
}
else if(cmp(typeChecker.getModule().getName(), "simple_pointer_cast_le") == 0)
{
file.writeln(`
#include<stdio.h>
#include<assert.h>
int main()
{
int retValue = thing();
assert(t_e159019f766be1a175186a13f16bcfb7 == 256+4);
assert(retValue == 256+4+2);
return 0;
}`);
}
else if(cmp(typeChecker.getModule().getName(), "simple_pointer_malloc") == 0)
{
file.writeln(`
#include<stdio.h>
#include<assert.h>
int main()
{
test();
// TODO: Test the value
Check - Added new symbol types `EXTERN`, `EXTERN_EFUNC` and `EXTERN_EVAR` and related back-mappings Parser - `parseFuncDef()` now accepts a default argument (set to `true`) on whether to expect a body for a function or not, in the not case expect a semi-colon - this helps with extern support - Likewise because `parseFuncDef(bool wantsBody = true)` is called by `parseTypedDeclaration()` we have added same argument to `parseTypedDeclaration(bool wantsBody = true)` - Ensure we pass the parameter from `parseTypedDeclaration()` into `parseFuncDef(bool)` in function definition case - Implemented `parseExtern()` for extern support - `parse()` supports `SymbolType.EXTERN` now Data - Added `ExternStmt` to represent the parser node derived from a call to `parseExtern()` - The `Entity` parser node type now has an `isExternal()` flag to know if the entity is marked for `extern` link time or TLang internal time (default) Typechecker - Implemented `processPseudoEntities(Container)` which loops through the given container and finds all extern statements and then extracts those nodes, parents them to the given container and marks them as external (pseudo-handling support) - Added first call inside `beginCheck()` to be a call to `processPseudoEntities(modulle)` Dependency - Added useless no-op check for `ExternStmt` - it does nothing DGen - In `emitFunctionSignature()`, prepend the string `extern ` to the signatur if the given `Function` entity is marked as external (`isExternal()` is true) - In `emitFunctionDefinitions()` do not emit a function body at all (or anything, no signature) if the `Function` is marked as external (`isExternal()` is true) - Added entry point test for `simple_extern.t`
2023-01-15 18:48:40 +00:00
return 0;
}`);
}
else if(cmp(typeChecker.getModule().getName(), "simple_extern") == 0)
{
file.writeln(`
#include<stdio.h>
#include<assert.h>
int main()
{
test();
return 0;
}`);
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`
2022-12-19 13:37:55 +00:00
}
else
{
file.writeln(`
int main()
{
return 0;
}
`);
}
}
public override void finalize()
{
try
{
//NOTE: Change to system compiler (maybe, we need to choose a good C compiler)
string[] compileArgs = ["clang", "-o", "tlang.out", file.name()];
// Check for object files to be linked in
string[] objectFilesLink;
if(config.hasConfig("linker:link_files"))
{
objectFilesLink = config.getConfig("linker:link_files").getArray();
gprintln("Object files to be linked in: "~to!(string)(objectFilesLink));
}
else
{
gprintln("No files to link in");
}
Pid ccPID = spawnProcess(compileArgs~objectFilesLink);
int code = wait(ccPID);
if(code)
{
//NOTE: Make this a TLang exception
throw new Exception("The CC exited with a non-zero exit code ("~to!(string)(code)~")");
}
}
catch(ProcessException e)
{
gprintln("NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?", DebugType.ERROR);
assert(false);
}
}
2021-11-02 08:41:03 +00:00
}