From b0d9d2aabe0f6c37b36a8ff1404b86a83a350db8 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Mon, 12 Dec 2022 15:36:07 +0200 Subject: [PATCH] Instruction - Removed all `emit()` methods (this is now done in the language-specific emitter - DGen) CoreEmitter - Added docstrings - Added required `transform(Instruction)` method which must transform each provided Instruction into a string (a.k.a. do the actual emit()-ting) DGen - Migrated C-emit code into the overrided `transform(Instruction)` method --- source/tlang/compiler/codegen/emit/core.d | 18 ++++ source/tlang/compiler/codegen/emit/dgen.d | 105 +++++++++++++++++--- source/tlang/compiler/codegen/instruction.d | 70 +------------ 3 files changed, 111 insertions(+), 82 deletions(-) diff --git a/source/tlang/compiler/codegen/emit/core.d b/source/tlang/compiler/codegen/emit/core.d index 4a3e1d57..13220303 100644 --- a/source/tlang/compiler/codegen/emit/core.d +++ b/source/tlang/compiler/codegen/emit/core.d @@ -6,6 +6,7 @@ import std.container.slist : SList; import compiler.codegen.instruction; import std.stdio; import std.file; +import compiler.codegen.instruction : Instruction; /** * TODO: Perhaps have an interface that can emit(Context/Parent, Statement) @@ -40,7 +41,24 @@ public abstract class CodeEmitter this.file = file; } + /** + * Begins the emit process + */ public abstract void emit(); + /** + * Finalizes the emitting process (only + * to be called after the `emit()` finishes) + */ public abstract void finalize(); + + /** + * Transforms or emits a single Instruction + * and returns the transformation + * + * Params: + * instruction = The Instruction to transform/emit + * Returns: The Instruction emit as a string + */ + public abstract string transform(Instruction instruction); } \ No newline at end of file diff --git a/source/tlang/compiler/codegen/emit/dgen.d b/source/tlang/compiler/codegen/emit/dgen.d index 763b8ed0..2f2f2255 100644 --- a/source/tlang/compiler/codegen/emit/dgen.d +++ b/source/tlang/compiler/codegen/emit/dgen.d @@ -12,6 +12,10 @@ 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.codegen.mapper : SymbolMapper; +import compiler.symbols.data : SymbolType; +import compiler.symbols.check : getCharacter; public final class DCodeEmitter : CodeEmitter { @@ -20,31 +24,64 @@ public final class DCodeEmitter : CodeEmitter super(typeChecker, file); } - public override void finalize() + public override string transform(const Instruction instruction) { - try + /* VariableAssignmentInstr */ + if(cast(VariableAssignmentInstr)instruction) { - //NOTE: Change to system compiler (maybe, we need to choose a good C compiler) - Pid ccPID = spawnProcess(["gcc", "-o", "tlang.out", file.name()]); + VariableAssignmentInstr varAs = cast(VariableAssignmentInstr)instruction; + Context context = varAs.getContext(); - //NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)? - int code = wait(ccPID); - gprintln(code); + gprintln("Is ContextNull?: "~to!(string)(context is null)); + auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto` + string typedEntityVariableName = context.tc.getResolver().generateName(context.getContainer(), typedEntityVariable); - if(code) - { - //NOTE: Make this a TLang exception - throw new Exception("The CC exited with a non-zero exit code"); - } + + import compiler.codegen.mapper : SymbolMapper; + string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), typedEntityVariableName); + + + return renamedSymbol~" = "~transform(varAs.data)~";"; } - catch(ProcessException e) + /* VariableDeclaration */ + else if(cast(VariableDeclaration)instruction) { - gprintln("NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)?", DebugType.ERROR); - assert(false); + VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction; + Context context = varDecInstr.getContext(); + auto typedEntityVariable = 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 + // 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 + import compiler.codegen.mapper : SymbolMapper; + string renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), varDecInstr.varName); + + return varDecInstr.varType~" "~renamedSymbol~";"; } + /* LiteralValue */ + else if(cast(LiteralValue)instruction) + { + LiteralValue literalValueInstr = cast(LiteralValue)instruction; + + return to!(string)(literalValueInstr.data); + } + /* BinOpInstr */ + else if(cast(BinOpInstr)instruction) + { + BinOpInstr binOpInstr = cast(BinOpInstr)instruction; + + return transform(binOpInstr.lhs)~to!(string)(getCharacter(binOpInstr.operator))~transform(binOpInstr.rhs); + } + return ""; } + public override void emit() { // Emit header comment (NOTE: Change this to a useful piece of text) @@ -111,7 +148,8 @@ public final class DCodeEmitter : CodeEmitter foreach(Instruction currentInstruction; codeQueue) { - file.writeln(currentInstruction.emit()); + // file.writeln(currentInstruction.emit()); + file.writeln(transform(currentInstruction)); } } @@ -125,4 +163,39 @@ int main() return 0; }`); } + + + + + + + + + + + + public override void finalize() + { + try + { + //NOTE: Change to system compiler (maybe, we need to choose a good C compiler) + Pid ccPID = spawnProcess(["gcc", "-o", "tlang.out", file.name()]); + + //NOTE: Case where it exited and Pid now inavlid (if it happens it would throw processexception surely)? + int code = wait(ccPID); + gprintln(code); + + if(code) + { + //NOTE: Make this a TLang exception + throw new Exception("The CC exited with a non-zero exit 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); + + } + } } \ No newline at end of file diff --git a/source/tlang/compiler/codegen/instruction.d b/source/tlang/compiler/codegen/instruction.d index c5310025..01ac74f1 100644 --- a/source/tlang/compiler/codegen/instruction.d +++ b/source/tlang/compiler/codegen/instruction.d @@ -8,11 +8,6 @@ import compiler.symbols.data : SymbolType; import compiler.symbols.check : getCharacter; import gogga; -/** - * TODO: We should actually remove the emits from here probably and rather do those in DGen - * as they are C specific - */ - public class Instruction { /* Context for the Instruction (used in emitter for name resolution) */ @@ -30,11 +25,6 @@ public class Instruction return "[Instruction: "~this.classinfo.name~":"~addInfo~"]"; } - public string emit() - { - return "TODO: This instruction has not provided an emit text yet! (This is an error!)"; - } - public final Context getContext() { return context; @@ -69,7 +59,7 @@ public class VariableAssignmentInstr : Instruction /* Name of variable being declared */ public string varName; /*TODO: Might not be needed */ - public Instruction data; + public const Instruction data; this(string varName, Instruction data) { @@ -78,21 +68,6 @@ public class VariableAssignmentInstr : Instruction addInfo = "assignTo: "~varName~", valInstr: "~data.toString(); } - - public override string emit() - { - gprintln("Is ContextNull?: "~to!(string)(context is null)); - auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), 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); - - - return renamedSymbol~" = "~data.emit()~";"; - // return " ; - * - * Returns: The emitted code - */ - public override string emit() - { - auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), 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 - // 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 - string renamedSymbol = symbolRename(typedEntityVariableName); - - import compiler.codegen.mapper : SymbolMapper; - renamedSymbol = SymbolMapper.symbolLookup(context.getContainer(), varName); - - return varType~" "~renamedSymbol~";"; - } } public final class FetchValueVar : Value @@ -175,11 +123,6 @@ public final class LiteralValue : Value addInfo = "Data: "~to!(string)(data)~", Length: "~to!(string)(len); } - - public override string emit() - { - return to!(string)(data); - } } public final class LiteralValueFloat : Value @@ -253,9 +196,9 @@ public final class StringLiteral : Value */ public class BinOpInstr : Value { - private Instruction lhs; - private Instruction rhs; - private SymbolType operator; + public const Instruction lhs; + public const Instruction rhs; + public const SymbolType operator; this(Instruction lhs, Instruction rhs, SymbolType operator) { @@ -265,11 +208,6 @@ public class BinOpInstr : Value addInfo = "BinOpType: "~to!(string)(operator)~", LhsValInstr: "~lhs.toString()~", RhsValInstr: "~rhs.toString(); } - - public override string emit() - { - return lhs.emit()~to!(string)(getCharacter(operator))~rhs.emit(); - } } /**