- 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)
This commit is contained in:
Tristan B. Velloza Kildaire 2023-01-19 21:06:20 +02:00
parent a772b55966
commit a987f114ac
3 changed files with 79 additions and 28 deletions

View File

@ -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;
}
/**

View File

@ -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();
}
}
/**

View File

@ -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_<x>.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]);
// }
}