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)
|
if (dec.autoDeclaration !is null)
|
||||||
{
|
{
|
||||||
foreach (identifier; dec.autoDeclaration.identifiers)
|
foreach (i, identifier; dec.autoDeclaration.identifiers)
|
||||||
{
|
{
|
||||||
SemanticSymbol* symbol = allocateSemanticSymbol(
|
SemanticSymbol* symbol = allocateSemanticSymbol(
|
||||||
identifier.text, CompletionKind.variableName, symbolFile,
|
identifier.text, CompletionKind.variableName, symbolFile,
|
||||||
identifier.index, null);
|
identifier.index, null);
|
||||||
|
populateInitializer(symbol, dec.autoDeclaration.initializers[i]);
|
||||||
symbol.protection = protection;
|
symbol.protection = protection;
|
||||||
symbol.parent = currentSymbol;
|
symbol.parent = currentSymbol;
|
||||||
symbol.acSymbol.doc = internString(dec.comment);
|
symbol.acSymbol.doc = internString(dec.comment);
|
||||||
|
|
@ -525,6 +526,12 @@ private:
|
||||||
return internString(cast(string) app[]);
|
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,
|
SemanticSymbol* allocateSemanticSymbol(string name, CompletionKind kind,
|
||||||
string symbolFile, size_t location = 0, const Type type = null)
|
string symbolFile, size_t location = 0, const Type type = null)
|
||||||
in
|
in
|
||||||
|
|
@ -598,3 +605,99 @@ static string convertChainToImportPath(const IdentifierChain ic)
|
||||||
}
|
}
|
||||||
return internString(cast(string) app[]);
|
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 memberVariableName:
|
||||||
case functionName:
|
case functionName:
|
||||||
case aliasName:
|
case aliasName:
|
||||||
ACSymbol* t = resolveType(currentSymbol.type,
|
ACSymbol* t = resolveType(currentSymbol.initializer,
|
||||||
currentSymbol.acSymbol.location);
|
currentSymbol.type, currentSymbol.acSymbol.location);
|
||||||
while (t !is null && t.kind == CompletionKind.aliasName)
|
while (t !is null && t.kind == CompletionKind.aliasName)
|
||||||
t = t.type;
|
t = t.type;
|
||||||
currentSymbol.acSymbol.type = t;
|
currentSymbol.acSymbol.type = t;
|
||||||
|
|
@ -154,15 +154,59 @@ private:
|
||||||
// TODO:
|
// 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;
|
if (t.type2 is null) return null;
|
||||||
ACSymbol* s;
|
ACSymbol* s;
|
||||||
if (t.type2.builtinType != tok!"")
|
if (t.type2.builtinType != tok!"")
|
||||||
s = convertBuiltinType(t.type2);
|
s = convertBuiltinType(t.type2);
|
||||||
else if (t.type2.typeConstructor != tok!"")
|
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)
|
else if (t.type2.symbol !is null)
|
||||||
{
|
{
|
||||||
// TODO: global scoped symbol handling
|
// TODO: global scoped symbol handling
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ public:
|
||||||
|
|
||||||
/// Child symbols
|
/// Child symbols
|
||||||
UnrolledList!(SemanticSymbol*) children;
|
UnrolledList!(SemanticSymbol*) children;
|
||||||
|
|
||||||
|
/// Assign expression identifier chain used for auto declarations
|
||||||
|
UnrolledList!(string) initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue