- Compiler flag name change
- Comment formatting

Compiler

- Implemented `getConfig()` in order to return the `Compiler` object's `CompilerConfiguration` instance
- Updated a configuration parameters name in the `defaultConfig()`
- Added some work-in-progress data structures `ConfigObject` and `ConfigList`

Command-line

- Added a plethorah of new flags and re-worked a lot of the common flags across the multiple commands to use mixins to avoid code duplication and enforce code re-use
- The compilation command now uses the `Compiler` object
- You can now control the symbol mapper used
- You can now set the verbosity level (no-oped currently)
- You can set the output filename
- You can set whether pretty code is to be used or not
- You can set whether or not to generate the entrypoint testing code during emit
This commit is contained in:
Tristan B. Velloza Kildaire 2023-01-24 19:57:27 +02:00
parent 1f6e9cbbb6
commit 3f84020e22
3 changed files with 154 additions and 72 deletions

View File

@ -16,29 +16,143 @@ import compiler.parsing.core : Parser;
import compiler.typecheck.core : TypeChecker;
import gogga;
import compiler.compiler : Compiler;
import std.conv : to;
//TODO: Re-order the definitions below so that they appear with compile first, then lex, parse, ..., help
public enum SymbolMappingTechnique
{
hashmapper,
lebanese
}
public enum VerbosityLevel
{
info,
warning,
error,
debugg
}
// TODO: Add base command as verbosity is something we will always want to control
// TODO: Try get inheritane working as we may be able to set things then
// Stuff that all commands need
mixin template BaseCommand()
{
@ArgPositional("source file", "The source file to compile")
string sourceFile;
@ArgNamed("verbose|v", "Verbosity level")
VerbosityLevel debugLevel;
void BaseCommandInit(Compiler compiler)
{
// Set the verbosity level
compiler.getConfig().setConfig("verbosity", debugLevel);
}
}
/**
* Base requirements for Emit+
*/
mixin template EmitBase()
{
@ArgGroup("Emit", "Options pertaining to the code emitter")
{
@ArgNamed("symbol-mapper|sm", "The symbol mapping technique to use")
@(ArgExistence.optional)
SymbolMappingTechnique symbolTechnique;
@ArgNamed("prettygen|pg", "Generate pretty-printed code")
@(ArgExistence.optional)
bool prettyPrintCodeGen;
@ArgNamed("output|o", "Filename of generated object file")
@(ArgExistence.optional)
string outputFilename = "tlangout.c";
@ArgNamed("entrypointTest|et", "Whether or not to emit entrypoint testing code")
@(ArgExistence.optional)
bool entrypointTestEmit = true; // TODO: Change this later to `false` of course
}
void EmitBaseInit(Compiler compiler)
{
// Set the symbol mapper technique
compiler.getConfig().setConfig("emit:mapper", symbolTechnique);
// Set whether pretty-printed code should be generated
compiler.getConfig().setConfig("dgen:pretty_code", prettyPrintCodeGen);
// Set whether or not to enable the entry point testing code
compiler.getConfig().setConfig("dgen:emit_entrypoint_test", entrypointTestEmit);
}
}
/**
* Compile the given source file from start to finish
*/
@Command("compile", "Compiles the given file(s)")
struct compileCommand
{
@ArgPositional("source file", "The source file to compile")
string sourceFile;
mixin BaseCommand!();
mixin EmitBase!();
void onExecute()
{
writeln("Compiling source file: "~sourceFile);
try
{
beginCompilation([sourceFile]);
/* 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 */
File outFile;
outFile.open(outputFilename, "w");
Compiler compiler = new Compiler(sourceText, outFile);
/* Setup general configuration parameters */
BaseCommandInit(compiler);
/* Perform tokenization */
compiler.doLex();
writeln("=== Tokens ===\n");
writeln(compiler.getTokens());
/* Perform parsing */
compiler.doParse();
// TODO: Do something with the returned module
auto modulel = compiler.getModule();
/* Perform typechecking/codegen */
compiler.doTypeCheck();
/**
* Configure the emitter and then perform code emit
*/
EmitBaseInit(compiler);
compiler.doEmit();
}
catch(TError t)
{
gprintln(t.msg, DebugType.ERROR);
}
catch(ErrnoException e)
{
/* TODO: Use gogga error */
writeln("Could not open source file "~sourceFile);
}
}
}
@ -48,8 +162,7 @@ struct compileCommand
@Command("lex", "Performs tokenization of the given file(s)")
struct lexCommand
{
@ArgPositional("source file", "The source file to lex")
string sourceFile;
mixin BaseCommand!();
void onExecute()
{
@ -69,6 +182,11 @@ struct lexCommand
/* Begin lexing process */
Compiler compiler = new Compiler(sourceText, File());
/* Setup general configuration parameters */
BaseCommandInit(compiler);
compiler.doLex();
writeln("=== Tokens ===\n");
writeln(compiler.getTokens());
@ -88,8 +206,8 @@ struct lexCommand
@Command("syntaxcheck", "Check the syntax of the program")
struct parseCommand
{
@ArgPositional("source file", "The source file to check syntax of")
string sourceFile;
mixin BaseCommand!();
/* TODO: Add missing implementation for this */
void onExecute()
@ -108,6 +226,10 @@ struct parseCommand
/* Begin lexing process */
Compiler compiler = new Compiler(sourceText, File());
/* Setup general configuration parameters */
BaseCommandInit(compiler);
compiler.doLex();
writeln("=== Tokens ===\n");
writeln(compiler.getTokens());
@ -132,8 +254,8 @@ struct parseCommand
@Command("typecheck", "Perform typechecking on the program")
struct typecheckCommand
{
@ArgPositional("source file", "The source file to typecheck")
string sourceFile;
mixin BaseCommand!();
void onExecute()
{
@ -151,6 +273,10 @@ struct typecheckCommand
/* Begin lexing process */
Compiler compiler = new Compiler(sourceText, File());
/* Setup general configuration parameters */
BaseCommandInit(compiler);
compiler.doLex();
writeln("=== Tokens ===\n");
writeln(compiler.getTokens());
@ -175,63 +301,6 @@ struct typecheckCommand
}
}
// @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
{

View File

@ -554,7 +554,7 @@ public final class DCodeEmitter : CodeEmitter
// If enabled (default: yes) then emit entry point (TODO: change later)
if(config.getConfig!(bool)("dgen_emit_entrypoint_test"))
if(config.getConfig!(bool)("dgen:emit_entrypoint_test"))
{
//TODO: Emit main (entry point)
emitEntryPoint();
@ -776,7 +776,7 @@ public final class DCodeEmitter : CodeEmitter
private void emitEntryPoint()
{
//TODO: Implement me
// TODO: Implement me
// Test for `simple_functions.t` (function call testing)
if(cmp(typeChecker.getModule().getName(), "simple_functions") == 0)

View File

@ -39,6 +39,16 @@ public final class CompilerException : TError
}
}
public class ConfigObject
{
}
public class ConfigList : ConfigObject
{
private ConfigObject[] list;
}
public class CompilerConfiguration
{
private string[string] config;
@ -105,13 +115,16 @@ public class Compiler
config.setConfig("dgen:pretty_code", true);
/* Enable entry point test generation for DGen */
config.setConfig("dgen_emit_entrypoint_test", true);
config.setConfig("dgen:emit_entrypoint_test", true);
/* Set the mapping to hashing of entity names (TODO: This should be changed before release) */
config.setConfig("emit:mapper", "hashmapper");
}
public CompilerConfiguration getConfig()
{
return config;
}
/**
* Create a new compiler instance to compile the given