Merge branch 'vardec_varass_dependency' into feature/operator_precedence
commit
3dddbc059e
@ -0,0 +1,124 @@
|
||||
module tlang.compiler.lexer.kinds.arr;
|
||||
|
||||
import tlang.compiler.lexer.core;
|
||||
|
||||
/**
|
||||
* An array-based tokenizer which takes a
|
||||
* provided array of `Token[]`. useful
|
||||
* for testing parser-only related things
|
||||
* with concrete tokens
|
||||
*/
|
||||
public final class ArrLexer : LexerInterface
|
||||
{
|
||||
/**
|
||||
* The concrete token source
|
||||
*/
|
||||
private Token[] tokens;
|
||||
|
||||
/**
|
||||
* Position in the `tokens` array
|
||||
*/
|
||||
private ulong tokenPtr = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new `ArrLexer` (dummy lexer) with
|
||||
* the tokens already in concrete form in the
|
||||
* provided array.
|
||||
*
|
||||
* Params:
|
||||
* tokens = the `Token[]`
|
||||
*/
|
||||
this(Token[] tokens)
|
||||
{
|
||||
this.tokens = tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the token at the current cursor
|
||||
* position
|
||||
*
|
||||
* Returns: the `Token`
|
||||
*/
|
||||
public Token getCurrentToken()
|
||||
{
|
||||
return tokens[tokenPtr];
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor one token forward
|
||||
*/
|
||||
public void nextToken()
|
||||
{
|
||||
tokenPtr++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the cursor one token backwards
|
||||
*/
|
||||
public void previousToken()
|
||||
{
|
||||
tokenPtr--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the cursor
|
||||
*
|
||||
* Params:
|
||||
* cursor = the new position
|
||||
*/
|
||||
public void setCursor(ulong cursor)
|
||||
{
|
||||
this.tokenPtr = cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cursor's current position
|
||||
*
|
||||
* Returns: the position
|
||||
*/
|
||||
public ulong getCursor()
|
||||
{
|
||||
return this.tokenPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether more tokens are available
|
||||
* of not
|
||||
*
|
||||
* Returns: true if more tokens are available, false otherwise
|
||||
*/
|
||||
public bool hasTokens()
|
||||
{
|
||||
return tokenPtr < tokens.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the line position of the lexer in the source text
|
||||
*
|
||||
* Returns: the position
|
||||
*/
|
||||
public ulong getLine()
|
||||
{
|
||||
return 0; // TODO: anything meaningful?
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the column position of the lexer in the source text
|
||||
*
|
||||
* Returns: the position
|
||||
*/
|
||||
public ulong getColumn()
|
||||
{
|
||||
return 0; // TODO: anything meaningful?
|
||||
}
|
||||
|
||||
/**
|
||||
* Exhaustively provide a list of all tokens
|
||||
*
|
||||
* Returns: a `Token[]` containing all tokens
|
||||
*/
|
||||
public Token[] getTokens()
|
||||
{
|
||||
return tokens;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,216 @@
|
||||
/**
|
||||
* Implementation of the `IPoolManager`
|
||||
* interface
|
||||
*/
|
||||
module tlang.compiler.typecheck.dependency.pool.impls;
|
||||
|
||||
import tlang.compiler.typecheck.dependency.pool.interfaces;
|
||||
import tlang.compiler.typecheck.dependency.core : DNode, DNodeGenerator;
|
||||
import tlang.compiler.typecheck.dependency.expression : ExpressionDNode;
|
||||
import tlang.compiler.typecheck.dependency.variables : VariableNode, FuncDecNode, StaticVariableDeclaration, ModuleVariableDeclaration;
|
||||
import tlang.compiler.typecheck.dependency.classes.classStaticDep : ClassStaticNode;
|
||||
import tlang.compiler.symbols.data : Statement, Expression, Variable, Function, Clazz;
|
||||
import std.traits : isAssignable;
|
||||
|
||||
/**
|
||||
* Provides an implementation of
|
||||
* the `IPoolManager` interface
|
||||
* such that you can use this
|
||||
* as part of the dependency
|
||||
* generation process
|
||||
*/
|
||||
public final class PoolManager : IPoolManager
|
||||
{
|
||||
/**
|
||||
* The pool itself
|
||||
*/
|
||||
private DNode[] nodePool;
|
||||
|
||||
/**
|
||||
* Constructs a new pooling manager
|
||||
*/
|
||||
this()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided AST node
|
||||
* to a dependency node, creating
|
||||
* one if one did not yet exist
|
||||
*
|
||||
* Params:
|
||||
* statement = the AST node
|
||||
* Returns: the dependency node
|
||||
*/
|
||||
public DNode pool(Statement statement)
|
||||
{
|
||||
return poolT!(DNode, Statement)(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided `Clazz`
|
||||
* AST node but with an additional
|
||||
* check that it should match
|
||||
* against a `ClassStaticNode`
|
||||
* and if one does not exist
|
||||
* then one such dependency
|
||||
* node should be created
|
||||
*
|
||||
* Params:
|
||||
* clazz = the class to statcally
|
||||
* pool
|
||||
* Returns: the pooled `ClassStaticNode`
|
||||
*/
|
||||
public ClassStaticNode poolClassStatic(Clazz clazz)
|
||||
{
|
||||
foreach(DNode dnode; nodePool)
|
||||
{
|
||||
Statement entity = dnode.getEntity();
|
||||
if(entity == clazz && cast(ClassStaticNode)dnode)
|
||||
{
|
||||
return cast(ClassStaticNode)dnode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If no DNode is found that is associated with
|
||||
* the provided Entity then create a new one and
|
||||
* pool it
|
||||
*/
|
||||
ClassStaticNode newDNode = new ClassStaticNode(clazz);
|
||||
nodePool ~= newDNode;
|
||||
|
||||
return newDNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided `Expression`
|
||||
* AST node into an `ExpressionDNode`
|
||||
*
|
||||
* Params:
|
||||
* expression = the AST node
|
||||
* Returns: the pooled `ExpressionDNode`
|
||||
*/
|
||||
public ExpressionDNode poolExpression(Expression expression)
|
||||
{
|
||||
return poolT!(ExpressionDNode, Expression)(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided `Variable`
|
||||
* AST node into a `VariableNode`
|
||||
*
|
||||
* Params:
|
||||
* variable = the AST node
|
||||
* Returns: the pooled `VariableNode`
|
||||
*/
|
||||
public VariableNode poolVariable(Variable variable)
|
||||
{
|
||||
return poolT!(VariableNode, Variable)(variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided `Variable`
|
||||
* AST node into a `StaticVariableDeclaration`
|
||||
*
|
||||
* Params:
|
||||
* variable = the AST node
|
||||
* Returns: the pooled `StaticVariableDeclaration`
|
||||
*/
|
||||
public StaticVariableDeclaration poolStaticVariable(Variable variable)
|
||||
{
|
||||
return poolT!(StaticVariableDeclaration, Variable)(variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided `Variable`
|
||||
* AST node into a `ModuleVariableDeclaration`
|
||||
*
|
||||
* Params:
|
||||
* variable = the AST node
|
||||
* Returns: the pooled `ModuleVariableDeclaration`
|
||||
*/
|
||||
public ModuleVariableDeclaration poolModuleVariableDeclaration(Variable variable)
|
||||
{
|
||||
return poolT!(ModuleVariableDeclaration, Variable)(variable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided `Function`
|
||||
* AST node into a `FuncDecNode`
|
||||
*
|
||||
* Params:
|
||||
* func = the AST node
|
||||
* Returns: the pooled `FUncDecNode`
|
||||
*/
|
||||
public FuncDecNode poolFuncDec(Function func)
|
||||
{
|
||||
return poolT!(FuncDecNode, Function)(func);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pools the provided AST node
|
||||
* to a dependency node, creating
|
||||
* one if one did not yet exist.
|
||||
*
|
||||
* This is a templatised version
|
||||
* which lets you specify the
|
||||
* kind-of `DNode` to be constructed
|
||||
* (if it does not yet exist) and
|
||||
* the incoming type of AST node.
|
||||
*
|
||||
* Params:
|
||||
* entity = the AST node
|
||||
* Returns: the dependency node
|
||||
*/
|
||||
public DNodeType poolT(DNodeType, EntityType)(EntityType entity)
|
||||
if(isAssignable!(DNode, DNodeType))
|
||||
{
|
||||
foreach(DNode dnode; nodePool)
|
||||
{
|
||||
if(dnode.getEntity() == entity)
|
||||
{
|
||||
return cast(DNodeType)dnode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If no DNode is found that is associated with
|
||||
* the provided Entity then create a new one and
|
||||
* pool it
|
||||
*/
|
||||
DNodeType newDNode = new DNodeType(entity);
|
||||
nodePool ~= newDNode;
|
||||
|
||||
return newDNode;
|
||||
}
|
||||
}
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import tlang.compiler.symbols.data : Module, Variable;
|
||||
import tlang.compiler.typecheck.core : TypeChecker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the pooling of AST nodes
|
||||
* to dependency nodes using the
|
||||
* `PoolManager` implementation
|
||||
*/
|
||||
unittest
|
||||
{
|
||||
// Create bogus module and type checker
|
||||
Module testModule = new Module("myModule");
|
||||
TypeChecker tc = new TypeChecker(testModule);
|
||||
|
||||
// Create a pool manager
|
||||
IPoolManager pool = new PoolManager();
|
||||
|
||||
// Pool an AST node
|
||||
Variable astNode = new Variable("int", "age");
|
||||
DNode astDNode = pool.pool(astNode);
|
||||
|
||||
// Now pool it (again) and ensure it matches
|
||||
// the dependency node just created
|
||||
assert(astDNode is pool.pool(astNode));
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Defines interfaces for managing
|
||||
* the pooling of AST nodes to
|
||||
* dependency nodes which are to be
|
||||
* used within the dependency generator
|
||||
* and later the codegen/typechecker
|
||||
* which consumes these dependency
|
||||
* nodes
|
||||
*/
|
||||
module tlang.compiler.typecheck.dependency.pool.interfaces;
|
||||
|
||||
import tlang.compiler.typecheck.dependency.core : DNode;
|
||||
import tlang.compiler.typecheck.dependency.expression : ExpressionDNode;
|
||||
import tlang.compiler.typecheck.dependency.variables : VariableNode, FuncDecNode, StaticVariableDeclaration, ModuleVariableDeclaration;
|
||||
import tlang.compiler.typecheck.dependency.classes.classStaticDep : ClassStaticNode;
|
||||
import tlang.compiler.symbols.data : Statement, Expression, Variable, Function, Clazz;
|
||||
|
||||
// TODO: In future if we do not require the specific `ExpressionDNode` et al
|
||||
// ... then remove them from the interface definition below
|
||||
|
||||
/**
|
||||
* Defines an interface by which
|
||||
* `Statement`s (i.e. AST nodes)
|
||||
* can be mapped to a `DNode`
|
||||
* and if one does not exist
|
||||
* then it is created on the
|
||||
* first use
|
||||
*/
|
||||
public interface IPoolManager
|
||||
{
|
||||
/**
|
||||
* Pools the provided AST node
|
||||
* to a dependency node
|
||||
*
|
||||
* Params:
|
||||
* statement = the AST node
|
||||
* Returns: the pooled `DNode`
|
||||
*/
|
||||
public DNode pool(Statement statement);
|
||||
|
||||
/**
|
||||
* Pools the provided `Clazz`
|
||||
* AST node but with an additional
|
||||
* check that it should match
|
||||
* against a `ClassStaticNode`
|
||||
* and if one does not exist
|
||||
* then one such dependency
|
||||
* node should be created
|
||||
*
|
||||
* Params:
|
||||
* clazz = the class to statcally
|
||||
* pool
|
||||
* Returns: the pooled `ClassStaticNode`
|
||||
*/
|
||||
public ClassStaticNode poolClassStatic(Clazz clazz);
|
||||
|
||||
/**
|
||||
* Pools the provided `Expression`
|
||||
* AST node into an `ExpressionDNode`
|
||||
*
|
||||
* Params:
|
||||
* expression = the AST node
|
||||
* Returns: the pooled `ExpressionDNode`
|
||||
*/
|
||||
public ExpressionDNode poolExpression(Expression expression);
|
||||
|
||||
/**
|
||||
* Pools the provided `Variable`
|
||||
* AST node into a `VariableNode`
|
||||
*
|
||||
* Params:
|
||||
* variable = the AST node
|
||||
* Returns: the pooled `VariableNode`
|
||||
*/
|
||||
public VariableNode poolVariable(Variable variable);
|
||||
|
||||
/**
|
||||
* Pools the provided `Variable`
|
||||
* AST node into a `StaticVariableDeclaration`
|
||||
*
|
||||
* Params:
|
||||
* variable = the AST node
|
||||
* Returns: the pooled `StaticVariableDeclaration`
|
||||
*/
|
||||
public StaticVariableDeclaration poolStaticVariable(Variable variable);
|
||||
|
||||
/**
|
||||
* Pools the provided `Variable`
|
||||
* AST node into a `ModuleVariableDeclaration`
|
||||
*
|
||||
* Params:
|
||||
* variable = the AST node
|
||||
* Returns: the pooled `ModuleVariableDeclaration`
|
||||
*/
|
||||
public ModuleVariableDeclaration poolModuleVariableDeclaration(Variable variable);
|
||||
|
||||
/**
|
||||
* Pools the provided `Function`
|
||||
* AST node into a `FuncDecNode`
|
||||
*
|
||||
* Params:
|
||||
* func = the AST node
|
||||
* Returns: the pooled `FUncDecNode`
|
||||
*/
|
||||
public FuncDecNode poolFuncDec(Function func);
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Provides implementation of the `IFuncDefStore`
|
||||
* interface
|
||||
*/
|
||||
module tlang.compiler.typecheck.dependency.store.impls;
|
||||
|
||||
import tlang.compiler.typecheck.dependency.store.interfaces;
|
||||
import tlang.compiler.symbols.data : Function;
|
||||
import tlang.compiler.typecheck.dependency.core : FunctionData, DFunctionInnerGenerator;
|
||||
import tlang.compiler.typecheck.core : TypeChecker;
|
||||
import tlang.compiler.typecheck.dependency.pool.interfaces : IPoolManager;
|
||||
|
||||
/**
|
||||
* An implementation of the `IFuncDefStore`
|
||||
* which provides us with a way to store
|
||||
* function definitions and retrieve them
|
||||
* later
|
||||
*/
|
||||
public final class FuncDefStore : IFuncDefStore
|
||||
{
|
||||
/**
|
||||
* All declared functions
|
||||
*/
|
||||
private FunctionData[string] functions;
|
||||
|
||||
/**
|
||||
* The type checker instance
|
||||
*/
|
||||
private TypeChecker tc;
|
||||
|
||||
/**
|
||||
* The pool management
|
||||
*/
|
||||
private IPoolManager poolManager;
|
||||
|
||||
/**
|
||||
* Constructs a new function
|
||||
* definition store with
|
||||
* the provided type
|
||||
* checking instance
|
||||
*
|
||||
* Params:
|
||||
* typeChecker = the `TypeChecker`
|
||||
* poolManager = the `IPoolManager`
|
||||
*/
|
||||
this(TypeChecker typeChecker, IPoolManager poolManager)
|
||||
{
|
||||
this.tc = typeChecker;
|
||||
this.poolManager = poolManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the function definition
|
||||
* to the store
|
||||
*
|
||||
* Params:
|
||||
* func = the function to add
|
||||
* Throws:
|
||||
* FuncDefStoreException if the function
|
||||
* has already been added
|
||||
*/
|
||||
public void addFunctionDef(Function func)
|
||||
{
|
||||
/* (Sanity Check) This should never be called again */
|
||||
foreach(string cFuncKey; functions.keys())
|
||||
{
|
||||
FunctionData cFuncData = functions[cFuncKey];
|
||||
Function cFunc = cFuncData.func;
|
||||
|
||||
if(cFunc == func)
|
||||
{
|
||||
throw new FuncDefStoreException("The provided Function already exists within the store");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the FunctionData, coupled with it own DNodeGenerator
|
||||
* context etc.
|
||||
*/
|
||||
FunctionData funcData;
|
||||
funcData.ownGenerator = new DFunctionInnerGenerator(tc, this.poolManager, this, func);
|
||||
// TODO: Should we not generate a HELLA long name rather, to avoid duplication problems and overwrites of key values
|
||||
|
||||
funcData.name = tc.getResolver().generateName(tc.getModule(), func);
|
||||
|
||||
funcData.name = func.getName();
|
||||
funcData.func = func;
|
||||
|
||||
|
||||
functions[funcData.name] = funcData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs all of the function
|
||||
* definitions currently stored
|
||||
*
|
||||
* Returns: a `FunctionData[string]`
|
||||
* map
|
||||
*/
|
||||
public FunctionData[string] grabFunctionDefs()
|
||||
{
|
||||
return this.functions.dup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs a function definition by its
|
||||
* name
|
||||
*
|
||||
* Params:
|
||||
* name = the name of the function
|
||||
* Returns: the `FunctionData`
|
||||
* Throws:
|
||||
* FuncDefStoreException if the function
|
||||
* could not be found
|
||||
*/
|
||||
public FunctionData grabFunctionDef(string name)
|
||||
{
|
||||
if(name in this.functions)
|
||||
{
|
||||
return this.functions[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new FuncDefStoreException("Could not find function by name '"~name~"'");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Provides the definition of a function definition
|
||||
* store and retrieval system
|
||||
*/
|
||||
module tlang.compiler.typecheck.dependency.store.interfaces;
|
||||
|
||||
import tlang.compiler.symbols.data : Function;
|
||||
import tlang.compiler.typecheck.dependency.core : FunctionData;
|
||||
import misc.exceptions : TError;
|
||||
|
||||
/**
|
||||
* Represents a storage mechanism
|
||||
* which can store and retrieve
|
||||
* function definition datas
|
||||
*/
|
||||
public interface IFuncDefStore
|
||||
{
|
||||
/**
|
||||
* Adds the function definition
|
||||
* to the store
|
||||
*
|
||||
* Params:
|
||||
* func = the function to add
|
||||
* Throws:
|
||||
* FuncDefStoreException if the function
|
||||
* has already been added
|
||||
*/
|
||||
public void addFunctionDef(Function func);
|
||||
|
||||
/**
|
||||
* Grabs all of the function
|
||||
* definitions currently stored
|
||||
*
|
||||
* Returns: a `FunctionData[string]`
|
||||
* map
|
||||
*/
|
||||
public FunctionData[string] grabFunctionDefs();
|
||||
|
||||
/**
|
||||
* Grabs a function definition by its
|
||||
* name
|
||||
*
|
||||
* Params:
|
||||
* name = the name of the function
|
||||
* Returns: the `FunctionData`
|
||||
* Throws:
|
||||
* FuncDefStoreException if the function
|
||||
* could not be found
|
||||
*/
|
||||
public FunctionData grabFunctionDef(string name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when an error occurs
|
||||
* with the `IFuncDefStore` system
|
||||
*/
|
||||
public final class FuncDefStoreException : TError
|
||||
{
|
||||
/**
|
||||
* Constructs a new `FuncDefStoreException`
|
||||
* with the given error message
|
||||
*
|
||||
* Params:
|
||||
* msg = the error message
|
||||
*/
|
||||
this(string msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue