tlang/source/tlang/commandline/commands.d

327 lines
8.4 KiB
D

/**
* Commands
*
* All command-line arguments and their impementations
*/
module commandline.commands;
import jcli;
import std.stdio;
import compiler.compiler : beginCompilation;
import misc.exceptions : TError;
import std.exception : ErrnoException;
import compiler.lexer : Lexer, Token;
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")
@(ArgConfig.optional)
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")
@(ArgConfig.optional)
SymbolMappingTechnique symbolTechnique;
@ArgNamed("prettygen|pg", "Generate pretty-printed code")
@(ArgConfig.optional)
bool prettyPrintCodeGen;
@ArgNamed("output|o", "Filename of generated object file")
@(ArgConfig.optional)
string outputFilename = "tlangout.c";
@ArgNamed("entrypointTest|et", "Whether or not to emit entrypoint testing code")
@(ArgConfig.optional)
bool entrypointTestEmit = true; // TODO: Change this later to `false` of course
@ArgNamed("library-link|ll", "Paths to any object files to ,ink in during the linking phase")
@(ArgConfig.optional)
@(ArgConfig.aggregate)
string[] bruh;
}
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);
}
}
/**
* Base requirements for TypeChecker+
*/
mixin template TypeCheckerBase()
{
}
/**
* Compile the given source file from start to finish
*/
@Command("compile", "Compiles the given file(s)")
struct compileCommand
{
mixin BaseCommand!();
mixin EmitBase!();
void onExecute()
{
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 */
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);
}
}
}
/**
* Only perform tokenization of the given source files
*/
@Command("lex", "Performs tokenization of the given file(s)")
struct lexCommand
{
mixin BaseCommand!();
void onExecute()
{
writeln("Performing tokenization on file: "~sourceFile);
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 */
Compiler compiler = new Compiler(sourceText, File());
/* Setup general configuration parameters */
BaseCommandInit(compiler);
compiler.doLex();
writeln("=== Tokens ===\n");
writeln(compiler.getTokens());
}
catch(TError t)
{
gprintln(t.msg, DebugType.ERROR);
}
catch(ErrnoException e)
{
/* TODO: Use gogga error */
writeln("Could not open source file "~sourceFile);
}
}
}
@Command("syntaxcheck", "Check the syntax of the program")
struct parseCommand
{
mixin BaseCommand!();
/* TODO: Add missing implementation for this */
void onExecute()
{
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 */
Compiler compiler = new Compiler(sourceText, File());
/* Setup general configuration parameters */
BaseCommandInit(compiler);
compiler.doLex();
writeln("=== Tokens ===\n");
writeln(compiler.getTokens());
/* Perform parsing */
compiler.doParse();
// TODO: Do something with the returned module
auto modulel = compiler.getModule();
}
catch(TError t)
{
gprintln(t.msg, DebugType.ERROR);
}
catch(ErrnoException e)
{
/* TODO: Use gogga error */
writeln("Could not open source file "~sourceFile);
}
}
}
@Command("typecheck", "Perform typechecking on the program")
struct typecheckCommand
{
mixin BaseCommand!();
void onExecute()
{
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 */
Compiler compiler = new Compiler(sourceText, File());
/* Setup general configuration parameters */
BaseCommandInit(compiler);
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();
}
catch(TError t)
{
gprintln(t.msg, DebugType.ERROR);
}
catch(ErrnoException e)
{
/* TODO: Use gogga error */
writeln("Could not open source file "~sourceFile);
}
}
}
@Command("help", "Shows the help screen")
struct helpCommand
{
/* TODO: Add missing implementation for this */
void onExecute()
{
/* TODO: We want to show the commands list, not a seperate help command */
}
}