Merge branch 'extern_symbols' into vardec_varass_dependency
This commit is contained in:
commit
8edc03e3f3
|
@ -127,23 +127,33 @@ public final class DCodeEmitter : CodeEmitter
|
|||
gprintln("Wazza contect: "~to!(string)(context.container));
|
||||
auto typedEntityVariable = context.tc.getResolver().resolveBest(context.getContainer(), varAs.varName); //TODO: Remove `auto`
|
||||
|
||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
||||
|
||||
|
||||
// If we are needed as part of a VariabvleDeclaration-with-assignment
|
||||
if(varDecWantsConsumeVarAss)
|
||||
/* If it is not external */
|
||||
if(!typedEntityVariable.isExternal())
|
||||
{
|
||||
// Generate the code to emit (only the RHS of the = sign)
|
||||
string emitCode = transform(varAs.data);
|
||||
string renamedSymbol = SymbolMapper.symbolLookup(typedEntityVariable);
|
||||
|
||||
// Reset flag
|
||||
varDecWantsConsumeVarAss = false;
|
||||
|
||||
// If we are needed as part of a VariabvleDeclaration-with-assignment
|
||||
if(varDecWantsConsumeVarAss)
|
||||
{
|
||||
// Generate the code to emit (only the RHS of the = sign)
|
||||
string emitCode = transform(varAs.data);
|
||||
|
||||
return emitCode;
|
||||
// Reset flag
|
||||
varDecWantsConsumeVarAss = false;
|
||||
|
||||
return emitCode;
|
||||
}
|
||||
|
||||
|
||||
return renamedSymbol~" = "~transform(varAs.data)~";";
|
||||
}
|
||||
/* If it is external */
|
||||
else
|
||||
{
|
||||
return typedEntityVariable.getName()~" = "~transform(varAs.data)~";";
|
||||
}
|
||||
|
||||
|
||||
return renamedSymbol~" = "~transform(varAs.data)~";";
|
||||
}
|
||||
/* VariableDeclaration */
|
||||
else if(cast(VariableDeclaration)instruction)
|
||||
|
@ -155,36 +165,44 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), varDecInstr.varName); //TODO: Remove `auto`
|
||||
|
||||
//NOTE: We should remove all dots from generated symbol names as it won't be valid C (I don't want to say C because
|
||||
// a custom CodeEmitter should be allowed, so let's call it a general rule)
|
||||
//
|
||||
//simple_variables.x -> simple_variables_x
|
||||
//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);
|
||||
|
||||
|
||||
// Check to see if this declaration has an assignment attached
|
||||
if(typedEntityVariable.getAssignment())
|
||||
/* If the variable is not external */
|
||||
if(!typedEntityVariable.isExternal())
|
||||
{
|
||||
// Set flag to expect different transform generation for VariableAssignment
|
||||
varDecWantsConsumeVarAss = true;
|
||||
//NOTE: We should remove all dots from generated symbol names as it won't be valid C (I don't want to say C because
|
||||
// a custom CodeEmitter should be allowed, so let's call it a general rule)
|
||||
//
|
||||
//simple_variables.x -> simple_variables_x
|
||||
//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);
|
||||
|
||||
// Fetch the variable assignment instruction
|
||||
// gprintln("Before crash: "~to!(string)(getCurrentInstruction()));
|
||||
// nextInstruction();
|
||||
// Instruction varAssInstr = getCurrentInstruction();
|
||||
|
||||
VariableAssignmentInstr varAssInstr = varDecInstr.getAssignmentInstr();
|
||||
|
||||
// Generate the code to emit
|
||||
return typeTransform(cast(Type)varDecInstr.varType)~" "~renamedSymbol~" = "~transform(varAssInstr)~";";
|
||||
// Check to see if this declaration has an assignment attached
|
||||
if(typedEntityVariable.getAssignment())
|
||||
{
|
||||
// Set flag to expect different transform generation for VariableAssignment
|
||||
varDecWantsConsumeVarAss = true;
|
||||
|
||||
// Fetch the variable assignment instruction
|
||||
// gprintln("Before crash: "~to!(string)(getCurrentInstruction()));
|
||||
// nextInstruction();
|
||||
// Instruction varAssInstr = getCurrentInstruction();
|
||||
|
||||
VariableAssignmentInstr varAssInstr = varDecInstr.getAssignmentInstr();
|
||||
|
||||
// Generate the code to emit
|
||||
return typeTransform(cast(Type)varDecInstr.varType)~" "~renamedSymbol~" = "~transform(varAssInstr)~";";
|
||||
}
|
||||
|
||||
return typeTransform(cast(Type)varDecInstr.varType)~" "~renamedSymbol~";";
|
||||
}
|
||||
/* If the variable is external */
|
||||
else
|
||||
{
|
||||
return "extern "~typeTransform(cast(Type)varDecInstr.varType)~" "~typedEntityVariable.getName()~";";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return typeTransform(cast(Type)varDecInstr.varType)~" "~renamedSymbol~";";
|
||||
}
|
||||
/* LiteralValue */
|
||||
else if(cast(LiteralValue)instruction)
|
||||
|
@ -205,12 +223,21 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
Variable typedEntityVariable = cast(Variable)context.tc.getResolver().resolveBest(context.getContainer(), fetchValueVarInstr.varName); //TODO: Remove `auto`
|
||||
|
||||
//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)
|
||||
/* If it is not external */
|
||||
if(!typedEntityVariable.isExternal())
|
||||
{
|
||||
//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 = SymbolMapper.symbolLookup(typedEntityVariable);
|
||||
|
||||
return renamedSymbol;
|
||||
return renamedSymbol;
|
||||
}
|
||||
/* If it is external */
|
||||
else
|
||||
{
|
||||
return typedEntityVariable.getName();
|
||||
}
|
||||
}
|
||||
/* BinOpInstr */
|
||||
else if(cast(BinOpInstr)instruction)
|
||||
|
@ -499,6 +526,8 @@ public final class DCodeEmitter : CodeEmitter
|
|||
|
||||
return emit;
|
||||
}
|
||||
// TODO: MAAAAN we don't even have this yet
|
||||
// else if(cast(StringExpression))
|
||||
|
||||
return "<TODO: Base emit: "~to!(string)(instruction)~">";
|
||||
}
|
||||
|
@ -658,6 +687,12 @@ public final class DCodeEmitter : CodeEmitter
|
|||
// )
|
||||
signature~=")";
|
||||
|
||||
// If the function is marked as external then place `extern` infront
|
||||
if(func.isExternal())
|
||||
{
|
||||
signature = "extern "~signature;
|
||||
}
|
||||
|
||||
return signature;
|
||||
|
||||
}
|
||||
|
@ -686,26 +721,35 @@ public final class DCodeEmitter : CodeEmitter
|
|||
//TODO: And what about methods defined in classes? Those should technically be here too
|
||||
Function functionEntity = cast(Function)typeChecker.getResolver().resolveBest(typeChecker.getModule(), functionName); //TODO: Remove `auto`
|
||||
|
||||
// Emit the function signature
|
||||
file.writeln(generateSignature(functionEntity));
|
||||
|
||||
// Emit opening curly brace
|
||||
file.writeln(getCharacter(SymbolType.OCURLY));
|
||||
|
||||
// Emit body
|
||||
while(hasInstructions())
|
||||
// If the Entity is NOT external then emit the signature+body
|
||||
if(!functionEntity.isExternal())
|
||||
{
|
||||
Instruction curFuncBodyInstr = getCurrentInstruction();
|
||||
// Emit the function signature
|
||||
file.writeln(generateSignature(functionEntity));
|
||||
|
||||
string emit = transform(curFuncBodyInstr);
|
||||
gprintln("emitFunctionDefinition("~functionName~"): Emit: "~emit);
|
||||
file.writeln("\t"~emit);
|
||||
|
||||
nextInstruction();
|
||||
// Emit opening curly brace
|
||||
file.writeln(getCharacter(SymbolType.OCURLY));
|
||||
|
||||
// Emit body
|
||||
while(hasInstructions())
|
||||
{
|
||||
Instruction curFuncBodyInstr = getCurrentInstruction();
|
||||
|
||||
string emit = transform(curFuncBodyInstr);
|
||||
gprintln("emitFunctionDefinition("~functionName~"): Emit: "~emit);
|
||||
file.writeln("\t"~emit);
|
||||
|
||||
nextInstruction();
|
||||
}
|
||||
|
||||
// Emit closing curly brace
|
||||
file.writeln(getCharacter(SymbolType.CCURLY));
|
||||
}
|
||||
// If the Entity IS external then don't emit anything as the signature would have been emitted via a prorotype earlier with `emitPrototypes()`
|
||||
else
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// Emit closing curly brace
|
||||
file.writeln(getCharacter(SymbolType.CCURLY));
|
||||
}
|
||||
|
||||
private void emitCodeQueue()
|
||||
|
@ -790,6 +834,20 @@ int main()
|
|||
assert(t_87bc875d0b65f741b69fb100a0edebc7 == 4);
|
||||
assert(retValue == 6);
|
||||
|
||||
return 0;
|
||||
}`);
|
||||
}
|
||||
else if(cmp(typeChecker.getModule().getName(), "simple_extern") == 0)
|
||||
{
|
||||
file.writeln(`
|
||||
#include<stdio.h>
|
||||
#include<assert.h>
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}`);
|
||||
}
|
||||
|
|
|
@ -450,6 +450,24 @@ public final class Parser
|
|||
{
|
||||
previousToken();
|
||||
ret = parseTypedDeclaration();
|
||||
|
||||
/* If it is a function definition, then do nothing */
|
||||
if(cast(Function)ret)
|
||||
{
|
||||
// The ending `}` would have already been consumed
|
||||
}
|
||||
/* If it is a variable declaration then */
|
||||
else if(cast(Variable)ret)
|
||||
{
|
||||
/* Expect a semicolon and consume it */
|
||||
expect(SymbolType.SEMICOLON, getCurrentToken());
|
||||
nextToken();
|
||||
}
|
||||
/* This should never happen */
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
/* Assignment */
|
||||
else if(type == SymbolType.ASSIGN)
|
||||
|
@ -462,7 +480,6 @@ public final class Parser
|
|||
{
|
||||
gprintln(getCurrentToken);
|
||||
expect("Error expected ( for var/func def");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -854,7 +871,7 @@ public final class Parser
|
|||
VariableParameter[] params;
|
||||
}
|
||||
|
||||
private funcDefPair parseFuncDef()
|
||||
private funcDefPair parseFuncDef(bool wantsBody = true)
|
||||
{
|
||||
gprintln("parseFuncDef(): Enter", DebugType.WARNING);
|
||||
|
||||
|
@ -938,11 +955,21 @@ public final class Parser
|
|||
}
|
||||
}
|
||||
|
||||
expect(SymbolType.OCURLY, getCurrentToken());
|
||||
/* If a body is required then allow it */
|
||||
if(wantsBody)
|
||||
{
|
||||
expect(SymbolType.OCURLY, getCurrentToken());
|
||||
|
||||
/* Parse the body (and it leaves ONLY when it gets the correct symbol, no expect needed) */
|
||||
statements = parseBody();
|
||||
nextToken();
|
||||
/* Parse the body (and it leaves ONLY when it gets the correct symbol, no expect needed) */
|
||||
statements = parseBody();
|
||||
|
||||
nextToken();
|
||||
}
|
||||
/* If no body is requested */
|
||||
else
|
||||
{
|
||||
expect(SymbolType.SEMICOLON, getCurrentToken());
|
||||
}
|
||||
|
||||
gprintln("ParseFuncDef: Parameter count: " ~ to!(string)(parameterCount));
|
||||
gprintln("parseFuncDef(): Leave", DebugType.WARNING);
|
||||
|
@ -1294,7 +1321,7 @@ public final class Parser
|
|||
return retExpression[0];
|
||||
}
|
||||
|
||||
private TypedEntity parseTypedDeclaration()
|
||||
private TypedEntity parseTypedDeclaration(bool wantsBody = true, bool allowVarDec = true, bool allowFuncDef = true)
|
||||
{
|
||||
gprintln("parseTypedDeclaration(): Enter", DebugType.WARNING);
|
||||
|
||||
|
@ -1336,63 +1363,88 @@ public final class Parser
|
|||
gprintln("ParseTypedDec: SymbolType=" ~ to!(string)(symbolType));
|
||||
if (symbolType == SymbolType.LBRACE)
|
||||
{
|
||||
funcDefPair pair = parseFuncDef();
|
||||
// Only continue is function definitions are allowed
|
||||
if(allowFuncDef)
|
||||
{
|
||||
/* Will consume the `}` (or `;` if wantsBody-false) */
|
||||
funcDefPair pair = parseFuncDef(wantsBody);
|
||||
|
||||
generated = new Function(identifier, type, pair.bodyStatements, pair.params);
|
||||
|
||||
import std.stdio;
|
||||
writeln(to!(string)((cast(Function)generated).getVariables()));
|
||||
generated = new Function(identifier, type, pair.bodyStatements, pair.params);
|
||||
|
||||
import std.stdio;
|
||||
writeln(to!(string)((cast(Function)generated).getVariables()));
|
||||
|
||||
// Parent the parameters of the function to the Function
|
||||
parentToContainer(cast(Container)generated, cast(Statement[])pair.params);
|
||||
// Parent the parameters of the function to the Function
|
||||
parentToContainer(cast(Container)generated, cast(Statement[])pair.params);
|
||||
|
||||
// Parent the statements that make up the function to the Function
|
||||
parentToContainer(cast(Container)generated, pair.bodyStatements);
|
||||
// Parent the statements that make up the function to the Function
|
||||
parentToContainer(cast(Container)generated, pair.bodyStatements);
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("Function definitions not allowed");
|
||||
}
|
||||
}
|
||||
/* Check for semi-colon (var dec) */
|
||||
else if (symbolType == SymbolType.SEMICOLON)
|
||||
{
|
||||
nextToken();
|
||||
gprintln("ParseTypedDec: VariableDeclaration: (Type: " ~ type ~ ", Identifier: " ~ identifier ~ ")",
|
||||
DebugType.WARNING);
|
||||
// Only continue if variable declarations are allowed
|
||||
if(allowVarDec)
|
||||
{
|
||||
gprintln("Semi: "~to!(string)(getCurrentToken()));
|
||||
gprintln("Semi: "~to!(string)(getCurrentToken()));
|
||||
gprintln("ParseTypedDec: VariableDeclaration: (Type: " ~ type ~ ", Identifier: " ~ identifier ~ ")",
|
||||
DebugType.WARNING);
|
||||
|
||||
generated = new Variable(type, identifier);
|
||||
generated = new Variable(type, identifier);
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("Variables declarations are not allowed.");
|
||||
}
|
||||
}
|
||||
/* Check for `=` (var dec) */
|
||||
else if (symbolType == SymbolType.ASSIGN)
|
||||
{
|
||||
nextToken();
|
||||
// Only continue if variable declarations are allowed
|
||||
if(allowVarDec)
|
||||
{
|
||||
// Only continue if assignments are allowed
|
||||
if(wantsBody)
|
||||
{
|
||||
/* Consume the `=` token */
|
||||
nextToken();
|
||||
|
||||
/* Now parse an expression */
|
||||
Expression expression = parseExpression();
|
||||
/* Now parse an expression */
|
||||
Expression expression = parseExpression();
|
||||
|
||||
VariableAssignment varAssign = new VariableAssignment(expression);
|
||||
VariableAssignment varAssign = new VariableAssignment(expression);
|
||||
|
||||
/**
|
||||
* The symbol that returned us from `parseExpression` must
|
||||
* be a semi-colon
|
||||
*/
|
||||
expect(SymbolType.SEMICOLON, getCurrentToken());
|
||||
gprintln("ParseTypedDec: VariableDeclarationWithAssingment: (Type: "
|
||||
~ type ~ ", Identifier: " ~ identifier ~ ")", DebugType.WARNING);
|
||||
|
||||
Variable variable = new Variable(type, identifier);
|
||||
variable.addAssignment(varAssign);
|
||||
|
||||
nextToken();
|
||||
varAssign.setVariable(variable);
|
||||
|
||||
gprintln("ParseTypedDec: VariableDeclarationWithAssingment: (Type: "
|
||||
~ type ~ ", Identifier: " ~ identifier ~ ")", DebugType.WARNING);
|
||||
|
||||
Variable variable = new Variable(type, identifier);
|
||||
variable.addAssignment(varAssign);
|
||||
|
||||
varAssign.setVariable(variable);
|
||||
|
||||
generated = variable;
|
||||
generated = variable;
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("Variable assignments+declarations are not allowed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("Variables declarations are not allowed.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("Expected one of the following: (, ; or =");
|
||||
}
|
||||
|
||||
/* TODO: If we outta tokens we should not call this */
|
||||
// gprintln(getCurrentToken());
|
||||
gprintln("parseTypedDeclaration(): Leave", DebugType.WARNING);
|
||||
|
||||
return generated;
|
||||
|
@ -1767,6 +1819,55 @@ public final class Parser
|
|||
return new FunctionCall(functionName, arguments);
|
||||
}
|
||||
|
||||
private ExternStmt parseExtern()
|
||||
{
|
||||
ExternStmt externStmt;
|
||||
|
||||
/* Consume the `extern` token */
|
||||
nextToken();
|
||||
|
||||
/* Expect the next token to be either `efunc` or `evariable` */
|
||||
SymbolType externType = getSymbolType(getCurrentToken());
|
||||
nextToken();
|
||||
|
||||
/* Pseudo-entity */
|
||||
Entity pseudoEntity;
|
||||
|
||||
/* External function symbol */
|
||||
if(externType == SymbolType.EXTERN_EFUNC)
|
||||
{
|
||||
// TODO: (For one below)(we should also disallow somehow assignment) - evar
|
||||
|
||||
// We now parse function definition but with `wantsBody` set to false
|
||||
// indicating no body should be allowed.
|
||||
pseudoEntity = parseTypedDeclaration(false, false, true);
|
||||
}
|
||||
/* External variable symbol */
|
||||
else if(externType == SymbolType.EXTERN_EVAR)
|
||||
{
|
||||
// We now parse a variable declaration but with the `wantsBody` set to false
|
||||
// indicating no assignment should be allowed.
|
||||
pseudoEntity = parseTypedDeclaration(false, true, false);
|
||||
}
|
||||
/* Anything else is invalid */
|
||||
else
|
||||
{
|
||||
expect("Expected either extern function (efunc) or extern variable (evar)");
|
||||
}
|
||||
|
||||
/* Expect a semicolon to end it all and then consume it */
|
||||
expect(SymbolType.SEMICOLON, getCurrentToken());
|
||||
nextToken();
|
||||
|
||||
externStmt = new ExternStmt(pseudoEntity, externType);
|
||||
|
||||
/* Mark the Entity as external */
|
||||
pseudoEntity.makeExternal();
|
||||
|
||||
return externStmt;
|
||||
}
|
||||
|
||||
|
||||
/* Almost like parseBody but has more */
|
||||
/**
|
||||
* TODO: For certain things like `parseClass` we should
|
||||
|
@ -1859,6 +1960,13 @@ public final class Parser
|
|||
/* Add the struct definition to the program */
|
||||
modulle.addStatement(ztruct);
|
||||
}
|
||||
/* If it is an extern */
|
||||
else if(symbol == SymbolType.EXTERN)
|
||||
{
|
||||
ExternStmt externStatement = parseExtern();
|
||||
|
||||
modulle.addStatement(externStatement);
|
||||
}
|
||||
else
|
||||
{
|
||||
expect("parse(): Unknown '" ~ tok.getToken() ~ "'");
|
||||
|
|
|
@ -59,6 +59,9 @@ public enum SymbolType
|
|||
GREATER_THAN_OR_EQUALS,
|
||||
SMALLER_THAN_OR_EQUALS,
|
||||
CAST,
|
||||
EXTERN,
|
||||
EXTERN_EFUNC,
|
||||
EXTERN_EVAR,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
|
@ -317,6 +320,21 @@ public SymbolType getSymbolType(Token tokenIn)
|
|||
{
|
||||
return SymbolType.DELETE;
|
||||
}
|
||||
/* efunc keyword */
|
||||
else if(cmp(token, "efunc") == 0)
|
||||
{
|
||||
return SymbolType.EXTERN_EFUNC;
|
||||
}
|
||||
/* evar keyword */
|
||||
else if(cmp(token, "evar") == 0)
|
||||
{
|
||||
return SymbolType.EXTERN_EVAR;
|
||||
}
|
||||
/* extern keyword */
|
||||
else if(cmp(token, "extern") == 0)
|
||||
{
|
||||
return SymbolType.EXTERN;
|
||||
}
|
||||
/* module keyword */
|
||||
else if(cmp(token, "module") == 0)
|
||||
{
|
||||
|
@ -527,6 +545,10 @@ public string getCharacter(SymbolType symbolIn)
|
|||
{
|
||||
return "&";
|
||||
}
|
||||
else if(symbolIn == SymbolType.SEMICOLON)
|
||||
{
|
||||
return ";";
|
||||
}
|
||||
else
|
||||
{
|
||||
gprintln("getCharacter: No back-mapping for "~to!(string)(symbolIn), DebugType.ERROR);
|
||||
|
|
|
@ -169,9 +169,23 @@ public class Entity : Statement
|
|||
/* Name of the entity (class's name, function's name, variable's name) */
|
||||
protected string name;
|
||||
|
||||
this(string name)
|
||||
/* If this entity is extern'd */
|
||||
private bool isExternalEntity;
|
||||
|
||||
this(string name, bool isExternalEntity = false)
|
||||
{
|
||||
this.name = name;
|
||||
this.isExternalEntity = isExternalEntity;
|
||||
}
|
||||
|
||||
public bool isExternal()
|
||||
{
|
||||
return isExternalEntity;
|
||||
}
|
||||
|
||||
public void makeExternal()
|
||||
{
|
||||
isExternalEntity = true;
|
||||
}
|
||||
|
||||
public void setAccessorType(AccessorType accessorType)
|
||||
|
@ -895,4 +909,41 @@ public final class DiscardStatement : Statement
|
|||
{
|
||||
return "[DiscardStatement: (Exp: "~expression.toString()~")]";
|
||||
}
|
||||
}
|
||||
|
||||
public final class ExternStmt : Statement
|
||||
{
|
||||
// Pseudo entity created
|
||||
private Entity pseudoEntity;
|
||||
|
||||
private SymbolType externType;
|
||||
|
||||
this(Entity pseudoEntity, SymbolType externType)
|
||||
{
|
||||
// External symbols are either external functions or external variables
|
||||
assert(externType == SymbolType.EXTERN_EFUNC || externType == SymbolType.EXTERN_EVAR);
|
||||
|
||||
this.pseudoEntity = pseudoEntity;
|
||||
this.externType = externType;
|
||||
}
|
||||
|
||||
public string getExternalName()
|
||||
{
|
||||
return pseudoEntity.getName();
|
||||
}
|
||||
|
||||
public SymbolType getExternType()
|
||||
{
|
||||
return externType;
|
||||
}
|
||||
|
||||
public Entity getPseudoEntity()
|
||||
{
|
||||
return pseudoEntity;
|
||||
}
|
||||
|
||||
public override string toString()
|
||||
{
|
||||
return "[ExternStatement: (Symbol name: "~getExternalName()~")]";
|
||||
}
|
||||
}
|
|
@ -1273,6 +1273,9 @@ public final class TypeChecker
|
|||
*/
|
||||
public void beginCheck()
|
||||
{
|
||||
/* Process all pseudo entities of the given module */
|
||||
processPseudoEntities(modulle);
|
||||
|
||||
/**
|
||||
* Make sure there are no name collisions anywhere
|
||||
* in the Module with an order of precedence of
|
||||
|
@ -1286,6 +1289,39 @@ public final class TypeChecker
|
|||
dependencyCheck();
|
||||
}
|
||||
|
||||
private void processPseudoEntities(Container c)
|
||||
{
|
||||
/* Collect all `extern` declarations */
|
||||
ExternStmt[] externDeclarations;
|
||||
foreach(Statement curStatement; c.getStatements())
|
||||
{
|
||||
if(cast(ExternStmt)curStatement)
|
||||
{
|
||||
externDeclarations ~= cast(ExternStmt)curStatement;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We could remove them from the container too, means less loops in dependency/core.d
|
||||
|
||||
/* Add each Entity to the container */
|
||||
foreach(ExternStmt curExternStmt; externDeclarations)
|
||||
{
|
||||
SymbolType externType = curExternStmt.getExternType();
|
||||
string externalSymbolName = curExternStmt.getExternalName();
|
||||
Entity pseudoEntity = curExternStmt.getPseudoEntity();
|
||||
|
||||
/* Set the embedded pseudo entity's parent to that of the container */
|
||||
pseudoEntity.parentTo(c);
|
||||
|
||||
c.addStatements([pseudoEntity]);
|
||||
|
||||
assert(this.getResolver().resolveBest(c, externalSymbolName));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void checkClassInherit(Container c)
|
||||
{
|
||||
/* Get all types (Clazz so far) */
|
||||
|
|
|
@ -1535,6 +1535,15 @@ public class DNodeGenerator
|
|||
|
||||
return discardStatementDNode;
|
||||
}
|
||||
/**
|
||||
* Extern statement (ExternStmt)
|
||||
*/
|
||||
else if(cast(ExternStmt)entity)
|
||||
{
|
||||
/* We don't do anything, this is to be handled in typechecker pre-run */
|
||||
/* NOTE: If anything we ought to remove these ExternSTmt nodes during such a process */
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
module simple_extern;
|
||||
|
||||
extern efunc uint write(uint fd, ubyte* buffer, uint count);
|
||||
extern evar int kak;
|
||||
|
||||
void test()
|
||||
{
|
||||
ubyte* buff;
|
||||
discard write(cast(uint)0, buff, cast(uint)1001);
|
||||
|
||||
kak = kak + 1;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
int kak;
|
Loading…
Reference in New Issue