From a987f114ac411344e971f4f223ce38a557e88b40 Mon Sep 17 00:00:00 2001 From: "Tristan B. Velloza Kildaire" Date: Thu, 19 Jan 2023 21:06:20 +0200 Subject: [PATCH] Compiler - Moved configuration sub-system to its own class `CompilerConfiguration` - `getConfig()` and `setConfig()` are now templatised to generate, at compile-time, type-specific versions which will fetch and convert using the requested type - Added some more default configuration parameters for DGen DGen - Implemented configuration checking for `genTabs()` and `emitEntryPoint()` (both which have the default config value of `true`) - Added commented-out testing code (see issue #88) --- source/tlang/compiler/codegen/emit/core.d | 5 +- source/tlang/compiler/codegen/emit/dgen.d | 24 +++++-- source/tlang/compiler/compiler.d | 78 +++++++++++++++++------ 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/source/tlang/compiler/codegen/emit/core.d b/source/tlang/compiler/codegen/emit/core.d index 6ef09bc7..6016d9e3 100644 --- a/source/tlang/compiler/codegen/emit/core.d +++ b/source/tlang/compiler/codegen/emit/core.d @@ -10,6 +10,7 @@ import compiler.codegen.instruction : Instruction; import std.range : walkLength; import gogga; import std.conv : to; +import compiler.compiler : CompilerConfiguration; /** * TODO: Perhaps have an interface that can emit(Context/Parent, Statement) @@ -21,6 +22,7 @@ public abstract class CodeEmitter { protected TypeChecker typeChecker; protected File file; + protected CompilerConfiguration config; /** * The selected queue is the queue to be used @@ -125,7 +127,7 @@ public abstract class CodeEmitter return functionBodyInstrs.keys(); } - this(TypeChecker typeChecker, File file) + this(TypeChecker typeChecker, File file, CompilerConfiguration config) { this.typeChecker = typeChecker; @@ -138,6 +140,7 @@ public abstract class CodeEmitter gprintln("CodeEmitter: Got number of function defs: "~to!(string)(functionBodyInstrs)); this.file = file; + this.config = config; } /** diff --git a/source/tlang/compiler/codegen/emit/dgen.d b/source/tlang/compiler/codegen/emit/dgen.d index 0db1c31b..a6d7fba3 100644 --- a/source/tlang/compiler/codegen/emit/dgen.d +++ b/source/tlang/compiler/codegen/emit/dgen.d @@ -18,6 +18,7 @@ import compiler.symbols.data : SymbolType, Variable, Function, VariableParameter import compiler.symbols.check : getCharacter; import misc.utils : Stack; import compiler.symbols.typing.core : Type, Primitive, Integer, Void, Pointer; +import compiler.compiler : CompilerConfiguration; public final class DCodeEmitter : CodeEmitter { @@ -27,9 +28,9 @@ public final class DCodeEmitter : CodeEmitter private bool varDecWantsConsumeVarAss = false; - this(TypeChecker typeChecker, File file) + this(TypeChecker typeChecker, File file, CompilerConfiguration config) { - super(typeChecker, file); + super(typeChecker, file, config); } private ulong transformDepth = 0; @@ -37,10 +38,16 @@ public final class DCodeEmitter : CodeEmitter private string genTabs(ulong count) { string tabStr; - for(ulong i = 0; i < count; i++) + + /* Only generate tabs if enabled in compiler config */ + if(config.getConfig!(bool)("dgen:pretty_code")) { - tabStr~="\t"; + for(ulong i = 0; i < count; i++) + { + tabStr~="\t"; + } } + return tabStr; } @@ -515,8 +522,13 @@ public final class DCodeEmitter : CodeEmitter emitFunctionPrototypes(); emitFunctionDefinitions(); - //TODO: Emit main (entry point) - emitEntryPoint(); + + // If enabled (default: yes) then emit entry point (TODO: change later) + if(config.getConfig!(bool)("dgen_emit_entrypoint_test")) + { + //TODO: Emit main (entry point) + emitEntryPoint(); + } } /** diff --git a/source/tlang/compiler/compiler.d b/source/tlang/compiler/compiler.d index 126ea634..4b24f757 100644 --- a/source/tlang/compiler/compiler.d +++ b/source/tlang/compiler/compiler.d @@ -13,6 +13,30 @@ import core.stdc.stdlib; import compiler.codegen.emit.core; import compiler.codegen.emit.dgen; +public class CompilerConfiguration +{ + private string[string] config; + + public void setConfig(VType)(string key, VType value) + { + config[key] = to!(string)(value); + } + + public VType getConfig(VType)(string key) + { + import std.algorithm : canFind; + if(canFind(config.keys(), key)) + { + return to!(VType)(config[key]); + } + else + { + // TODO: Change to a TError + // throw new Exception("Key not found"); + return false; + } + } +} public class Compiler { @@ -32,33 +56,23 @@ public class Compiler private CodeEmitter emitter; private File emitOutFile; - private string[string] config; + /* The configuration */ + private CompilerConfiguration config; /* TODO: Make the default config */ private void defaultConfig() { /* Enable Behaviour-C fixes */ - setConfig("behavec:preinline_args", "true"); + config.setConfig("behavec:preinline_args", true); + + /* Enable pretty code generation for DGen */ + config.setConfig("dgen:pretty_code", true); + + /* Enable entry point test generation for DGen */ + config.setConfig("dgen_emit_entrypoint_test", true); } - public void setConfig(string key, string value) - { - config[key] = value; - } - - public string getConfig(string key) - { - import std.algorithm : canFind; - if(canFind(config.keys(), key)) - { - return config[key]; - } - else - { - // TODO: Change to a TError - throw new Exception("Key not found"); - } - } + /** * Create a new compiler instance to compile the given @@ -71,6 +85,8 @@ public class Compiler this.inputSource = sourceCode; this.emitOutFile = emitOutFile; + this.config = new CompilerConfiguration(); + /* Enable the default config */ defaultConfig(); } @@ -100,7 +116,7 @@ public class Compiler this.typeChecker.beginCheck(); /* Perform code emitting */ - this.emitter = new DCodeEmitter(typeChecker, emitOutFile); + this.emitter = new DCodeEmitter(typeChecker, emitOutFile, config); emitter.emit(); // Emit the code emitOutFile.close(); // Flush (perform the write() syscall) emitter.finalize(); // Call CC on the file containing generated C code @@ -147,4 +163,24 @@ void beginCompilation(string[] sourceFiles) /* Perform the compilation */ compiler.compile(); } +} + +unittest +{ + // TODO: Add tests here for our `simple_.t` tests or put them in DGen, I think here is better + // FIXME: Crashes and I think because too fast or actually bad state? Maybe something is not being + // cleared, I believe this may be what is happening + // ... see issue #88 + // string[] testFiles = ["source/tlang/testing/simple_functions.t", + // "source/tlang/testing/simple_while.t", + // "source/tlang/testing/simple_for_loops.t", + // "source/tlang/testing/simple_cast.t", + // "source/tlang/testing/simple_conditionals.t", + // "source/tlang/testing/nested_conditionals.t", + // "source/tlang/testing/simple_discard.t" + // ]; + // foreach(string testFile; testFiles) + // { + // beginCompilation([testFile]); + // } } \ No newline at end of file