diff --git a/source/tlang/commandline/commands.d b/source/tlang/commandline/commands.d index e430db2..50f7452 100644 --- a/source/tlang/commandline/commands.d +++ b/source/tlang/commandline/commands.d @@ -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 { diff --git a/source/tlang/compiler/codegen/emit/dgen.d b/source/tlang/compiler/codegen/emit/dgen.d index 5a80b7a..502530b 100644 --- a/source/tlang/compiler/codegen/emit/dgen.d +++ b/source/tlang/compiler/codegen/emit/dgen.d @@ -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) diff --git a/source/tlang/compiler/compiler.d b/source/tlang/compiler/compiler.d index 1c354c4..0714413 100644 --- a/source/tlang/compiler/compiler.d +++ b/source/tlang/compiler/compiler.d @@ -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