mirror of https://github.com/tbklang/tlang.git
Command-line
- All compilation stages now make use of the `Compiler` object Compiler - Added new exception type `CompilerException` complete with a sub-type enum, `CompilerError` - `getConfig()` will now throw a `CompilerException` when a key is not found, rather than return false (which didn't work under different template types anyways) - Implemented `hasConfig()` to check for the existence of a key in the configuration sub-system's key-value store - The `Compiler` object now stores the `Token[] tokens` generated from the call to `doLex()` - The `Compiler` object now stores the resulting container (`Module`) generated from the call to `doParse()` - Set default symbol mapping technique to the hashmapper technique - Implemented `dolex()` for performing tokenization, it will create and store a `Lexer` instance and the produced `Token[] tokens` into the `Compiler` object - Added `getTokens()` to fetch the tokens generated by `doLex()` - Implemented `doParse()`, `doTypeCheck()` and `doEmit()` in a similiar fashion to `doLex()` - Implemented `getMdoule()` to get the container (`Module`) generated by `doParse()` - Implemented `compile()` which calls `doLex()`, then `doParse()`, then `doTypeCheck()` and finally `doEmit()` CodeEmitter - The `CodeEmitter` constructor now takes in an instance of the chosen `SymbolMapper` DGen - Switched to the instance of the `mapper` inheited from the `CodeMapper` parent class for any `symbolMap` calls required - Use the inherited `TypeChecker` instance and not an instance of it provided by `Context` SymbolMapper - Reworked this class into an abstract class which must have its children implement a `symbolMap(Entity)` interface, this provides us pluggable mapping techniques HashMapper - Moved hashing symbol-mapping technique into `HashMapper` Lebanese - Created a kind-of `SymbolMapper` which, unlike `HashMapper`, produces human-redable-yet-valid C symbols (by replacing the `.`'s with `_`'s) TypeChecker - Removed code for setting now-nonexistent `SymbolMapper.tc` - Removed code for setting now-nonexistent `Context.tc` Context - Removed `static TypeChecker tc` field
This commit is contained in:
parent
a8a88c86e1
commit
d30ffb7684
|
@ -15,6 +15,7 @@ import compiler.lexer : Lexer, Token;
|
||||||
import compiler.parsing.core : Parser;
|
import compiler.parsing.core : Parser;
|
||||||
import compiler.typecheck.core : TypeChecker;
|
import compiler.typecheck.core : TypeChecker;
|
||||||
import gogga;
|
import gogga;
|
||||||
|
import compiler.compiler : Compiler;
|
||||||
|
|
||||||
//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
|
||||||
|
|
||||||
|
@ -67,11 +68,10 @@ struct lexCommand
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
/* Begin lexing process */
|
/* Begin lexing process */
|
||||||
Lexer lexer = new Lexer(sourceText);
|
Compiler compiler = new Compiler(sourceText, File());
|
||||||
lexer.performLex();
|
compiler.doLex();
|
||||||
|
|
||||||
writeln("=== Tokens ===\n");
|
writeln("=== Tokens ===\n");
|
||||||
writeln(lexer.getTokens());
|
writeln(compiler.getTokens());
|
||||||
}
|
}
|
||||||
catch(TError t)
|
catch(TError t)
|
||||||
{
|
{
|
||||||
|
@ -107,17 +107,15 @@ struct parseCommand
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
/* Begin lexing process */
|
/* Begin lexing process */
|
||||||
Lexer lexer = new Lexer(sourceText);
|
Compiler compiler = new Compiler(sourceText, File());
|
||||||
lexer.performLex();
|
compiler.doLex();
|
||||||
|
|
||||||
Token[] tokens = lexer.getTokens();
|
|
||||||
writeln("=== Tokens ===\n");
|
writeln("=== Tokens ===\n");
|
||||||
writeln(tokens);
|
writeln(compiler.getTokens());
|
||||||
|
|
||||||
// TODO: Catch exception
|
/* Perform parsing */
|
||||||
Parser parser = new Parser(tokens);
|
compiler.doParse();
|
||||||
// TODO: Do something with the returned module
|
// TODO: Do something with the returned module
|
||||||
auto modulel = parser.parse();
|
auto modulel = compiler.getModule();
|
||||||
}
|
}
|
||||||
catch(TError t)
|
catch(TError t)
|
||||||
{
|
{
|
||||||
|
@ -152,22 +150,18 @@ struct typecheckCommand
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
/* Begin lexing process */
|
/* Begin lexing process */
|
||||||
Lexer lexer = new Lexer(sourceText);
|
Compiler compiler = new Compiler(sourceText, File());
|
||||||
lexer.performLex();
|
compiler.doLex();
|
||||||
|
|
||||||
Token[] tokens = lexer.getTokens();
|
|
||||||
writeln("=== Tokens ===\n");
|
writeln("=== Tokens ===\n");
|
||||||
writeln(tokens);
|
writeln(compiler.getTokens());
|
||||||
|
|
||||||
// TODO: Catch exception
|
/* Perform parsing */
|
||||||
Parser parser = new Parser(tokens);
|
compiler.doParse();
|
||||||
// TODO: Do something with the returned module
|
// TODO: Do something with the returned module
|
||||||
auto modulel = parser.parse();
|
auto modulel = compiler.getModule();
|
||||||
|
|
||||||
//TODO: collect results here
|
/* Perform typechecking/codegen */
|
||||||
//TODO: catch exceptions
|
compiler.doTypeCheck();
|
||||||
TypeChecker typeChecker = new TypeChecker(modulel);
|
|
||||||
typeChecker.beginCheck();
|
|
||||||
}
|
}
|
||||||
catch(TError t)
|
catch(TError t)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ import std.range : walkLength;
|
||||||
import gogga;
|
import gogga;
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
import compiler.compiler : CompilerConfiguration;
|
import compiler.compiler : CompilerConfiguration;
|
||||||
|
import compiler.codegen.mapper.core : SymbolMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
||||||
|
@ -23,6 +24,7 @@ public abstract class CodeEmitter
|
||||||
protected TypeChecker typeChecker;
|
protected TypeChecker typeChecker;
|
||||||
protected File file;
|
protected File file;
|
||||||
protected CompilerConfiguration config;
|
protected CompilerConfiguration config;
|
||||||
|
protected SymbolMapper mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The selected queue is the queue to be used
|
* The selected queue is the queue to be used
|
||||||
|
@ -127,7 +129,8 @@ public abstract class CodeEmitter
|
||||||
return functionBodyInstrs.keys();
|
return functionBodyInstrs.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
this(TypeChecker typeChecker, File file, CompilerConfiguration config)
|
// TODO: Add allow for custom symbol mapper, use an interface or rather base class mechanism for it
|
||||||
|
this(TypeChecker typeChecker, File file, CompilerConfiguration config, SymbolMapper mapper)
|
||||||
{
|
{
|
||||||
this.typeChecker = typeChecker;
|
this.typeChecker = typeChecker;
|
||||||
|
|
||||||
|
@ -141,6 +144,8 @@ public abstract class CodeEmitter
|
||||||
|
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
|
this.mapper = mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,7 +13,7 @@ import std.range : walkLength;
|
||||||
import std.string : wrap;
|
import std.string : wrap;
|
||||||
import std.process : spawnProcess, Pid, ProcessException, wait;
|
import std.process : spawnProcess, Pid, ProcessException, wait;
|
||||||
import compiler.typecheck.dependency.core : Context, FunctionData, DNode;
|
import compiler.typecheck.dependency.core : Context, FunctionData, DNode;
|
||||||
import compiler.codegen.mapper : SymbolMapper;
|
import compiler.codegen.mapper.core : SymbolMapper;
|
||||||
import compiler.symbols.data : SymbolType, Variable, Function, VariableParameter;
|
import compiler.symbols.data : SymbolType, Variable, Function, VariableParameter;
|
||||||
import compiler.symbols.check : getCharacter;
|
import compiler.symbols.check : getCharacter;
|
||||||
import misc.utils : Stack;
|
import misc.utils : Stack;
|
||||||
|
@ -28,9 +28,10 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
private bool varDecWantsConsumeVarAss = false;
|
private bool varDecWantsConsumeVarAss = false;
|
||||||
|
|
||||||
|
|
||||||
this(TypeChecker typeChecker, File file, CompilerConfiguration config)
|
// NOTE: In future store the mapper in the config please
|
||||||
|
this(TypeChecker typeChecker, File file, CompilerConfiguration config, SymbolMapper mapper)
|
||||||
{
|
{
|
||||||
super(typeChecker, file, config);
|
super(typeChecker, file, config, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong transformDepth = 0;
|
private ulong transformDepth = 0;
|
||||||
|
@ -125,13 +126,13 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
|
|
||||||
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
||||||
gprintln("Wazza contect: "~to!(string)(context.container));
|
gprintln("Wazza contect: "~to!(string)(context.container));
|
||||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
auto typedEntityVariable = typeChecker.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
||||||
|
|
||||||
|
|
||||||
/* If it is not external */
|
/* If it is not external */
|
||||||
if(!typedEntityVariable.isExternal())
|
if(!typedEntityVariable.isExternal())
|
||||||
{
|
{
|
||||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
|
||||||
|
|
||||||
|
|
||||||
// If we are needed as part of a VariabvleDeclaration-with-assignment
|
// If we are needed as part of a VariabvleDeclaration-with-assignment
|
||||||
|
@ -163,7 +164,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
|
VariableDeclaration varDecInstr = cast(VariableDeclaration)instruction;
|
||||||
Context context = varDecInstr.getContext();
|
Context context = varDecInstr.getContext();
|
||||||
|
|
||||||
Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
|
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
|
||||||
|
|
||||||
/* If the variable is not external */
|
/* If the variable is not external */
|
||||||
if(!typedEntityVariable.isExternal())
|
if(!typedEntityVariable.isExternal())
|
||||||
|
@ -175,7 +176,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
//NOTE: We may need to create a symbol table actually and add to that and use that as these names
|
//NOTE: We may need to create a symbol table actually and add to that and use that as these names
|
||||||
//could get out of hand (too long)
|
//could get out of hand (too long)
|
||||||
// NOTE: Best would be identity-mapping Entity's to a name
|
// NOTE: Best would be identity-mapping Entity's to a name
|
||||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
|
||||||
|
|
||||||
|
|
||||||
// Check to see if this declaration has an assignment attached
|
// Check to see if this declaration has an assignment attached
|
||||||
|
@ -221,7 +222,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
FetchValueVar fetchValueVarInstr = cast(FetchValueVar)instruction;
|
FetchValueVar fetchValueVarInstr = cast(FetchValueVar)instruction;
|
||||||
Context context = fetchValueVarInstr.getContext();
|
Context context = fetchValueVarInstr.getContext();
|
||||||
|
|
||||||
Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), fetchValueVarInstr.varName); //TODO: Remove `auto`
|
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(context.getContainer(), fetchValueVarInstr.varName); //TODO: Remove `auto`
|
||||||
|
|
||||||
/* If it is not external */
|
/* If it is not external */
|
||||||
if(!typedEntityVariable.isExternal())
|
if(!typedEntityVariable.isExternal())
|
||||||
|
@ -229,7 +230,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
//TODO: THis is giving me kak (see issue #54), it's generating name but trying to do it for the given container, relative to it
|
//TODO: THis is giving me kak (see issue #54), it's generating name but trying to do it for the given container, relative to it
|
||||||
//TODO: We might need a version of generateName that is like generatenamebest (currently it acts like generatename, within)
|
//TODO: We might need a version of generateName that is like generatenamebest (currently it acts like generatename, within)
|
||||||
|
|
||||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
|
||||||
|
|
||||||
return renamedSymbol;
|
return renamedSymbol;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +260,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
Context context = funcCallInstr.getContext();
|
Context context = funcCallInstr.getContext();
|
||||||
assert(context);
|
assert(context);
|
||||||
|
|
||||||
Function functionToCall = cast(Function)context.tc.getResolver().resolveBest(context.getContainer(), funcCallInstr.functionName); //TODO: Remove `auto`
|
Function functionToCall = cast(Function)typeChecker.getResolver().resolveBest(context.getContainer(), funcCallInstr.functionName); //TODO: Remove `auto`
|
||||||
|
|
||||||
// TODO: SymbolLookup?
|
// TODO: SymbolLookup?
|
||||||
|
|
||||||
|
@ -669,7 +670,7 @@ public final class DCodeEmitter : CodeEmitter
|
||||||
|
|
||||||
// Generate the symbol-mapped names for the parameters
|
// Generate the symbol-mapped names for the parameters
|
||||||
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(func, currentParameter.getName()); //TODO: Remove `auto`
|
Variable typedEntityVariable = cast(Variable)typeChecker.getResolver().resolveBest(func, currentParameter.getName()); //TODO: Remove `auto`
|
||||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
|
||||||
|
|
||||||
|
|
||||||
// Generate <type> <parameter-name (symbol mapped)>
|
// Generate <type> <parameter-name (symbol mapped)>
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
module compiler.codegen.mapper.core;
|
||||||
|
|
||||||
|
import compiler.typecheck.core;
|
||||||
|
import compiler.symbols.data;
|
||||||
|
import std.conv : to;
|
||||||
|
import gogga;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SymbolMapper
|
||||||
|
*
|
||||||
|
* Maps Entity's to consistent but unique symbol
|
||||||
|
* names (strings)
|
||||||
|
*/
|
||||||
|
public class SymbolMapper
|
||||||
|
{
|
||||||
|
// Used to map names to entities
|
||||||
|
protected TypeChecker tc;
|
||||||
|
|
||||||
|
this(TypeChecker tc)
|
||||||
|
{
|
||||||
|
this.tc = tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract string symbolLookup(Entity entityIn);
|
||||||
|
}
|
|
@ -1,28 +1,16 @@
|
||||||
module compiler.codegen.mapper;
|
module compiler.codegen.mapper.hashmapper;
|
||||||
|
|
||||||
|
import compiler.codegen.mapper.core : SymbolMapper;
|
||||||
import compiler.typecheck.core;
|
import compiler.typecheck.core;
|
||||||
import compiler.symbols.data;
|
import compiler.symbols.data;
|
||||||
import std.conv : to;
|
|
||||||
import gogga;
|
|
||||||
|
|
||||||
/**
|
public final class HashMapper : SymbolMapper
|
||||||
* SymbolMapper
|
|
||||||
*
|
|
||||||
* Maps Entity's to consistent but unique symbol
|
|
||||||
* names (strings)
|
|
||||||
*/
|
|
||||||
public final class SymbolMapper
|
|
||||||
{
|
{
|
||||||
// Used to map names to entities
|
|
||||||
public static TypeChecker tc;
|
|
||||||
|
|
||||||
// Entity map
|
this(TypeChecker tc)
|
||||||
// private string[Entity] symbolMap;
|
{
|
||||||
|
super(tc);
|
||||||
// this(TypeChecker tc)
|
}
|
||||||
// {
|
|
||||||
// this.tc = tc;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an Entity this will generate a unique (but consistent)
|
* Given an Entity this will generate a unique (but consistent)
|
||||||
|
@ -34,7 +22,7 @@ public final class SymbolMapper
|
||||||
*
|
*
|
||||||
* Returns: The symbol hash
|
* Returns: The symbol hash
|
||||||
*/
|
*/
|
||||||
public static string symbolLookup(Entity entityIn)
|
public override string symbolLookup(Entity entityIn)
|
||||||
{
|
{
|
||||||
// Generate the absolute full path of the Entity
|
// Generate the absolute full path of the Entity
|
||||||
string absoluteFullPath = tc.getResolver().generateNameBest(entityIn);
|
string absoluteFullPath = tc.getResolver().generateNameBest(entityIn);
|
|
@ -0,0 +1,34 @@
|
||||||
|
module compiler.codegen.mapper.lebanese;
|
||||||
|
|
||||||
|
import compiler.codegen.mapper.core : SymbolMapper;
|
||||||
|
import compiler.typecheck.core;
|
||||||
|
import compiler.symbols.data;
|
||||||
|
import std.string : replace;
|
||||||
|
|
||||||
|
public final class LebaneseMapper : SymbolMapper
|
||||||
|
{
|
||||||
|
this(TypeChecker tc)
|
||||||
|
{
|
||||||
|
super(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps given Entity's name to a version whereby all the
|
||||||
|
* `.`'s are placed by underscores preceded by a `t_`
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* entityIn = the Entity to map
|
||||||
|
* Returns: A string of the mapped symbol
|
||||||
|
*/
|
||||||
|
public override string symbolLookup(Entity entityIn)
|
||||||
|
{
|
||||||
|
// Generate the absolute full path of the Entity
|
||||||
|
string absoluteFullPath = tc.getResolver().generateNameBest(entityIn);
|
||||||
|
|
||||||
|
// Generate the name as `_<underscored>`
|
||||||
|
string symbolName = replace(absoluteFullPath, ".", "_");
|
||||||
|
symbolName="t_"~symbolName;
|
||||||
|
|
||||||
|
return symbolName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,32 @@ import compiler.typecheck.exceptions;
|
||||||
import core.stdc.stdlib;
|
import core.stdc.stdlib;
|
||||||
import compiler.codegen.emit.core;
|
import compiler.codegen.emit.core;
|
||||||
import compiler.codegen.emit.dgen;
|
import compiler.codegen.emit.dgen;
|
||||||
|
import misc.exceptions : TError;
|
||||||
|
import compiler.codegen.mapper.core : SymbolMapper;
|
||||||
|
import compiler.codegen.mapper.hashmapper : HashMapper;
|
||||||
|
import compiler.codegen.mapper.lebanese : LebaneseMapper;
|
||||||
|
import std.string : cmp;
|
||||||
|
|
||||||
|
public enum CompilerError
|
||||||
|
{
|
||||||
|
LEX_NOT_PERFORMED,
|
||||||
|
NO_TOKENS,
|
||||||
|
PARSE_NOT_YET_PERFORMED,
|
||||||
|
TYPECHECK_NOT_YET_PERFORMED,
|
||||||
|
CONFIG_ERROR,
|
||||||
|
CONFIG_KEY_NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class CompilerException : TError
|
||||||
|
{
|
||||||
|
private CompilerError errType;
|
||||||
|
|
||||||
|
this(CompilerError errType, string msg = "")
|
||||||
|
{
|
||||||
|
super("CompilerError("~to!(string)(errType)~")"~(msg.length ? ": "~msg : ""));
|
||||||
|
this.errType = errType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class CompilerConfiguration
|
public class CompilerConfiguration
|
||||||
{
|
{
|
||||||
|
@ -31,11 +57,17 @@ public class CompilerConfiguration
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Change to a TError
|
throw new CompilerException(CompilerError.CONFIG_KEY_NOT_FOUND);
|
||||||
// throw new Exception("Key not found");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool hasConfig(string key)
|
||||||
|
{
|
||||||
|
string[] keys = config.keys();
|
||||||
|
import std.algorithm.searching : canFind;
|
||||||
|
|
||||||
|
return canFind(keys, key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Compiler
|
public class Compiler
|
||||||
|
@ -46,8 +78,12 @@ public class Compiler
|
||||||
/* The lexer */
|
/* The lexer */
|
||||||
private Lexer lexer;
|
private Lexer lexer;
|
||||||
|
|
||||||
|
/* The lexed tokens */
|
||||||
|
private Token[] tokens;
|
||||||
|
|
||||||
/* The parser */
|
/* The parser */
|
||||||
private Parser parser;
|
private Parser parser;
|
||||||
|
private Module modulle;
|
||||||
|
|
||||||
/* The typechecker/code generator */
|
/* The typechecker/code generator */
|
||||||
private TypeChecker typeChecker;
|
private TypeChecker typeChecker;
|
||||||
|
@ -70,6 +106,9 @@ public class Compiler
|
||||||
|
|
||||||
/* 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) */
|
||||||
|
config.setConfig("emit:mapper", "hashmapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,36 +130,115 @@ public class Compiler
|
||||||
defaultConfig();
|
defaultConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compile()
|
/* Setup the lexer and begin lexing */
|
||||||
|
public void doLex()
|
||||||
{
|
{
|
||||||
// TODO: Add each step of the pipeline here
|
|
||||||
|
|
||||||
/* Setup the lexer and begin lexing */
|
/* Setup the lexer and begin lexing */
|
||||||
this.lexer = new Lexer(inputSource);
|
this.lexer = new Lexer(inputSource);
|
||||||
this.lexer.performLex();
|
this.lexer.performLex();
|
||||||
|
|
||||||
/* Extract the tokens */
|
|
||||||
Token[] tokens = lexer.getTokens();
|
|
||||||
gprintln("Collected "~to!(string)(tokens));
|
|
||||||
|
|
||||||
/* Spawn a new parser with the provided tokens */
|
this.tokens = this.lexer.getTokens();
|
||||||
this.parser = new Parser(tokens);
|
}
|
||||||
|
|
||||||
/* The parsed Module */
|
public Token[] getTokens()
|
||||||
Module modulle = parser.parse();
|
{
|
||||||
|
if(this.lexer is null)
|
||||||
|
{
|
||||||
|
throw new CompilerException(CompilerError.LEX_NOT_PERFORMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spawn a new parser with the provided tokens */
|
||||||
|
public void doParse()
|
||||||
|
{
|
||||||
|
Token[] lexedTokens = getTokens();
|
||||||
|
|
||||||
|
if(lexedTokens.length == 0)
|
||||||
|
{
|
||||||
|
throw new CompilerException(CompilerError.NO_TOKENS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Spawn a new parser with the provided tokens */
|
||||||
|
this.parser = new Parser(lexedTokens);
|
||||||
|
|
||||||
|
modulle = parser.parse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Module getModule()
|
||||||
|
{
|
||||||
|
return modulle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawn a new typechecker/codegenerator on the module
|
||||||
|
* and perform type checking and code generation
|
||||||
|
*/
|
||||||
|
public void doTypeCheck()
|
||||||
|
{
|
||||||
|
if(this.parser is null)
|
||||||
|
{
|
||||||
|
throw new CompilerException(CompilerError.PARSE_NOT_YET_PERFORMED);
|
||||||
|
}
|
||||||
|
|
||||||
/* Spawn a new typechecker/codegenerator on the module */
|
|
||||||
this.typeChecker = new TypeChecker(modulle);
|
this.typeChecker = new TypeChecker(modulle);
|
||||||
|
|
||||||
/* Perform typechecking/codegen */
|
/* Perform typechecking/codegen */
|
||||||
this.typeChecker.beginCheck();
|
this.typeChecker.beginCheck();
|
||||||
|
}
|
||||||
|
|
||||||
/* Perform code emitting */
|
/* Perform code emitting */
|
||||||
this.emitter = new DCodeEmitter(typeChecker, emitOutFile, config);
|
public void doEmit()
|
||||||
|
{
|
||||||
|
if(typeChecker is null)
|
||||||
|
{
|
||||||
|
throw new CompilerException(CompilerError.TYPECHECK_NOT_YET_PERFORMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!config.hasConfig("emit:mapper"))
|
||||||
|
{
|
||||||
|
throw new CompilerException(CompilerError.CONFIG_ERROR, "Missing a symbol mapper");
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolMapper mapper;
|
||||||
|
string mapperType = config.getConfig!(string)("emit:mapper");
|
||||||
|
|
||||||
|
if(cmp(mapperType, "hashmapper") == 0)
|
||||||
|
{
|
||||||
|
mapper = new HashMapper(typeChecker);
|
||||||
|
}
|
||||||
|
else if(cmp(mapperType, "lebanese") == 0)
|
||||||
|
{
|
||||||
|
mapper = new LebaneseMapper(typeChecker);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new CompilerException(CompilerError.CONFIG_ERROR, "Invalid mapper type '"~mapperType~"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.emitter = new DCodeEmitter(typeChecker, emitOutFile, config, mapper);
|
||||||
emitter.emit(); // Emit the code
|
emitter.emit(); // Emit the code
|
||||||
emitOutFile.close(); // Flush (perform the write() syscall)
|
emitOutFile.close(); // Flush (perform the write() syscall)
|
||||||
emitter.finalize(); // Call CC on the file containing generated C code
|
emitter.finalize(); // Call CC on the file containing generated C code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void compile()
|
||||||
|
{
|
||||||
|
/* Setup the lexer, perform the tokenization and obtain the tokens */
|
||||||
|
doLex();
|
||||||
|
|
||||||
|
/* Setup the parser with the provided tokens and perform parsing */
|
||||||
|
doParse();
|
||||||
|
|
||||||
|
/* Spawn a new typechecker/codegenerator on the module and perform type checking */
|
||||||
|
doTypeCheck();
|
||||||
|
|
||||||
|
/* Perform code emitting */
|
||||||
|
doEmit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,6 +255,7 @@ void beginCompilation(string[] sourceFiles)
|
||||||
foreach(string sourceFile; sourceFiles)
|
foreach(string sourceFile; sourceFiles)
|
||||||
{
|
{
|
||||||
/* Read in the source code */
|
/* Read in the source code */
|
||||||
|
// TODO: THis below code is used so many times, for heavens-sake please make a helper function for it
|
||||||
gprintln("Reading source file '"~sourceFile~"' ...");
|
gprintln("Reading source file '"~sourceFile~"' ...");
|
||||||
File sourceFileFile;
|
File sourceFileFile;
|
||||||
sourceFileFile.open(sourceFile); /* TODO: Error handling with ANY file I/O */
|
sourceFileFile.open(sourceFile); /* TODO: Error handling with ANY file I/O */
|
||||||
|
|
|
@ -68,15 +68,6 @@ public final class TypeChecker
|
||||||
* non-cyclic
|
* non-cyclic
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Allow Context class access to the type checker (used in Instruction where only Context is available)
|
|
||||||
Context.tc = this;
|
|
||||||
|
|
||||||
// Allow the SymbolMapper class to access the type checker
|
|
||||||
import compiler.codegen.mapper : SymbolMapper;
|
|
||||||
SymbolMapper.tc = this;
|
|
||||||
|
|
||||||
// DNodeGenerator.staticTC = this;
|
|
||||||
|
|
||||||
|
|
||||||
DNodeGenerator dNodeGenerator = new DNodeGenerator(this);
|
DNodeGenerator dNodeGenerator = new DNodeGenerator(this);
|
||||||
|
|
|
@ -27,7 +27,7 @@ import compiler.typecheck.dependency.exceptions : DependencyException, Dependenc
|
||||||
public final class Context
|
public final class Context
|
||||||
{
|
{
|
||||||
// Required for cases where we need the functionality of the type checker
|
// Required for cases where we need the functionality of the type checker
|
||||||
static TypeChecker tc;
|
// static TypeChecker tc;
|
||||||
|
|
||||||
InitScope initScope;
|
InitScope initScope;
|
||||||
Container container;
|
Container container;
|
||||||
|
|
Loading…
Reference in New Issue