Auto declarations support

This commit is contained in:
Hackerpilot 2014-08-07 15:59:21 -07:00
parent d620f2428a
commit 8fadaba6ea
3 changed files with 156 additions and 6 deletions

View File

@ -188,11 +188,12 @@ final class FirstPass : ASTVisitor
}
if (dec.autoDeclaration !is null)
{
foreach (identifier; dec.autoDeclaration.identifiers)
foreach (i, identifier; dec.autoDeclaration.identifiers)
{
SemanticSymbol* symbol = allocateSemanticSymbol(
identifier.text, CompletionKind.variableName, symbolFile,
identifier.index, null);
populateInitializer(symbol, dec.autoDeclaration.initializers[i]);
symbol.protection = protection;
symbol.parent = currentSymbol;
symbol.acSymbol.doc = internString(dec.comment);
@ -525,6 +526,12 @@ private:
return internString(cast(string) app[]);
}
void populateInitializer(SemanticSymbol* symbol, const Initializer initializer)
{
auto visitor = scoped!InitializerVisitor(symbol);
visitor.visit(initializer);
}
SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind,
string symbolFile, size_t location = 0, const Type type = null)
in
@ -598,3 +605,99 @@ static string convertChainToImportPath(const IdentifierChain ic)
}
return internString(cast(string) app[]);
}
class InitializerVisitor : ASTVisitor
{
this (SemanticSymbol* semanticSymbol)
{
this.semanticSymbol = semanticSymbol;
}
alias visit = ASTVisitor.visit;
override void visit(const IdentifierOrTemplateInstance ioti)
{
if (on && ioti.identifier != tok!"")
semanticSymbol.initializer.insert(ioti.identifier.text);
ioti.accept(this);
}
override void visit(const PrimaryExpression primary)
{
// Add identifiers without processing. Convert literals to strings with
// the prefix '*' so that that the third pass can tell the difference
// between "int.abc" and "10.abc".
if (on && primary.basicType != tok!"")
semanticSymbol.initializer.insert(str(primary.basicType.type));
if (on) switch (primary.primary.type)
{
case tok!"identifier":
semanticSymbol.initializer.insert(primary.primary.text);
break;
case tok!"doubleLiteral":
semanticSymbol.initializer.insert("*double");
break;
case tok!"floatLiteral":
semanticSymbol.initializer.insert("*float");
break;
case tok!"idoubleLiteral":
semanticSymbol.initializer.insert("*idouble");
break;
case tok!"ifloatLiteral":
semanticSymbol.initializer.insert("*ifloat");
break;
case tok!"intLiteral":
semanticSymbol.initializer.insert("*int");
break;
case tok!"longLiteral":
semanticSymbol.initializer.insert("*long");
break;
case tok!"realLiteral":
semanticSymbol.initializer.insert("*real");
break;
case tok!"irealLiteral":
semanticSymbol.initializer.insert("*ireal");
break;
case tok!"uintLiteral":
semanticSymbol.initializer.insert("*uint");
break;
case tok!"ulongLiteral":
semanticSymbol.initializer.insert("*ulong");
break;
case tok!"characterLiteral":
semanticSymbol.initializer.insert("*char");
break;
case tok!"dstringLiteral":
semanticSymbol.initializer.insert("*dstring");
break;
case tok!"stringLiteral":
semanticSymbol.initializer.insert("*string");
break;
case tok!"wstringLiteral":
semanticSymbol.initializer.insert("*wstring");
break;
default:
break;
}
primary.accept(this);
}
override void visit(const UnaryExpression unary)
{
unary.accept(this);
if (unary.indexExpression)
semanticSymbol.initializer.insert("[]");
}
override void visit(const ArgumentList) {}
override void visit(const Initializer initializer)
{
on = true;
initializer.accept(this);
on = false;
}
SemanticSymbol* semanticSymbol;
bool on = false;
}

View File

@ -74,8 +74,8 @@ private:
case memberVariableName:
case functionName:
case aliasName:
ACSymbol* t = resolveType(currentSymbol.type,
currentSymbol.acSymbol.location);
ACSymbol* t = resolveType(currentSymbol.initializer,
currentSymbol.type, currentSymbol.acSymbol.location);
while (t !is null && t.kind == CompletionKind.aliasName)
t = t.type;
currentSymbol.acSymbol.type = t;
@ -154,15 +154,59 @@ private:
// TODO:
}
ACSymbol* resolveType(const Type t, size_t location)
ACSymbol* resolveInitializerType(I)(ref const I initializer, size_t location)
{
if (t is null) return null;
if (initializer.empty)
return null;
// import stupidlog;
// Log.trace("resolveInitializerType: ", __LINE__, ":", initializer[]);
auto slice = initializer[];
bool literal = slice.front[0] == '*';
if (literal && initializer.length > 1)
{
// Log.trace("Popping ", slice.front, " from slice");
slice.popFront();
literal = false;
}
auto symbols = moduleScope.getSymbolsByNameAndCursor(internString(
literal ? slice.front[1 .. $] : slice.front), location);
if (symbols.length == 0)
{
// Log.trace("Could not find ", literal ? slice.front[1 .. $] : slice.front);
return null;
}
if (literal)
return symbols[0];
slice.popFront();
auto s = symbols[0];
while (s !is null && s.type !is null && !slice.empty)
{
s = s.type;
// Log.trace("resolveInitializerType: ", __LINE__, ":", slice.front);
if (slice.front == "[]")
s = s.type;
else
{
auto parts = s.getPartsByName(internString(slice.front));
if (parts.length == 0)
return null;
s = parts[0];
}
slice.popFront();
}
return s;
}
ACSymbol* resolveType(I)(ref const I initializer, const Type t, size_t location)
{
if (t is null)
return resolveInitializerType(initializer, location);
if (t.type2 is null) return null;
ACSymbol* s;
if (t.type2.builtinType != tok!"")
s = convertBuiltinType(t.type2);
else if (t.type2.typeConstructor != tok!"")
s = resolveType(t.type2.type, location);
s = resolveType(initializer, t.type2.type, location);
else if (t.type2.symbol !is null)
{
// TODO: global scoped symbol handling

View File

@ -87,6 +87,9 @@ public:
/// Child symbols
UnrolledList!(SemanticSymbol*) children;
/// Assign expression identifier chain used for auto declarations
UnrolledList!(string) initializer;
}
/**