mirror of https://github.com/tbklang/tlang.git
DGen
- 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:
parent
1f6e9cbbb6
commit
3f84020e22
|
@ -16,29 +16,143 @@ import compiler.parsing.core : Parser;
|
||||||
import compiler.typecheck.core : TypeChecker;
|
import compiler.typecheck.core : TypeChecker;
|
||||||
import gogga;
|
import gogga;
|
||||||
import compiler.compiler : Compiler;
|
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
|
//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
|
* Compile the given source file from start to finish
|
||||||
*/
|
*/
|
||||||
@Command("compile", "Compiles the given file(s)")
|
@Command("compile", "Compiles the given file(s)")
|
||||||
struct compileCommand
|
struct compileCommand
|
||||||
{
|
{
|
||||||
@ArgPositional("source file", "The source file to compile")
|
mixin BaseCommand!();
|
||||||
string sourceFile;
|
|
||||||
|
|
||||||
|
|
||||||
|
mixin EmitBase!();
|
||||||
|
|
||||||
|
|
||||||
void onExecute()
|
void onExecute()
|
||||||
{
|
{
|
||||||
writeln("Compiling source file: "~sourceFile);
|
|
||||||
try
|
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)
|
catch(TError t)
|
||||||
{
|
{
|
||||||
gprintln(t.msg, DebugType.ERROR);
|
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)")
|
@Command("lex", "Performs tokenization of the given file(s)")
|
||||||
struct lexCommand
|
struct lexCommand
|
||||||
{
|
{
|
||||||
@ArgPositional("source file", "The source file to lex")
|
mixin BaseCommand!();
|
||||||
string sourceFile;
|
|
||||||
|
|
||||||
void onExecute()
|
void onExecute()
|
||||||
{
|
{
|
||||||
|
@ -69,6 +182,11 @@ struct lexCommand
|
||||||
|
|
||||||
/* Begin lexing process */
|
/* Begin lexing process */
|
||||||
Compiler compiler = new Compiler(sourceText, File());
|
Compiler compiler = new Compiler(sourceText, File());
|
||||||
|
|
||||||
|
/* Setup general configuration parameters */
|
||||||
|
BaseCommandInit(compiler);
|
||||||
|
|
||||||
|
|
||||||
compiler.doLex();
|
compiler.doLex();
|
||||||
writeln("=== Tokens ===\n");
|
writeln("=== Tokens ===\n");
|
||||||
writeln(compiler.getTokens());
|
writeln(compiler.getTokens());
|
||||||
|
@ -88,8 +206,8 @@ struct lexCommand
|
||||||
@Command("syntaxcheck", "Check the syntax of the program")
|
@Command("syntaxcheck", "Check the syntax of the program")
|
||||||
struct parseCommand
|
struct parseCommand
|
||||||
{
|
{
|
||||||
@ArgPositional("source file", "The source file to check syntax of")
|
mixin BaseCommand!();
|
||||||
string sourceFile;
|
|
||||||
|
|
||||||
/* TODO: Add missing implementation for this */
|
/* TODO: Add missing implementation for this */
|
||||||
void onExecute()
|
void onExecute()
|
||||||
|
@ -108,6 +226,10 @@ struct parseCommand
|
||||||
|
|
||||||
/* Begin lexing process */
|
/* Begin lexing process */
|
||||||
Compiler compiler = new Compiler(sourceText, File());
|
Compiler compiler = new Compiler(sourceText, File());
|
||||||
|
|
||||||
|
/* Setup general configuration parameters */
|
||||||
|
BaseCommandInit(compiler);
|
||||||
|
|
||||||
compiler.doLex();
|
compiler.doLex();
|
||||||
writeln("=== Tokens ===\n");
|
writeln("=== Tokens ===\n");
|
||||||
writeln(compiler.getTokens());
|
writeln(compiler.getTokens());
|
||||||
|
@ -132,8 +254,8 @@ struct parseCommand
|
||||||
@Command("typecheck", "Perform typechecking on the program")
|
@Command("typecheck", "Perform typechecking on the program")
|
||||||
struct typecheckCommand
|
struct typecheckCommand
|
||||||
{
|
{
|
||||||
@ArgPositional("source file", "The source file to typecheck")
|
mixin BaseCommand!();
|
||||||
string sourceFile;
|
|
||||||
|
|
||||||
void onExecute()
|
void onExecute()
|
||||||
{
|
{
|
||||||
|
@ -151,6 +273,10 @@ struct typecheckCommand
|
||||||
|
|
||||||
/* Begin lexing process */
|
/* Begin lexing process */
|
||||||
Compiler compiler = new Compiler(sourceText, File());
|
Compiler compiler = new Compiler(sourceText, File());
|
||||||
|
|
||||||
|
/* Setup general configuration parameters */
|
||||||
|
BaseCommandInit(compiler);
|
||||||
|
|
||||||
compiler.doLex();
|
compiler.doLex();
|
||||||
writeln("=== Tokens ===\n");
|
writeln("=== Tokens ===\n");
|
||||||
writeln(compiler.getTokens());
|
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")
|
@Command("help", "Shows the help screen")
|
||||||
struct helpCommand
|
struct helpCommand
|
||||||
{
|
{
|
||||||
|
|
|
@ -554,7 +554,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
|
|
||||||
|
|
||||||
// If enabled (default: yes) then emit entry point (TODO: change later)
|
// 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)
|
//TODO: Emit main (entry point)
|
||||||
emitEntryPoint();
|
emitEntryPoint();
|
||||||
|
@ -776,7 +776,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
|
|
||||||
private void emitEntryPoint()
|
private void emitEntryPoint()
|
||||||
{
|
{
|
||||||
//TODO: Implement me
|
// TODO: Implement me
|
||||||
|
|
||||||
// Test for `simple_functions.t` (function call testing)
|
// Test for `simple_functions.t` (function call testing)
|
||||||
if(cmp(typeChecker.getModule().getName(), "simple_functions") == 0)
|
if(cmp(typeChecker.getModule().getName(), "simple_functions") == 0)
|
||||||
|
|
|
@ -39,6 +39,16 @@ public final class CompilerException : TError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ConfigObject
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConfigList : ConfigObject
|
||||||
|
{
|
||||||
|
private ConfigObject[] list;
|
||||||
|
}
|
||||||
|
|
||||||
public class CompilerConfiguration
|
public class CompilerConfiguration
|
||||||
{
|
{
|
||||||
private string[string] config;
|
private string[string] config;
|
||||||
|
@ -105,13 +115,16 @@ public class Compiler
|
||||||
config.setConfig("dgen:pretty_code", true);
|
config.setConfig("dgen:pretty_code", true);
|
||||||
|
|
||||||
/* Enable entry point test generation for DGen */
|
/* 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) */
|
/* Set the mapping to hashing of entity names (TODO: This should be changed before release) */
|
||||||
config.setConfig("emit:mapper", "hashmapper");
|
config.setConfig("emit:mapper", "hashmapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CompilerConfiguration getConfig()
|
||||||
|
{
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new compiler instance to compile the given
|
* Create a new compiler instance to compile the given
|
||||||
|
|
Loading…
Reference in New Issue