diff --git a/README.md b/README.md index 63b47a4..8cc019c 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,16 @@ tlang Official Tristan Language project compiler -## Docs +## Documentation -Docs are available [here](http://deavmi.assigned.network/secret/tlang). +Docs are available [here](http://deavmi.assigned.network/projects/tlang/). ## Building To build you will need `dmd` and `dub` installed. You can then run the following: ``` -dub test +dub test --coverage dub build ``` diff --git a/source/tlang/app.d b/source/tlang/app.d index 1d6059d..91d3942 100644 --- a/source/tlang/app.d +++ b/source/tlang/app.d @@ -1,11 +1,9 @@ /** -* Tristan's programming language -* -* This is TOP SECRET code, not for RELEASE! -* Violators WILL BE PUT UP AGAINST A WALL AND -* SHOT! -*/ - + * TLP reference compiler + * + * This is the entry point for the TLP + * reference compiler. + */ module tlang; import std.stdio; @@ -14,7 +12,7 @@ import commandline.args; void main(string[] args) { /* TODO: Replace with something else */ - writeln("tlang NO_PUBLISH_RELEASE"); + writeln("tlang NO_PUBLISH_RELEASE\n"); /* Parse the command-line arguments */ parseCommandLine(args); diff --git a/source/tlang/commandline/commands.d b/source/tlang/commandline/commands.d index aff42d4..8cda5e3 100644 --- a/source/tlang/commandline/commands.d +++ b/source/tlang/commandline/commands.d @@ -1,8 +1,8 @@ /** -* Commands -* -* All command-line arguments and their impementations -*/ + * Commands + * + * All command-line arguments and their impementations + */ module commandline.commands; @@ -10,19 +10,11 @@ import jcli; import std.stdio; import compiler.compiler : beginCompilation; import std.exception : ErrnoException; -import compiler.lexer : Lexer; +import compiler.lexer : Lexer, Token; +import compiler.parsing.core : Parser; +import compiler.typecheck.core : TypeChecker; -// import jcli.cli; - -@Command("help", "Shows the help screen") -struct helpCommand -{ - /* TODO: Add missing implementation for this */ - void onExecute() - { - - } -} +//TODO: Re-order the definitions below so that they appear with compile first, then lex, parse, ..., help /** * Compile the given source file from start to finish @@ -40,11 +32,6 @@ struct compileCommand void onExecute() { writeln("Compiling source file: "~sourceFile); - - /* TODO: Read file */ - string sourceCode = ""; - - beginCompilation([sourceFile]); } } @@ -55,7 +42,7 @@ struct compileCommand @Command("lex", "Performs tokenization of the given file(s)") struct lexCommand { - @ArgPositional("source file", "The source file to compile") + @ArgPositional("source file", "The source file to lex") string sourceFile; void onExecute() @@ -72,6 +59,7 @@ struct lexCommand data.length = fSize; data = file.rawRead(data); string sourceText = cast(string)data; + file.close(); /* Begin lexing process */ Lexer lexer = new Lexer(sourceText); @@ -92,4 +80,175 @@ struct lexCommand writeln("Could not open source file "~sourceFile); } } +} + +@Command("syntaxcheck", "Check the syntax of the program") +struct parseCommand +{ + @ArgPositional("source file", "The source file to check syntax of") + string sourceFile; + + /* TODO: Add missing implementation for this */ + void onExecute() + { + // TODO: Add call to typechecker here + + try + { + /* Read the source file's data */ + File file; + file.open(sourceFile, "r"); + ulong fSize = file.size(); + byte[] data; + data.length = fSize; + data = file.rawRead(data); + string sourceText = cast(string)data; + file.close(); + + /* Begin lexing process */ + Lexer lexer = new Lexer(sourceText); + if(lexer.performLex()) + { + Token[] tokens = lexer.getTokens(); + writeln("=== Tokens ===\n"); + writeln(tokens); + + // TODO: Catch exception + Parser parser = new Parser(tokens); + // TODO: Do something with the returned module + auto modulel = parser.parse(); + } + else + { + /* TODO: Is the lexer.performLex() return value used? */ + writeln("There was an error whilst performing tokenization"); + } + } + catch(ErrnoException e) + { + /* TODO: Use gogga error */ + writeln("Could not open source file "~sourceFile); + } + } +} + +@Command("typecheck", "Perform typechecking on the program") +struct typecheckCommand +{ + @ArgPositional("source file", "The source file to typecheck") + string sourceFile; + + /* TODO: Add missing implementation for this */ + void onExecute() + { + // TODO: Add call to typechecker here + try + { + /* Read the source file's data */ + File file; + file.open(sourceFile, "r"); + ulong fSize = file.size(); + byte[] data; + data.length = fSize; + data = file.rawRead(data); + string sourceText = cast(string)data; + file.close(); + + /* Begin lexing process */ + Lexer lexer = new Lexer(sourceText); + if(lexer.performLex()) + { + Token[] tokens = lexer.getTokens(); + writeln("=== Tokens ===\n"); + writeln(tokens); + + // TODO: Catch exception + Parser parser = new Parser(tokens); + // TODO: Do something with the returned module + auto modulel = parser.parse(); + + //TODO: collect results here + //TODO: catch exceptions + TypeChecker typeChecker = new TypeChecker(modulel); + typeChecker.beginCheck(); + } + else + { + /* TODO: Is the lexer.performLex() return value used? */ + writeln("There was an error whilst performing tokenization"); + } + } + catch(ErrnoException e) + { + /* TODO: Use gogga error */ + writeln("Could not open source file "~sourceFile); + } + } +} + +// @Command("emit", "Perform emitting on the program") +// struct emitCommand +// { +// @ArgPositional("source file", "The source file to emit") +// string sourceFile; + +// /* TODO: Add missing implementation for this */ +// void onExecute() +// { +// // TODO: Add call to typechecker here +// try +// { +// /* Read the source file's data */ +// File file; +// file.open(sourceFile, "r"); +// ulong fSize = file.size(); +// byte[] data; +// data.length = fSize; +// data = file.rawRead(data); +// string sourceText = cast(string)data; +// file.close(); + +// /* Begin lexing process */ +// Lexer lexer = new Lexer(sourceText); +// if(lexer.performLex()) +// { +// Token[] tokens = lexer.getTokens(); +// writeln("=== Tokens ===\n"); +// writeln(tokens); + +// // TODO: Catch exception +// Parser parser = new Parser(tokens); +// // TODO: Do something with the returned module +// auto modulel = parser.parse(); + +// //TODO: collect results here +// //TODO: catch exceptions +// TypeChecker typeChecker = new TypeChecker(modulel); +// typeChecker.beginCheck(); + +// //TODO: emit is basically full cpmpile or nah? we should write emit to stdout actually +// //or nah? +// } +// else +// { +// /* TODO: Is the lexer.performLex() return value used? */ +// writeln("There was an error whilst performing tokenization"); +// } +// } +// catch(ErrnoException e) +// { +// /* TODO: Use gogga error */ +// writeln("Could not open source file "~sourceFile); +// } +// } +// } + +@Command("help", "Shows the help screen") +struct helpCommand +{ + /* TODO: Add missing implementation for this */ + void onExecute() + { + /* TODO: We want to show the commands list, not a seperate help command */ + } } \ No newline at end of file diff --git a/source/tlang/compiler/codegen/emit/core.d b/source/tlang/compiler/codegen/emit/core.d index e8bc1b6..0d2e408 100644 --- a/source/tlang/compiler/codegen/emit/core.d +++ b/source/tlang/compiler/codegen/emit/core.d @@ -8,6 +8,8 @@ import std.stdio; import std.file; import compiler.codegen.instruction : Instruction; import std.range : walkLength; +import gogga; +import std.conv : to; /** * TODO: Perhaps have an interface that can emit(Context/Parent, Statement) @@ -19,65 +21,157 @@ public abstract class CodeEmitter { protected TypeChecker typeChecker; + /** + * The selected queue is the queue to be used + * when using the cursor instructions such as + * `nextInstruction()`, `previousInstruction()` + * etc. + */ + private Instruction[] selectedQueue; + + public enum QueueType + { + ALLOC_QUEUE, + GLOBALS_QUEUE, + FUNCTION_DEF_QUEUE + } + + private ulong queueCursor = 0; + + public final void selectQueue(QueueType queueType, string funcDefName = "") + { + // Move the cursor back to the starting position + resetCursor(); + + if(queueType == QueueType.ALLOC_QUEUE) + { + selectedQueue = initQueue; + } + else if(queueType == QueueType.GLOBALS_QUEUE) + { + selectedQueue = globalCodeQueue; + } + else + { + //TODO: Ensure valid name by lookup via tc + + selectedQueue = functionBodyInstrs[funcDefName]; + } + } + + public final void resetCursor() + { + queueCursor = 0; + } + + public final void nextInstruction() + { + // TODO: Sanity check on length + + queueCursor++; + } + + public final void previousInstruction() + { + // TODO: Sanity check on lenght + + queueCursor--; + } + + public final bool hasInstructions() + { + return queueCursor < selectedQueue.length; + } + + public final Instruction getCurrentInstruction() + { + return selectedQueue[queueCursor]; + } + + /** * Required queues */ private Instruction[] initQueue; - private Instruction[] codeQueue; + private Instruction[] globalCodeQueue; + + /** + * Required queues (maps to them) + */ + private Instruction[][string] functionBodyInstrs; - // alias instructions = codeQueue; protected File file; - - private ulong codeQueueIdx = 0; - - - public final Instruction getCurrentCodeInstruction() + public final ulong getQueueLength() { - return codeQueue[codeQueueIdx]; - } - - public final bool hasCodeInstructions() - { - return codeQueueIdx < codeQueue.length; - } - - public final void nextCodeInstruction() - { - codeQueueIdx++; - } - - public final void previousCodeInstruction() - { - codeQueueIdx--; + return selectedQueue.length; } - public final ulong getInitQueueLen() + + + + + + public final string[] getFunctionDefinitionNames() { - return initQueue.length; + return functionBodyInstrs.keys(); } - public final ulong getCodeQueueLen() + /** + * TODO: Make some sort of like cursor object here that lets you move for function + * or actually just have a function cuirsor + */ + private ulong globalCurrentFunctionDefintionCodeQueueIdx = 0; + private string currentFunctionDefinitionName; + + /** + * Moves thr cursor (for the CFDCQ) back to the starting + * position (zero) + */ + public final void resetCFDCQCursor() { - return codeQueue.length; + globalCurrentFunctionDefintionCodeQueueIdx = 0; } + public final bool hasFunctionDefinitionInstructions() + { + return globalCurrentFunctionDefintionCodeQueueIdx < functionBodyInstrs[currentFunctionDefinitionName].length; + } + + public final void nextFunctionDefinitionCode() + { + globalCurrentFunctionDefintionCodeQueueIdx++; + } + + public final void previousFunctionDefinitionCode() + { + globalCurrentFunctionDefintionCodeQueueIdx--; + } + + public final Instruction getCurrentFunctionDefinitionInstruction() + { + return functionBodyInstrs[currentFunctionDefinitionName][globalCurrentFunctionDefintionCodeQueueIdx]; + } + + public final void setCurrentFunctionDefinition(string functionDefinitionName) + { + currentFunctionDefinitionName = functionDefinitionName; + } + this(TypeChecker typeChecker, File file) { this.typeChecker = typeChecker; /* Extract the allocation queue, the code queue */ - foreach(Instruction currentInstruction; typeChecker.getInitQueue()) - { - initQueue~=currentInstruction; - } - foreach(Instruction currentInstruction; typeChecker.getCodeQueue()) - { - codeQueue~=currentInstruction; - } + initQueue = typeChecker.getInitQueue(); + globalCodeQueue = typeChecker.getGlobalCodeQueue(); + + /* Extract the function definitions string-queue mapping */ + functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues(); + gprintln("CodeEmitter: Got number of function defs: "~to!(string)(functionBodyInstrs)); this.file = file; } diff --git a/source/tlang/compiler/codegen/emit/dgen.d b/source/tlang/compiler/codegen/emit/dgen.d index 725a1dc..c34ac88 100644 --- a/source/tlang/compiler/codegen/emit/dgen.d +++ b/source/tlang/compiler/codegen/emit/dgen.d @@ -12,17 +12,14 @@ import gogga; import std.range : walkLength; import std.string : wrap; import std.process : spawnProcess, Pid, ProcessException, wait; -import compiler.typecheck.dependency.core : Context; +import compiler.typecheck.dependency.core : Context, FunctionData, DNode; import compiler.codegen.mapper : SymbolMapper; -import compiler.symbols.data : SymbolType, Variable; +import compiler.symbols.data : SymbolType, Variable, Function; import compiler.symbols.check : getCharacter; import misc.utils : Stack; public final class DCodeEmitter : CodeEmitter -{ - private Stack!(Instruction) varAssStack; - - +{ // Set to true when processing a variable declaration // which expects an assignment. Set to false when // said variable assignment has been processed @@ -32,12 +29,12 @@ public final class DCodeEmitter : CodeEmitter this(TypeChecker typeChecker, File file) { super(typeChecker, file); - - varAssStack = new Stack!(Instruction)(); } public override string transform(const Instruction instruction) { + gprintln("transform(): "~to!(string)(instruction)); + /* VariableAssignmentInstr */ if(cast(VariableAssignmentInstr)instruction) { @@ -92,8 +89,8 @@ public final class DCodeEmitter : CodeEmitter varDecWantsConsumeVarAss = true; // Fetch the variable assignment instruction - nextCodeInstruction(); - Instruction varAssInstr = getCurrentCodeInstruction(); + nextInstruction(); + Instruction varAssInstr = getCurrentInstruction(); // Generate the code to emit return varDecInstr.varType~" "~renamedSymbol~" = "~transform(varAssInstr)~";"; @@ -140,12 +137,17 @@ public final class DCodeEmitter : CodeEmitter // 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 - gprintln("Static allocations needed: "~to!(string)(getInitQueueLen())); emitStaticAllocations(); - gprintln("Code emittings needed: "~to!(string)(getCodeQueueLen())); + gprintln("Function definitions needed: "~to!(string)(1)); //TODO: fix counter here + emitFunctionDefinitions(); + + gprintln("\n\n\n"); + emitCodeQueue(); + gprintln("\n\n\n"); + //TODO: Emit function definitions //TODO: Emit main (entry point) @@ -190,17 +192,109 @@ public final class DCodeEmitter : CodeEmitter */ private void emitStaticAllocations() { + selectQueue(QueueType.ALLOC_QUEUE); + gprintln("Static allocations needed: "~to!(string)(getQueueLength())); + } + /** + * TOOD: We should have an nextInstruction() esque thing for this + */ + private void emitFunctionDefinitions() + { + Instruction[][string] functionBodyInstrs = typeChecker.getFunctionBodyCodeQueues(); + + string[] functionNames = getFunctionDefinitionNames(); + + gprintln("WOAH: "~to!(string)(functionNames)); + + foreach(string currentFunctioName; functionNames) + { + emitFunctionDefinition(currentFunctioName); + } + + + } + + private string generateSignature(Function func) + { + string signature; + + // ( + signature = func.getType()~" "~func.getName()~"("; + + // Generate parameter list + if(func.hasParams()) + { + Variable[] parameters = func.getParams(); + string parameterString; + + for(ulong parIdx = 0; parIdx < parameters.length; parIdx++) + { + Variable currentParameter = parameters[parIdx]; + parameterString~=currentParameter.getType()~" "~currentParameter.getName(); + + if(parIdx != (parameters.length-1)) + { + parameterString~=", "; + } + } + + signature~=parameterString; + } + + // ) + signature~=")"; + + return signature; + + } + + private void emitFunctionDefinition(string functionName) + { + // // Reset the cursor + // resetCFDCQCursor(); + + // // Set the function we want to examine in CodeEmitter + // setCurrentFunctionDefinition(functionName); + selectQueue(QueueType.FUNCTION_DEF_QUEUE, functionName); + + //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)); + + // Emit opening curly brace + file.writeln(getCharacter(SymbolType.OCURLY)); + + // Emit body + while(hasInstructions()) + { + Instruction curFuncBodyInstr = getCurrentInstruction(); + + string emit = transform(curFuncBodyInstr); + gprintln("emitFunctionDefinition("~functionName~"): Emit: "~emit); + file.writeln("\t"~emit); + + nextInstruction(); + } + + // Emit closing curly brace + file.writeln(getCharacter(SymbolType.CCURLY)); } private void emitCodeQueue() { - while(hasCodeInstructions()) + selectQueue(QueueType.GLOBALS_QUEUE); + gprintln("Code emittings needed: "~to!(string)(getQueueLength())); + + while(hasInstructions()) { - Instruction currentInstruction = getCurrentCodeInstruction(); + Instruction currentInstruction = getCurrentInstruction(); file.writeln(transform(currentInstruction)); - nextCodeInstruction(); + nextInstruction(); } } diff --git a/source/tlang/compiler/codegen/mapper.d b/source/tlang/compiler/codegen/mapper.d index 784b7ff..730d515 100644 --- a/source/tlang/compiler/codegen/mapper.d +++ b/source/tlang/compiler/codegen/mapper.d @@ -2,6 +2,8 @@ module compiler.codegen.mapper; import compiler.typecheck.core; import compiler.symbols.data; +import std.conv : to; +import gogga; /** * SymbolMapper @@ -28,6 +30,8 @@ public final class SymbolMapper auto entity = tc.getResolver().resolveBest(container, entityNameIn); //TODO: Remove `auto` string entityNameAbsolute = tc.getResolver().generateName(tc.getModule(), entity); + gprintln("symbolLookup(): "~to!(string)(container)); + // Hash the absolute path name // FIXME: Ensure these hashes are unique (use the smbyol table!) import std.digest : toHexString, LetterCase; diff --git a/source/tlang/compiler/compiler.d b/source/tlang/compiler/compiler.d index 1282ea6..a03b5ba 100644 --- a/source/tlang/compiler/compiler.d +++ b/source/tlang/compiler/compiler.d @@ -13,6 +13,12 @@ import core.stdc.stdlib; import compiler.codegen.emit.core; import compiler.codegen.emit.dgen; +/** + * Performs compilation of the provided module(s) + * + * Params: + * sourceFiles = The module(s) to perform compilation with + */ void beginCompilation(string[] sourceFiles) { /* TODO: Begin compilation process, take in data here */ diff --git a/source/tlang/compiler/parsing/exceptions.d b/source/tlang/compiler/parsing/exceptions.d index 5435d59..be2f75f 100644 --- a/source/tlang/compiler/parsing/exceptions.d +++ b/source/tlang/compiler/parsing/exceptions.d @@ -17,8 +17,6 @@ public class ParserException : TError super(message); this.parser = parser; } - - } public final class SyntaxError : ParserException @@ -30,7 +28,7 @@ public final class SyntaxError : ParserException this(Parser parser, SymbolType expected, Token providedToken) { this.expected = expected; - provided = getSymbolType(providedToken); + this.provided = getSymbolType(providedToken); this.providedToken = providedToken; super(parser, "Syntax error: Expected "~to!(string)(expected)~" but got "~to!(string)(provided)~", see "~providedToken.toString()); diff --git a/source/tlang/compiler/symbols/check.d b/source/tlang/compiler/symbols/check.d index cbe47e6..d69ed13 100644 --- a/source/tlang/compiler/symbols/check.d +++ b/source/tlang/compiler/symbols/check.d @@ -482,6 +482,14 @@ public string getCharacter(SymbolType symbolIn) { return "/"; } + else if(symbolIn == SymbolType.OCURLY) + { + return "{"; + } + else if(symbolIn == SymbolType.CCURLY) + { + return "}"; + } else { gprintln("getCharacter: No back-mapping for "~to!(string)(symbolIn), DebugType.ERROR); diff --git a/source/tlang/compiler/symbols/data.d b/source/tlang/compiler/symbols/data.d index 6dfd140..394ad49 100644 --- a/source/tlang/compiler/symbols/data.d +++ b/source/tlang/compiler/symbols/data.d @@ -253,6 +253,11 @@ public class Function : TypedEntity, Container return params; } + public bool hasParams() + { + return params.length != 0; + } + public void addStatement(Statement statement) { this.bodyStatements~=statement; diff --git a/source/tlang/compiler/typecheck/core.d b/source/tlang/compiler/typecheck/core.d index bcdf523..d1ae0ad 100644 --- a/source/tlang/compiler/typecheck/core.d +++ b/source/tlang/compiler/typecheck/core.d @@ -86,43 +86,144 @@ public final class TypeChecker gprintln(tree); - - /* Grab functionData ??? */ - FunctionData[string] functions = grabFunctionDefs(); - gprintln("Defined functions: "~to!(string)(functions)); - /* TODO: Disable, this is just to peep */ - // foreach(FunctionData funcData; functions.values) - // { - // DNode funcNode = funcData.generate(); - // DNode[] actionListFunc = funcNode.poes; - // doTypeCheck(actionListFunc); - // printTypeQueue(); - // gprintln(funcNode.print()); - // } - - /* TODO: Work in progress (NEW!!!) */ /* Get the action-list (linearised bottom up graph) */ DNode[] actionList = rootNode.poes; doTypeCheck(actionList); printTypeQueue(); - /** - * TODO: What's next? - * - * 1. Fetch the tree from the DNodeGenerator - */ + * After processing globals executions the instructions will + * be placed into `codeQueue`, therefore copy them from the temporary + * scratchpad queue into `globalCodeQueue`. + * + * Then clean the codeQueue for next use + */ + foreach(Instruction curGlobInstr; codeQueue) + { + globalCodeQueue~=curGlobInstr; + } + codeQueue.clear(); + assert(codeQueue.empty() == true); + + //FIXME: Look at this, ffs why is it static + //Clear tree/linearized version (todo comment) + DNode.poes=[]; + + /* Grab functionData ??? */ + FunctionData[string] functionDefinitions = grabFunctionDefs(); + gprintln("Defined functions: "~to!(string)(functionDefinitions)); + + foreach(FunctionData funcData; functionDefinitions.values) + { + assert(codeQueue.empty() == true); + + + DNode funcNode = funcData.generate(); + //NOTE: We need to call this, it generates tree but also does the linearization + //NOTE: Rename that + funcNode.print(); + DNode[] actionListFunc = funcNode.poes; + + //TODO: Would this not mess with our queues? + doTypeCheck(actionListFunc); + printTypeQueue(); + gprintln(funcNode.print()); + + // The current code queue would be the function's body instructions + // a.k.a. the `codeQueue` + // functionBodies[funcData.name] = codeQueue; + + + // The call to `doTypeCheck()` above adds to this queue + // so we should clean it out before the next run + // + // NOTE: Static allocations in? Well, we don't clean init queue + // so is it fine then? We now have seperate dependency trees, + // we should make checking methods that check the `initQueue` + // whenever we come past a `ClassStaticNode` for example + // codeQueue.clear(); + + /** + * Copy over the function code queue into + * the function code queue respective key. + * + * Then clear the scratchpad code queue + */ + functionBodyCodeQueues[funcData.name]=[]; + foreach(Instruction curFuncInstr; codeQueue) + { + //TODO: Think about class funcs? Nah + functionBodyCodeQueues[funcData.name]~=curFuncInstr; + gprintln("FuncDef ("~funcData.name~"): Adding body instruction: "~to!(string)(curFuncInstr)); + } + codeQueue.clear(); + + // Clear the linearization for the next round + DNode.poes=[]; + + gprintln("FUNCDEF DONE: "~to!(string)(functionBodyCodeQueues[funcData.name])); + } + + } - /* Main code queue */ - private SList!(Instruction) codeQueue; + + /** + * Function definitions + * + * Holds their action lists which are to be used for the + * (later) emitting of their X-lang emit code + */ + //FUnctionDeifnition should couple `linearizedList` but `functionEntity` + // private FunctionDefinition[string] functionDefinitions2; //TODO: Use this + + + + /** + * Concrete queues + * + * These queues below are finalized and not used as a scratchpad. + * + * 1. Global code queue + * - This accounts for the globals needing to be executed + * 2. Function body code queues + * - This accounts for (every) function definition's code queue + */ + private Instruction[] globalCodeQueue; + private Instruction[][string] functionBodyCodeQueues; + + public Instruction[] getGlobalCodeQueue() + { + return globalCodeQueue; + } + + public Instruction[][string] getFunctionBodyCodeQueues() + { + return functionBodyCodeQueues; + } + + + + + + /* Main code queue (used for temporary passes) */ + private SList!(Instruction) codeQueue; //TODO: Rename to `currentCodeQueue` /* Initialization queue */ private SList!(Instruction) initQueue; - public SList!(Instruction) getInitQueue() + + //TODO: CHange to oneshot in the function + public Instruction[] getInitQueue() { - return initQueue; + Instruction[] initQueueConcrete; + + foreach(Instruction currentInstruction; initQueue) + { + initQueueConcrete~=currentInstruction; + } + + return initQueueConcrete; } /* Adds an initialization instruction to the initialization queue (at the back) */ @@ -176,10 +277,17 @@ public final class TypeChecker return codeQueue.empty; } - public SList!(Instruction) getCodeQueue() - { - return codeQueue; - } + // public Instruction[] getCodeQueue() + // { + // Instruction[] codeQueueConcrete; + + // foreach(Instruction currentInstruction; codeQueue) + // { + // codeQueueConcrete~=currentInstruction; + // } + + // return codeQueueConcrete; + // } /* * Prints the current contents of the code-queue @@ -702,7 +810,8 @@ public final class TypeChecker /* TODO: Get the STatement */ Statement statement = dnode.getEntity(); - gprintln("Generic DNode typecheck(): Begin"); + gprintln("Generic DNode typecheck(): Begin (examine: "~to!(string)(dnode)~" )"); + /* VariableAssignmentStdAlone */ if(cast(VariableAssignmentStdAlone)statement) diff --git a/source/tlang/compiler/typecheck/dependency/core.d b/source/tlang/compiler/typecheck/dependency/core.d index 1758ae7..d934ac9 100644 --- a/source/tlang/compiler/typecheck/dependency/core.d +++ b/source/tlang/compiler/typecheck/dependency/core.d @@ -163,7 +163,8 @@ public class DNode private DNode[] dependencies; - + //TODO: Commen this + //NOTE: This is the linearized version public static DNode[] poes; this(DNodeGenerator dnodegen, Statement entity) @@ -1280,6 +1281,11 @@ public class DNodeGenerator /* TODO: CHeck avriable name even */ gprintln("YEAST ENJOYER"); + + + // FIXME: The below assert fails for function definitions trying to refer to global values + // as a reoslveBest (up) is needed. We should firstly check if within fails, if so, + // resolveBest, if that fails, then it is an error (see #46) assert(tc.getResolver().resolveWithin(c, vAsStdAl.getVariableName())); gprintln("YEAST ENJOYER"); Variable variable = cast(Variable)tc.getResolver().resolveWithin(c, vAsStdAl.getVariableName()); diff --git a/source/tlang/testing/simple_function_decls.t b/source/tlang/testing/simple_function_decls.t new file mode 100644 index 0000000..e8ec7f4 --- /dev/null +++ b/source/tlang/testing/simple_function_decls.t @@ -0,0 +1,15 @@ +module simple_function_decls; + +int j = 21; +int k = 22; + +int apple(int j) +{ + int h = 69; +} + +int banana(int j) +{ + int h = 64; + k=1; +} \ No newline at end of file diff --git a/source/tlang/testing/simple_variables.t b/source/tlang/testing/simple_variables.t index 1edb22a..4f60b36 100644 --- a/source/tlang/testing/simple_variables.t +++ b/source/tlang/testing/simple_variables.t @@ -3,7 +3,7 @@ module simple_variables_decls_ass; int x = 1+2*2/1-6; -discard "TDOO: Technically also not allowed (not compile-time constant in C)" +discard "TDOO: Technically also not allowed (not compile-time constant in C)"; int y = 2+x; discard "TODO: Technically the below should not be allowed as we cannot do it in C - sadly";