diff --git a/source/tlang/compiler/codegen/emit/core.d b/source/tlang/compiler/codegen/emit/core.d index d2e486f7..e8bc1b65 100644 --- a/source/tlang/compiler/codegen/emit/core.d +++ b/source/tlang/compiler/codegen/emit/core.d @@ -7,6 +7,7 @@ import compiler.codegen.instruction; import std.stdio; import std.file; import compiler.codegen.instruction : Instruction; +import std.range : walkLength; /** * TODO: Perhaps have an interface that can emit(Context/Parent, Statement) @@ -21,37 +22,63 @@ public abstract class CodeEmitter /** * Required queues */ - protected SList!(Instruction) initQueue; - protected SList!(Instruction) codeQueue; + private Instruction[] initQueue; + private Instruction[] codeQueue; - alias instructions = codeQueue; + // alias instructions = codeQueue; protected File file; - protected string currentEmitBuildUp; + private ulong codeQueueIdx = 0; - public void buildEmit(string data) + + public final Instruction getCurrentCodeInstruction() { - currentEmitBuildUp~=data; + return codeQueue[codeQueueIdx]; } - public void flushEmit() + public final bool hasCodeInstructions() { - file.writeln(currentEmitBuildUp); - currentEmitBuildUp = ""; + return codeQueueIdx < codeQueue.length; } + public final void nextCodeInstruction() + { + codeQueueIdx++; + } + + public final void previousCodeInstruction() + { + codeQueueIdx--; + } + + + public final ulong getInitQueueLen() + { + return initQueue.length; + } + + public final ulong getCodeQueueLen() + { + return codeQueue.length; + } + + this(TypeChecker typeChecker, File file) { this.typeChecker = typeChecker; /* Extract the allocation queue, the code queue */ - initQueue = typeChecker.getInitQueue(); - codeQueue = typeChecker.getCodeQueue(); + foreach(Instruction currentInstruction; typeChecker.getInitQueue()) + { + initQueue~=currentInstruction; + } + foreach(Instruction currentInstruction; typeChecker.getCodeQueue()) + { + codeQueue~=currentInstruction; + } - - this.file = file; } diff --git a/source/tlang/compiler/codegen/emit/dgen.d b/source/tlang/compiler/codegen/emit/dgen.d index 0b6e8320..c3e11621 100644 --- a/source/tlang/compiler/codegen/emit/dgen.d +++ b/source/tlang/compiler/codegen/emit/dgen.d @@ -23,7 +23,10 @@ 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 + private bool varDecWantsConsumeVarAss = false; this(TypeChecker typeChecker, File file) @@ -42,22 +45,24 @@ public final class DCodeEmitter : CodeEmitter Context context = varAs.getContext(); gprintln("Is ContextNull?: "~to!(string)(context is null)); - Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto` + auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto` string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable); import compiler.codegen.mapper : SymbolMapper; string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), typedEntityVariableName); - /* TODO: Add check for variable assigmen tto here */ - if(typedEntityVariable.getAssignment()) + + // If we are needed as part of a VariabvleDeclaration-with-assignment + if(varDecWantsConsumeVarAss) { - //TODO: Set a field here that gets checked for VariableDeclaration instruction - //to return only RHS (and not assignment with variable) - //It will then reset said bit - //TODO: We will also then need a peak (cursor rather than an iterator I think) - //and in such case the VariableDeclaration branch (under that bit set - once again) - //must then progress the cursor (such that we skip it next time) + // Generate the code to emit (only the RHS of the = sign) + string emitCode = transform(varAs.data); + + // Reset flag + varDecWantsConsumeVarAss = false; + + return emitCode; } @@ -69,7 +74,7 @@ public final class DCodeEmitter : CodeEmitter VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction; Context context = varDecInstr.getContext(); - auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto` + Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto` string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable); //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 @@ -88,6 +93,31 @@ public final class DCodeEmitter : CodeEmitter /* TODO: I like the hold technique */ + /* TODO: Add check for variable assigmen tto here */ + if(typedEntityVariable.getAssignment()) + { + //TODO: Set a field here that gets checked for VariableDeclaration instruction + //to return only RHS (and not assignment with variable) + //It will then reset said bit + //TODO: We will also then need a peak (cursor rather than an iterator I think) + //and in such case the VariableDeclaration branch (under that bit set - once again) + //must then progress the cursor (such that we skip it next time) + varDecWantsConsumeVarAss = true; + + // Fetch the variable assignment instruction + nextCodeInstruction(); + Instruction varAssInstr = getCurrentCodeInstruction(); + + // Generate the code to emit + string emit = varDecInstr.varType~" "~renamedSymbol~" = "~transform(varAssInstr)~";"; + + + + + + return emit; + } + return varDecInstr.varType~" "~renamedSymbol~";"; @@ -115,11 +145,11 @@ 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)(walkLength(initQueue[]))); - emitStaticAllocations(initQueue); + gprintln("Static allocations needed: "~to!(string)(getInitQueueLen())); + emitStaticAllocations(); - gprintln("Code emittings needed: "~to!(string)(walkLength(codeQueue[]))); - emitCodeQueue(codeQueue); + gprintln("Code emittings needed: "~to!(string)(getCodeQueueLen())); + emitCodeQueue(); //TODO: Emit function definitions @@ -163,21 +193,19 @@ public final class DCodeEmitter : CodeEmitter * Params: * initQueue = The allocation queue to emit static allocations from */ - private void emitStaticAllocations(SList!(Instruction) initQueue) + private void emitStaticAllocations() { } - private void emitCodeQueue(SList!(Instruction) codeQueue) + private void emitCodeQueue() { - //TODO: Implement me - //NOTE: I think that every `Instruction` will need an `emit()` method - //of which sometimes can be recursive for instructions that are nested - - foreach(Instruction currentInstruction; codeQueue) + while(hasCodeInstructions()) { - // file.writeln(currentInstruction.emit()); + Instruction currentInstruction = getCurrentCodeInstruction(); file.writeln(transform(currentInstruction)); + + nextCodeInstruction(); } } diff --git a/source/tlang/testing/simple_variables.t b/source/tlang/testing/simple_variables.t index 617dd303..b9f58702 100644 --- a/source/tlang/testing/simple_variables.t +++ b/source/tlang/testing/simple_variables.t @@ -1,5 +1,5 @@ module simple_variables; -int x = 1+2; +int x = 1+2+2+1; int y = 2; \ No newline at end of file