From d9abe32f6cf4b172e3d46d3c8b56b701bc5464c2 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Mon, 22 Sep 2014 00:21:23 +0000 Subject: [PATCH] Implement with statement support. #56 --- libdparse | 2 +- src/actypes.d | 34 +++++++++++++++++++++++++++++++--- src/conversion/first.d | 28 ++++++++++++++++++++++++++-- src/conversion/second.d | 4 +++- src/conversion/third.d | 7 ++++++- src/messages.d | 4 ++++ 6 files changed, 71 insertions(+), 8 deletions(-) diff --git a/libdparse b/libdparse index 27f45e6..d57e38c 160000 --- a/libdparse +++ b/libdparse @@ -1 +1 @@ -Subproject commit 27f45e6490e7ef0e9a6ef604e51f68a54b10ee2d +Subproject commit d57e38c169613edfa39088adb933fd220b6208f3 diff --git a/src/actypes.d b/src/actypes.d index 138ce72..19c955f 100644 --- a/src/actypes.d +++ b/src/actypes.d @@ -41,7 +41,7 @@ enum SymbolQualifier : ubyte { /// _none none, - /// the symbol is an _array + /// the symbol is an array array, /// the symbol is a associative array assocArray, @@ -61,6 +61,9 @@ public: */ @disable this(); + /// ditto + @disable this(this); + /** * Params: * name = the symbol's name @@ -253,8 +256,12 @@ struct Scope { foreach (item; sc.symbols[]) { - if (item.kind == CompletionKind.importSymbol) foreach (i; item.type.parts[]) - symbols.insert(i); + if (item.kind == CompletionKind.importSymbol + || item.kind == CompletionKind.withSymbol) + { + foreach (i; item.type.parts[]) + symbols.insert(i); + } else symbols.insert(item); } @@ -276,6 +283,25 @@ struct Scope auto er = symbols.equalRange(&s); if (!er.empty) return array(er); + +// Check symbols from "with" statement + ACSymbol ir2 = ACSymbol(WITH_SYMBOL_NAME); + auto r2 = symbols.equalRange(&ir2); + if (!r2.empty) + { + auto app = appender!(ACSymbol*[])(); + foreach (e; r2) + { + if (e.type is null) + continue; + foreach (withSymbol; e.type.parts.equalRange(&s)) + app.put(withSymbol); + } + if (app.data.length > 0) + return app.data; + } + + // Check imported symbols ACSymbol ir = ACSymbol(IMPORT_SYMBOL_NAME); auto r = symbols.equalRange(&ir); if (!r.empty) @@ -386,6 +412,7 @@ private immutable(string[24]) builtinTypeNames; * static construction. */ immutable string IMPORT_SYMBOL_NAME; +immutable string WITH_SYMBOL_NAME; /** * Translates the IDs for built-in types into an interned string. @@ -454,6 +481,7 @@ static this() builtinTypeNames[23] = internString("creal"); IMPORT_SYMBOL_NAME = internString("public"); + WITH_SYMBOL_NAME = internString("with"); auto bool_ = allocate!ACSymbol(Mallocator.it, "bool", CompletionKind.keyword); diff --git a/src/conversion/first.d b/src/conversion/first.d index 56f448f..49f8b77 100644 --- a/src/conversion/first.d +++ b/src/conversion/first.d @@ -385,9 +385,9 @@ final class FirstPass : ASTVisitor if (blockStatement.declarationsAndStatements !is null) { - currentScope = s; + currentScope = s; visit (blockStatement.declarationsAndStatements); - currentScope = s.parent; + currentScope = s.parent; } } @@ -453,6 +453,30 @@ final class FirstPass : ASTVisitor currentSymbol.addChild(symbol); } + override void visit(const WithStatement withStatement) + { + if (withStatement.expression !is null + && withStatement.statementNoCaseNoDefault !is null) + { + Scope* s = allocate!Scope(semanticAllocator, + withStatement.statementNoCaseNoDefault.startLocation, + withStatement.statementNoCaseNoDefault.endLocation); + SemanticSymbol* symbol = allocateSemanticSymbol(WITH_SYMBOL_NAME, + CompletionKind.withSymbol, symbolFile, s.startLocation, null); + symbol.acSymbol.qualifier = SymbolQualifier.withSymbol; + Log.trace("WithStatement bounds: ", s.startLocation, " ", s.endLocation); + s.parent = currentScope; + currentScope.children.insert(s); + populateInitializer(symbol, withStatement.expression, false); + symbol.parent = currentSymbol; + currentSymbol.addChild(symbol); + withStatement.accept(this); + currentScope = currentScope.parent; + } + else + withStatement.accept(this); + } + alias visit = ASTVisitor.visit; /// Module scope diff --git a/src/conversion/second.d b/src/conversion/second.d index a8ca4ad..72c4076 100644 --- a/src/conversion/second.d +++ b/src/conversion/second.d @@ -81,9 +81,11 @@ private: */ void assignToScopes(ACSymbol* currentSymbol) { - Scope* s = moduleScope.getScopeByCursor(currentSymbol.location); if (currentSymbol.kind != CompletionKind.moduleName) + { + Scope* s = moduleScope.getScopeByCursor(currentSymbol.location); s.symbols.insert(currentSymbol); + } foreach (part; currentSymbol.parts[]) { if (part.kind != CompletionKind.keyword) diff --git a/src/conversion/third.d b/src/conversion/third.d index bc0d24e..06720bd 100644 --- a/src/conversion/third.d +++ b/src/conversion/third.d @@ -70,14 +70,19 @@ private: case interfaceName: resolveInheritance(currentSymbol); break; + case withSymbol: case variableName: case memberVariableName: case functionName: case aliasName: ACSymbol* t = resolveType(currentSymbol.initializer, currentSymbol.type, currentSymbol.acSymbol.location); - while (t !is null && t.kind == CompletionKind.aliasName) + while (t !is null && (t.kind == CompletionKind.aliasName + || (currentSymbol.acSymbol.kind == CompletionKind.withSymbol + && t.kind == CompletionKind.variableName))) + { t = t.type; + } currentSymbol.acSymbol.type = t; break; case structName: diff --git a/src/messages.d b/src/messages.d index 5b2b570..8f1db4d 100644 --- a/src/messages.d +++ b/src/messages.d @@ -31,6 +31,10 @@ enum CompletionKind : char /// be returned in a completion response. importSymbol = '*', + /// With symbol. This is used internally and will never + /// be returned in a completion response. + withSymbol = 'w', + /// class names className = 'c',