Auto declarations support
This commit is contained in:
parent
d620f2428a
commit
8fadaba6ea
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ public:
|
|||
|
||||
/// Child symbols
|
||||
UnrolledList!(SemanticSymbol*) children;
|
||||
|
||||
/// Assign expression identifier chain used for auto declarations
|
||||
UnrolledList!(string) initializer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue