diff options
author | Araq <rumpf_a@web.de> | 2013-09-24 09:36:31 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-09-24 09:36:31 +0200 |
commit | 83584bf88934c45ce10e770ee15d070a09f88f45 (patch) | |
tree | c681f943c2f4ba6348eb8f5208c4a577ff183acd /compiler | |
parent | 367abca3825fcd2f2a7fdf2bd699986f0535e6b1 (diff) | |
download | Nim-83584bf88934c45ce10e770ee15d070a09f88f45.tar.gz |
implemented 'import a as b'
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 23 | ||||
-rw-r--r-- | compiler/importer.nim | 57 | ||||
-rw-r--r-- | compiler/parser.nim | 23 | ||||
-rw-r--r-- | compiler/renderer.nim | 6 |
4 files changed, 84 insertions, 25 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index ea60284da..c9c049137 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -131,7 +131,7 @@ type nkFormalParams, # formal parameters nkOfInherit, # inherited from symbol - nkModule, # the syntax tree of a module + nkImportAs, # a 'as' b in an import statement nkProcDef, # a proc nkMethodDef, # a method nkConverterDef, # a converter @@ -641,6 +641,11 @@ type # this is because in incremental compilation, when a module is about to # be replaced with a newer version, we must decrement the usage count # of all previously used generics. + # For 'import as' we copy the module symbol but shallowCopy the 'tab' + # and set the 'usedGenerics' to ... XXX gah! Better set module.name + # instead? But this doesn't work either. --> We need an skModuleAlias? + # No need, just leave it as skModule but set the owner accordingly and + # check for the owner when touching 'usedGenerics'. usedGenerics*: seq[PInstantiation] tab*: TStrTable # interface table for modules else: nil @@ -1106,7 +1111,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType = proc copySym(s: PSym, keepId: bool = false): PSym = result = newSym(s.kind, s.name, s.owner, s.info) - result.ast = nil # BUGFIX; was: s.ast which made problems + #result.ast = nil # BUGFIX; was: s.ast which made problems result.typ = s.typ if keepId: result.id = s.id @@ -1121,6 +1126,20 @@ proc copySym(s: PSym, keepId: bool = false): PSym = result.position = s.position result.loc = s.loc result.annex = s.annex # BUGFIX + +proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = + result = newSym(s.kind, newIdent, s.owner, info) + # keep ID! + result.ast = s.ast + result.id = s.id + result.flags = s.flags + system.shallowCopy(result.tab, s.tab) + result.options = s.options + result.position = s.position + result.loc = s.loc + result.annex = s.annex + # XXX once usedGenerics is used, ensure module aliases keep working! + assert s.usedGenerics == nil proc newSym(symKind: TSymKind, Name: PIdent, owner: PSym, info: TLineInfo): PSym = diff --git a/compiler/importer.nim b/compiler/importer.nim index 7159072f7..077e5e0c9 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -1,7 +1,7 @@ # # # The Nimrod Compiler -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -27,12 +27,24 @@ proc getModuleName*(n: PNode): string = result = n.ident.s of nkSym: result = n.sym.name.s - else: + of nkInfix: + if n.sons[0].kind == nkIdent and n.sons[0].ident.id == getIdent("as").id: + # XXX hack ahead: + n.kind = nkImportAs + n.sons[0] = n.sons[1] + n.sons[1] = n.sons[2] + n.sons.setLen(2) + return getModuleName(n.sons[0]) # hacky way to implement 'x / y /../ z': result = renderTree(n, {renderNoComments}).replace(" ") - #localError(n.info, errGenerated, - # "invalide module name: '$1'" % renderTree(n)) - #result = "" + of nkDotExpr: + result = renderTree(n, {renderNoComments}).replace(".") + of nkImportAs: + result = getModuleName(n.sons[0]) + else: + localError(n.info, errGenerated, + "invalid module name: '$1'" % renderTree(n)) + result = "" proc checkModuleName*(n: PNode): int32 = # This returns the full canonical path for a given module import @@ -135,15 +147,28 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: TIntSet) = for i in 0 ..safeLen(n)-1: importForwarded(c, n.sons[i], exceptSet) +proc importModuleAs(n: PNode, realModule: PSym): PSym = + result = realModule + if n.kind != nkImportAs: discard + elif n.len != 2 or n.sons[1].kind != nkIdent: + localError(n.info, errGenerated, "module alias must be an identifier") + elif n.sons[1].ident.id != realModule.name.id: + # some misguided guy will write 'import abc.foo as foo' ... + result = createModuleAlias(realModule, n.sons[1].ident, n.sons[1].info) + +proc myImportModule(c: PContext, n: PNode): PSym = + var f = checkModuleName(n) + if f != InvalidFileIDX: + result = importModuleAs(n, gImportModule(c.module, f)) + if sfDeprecated in result.flags: + Message(n.info, warnDeprecated, result.name.s) + proc evalImport(c: PContext, n: PNode): PNode = result = n var emptySet: TIntSet for i in countup(0, sonsLen(n) - 1): - var f = checkModuleName(n.sons[i]) - if f != InvalidFileIDX: - var m = gImportModule(c.module, f) - if sfDeprecated in m.flags: - Message(n.sons[i].info, warnDeprecated, m.name.s) + var m = myImportModule(c, n.sons[i]) + if m != nil: # ``addDecl`` needs to be done before ``importAllSymbols``! addDecl(c, m) # add symbol to symbol table of module importAllSymbolsExcept(c, m, emptySet) @@ -152,21 +177,19 @@ proc evalImport(c: PContext, n: PNode): PNode = proc evalFrom(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 2) - var f = checkModuleName(n.sons[0]) - if f != InvalidFileIDX: - var m = gImportModule(c.module, f) + var m = myImportModule(c, n.sons[0]) + if m != nil: n.sons[0] = newSymNode(m) addDecl(c, m) # add symbol to symbol table of module - for i in countup(1, sonsLen(n) - 1): + for i in countup(1, sonsLen(n) - 1): if n.sons[i].kind != nkNilLit: importSymbol(c, n.sons[i], m) proc evalImportExcept*(c: PContext, n: PNode): PNode = result = n checkMinSonsLen(n, 2) - var f = checkModuleName(n.sons[0]) - if f != InvalidFileIDX: - var m = gImportModule(c.module, f) + var m = myImportModule(c, n.sons[0]) + if m != nil: n.sons[0] = newSymNode(m) addDecl(c, m) # add symbol to symbol table of module var exceptSet = initIntSet() diff --git a/compiler/parser.nim b/compiler/parser.nim index 0d9d27e02..a2fe34849 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1088,6 +1088,17 @@ proc parseExprStmt(p: var TParser): PNode = addSon(result, b) if b.kind == nkElse: break +proc parseModuleName(p: var TParser, kind: TNodeKind): PNode = + result = parseExpr(p) + when false: + # parseExpr already handles 'as' syntax ... + if p.tok.tokType == tkAs and kind == nkImportStmt: + let a = result + result = newNodeP(nkImportAs, p) + getTok(p) + result.add(a) + result.add(parseExpr(p)) + proc parseImport(p: var TParser, kind: TNodeKind): PNode = #| importStmt = 'import' optInd expr #| ((comma expr)* @@ -1095,7 +1106,7 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode = result = newNodeP(kind, p) getTok(p) # skip `import` or `export` optInd(p, result) - var a = parseExpr(p) + var a = parseModuleName(p, kind) addSon(result, a) if p.tok.tokType in {tkComma, tkExcept}: if p.tok.tokType == tkExcept: @@ -1104,10 +1115,10 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode = optInd(p, result) while true: # was: while p.tok.tokType notin {tkEof, tkSad, tkDed}: - a = parseExpr(p) - if a.kind == nkEmpty: break + a = parseModuleName(p, kind) + if a.kind == nkEmpty: break addSon(result, a) - if p.tok.tokType != tkComma: break + if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) #expectNl(p) @@ -1128,11 +1139,11 @@ proc parseIncludeStmt(p: var TParser): PNode = #expectNl(p) proc parseFromStmt(p: var TParser): PNode = - #| fromStmt = 'from' expr 'import' optInd expr (comma expr)* + #| fromStmt = 'from' moduleName 'import' optInd expr (comma expr)* result = newNodeP(nkFromStmt, p) getTok(p) # skip `from` optInd(p, result) - var a = parseExpr(p) + var a = parseModuleName(p, nkImportStmt) addSon(result, a) #optInd(p, a); eat(p, tkImport) optInd(p, result) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index efa4ecaba..f6fb0f8c0 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -448,6 +448,7 @@ proc lsub(n: PNode): int = of nkPragma: result = lcomma(n) + 4 of nkCommentStmt: result = len(n.comment) of nkOfBranch: result = lcomma(n, 0, - 2) + lsub(lastSon(n)) + len("of_:_") + of nkImportAs: result = lsub(n.sons[0]) + len("_as_") + lsub(n.sons[1]) of nkElifBranch: result = lsons(n) + len("elif_:_") of nkElse: result = lsub(n.sons[0]) + len("else:_") of nkFinally: result = lsub(n.sons[0]) + len("finally:_") @@ -1191,6 +1192,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = putWithSpace(g, tkColon, ":") gcoms(g) gstmts(g, lastSon(n), c) + of nkImportAs: + gsub(g, n.sons[0]) + put(g, tkSpaces, Space) + putWithSpace(g, tkAs, "as") + gsub(g, n.sons[1]) of nkBindStmt: putWithSpace(g, tkBind, "bind") gcomma(g, n, c) |