From 8fadaba6ea9aeeaf6c87101095e6bab91461a3c0 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Thu, 7 Aug 2014 15:59:21 -0700 Subject: [PATCH] Auto declarations support --- conversion/first.d | 105 ++++++++++++++++++++++++++++++++++++++++++++- conversion/third.d | 54 ++++++++++++++++++++--- semantic.d | 3 ++ 3 files changed, 156 insertions(+), 6 deletions(-) diff --git a/conversion/first.d b/conversion/first.d index b4411d8..f29d0f9 100644 --- a/conversion/first.d +++ b/conversion/first.d @@ -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; +} diff --git a/conversion/third.d b/conversion/third.d index 705cf94..a76e9a2 100644 --- a/conversion/third.d +++ b/conversion/third.d @@ -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 diff --git a/semantic.d b/semantic.d index 660f84b..f599db1 100644 --- a/semantic.d +++ b/semantic.d @@ -87,6 +87,9 @@ public: /// Child symbols UnrolledList!(SemanticSymbol*) children; + + /// Assign expression identifier chain used for auto declarations + UnrolledList!(string) initializer; } /**