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.typecheck.core : TypeChecker;
|
||||
import gogga;
|
||||
import compiler.compiler : Compiler;
|
||||
|
||||
//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();
|
||||
|
||||
/* Begin lexing process */
|
||||
Lexer lexer = new Lexer(sourceText);
|
||||
lexer.performLex();
|
||||
|
||||
Compiler compiler = new Compiler(sourceText, File());
|
||||
compiler.doLex();
|
||||
writeln("=== Tokens ===\n");
|
||||
writeln(lexer.getTokens());
|
||||
writeln(compiler.getTokens());
|
||||
}
|
||||
catch(TError t)
|
||||
{
|
||||
|
@ -107,17 +107,15 @@ struct parseCommand
|
|||
file.close();
|
||||
|
||||
/* Begin lexing process */
|
||||
Lexer lexer = new Lexer(sourceText);
|
||||
lexer.performLex();
|
||||
|
||||
Token[] tokens = lexer.getTokens();
|
||||
Compiler compiler = new Compiler(sourceText, File());
|
||||
compiler.doLex();
|
||||
writeln("=== Tokens ===\n");
|
||||
writeln(tokens);
|
||||
writeln(compiler.getTokens());
|
||||
|
||||
// TODO: Catch exception
|
||||
Parser parser = new Parser(tokens);
|
||||
/* Perform parsing */
|
||||
compiler.doParse();
|
||||
// TODO: Do something with the returned module
|
||||
auto modulel = parser.parse();
|
||||
auto modulel = compiler.getModule();
|
||||
}
|
||||
catch(TError t)
|
||||
{
|
||||
|
@ -152,22 +150,18 @@ struct typecheckCommand
|
|||
file.close();
|
||||
|
||||
/* Begin lexing process */
|
||||
Lexer lexer = new Lexer(sourceText);
|
||||
lexer.performLex();
|
||||
|
||||
Token[] tokens = lexer.getTokens();
|
||||
Compiler compiler = new Compiler(sourceText, File());
|
||||
compiler.doLex();
|
||||
writeln("=== Tokens ===\n");
|
||||
writeln(tokens);
|
||||
writeln(compiler.getTokens());
|
||||
|
||||
// TODO: Catch exception
|
||||
Parser parser = new Parser(tokens);
|
||||
/* Perform parsing */
|
||||
compiler.doParse();
|
||||
// TODO: Do something with the returned module
|
||||
auto modulel = parser.parse();
|
||||
auto modulel = compiler.getModule();
|
||||
|
||||
//TODO: collect results here
|
||||
//TODO: catch exceptions
|
||||
TypeChecker typeChecker = new TypeChecker(modulel);
|
||||
typeChecker.beginCheck();
|
||||
/* Perform typechecking/codegen */
|
||||
compiler.doTypeCheck();
|
||||
}
|
||||
catch(TError t)
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@ import std.range : walkLength;
|
|||
import gogga;
|
||||
import std.conv : to;
|
||||
import compiler.compiler : CompilerConfiguration;
|
||||
import compiler.codegen.mapper.core : SymbolMapper;
|
||||
|
||||
/**
|
||||
* TODO: Perhaps have an interface that can emit(Context/Parent, Statement)
|
||||
|
@ -23,6 +24,7 @@ public abstract class CodeEmitter
|
|||
protected TypeChecker typeChecker;
|
||||
protected File file;
|
||||
protected CompilerConfiguration config;
|
||||
protected SymbolMapper mapper;
|
||||
|
||||
/**
|
||||
* The selected queue is the queue to be used
|
||||
|
@ -127,7 +129,8 @@ public abstract class CodeEmitter
|
|||
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;
|
||||
|
||||
|
@ -141,6 +144,8 @@ public abstract class CodeEmitter
|
|||
|
||||
this.file = file;
|
||||
this.config = config;
|
||||
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@ import std.range : walkLength;
|
|||
import std.string : wrap;
|
||||
import std.process : spawnProcess, Pid, ProcessException, wait;
|
||||
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.check : getCharacter;
|
||||
import misc.utils : Stack;
|
||||
|
@ -28,9 +28,10 @@ public final class DCodeEmitter : CodeEmitter
|
|||
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;
|
||||
|
@ -125,13 +126,13 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
gprintln("Is ContextNull?: "~to!(string)(context is null));
|
||||
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(!typedEntityVariable.isExternal())
|
||||
{
|
||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
||||
string renamedSymbol = mapper.symbolLookup(typedEntityVariable);
|
||||
|
||||
|
||||
// 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;
|
||||
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(!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
|
||||
//could get out of hand (too long)
|
||||
// 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
|
||||
|
@ -221,7 +222,7 @@ public final class DCodeEmitter : CodeEmitter
|
|||
FetchValueVar fetchValueVarInstr = cast(FetchValueVar)instruction;
|
||||
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(!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: 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;
|
||||
}
|
||||
|
@ -259,7 +260,7 @@ public final class DCodeEmitter : CodeEmitter
|
|||
Context context = funcCallInstr.getContext();
|
||||
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?
|
||||
|
||||
|
@ -669,7 +670,7 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
// Generate the symbol-mapped names for the parameters
|
||||
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)>
|
||||
|
|
|
@ -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.symbols.data;
|
||||
import std.conv : to;
|
||||
import gogga;
|
||||
|
||||
/**
|
||||
* SymbolMapper
|
||||
*
|
||||
* Maps Entity's to consistent but unique symbol
|
||||
* names (strings)
|
||||
*/
|
||||
public final class SymbolMapper
|
||||
public final class HashMapper : SymbolMapper
|
||||
{
|
||||
// Used to map names to entities
|
||||
public static TypeChecker tc;
|
||||
|
||||
// Entity map
|
||||
// private string[Entity] symbolMap;
|
||||
|
||||
// this(TypeChecker tc)
|
||||
// {
|
||||
// this.tc = tc;
|
||||
// }
|
||||
this(TypeChecker tc)
|
||||
{
|
||||
super(tc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an Entity this will generate a unique (but consistent)
|
||||
|
@ -34,7 +22,7 @@ public final class SymbolMapper
|
|||
*
|
||||
* Returns: The symbol hash
|
||||
*/
|
||||
public static string symbolLookup(Entity entityIn)
|
||||
public override string symbolLookup(Entity entityIn)
|
||||
{
|
||||
// Generate the absolute full path of the Entity
|
||||
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 compiler.codegen.emit.core;
|
||||
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
|
||||
{
|
||||
|
@ -31,11 +57,17 @@ public class CompilerConfiguration
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO: Change to a TError
|
||||
// throw new Exception("Key not found");
|
||||
return false;
|
||||
throw new CompilerException(CompilerError.CONFIG_KEY_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
public bool hasConfig(string key)
|
||||
{
|
||||
string[] keys = config.keys();
|
||||
import std.algorithm.searching : canFind;
|
||||
|
||||
return canFind(keys, key);
|
||||
}
|
||||
}
|
||||
|
||||
public class Compiler
|
||||
|
@ -46,8 +78,12 @@ public class Compiler
|
|||
/* The lexer */
|
||||
private Lexer lexer;
|
||||
|
||||
/* The lexed tokens */
|
||||
private Token[] tokens;
|
||||
|
||||
/* The parser */
|
||||
private Parser parser;
|
||||
private Module modulle;
|
||||
|
||||
/* The typechecker/code generator */
|
||||
private TypeChecker typeChecker;
|
||||
|
@ -70,6 +106,9 @@ public class Compiler
|
|||
|
||||
/* Enable entry point test generation for DGen */
|
||||
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();
|
||||
}
|
||||
|
||||
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 */
|
||||
this.lexer = new Lexer(inputSource);
|
||||
this.lexer.performLex();
|
||||
|
||||
/* Extract the tokens */
|
||||
Token[] tokens = lexer.getTokens();
|
||||
gprintln("Collected "~to!(string)(tokens));
|
||||
this.tokens = this.lexer.getTokens();
|
||||
}
|
||||
|
||||
public Token[] getTokens()
|
||||
{
|
||||
if(this.lexer is null)
|
||||
{
|
||||
throw new CompilerException(CompilerError.LEX_NOT_PERFORMED);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/* Spawn a new parser with the provided tokens */
|
||||
this.parser = new Parser(tokens);
|
||||
public void doParse()
|
||||
{
|
||||
Token[] lexedTokens = getTokens();
|
||||
|
||||
/* The parsed Module */
|
||||
Module modulle = parser.parse();
|
||||
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);
|
||||
|
||||
/* Perform typechecking/codegen */
|
||||
this.typeChecker.beginCheck();
|
||||
}
|
||||
|
||||
/* 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
|
||||
emitOutFile.close(); // Flush (perform the write() syscall)
|
||||
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)
|
||||
{
|
||||
/* 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~"' ...");
|
||||
File sourceFileFile;
|
||||
sourceFileFile.open(sourceFile); /* TODO: Error handling with ANY file I/O */
|
||||
|
|
|
@ -69,15 +69,6 @@ public final class TypeChecker
|
|||
*
|
||||
*/
|
||||
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import compiler.typecheck.dependency.exceptions : DependencyException, Dependenc
|
|||
public final class Context
|
||||
{
|
||||
// Required for cases where we need the functionality of the type checker
|
||||
static TypeChecker tc;
|
||||
// static TypeChecker tc;
|
||||
|
||||
InitScope initScope;
|
||||
Container container;
|
||||
|
|
Loading…
Reference in New Issue