mirror of https://github.com/tbklang/tlang.git
Merge branch 'vardec_varass_dependency' into feature/unused_vars_detection
This commit is contained in:
parent
48fe528922
commit
b98fa1fd38
|
@ -71,6 +71,7 @@ jobs:
|
|||
# mv doveralls_linux_travis doveralls
|
||||
# chmod +x doveralls
|
||||
dub fetch doveralls
|
||||
sudo apt update
|
||||
sudo apt install libcurl4-openssl-dev
|
||||
|
||||
- name: DUB unit tests with coverage
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module tlang.compiler.lexer.core.lexer;
|
||||
|
||||
import tlang.compiler.lexer.core.tokens : Token;
|
||||
import std.ascii : isDigit, isAlpha, isWhite;
|
||||
|
||||
/**
|
||||
* Defines the interface a lexer must provide
|
||||
|
@ -73,4 +74,163 @@ public interface LexerInterface
|
|||
* Returns: a `Token[]` containing all tokens
|
||||
*/
|
||||
public Token[] getTokens();
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable names assigned
|
||||
* to commonly used character
|
||||
* constants
|
||||
*/
|
||||
public enum LexerSymbols : char
|
||||
{
|
||||
L_PAREN = '(',
|
||||
R_PAREN = ')',
|
||||
SEMI_COLON = ';',
|
||||
COMMA = ',',
|
||||
L_BRACK = '[' ,
|
||||
R_BRACK = ']' ,
|
||||
PLUS = '+' ,
|
||||
MINUS = '-' ,
|
||||
FORWARD_SLASH = '/' ,
|
||||
PERCENT = '%' ,
|
||||
STAR = '*' ,
|
||||
AMPERSAND = '&' ,
|
||||
L_BRACE = '{' ,
|
||||
R_BRACE = '}' ,
|
||||
EQUALS = '=' ,
|
||||
SHEFFER_STROKE = '|' ,
|
||||
CARET = '^' ,
|
||||
EXCLAMATION = '!' ,
|
||||
TILDE = '~' ,
|
||||
DOT = '.' ,
|
||||
COLON = ':',
|
||||
SPACE = ' ',
|
||||
TAB = '\t',
|
||||
NEWLINE = '\n',
|
||||
DOUBLE_QUOTE = '"',
|
||||
SINGLE_QUOTE = '\'' ,
|
||||
BACKSLASH = '\\' ,
|
||||
UNDERSCORE = '_' ,
|
||||
LESS_THAN = '<' ,
|
||||
BIGGER_THAN = '>' ,
|
||||
|
||||
ESC_NOTHING = '0' ,
|
||||
ESC_CARRIAGE_RETURN = 'r' ,
|
||||
ESC_TAB = 't' ,
|
||||
ESC_NEWLINE = 'n' ,
|
||||
ESC_BELL= 'a' ,
|
||||
|
||||
ENC_BYTE = 'B' ,
|
||||
ENC_INT = 'I' ,
|
||||
ENC_LONG = 'L' ,
|
||||
ENC_WORD = 'W' ,
|
||||
ENC_UNSIGNED = 'U' ,
|
||||
ENC_SIGNED = 'S' ,
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias to `LexerSymbols`
|
||||
*/
|
||||
public alias LS = LexerSymbols;
|
||||
|
||||
/**
|
||||
* Checks if the provided character is an operator
|
||||
*
|
||||
* Params:
|
||||
* c = the character to check
|
||||
* Returns: `true` if it is a character, `false`
|
||||
* otherwise
|
||||
*/
|
||||
public bool isOperator(char c)
|
||||
{
|
||||
return c == LS.PLUS || c == LS.TILDE || c == LS.MINUS ||
|
||||
c == LS.STAR || c == LS.FORWARD_SLASH || c == LS.AMPERSAND ||
|
||||
c == LS.CARET || c == LS.EXCLAMATION || c == LS.SHEFFER_STROKE ||
|
||||
c == LS.LESS_THAN || c == LS.BIGGER_THAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided character is a splitter
|
||||
*
|
||||
* Params:
|
||||
* c = the character to check
|
||||
* Returns: `true` if it is a splitter, `false`
|
||||
* otherwise
|
||||
*/
|
||||
public bool isSplitter(char c)
|
||||
{
|
||||
return c == LS.SEMI_COLON || c == LS.COMMA || c == LS.L_PAREN ||
|
||||
c == LS.R_PAREN || c == LS.L_BRACK || c == LS.R_BRACK ||
|
||||
c == LS.PERCENT || c == LS.L_BRACE || c == LS.R_BRACE ||
|
||||
c == LS.EQUALS || c == LS.DOT || c == LS.COLON ||
|
||||
isOperator(c) || isWhite(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided character is a
|
||||
* numerical size encoder
|
||||
*
|
||||
* Params:
|
||||
* character = the character to check
|
||||
* Returns: `true` if so, `false` otheriwse
|
||||
*/
|
||||
public bool isNumericalEncoder_Size(char character)
|
||||
{
|
||||
return character == LS.ENC_BYTE || character == LS.ENC_WORD ||
|
||||
character == LS.ENC_INT || character == LS.ENC_LONG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided character is a
|
||||
* numerical signage encoder
|
||||
*
|
||||
* Params:
|
||||
* character = the character to check
|
||||
* Returns: `true` if so, `false` otherwise
|
||||
*/
|
||||
public bool isNumericalEncoder_Signage(char character)
|
||||
{
|
||||
return character == LS.ENC_SIGNED || character == LS.ENC_UNSIGNED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the provided character is
|
||||
* either a numerical size encoder
|
||||
* or signage encoder
|
||||
*
|
||||
* Params:
|
||||
* character = the character to check
|
||||
* Returns: `true` if so, `false` otherwise
|
||||
*/
|
||||
public bool isNumericalEncoder(char character)
|
||||
{
|
||||
return isNumericalEncoder_Size(character) ||
|
||||
isNumericalEncoder_Signage(character);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given character is a valid
|
||||
* escape character (something which would
|
||||
* have followed a `\`)
|
||||
*
|
||||
* Params:
|
||||
* character = the character to check
|
||||
* Returns: `true` if so, `false` otherwise
|
||||
*/
|
||||
public bool isValidEscape_String(char character)
|
||||
{
|
||||
return character == LS.BACKSLASH || character == LS.DOUBLE_QUOTE || character == LS.SINGLE_QUOTE ||
|
||||
character == LS.ESC_NOTHING || character == LS.ESC_NEWLINE || character == LS.ESC_CARRIAGE_RETURN ||
|
||||
character == LS.TAB || character == LS.ESC_BELL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a character return whether it is valid entry
|
||||
* for preceding a '.'.
|
||||
*
|
||||
* Returns: `true` if so, otherwise `false`
|
||||
*/
|
||||
public bool isValidDotPrecede(char character)
|
||||
{
|
||||
return character == LS.R_PAREN || character == LS.R_BRACK; // || isAlpha(character) || isDigit(character);
|
||||
}
|
|
@ -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
|
@ -562,8 +562,12 @@ public final class Parser
|
|||
/* If it is a type */
|
||||
if (symbolType == SymbolType.IDENT_TYPE)
|
||||
{
|
||||
/* Might be a function, might be a variable, or assignment */
|
||||
structMember = parseName();
|
||||
/* Might be a function definition or variable declaration */
|
||||
structMember = parseTypedDeclaration();
|
||||
|
||||
/* Should have a semi-colon and consume it */
|
||||
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
||||
lexer.nextToken();
|
||||
}
|
||||
/* If it is an accessor */
|
||||
else if (isAccessor(lexer.getCurrentToken()))
|
||||
|
@ -1880,8 +1884,12 @@ public final class Parser
|
|||
/* If it is a type */
|
||||
if (symbolType == SymbolType.IDENT_TYPE)
|
||||
{
|
||||
/* Might be a function, might be a variable, or assignment */
|
||||
structMember = parseName();
|
||||
/* Might be a function definition or variable declaration */
|
||||
structMember = parseTypedDeclaration();
|
||||
|
||||
/* Should have a semi-colon and consume it */
|
||||
expect(SymbolType.SEMICOLON, lexer.getCurrentToken());
|
||||
lexer.nextToken();
|
||||
}
|
||||
/* If it is a class */
|
||||
else if(symbolType == SymbolType.CLASS)
|
||||
|
@ -2008,6 +2016,124 @@ public final class Parser
|
|||
return statement;
|
||||
}
|
||||
|
||||
import std.container.slist : SList;
|
||||
private SList!(Token) commentStack;
|
||||
private void pushComment(Token commentToken)
|
||||
{
|
||||
// Sanity check
|
||||
assert(getSymbolType(commentToken) == SymbolType.SINGLE_LINE_COMMENT ||
|
||||
getSymbolType(commentToken) == SymbolType.MULTI_LINE_COMMENT
|
||||
);
|
||||
|
||||
// Push it onto top of stack
|
||||
commentStack.insertFront(commentToken);
|
||||
}
|
||||
//TODO: Add a popToken() (also think if we want a stack-based mechanism)
|
||||
private bool hasCommentsOnStack()
|
||||
{
|
||||
return getCommentCount() != 0;
|
||||
}
|
||||
|
||||
private ulong getCommentCount()
|
||||
{
|
||||
import std.range : walkLength;
|
||||
return walkLength(commentStack[]);
|
||||
}
|
||||
|
||||
private void parseComment()
|
||||
{
|
||||
gprintln("parseComment(): Enter", DebugType.WARNING);
|
||||
|
||||
Token curCommentToken = lexer.getCurrentToken();
|
||||
|
||||
pushComment(curCommentToken);
|
||||
|
||||
// TODO: Do something here like placing it on some kind of stack
|
||||
gprintln("Comment is: '"~curCommentToken.getToken()~"'");
|
||||
lexer.nextToken(); // Move off comment
|
||||
|
||||
gprintln("parseComment(): Leave", DebugType.WARNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the handling of comments
|
||||
*/
|
||||
unittest
|
||||
{
|
||||
import tlang.compiler.lexer.kinds.arr : ArrLexer;
|
||||
|
||||
string sourceCode = `module myCommentModule;
|
||||
// Hello`;
|
||||
|
||||
LexerInterface currentLexer = new BasicLexer(sourceCode);
|
||||
(cast(BasicLexer)currentLexer).performLex();
|
||||
|
||||
Parser parser = new Parser(currentLexer);
|
||||
|
||||
try
|
||||
{
|
||||
Module modulle = parser.parse();
|
||||
|
||||
assert(parser.hasCommentsOnStack());
|
||||
assert(parser.getCommentCount() == 1);
|
||||
}
|
||||
catch(TError e)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
sourceCode = `module myCommntedModule;
|
||||
/*Hello */
|
||||
|
||||
/* Hello*/`;
|
||||
|
||||
currentLexer = new BasicLexer(sourceCode);
|
||||
(cast(BasicLexer)currentLexer).performLex();
|
||||
parser = new Parser(currentLexer);
|
||||
|
||||
try
|
||||
{
|
||||
Module modulle = parser.parse();
|
||||
|
||||
assert(parser.hasCommentsOnStack());
|
||||
assert(parser.getCommentCount() == 2);
|
||||
}
|
||||
catch(TError e)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
sourceCode = `module myCommentedModule;
|
||||
|
||||
void function()
|
||||
{
|
||||
/*Hello */
|
||||
/* Hello */
|
||||
// Hello
|
||||
//Hello
|
||||
}
|
||||
`;
|
||||
|
||||
currentLexer = new BasicLexer(sourceCode);
|
||||
(cast(BasicLexer)currentLexer).performLex();
|
||||
parser = new Parser(currentLexer);
|
||||
|
||||
try
|
||||
{
|
||||
Module modulle = parser.parse();
|
||||
|
||||
assert(parser.hasCommentsOnStack());
|
||||
assert(parser.getCommentCount() == 4);
|
||||
}
|
||||
catch(TError e)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We need to add `parseComment()`
|
||||
// support here (see issue #84)
|
||||
// TODO: This ic currently dead code and ought to be used/implemented
|
||||
private Statement parseStatement(SymbolType terminatingSymbol = SymbolType.SEMICOLON)
|
||||
{
|
||||
gprintln("parseStatement(): Enter", DebugType.WARNING);
|
||||
|
@ -2080,6 +2206,12 @@ public final class Parser
|
|||
{
|
||||
statement = parseDerefAssignment();
|
||||
}
|
||||
/* If it is a kind-of comment */
|
||||
else if(symbol == SymbolType.SINGLE_LINE_COMMENT || symbol == SymbolType.MULTI_LINE_COMMENT)
|
||||
{
|
||||
gprintln("COMMENTS NOT YET PROPERLY SUPOORTED", DebugType.ERROR);
|
||||
parseComment();
|
||||
}
|
||||
/* Error out */
|
||||
else
|
||||
{
|
||||
|
@ -2303,6 +2435,12 @@ public final class Parser
|
|||
|
||||
modulle.addStatement(externStatement);
|
||||
}
|
||||
/* If it is a kind-of comment */
|
||||
else if(symbol == SymbolType.SINGLE_LINE_COMMENT || symbol == SymbolType.MULTI_LINE_COMMENT)
|
||||
{
|
||||
gprintln("COMMENTS NOT YET PROPERLY SUPOORTED", DebugType.ERROR);
|
||||
parseComment();
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("parse(): Unknown '" ~ tok.getToken() ~ "'");
|
||||
|
|
|
@ -290,6 +290,16 @@ public enum SymbolType
|
|||
*/
|
||||
GENERIC_TYPE_DECLARE,
|
||||
|
||||
/**
|
||||
* Multi-line comment (frwd-slash-star)
|
||||
*/
|
||||
MULTI_LINE_COMMENT,
|
||||
|
||||
/**
|
||||
* Singleiline comment (frwd-slash-slash)
|
||||
*/
|
||||
SINGLE_LINE_COMMENT,
|
||||
|
||||
/**
|
||||
* Unknown symbol
|
||||
*/
|
||||
|
@ -780,6 +790,16 @@ public SymbolType getSymbolType(Token tokenIn)
|
|||
{
|
||||
return SymbolType.STAR;
|
||||
}
|
||||
/* Multi-line comment (fwrd-slash-star) check */
|
||||
else if(token[0] == '/' && token.length >= 2 && token[1]=='*')
|
||||
{
|
||||
return SymbolType.MULTI_LINE_COMMENT;
|
||||
}
|
||||
/* Single-line comment (fwrd-slash-slash) check */
|
||||
else if(token[0] == '/' && token.length >= 2 && token[1]=='/')
|
||||
{
|
||||
return SymbolType.SINGLE_LINE_COMMENT;
|
||||
}
|
||||
/* Divide `/` operator check */
|
||||
else if(token[0] == '/')
|
||||
{
|
||||
|
|
|
@ -36,10 +36,33 @@ public Statement[] weightReorder(Statement[] statements)
|
|||
// AND MCloneable
|
||||
public interface Container : MStatementSearchable, MStatementReplaceable
|
||||
{
|
||||
/**
|
||||
* Appends the given statement to
|
||||
* this container's body
|
||||
*
|
||||
* Params:
|
||||
* statement = the `Statement`
|
||||
* to add
|
||||
*/
|
||||
public void addStatement(Statement statement);
|
||||
|
||||
/**
|
||||
* Appends the list of statemnets
|
||||
* (in order) to this container's
|
||||
* body
|
||||
*
|
||||
* Params:
|
||||
* statements = the `Statement[]`
|
||||
* to add
|
||||
*/
|
||||
public void addStatements(Statement[] statements);
|
||||
|
||||
/**
|
||||
* Returns the body of this
|
||||
* container
|
||||
*
|
||||
* Returns: a `Statement[]`
|
||||
*/
|
||||
public Statement[] getStatements();
|
||||
}
|
||||
|
||||
|
@ -66,6 +89,7 @@ public class Module : Entity, Container
|
|||
|
||||
public Statement[] getStatements()
|
||||
{
|
||||
// TODO: Holy naai this is expensive
|
||||
return weightReorder(statements);
|
||||
}
|
||||
|
||||
|
@ -166,6 +190,7 @@ public class Struct : Type, Container, MCloneable
|
|||
|
||||
public Statement[] getStatements()
|
||||
{
|
||||
// TODO: Holy naai this is expensive
|
||||
return weightReorder(statements);
|
||||
}
|
||||
|
||||
|
@ -331,6 +356,7 @@ public class Clazz : Type, Container
|
|||
|
||||
public Statement[] getStatements()
|
||||
{
|
||||
// TODO: Holy naai this is expensive
|
||||
return weightReorder(statements);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ import std.container.slist;
|
|||
import std.algorithm : reverse;
|
||||
import tlang.compiler.typecheck.meta;
|
||||
import tlang.compiler.configuration;
|
||||
import tlang.compiler.typecheck.dependency.store.interfaces : IFuncDefStore;
|
||||
import tlang.compiler.typecheck.dependency.store.impls : FuncDefStore;
|
||||
|
||||
/**
|
||||
* The Parser only makes sure syntax
|
||||
|
@ -107,14 +109,6 @@ public final class TypeChecker
|
|||
/* TODO: Implement me */
|
||||
checkClassInherit(modulle);
|
||||
|
||||
// TODO: Issue 88: Don't use static state
|
||||
scope(exit)
|
||||
{
|
||||
/* Clear the FunctionData map (for next compilation) */
|
||||
clearFuncDefs();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dependency tree generation
|
||||
*
|
||||
|
@ -125,8 +119,15 @@ public final class TypeChecker
|
|||
*
|
||||
*/
|
||||
|
||||
// Create a pooling mechanism
|
||||
import tlang.compiler.typecheck.dependency.pool.interfaces;
|
||||
import tlang.compiler.typecheck.dependency.pool.impls;
|
||||
|
||||
|
||||
DNodeGenerator dNodeGenerator = new DNodeGenerator(this);
|
||||
/* Create the dependency generator */
|
||||
IPoolManager poolManager = new PoolManager();
|
||||
IFuncDefStore funcDefStore = new FuncDefStore(this, poolManager);
|
||||
DNodeGenerator dNodeGenerator = new DNodeGenerator(this, poolManager, funcDefStore);
|
||||
|
||||
/* Generate the dependency tree */
|
||||
DNode rootNode = dNodeGenerator.generate(); /* TODO: This should make it acyclic */
|
||||
|
@ -157,7 +158,7 @@ public final class TypeChecker
|
|||
assert(codeQueue.empty() == true);
|
||||
|
||||
/* Grab functionData ??? */
|
||||
FunctionData[string] functionDefinitions = grabFunctionDefs();
|
||||
FunctionData[string] functionDefinitions = funcDefStore.grabFunctionDefs();
|
||||
gprintln("Defined functions: "~to!(string)(functionDefinitions));
|
||||
|
||||
foreach(FunctionData funcData; functionDefinitions.values)
|
||||
|
@ -209,8 +210,6 @@ public final class TypeChecker
|
|||
gprintln("FUNCDEF DONE: "~to!(string)(functionBodyCodeQueues[funcData.name]));
|
||||
}
|
||||
|
||||
// NOTE: Check scope guard for "exit routines" which run here
|
||||
|
||||
/* Collect statistics */
|
||||
doPostChecks();
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ public class ObjectInitializationNode : DNode
|
|||
/* Object actual type */
|
||||
private Clazz clazz;
|
||||
|
||||
this(DNodeGenerator dnodegen, Clazz objectActualType, NewExpression entity)
|
||||
this(Clazz objectActualType, NewExpression entity)
|
||||
{
|
||||
super(dnodegen, entity);
|
||||
super(entity);
|
||||
|
||||
// this.newExpression = entity;
|
||||
this.clazz = objectActualType;
|
||||
|
|
|
@ -13,19 +13,22 @@ import tlang.compiler.typecheck.core;
|
|||
import tlang.compiler.symbols.typing.core;
|
||||
import tlang.compiler.symbols.typing.builtins;
|
||||
import tlang.compiler.typecheck.dependency.core;
|
||||
import std.conv : to;
|
||||
|
||||
public class ClassStaticNode : DNode
|
||||
{
|
||||
private Clazz entity;
|
||||
|
||||
this(DNodeGenerator dnodegen, Clazz entity)
|
||||
this(Clazz entity)
|
||||
{
|
||||
super(dnodegen, entity);
|
||||
super(entity);
|
||||
|
||||
this.entity = entity;
|
||||
initName();
|
||||
}
|
||||
|
||||
private void initName()
|
||||
{
|
||||
name = "ClassStaticInit: "~resolver.generateName(cast(Container)dnodegen.root.getEntity(), cast(Entity)entity);
|
||||
name = "ClassStaticInit: "~to!(string)(entity);
|
||||
}
|
||||
}
|
|
@ -13,11 +13,23 @@ import tlang.compiler.typecheck.core;
|
|||
import tlang.compiler.symbols.typing.core;
|
||||
import tlang.compiler.symbols.typing.builtins;
|
||||
import tlang.compiler.typecheck.dependency.core;
|
||||
import std.conv : to;
|
||||
|
||||
|
||||
public class ClassVirtualInit : DNode
|
||||
{
|
||||
this(DNodeGenerator dnodegen, Clazz clazz)
|
||||
private Clazz clazz;
|
||||
|
||||
this(Clazz clazz)
|
||||
{
|
||||
super(dnodegen, clazz);
|
||||
super(clazz);
|
||||
|
||||
this.clazz = clazz;
|
||||
initName();
|
||||
}
|
||||
|
||||
private void initName()
|
||||
{
|
||||
name = "ClassVirtualInit: "~to!(string)(clazz);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,9 @@ import tlang.compiler.typecheck.core;
|
|||
import tlang.compiler.symbols.typing.core;
|
||||
import tlang.compiler.symbols.typing.builtins;
|
||||
import tlang.compiler.typecheck.dependency.exceptions : DependencyException, DependencyError;
|
||||
import tlang.compiler.typecheck.dependency.pool.interfaces;
|
||||
import tlang.compiler.typecheck.dependency.pool.impls;
|
||||
import tlang.compiler.typecheck.dependency.store.interfaces : IFuncDefStore;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -91,72 +94,6 @@ public struct FunctionData
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All declared functions
|
||||
*/
|
||||
private FunctionData[string] functions;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the declared functions
|
||||
*/
|
||||
public FunctionData[string] grabFunctionDefs()
|
||||
{
|
||||
return functions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clars the `FunctionData[string]` map
|
||||
*
|
||||
* This is called normally after the
|
||||
* typechecking and code generation such
|
||||
* that the module-static field inside
|
||||
* this module can be cleared and not
|
||||
* persist across compilations
|
||||
*/
|
||||
public void clearFuncDefs()
|
||||
{
|
||||
foreach(string key; functions.keys())
|
||||
{
|
||||
functions.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FunctionData and adds it to the
|
||||
* list of declared functions
|
||||
*
|
||||
* Requires a TypeChecker `tc`
|
||||
*/
|
||||
private void addFunctionDef(TypeChecker tc, 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)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the FunctionData, coupled with it own DNodeGenerator
|
||||
* context etc.
|
||||
*/
|
||||
FunctionData funcData;
|
||||
funcData.ownGenerator = new DFunctionInnerGenerator(tc, func);
|
||||
funcData.name = func.getName();
|
||||
funcData.func = func;
|
||||
|
||||
|
||||
functions[funcData.name] = funcData;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* DNode
|
||||
*
|
||||
|
@ -172,18 +109,13 @@ public class DNode
|
|||
|
||||
protected string name;
|
||||
|
||||
protected DNodeGenerator dnodegen;
|
||||
protected Resolver resolver;
|
||||
|
||||
private bool visited;
|
||||
private bool complete;
|
||||
private DNode[] dependencies;
|
||||
|
||||
this(DNodeGenerator dnodegen, Statement entity)
|
||||
this(Statement entity)
|
||||
{
|
||||
this.entity = entity;
|
||||
this.dnodegen = dnodegen;
|
||||
this.resolver = dnodegen.resolver;
|
||||
|
||||
initName();
|
||||
}
|
||||
|
@ -408,9 +340,9 @@ public final class DFunctionInnerGenerator : DNodeGenerator
|
|||
{
|
||||
private Function func;
|
||||
|
||||
this(TypeChecker tc, Function func)
|
||||
this(TypeChecker tc, IPoolManager poolManager, IFuncDefStore funcDefStore, Function func)
|
||||
{
|
||||
super(tc);
|
||||
super(tc, poolManager, funcDefStore);
|
||||
this.func = func;
|
||||
}
|
||||
|
||||
|
@ -441,56 +373,29 @@ public class DNodeGenerator
|
|||
*/
|
||||
private DNode[string] functionDefinitions;
|
||||
|
||||
/**
|
||||
* Given a DNode generated by a Function (function definition)
|
||||
* this will extract the name of the function and save the DNode
|
||||
* into the map for later retrieval by `retrieveFunctionDefinitionNode`
|
||||
*/
|
||||
private void saveFunctionDefinitionNode(DNode funcDefNode)
|
||||
{
|
||||
gprintln("saveFunctionDefinitionNode: Implement me please");
|
||||
private IFuncDefStore funcDefStore;
|
||||
|
||||
// Extract the name of the function
|
||||
Function functionDefinition = cast(Function)funcDefNode.getEntity();
|
||||
assert(functionDefinition);
|
||||
string functionNameAbsolutePath = resolver.generateName(cast(Container)root.getEntity(), cast(Entity)functionDefinition);
|
||||
/**
|
||||
* Dependency node pooling
|
||||
* management
|
||||
*/
|
||||
private IPoolManager poolManager;
|
||||
|
||||
// Save to the map
|
||||
functionDefinitions[functionNameAbsolutePath] = funcDefNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the absolute path to a function, this will retrieve the
|
||||
* Function (function definition) DNode from the map
|
||||
*/
|
||||
private DNode retrieveFunctionDefinitionNode(string functionAbsolutePath)
|
||||
{
|
||||
gprintln("retrieveFunctionDefinitionNode: Implement me please");
|
||||
|
||||
// TODO: Add an assertion for failed lookup
|
||||
return functionDefinitions[functionAbsolutePath];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DNode pool
|
||||
*
|
||||
* This holds unique pool entries
|
||||
*/
|
||||
private static DNode[] nodePool;
|
||||
|
||||
this(TypeChecker tc)
|
||||
this(TypeChecker tc, IPoolManager poolManager, IFuncDefStore funcDefStore)
|
||||
{
|
||||
// /* NOTE: NEW STUFF 1st Oct 2022 */
|
||||
// Module modulle = tc.getModule();
|
||||
// Context context = new Context(modulle, InitScope.STATIC);
|
||||
// super(tc, context, context.getContainer().getStatements());
|
||||
|
||||
|
||||
|
||||
// TODO: See if we can pass it in rather, but
|
||||
// ... because this needs a this we must make
|
||||
// ... it here
|
||||
this.poolManager = poolManager;
|
||||
|
||||
this.tc = tc;
|
||||
this.resolver = tc.getResolver();
|
||||
this.funcDefStore = funcDefStore;
|
||||
|
||||
/* TODO: Make this call in the TypeChecker instance */
|
||||
//generate();
|
||||
|
@ -529,23 +434,7 @@ public class DNodeGenerator
|
|||
|
||||
private DNode pool(Statement entity)
|
||||
{
|
||||
foreach(DNode dnode; nodePool)
|
||||
{
|
||||
if(dnode.getEntity() == entity)
|
||||
{
|
||||
return dnode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If no DNode is found that is associated with
|
||||
* the provided Entity then create a new one and
|
||||
* pool it
|
||||
*/
|
||||
DNode newDNode = new DNode(this, entity);
|
||||
nodePool ~= newDNode;
|
||||
|
||||
return newDNode;
|
||||
return this.poolManager.pool(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -555,23 +444,27 @@ public class DNodeGenerator
|
|||
*/
|
||||
private DNodeType poolT(DNodeType, EntityType)(EntityType entity)
|
||||
{
|
||||
foreach(DNode dnode; nodePool)
|
||||
static if(__traits(isSame, DNodeType, ExpressionDNode))
|
||||
{
|
||||
if(dnode.getEntity() == entity)
|
||||
{
|
||||
return cast(DNodeType)dnode;
|
||||
}
|
||||
return this.poolManager.poolExpression(cast(Expression)entity);
|
||||
}
|
||||
else static if(__traits(isSame, DNodeType, VariableNode))
|
||||
{
|
||||
return this.poolManager.poolVariable(cast(Variable)entity);
|
||||
}
|
||||
else static if(__traits(isSame, DNodeType, StaticVariableDeclaration))
|
||||
{
|
||||
return this.poolManager.poolStaticVariable(cast(Variable)entity);
|
||||
}
|
||||
else static if(__traits(isSame, DNodeType, FuncDecNode))
|
||||
{
|
||||
return this.poolManager.poolFuncDec(cast(Function)entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
pragma(msg, "This is an invalid case");
|
||||
static assert(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* If no DNode is found that is associated with
|
||||
* the provided Entity then create a new one and
|
||||
* pool it
|
||||
*/
|
||||
DNodeType newDNode = new DNodeType(this, entity);
|
||||
nodePool ~= newDNode;
|
||||
|
||||
return newDNode;
|
||||
}
|
||||
|
||||
|
||||
|
@ -601,7 +494,7 @@ public class DNodeGenerator
|
|||
{
|
||||
/* We don't pool anything here - a constructor call is unique */
|
||||
|
||||
ObjectInitializationNode node = new ObjectInitializationNode(this, clazz, newExpression);
|
||||
ObjectInitializationNode node = new ObjectInitializationNode(clazz, newExpression);
|
||||
|
||||
|
||||
/* TODO: Call a virtual pass over the class */
|
||||
|
@ -1036,23 +929,7 @@ public class DNodeGenerator
|
|||
import tlang.compiler.typecheck.dependency.variables;
|
||||
private ModuleVariableDeclaration pool_module_vardec(Variable entity)
|
||||
{
|
||||
foreach(DNode dnode; nodePool)
|
||||
{
|
||||
if(dnode.getEntity() == entity)
|
||||
{
|
||||
return cast(ModuleVariableDeclaration)dnode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If no DNode is found that is associated with
|
||||
* the provided Entity then create a new one and
|
||||
* pool it
|
||||
*/
|
||||
ModuleVariableDeclaration newDNode = new ModuleVariableDeclaration(this, entity);
|
||||
nodePool ~= newDNode;
|
||||
|
||||
return newDNode;
|
||||
return this.poolManager.poolModuleVariableDeclaration(entity);
|
||||
}
|
||||
|
||||
// TODO: Work in progress
|
||||
|
@ -1289,7 +1166,7 @@ public class DNodeGenerator
|
|||
|
||||
/* Add funtion definition */
|
||||
gprintln("Hello");
|
||||
addFunctionDef(tc, func);
|
||||
this.funcDefStore.addFunctionDef(func);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -1636,25 +1513,7 @@ public class DNodeGenerator
|
|||
// assert(clazz.getModifierType() == InitScope.STATIC);
|
||||
}
|
||||
|
||||
|
||||
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(this, clazz);
|
||||
nodePool ~= newDNode;
|
||||
|
||||
return newDNode;
|
||||
return this.poolManager.poolClassStatic(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,12 +13,13 @@ import tlang.compiler.typecheck.core;
|
|||
import tlang.compiler.symbols.typing.core;
|
||||
import tlang.compiler.symbols.typing.builtins;
|
||||
import tlang.compiler.typecheck.dependency.core;
|
||||
import std.conv : to;
|
||||
|
||||
public class ExpressionDNode : DNode
|
||||
{
|
||||
this(DNodeGenerator dnodegen, Expression entity)
|
||||
this(Expression entity)
|
||||
{
|
||||
super(dnodegen, entity);
|
||||
super(entity);
|
||||
|
||||
initName();
|
||||
}
|
||||
|
@ -52,14 +53,16 @@ public class ExpressionDNode : DNode
|
|||
*/
|
||||
public class AccessDNode : DNode
|
||||
{
|
||||
private Entity entity;
|
||||
|
||||
/**
|
||||
* Construct a new AccessNode given the `entity`
|
||||
* being accessed
|
||||
*/
|
||||
this(DNodeGenerator dnodegen, Entity entity)
|
||||
this(Entity entity)
|
||||
{
|
||||
super(dnodegen, entity);
|
||||
// this.entity = entity;
|
||||
super(entity);
|
||||
this.entity = entity;
|
||||
|
||||
|
||||
initName();
|
||||
|
@ -67,8 +70,6 @@ public class AccessDNode : DNode
|
|||
|
||||
private void initName()
|
||||
{
|
||||
name = resolver.generateName(cast(Container)dnodegen.root.getEntity(), cast(Entity)entity);
|
||||
name = "[AccessNode] (Name: "~name~")";
|
||||
|
||||
name = "[AccessNode] (Name: "~to!(string)(entity)~")";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ module tlang.compiler.typecheck.dependency.variables;
|
|||
|
||||
import tlang.compiler.typecheck.dependency.core;
|
||||
import tlang.compiler.symbols.data;
|
||||
import std.conv : to;
|
||||
|
||||
/**
|
||||
* This module holds types related to variable declarations
|
||||
|
@ -15,9 +16,9 @@ public class VariableNode : DNode
|
|||
{
|
||||
private Variable variable;
|
||||
|
||||
this(DNodeGenerator dnodegen, Variable variable)
|
||||
this(Variable variable)
|
||||
{
|
||||
super(dnodegen, variable);
|
||||
super(variable);
|
||||
|
||||
this.variable = variable;
|
||||
|
||||
|
@ -26,60 +27,55 @@ public class VariableNode : DNode
|
|||
|
||||
private void initName()
|
||||
{
|
||||
name = resolver.generateName(cast(Container)dnodegen.root.getEntity(), cast(Entity)entity);
|
||||
name = to!(string)(variable);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class FuncDecNode : DNode
|
||||
{
|
||||
private Function funcHandle;
|
||||
|
||||
this(DNodeGenerator dnodegen, Function funcHandle)
|
||||
this(Function funcHandle)
|
||||
{
|
||||
super(dnodegen, funcHandle);
|
||||
super(funcHandle);
|
||||
|
||||
this.funcHandle = funcHandle;
|
||||
|
||||
initName();
|
||||
}
|
||||
|
||||
private void initName()
|
||||
{
|
||||
name = "FuncHandle:"~resolver.generateName(cast(Container)dnodegen.root.getEntity(), cast(Entity)entity);
|
||||
name = "FuncHandle:"~to!(string)(funcHandle);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ModuleVariableDeclaration : VariableNode
|
||||
{
|
||||
this(DNodeGenerator dnodegen, Variable variable)
|
||||
this(Variable variable)
|
||||
{
|
||||
super(dnodegen, variable);
|
||||
super(variable);
|
||||
|
||||
initName();
|
||||
}
|
||||
|
||||
private void initName()
|
||||
{
|
||||
name = "(S) "~resolver.generateName(cast(Container)dnodegen.root.getEntity(), cast(Entity)entity);
|
||||
name = "(S) "~to!(string)(variable);
|
||||
}
|
||||
}
|
||||
|
||||
public class StaticVariableDeclaration : VariableNode
|
||||
{
|
||||
this(DNodeGenerator dnodegen, Variable variable)
|
||||
this(Variable variable)
|
||||
{
|
||||
super(dnodegen, variable);
|
||||
super(variable);
|
||||
|
||||
initName();
|
||||
}
|
||||
|
||||
private void initName()
|
||||
{
|
||||
name = "(S) "~resolver.generateName(cast(Container)dnodegen.root.getEntity(), cast(Entity)entity);
|
||||
name = "(S) "~to!(string)(variable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,12 +83,11 @@ public class VariableAssignmentNode : DNode
|
|||
{
|
||||
private VariableAssignment variableAssignment;
|
||||
|
||||
this(DNodeGenerator dnodegen, VariableAssignment variableAssignment)
|
||||
this(VariableAssignment variableAssignment)
|
||||
{
|
||||
super(dnodegen, variableAssignment);
|
||||
super(variableAssignment);
|
||||
|
||||
this.variableAssignment = variableAssignment;
|
||||
|
||||
initName();
|
||||
}
|
||||
|
||||
|
@ -101,6 +96,6 @@ public class VariableAssignmentNode : DNode
|
|||
/* get the associated variable */
|
||||
Variable associatedVariable = variableAssignment.getVariable();
|
||||
|
||||
name = resolver.generateName(cast(Container)dnodegen.root.getEntity(), associatedVariable)~" (assignment)";
|
||||
name = to!(string)(associatedVariable)~" (assignment)";
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue