implemented 'import a as b'

This commit is contained in:
Araq 2013-09-24 09:36:31 +02:00
commit 83584bf889
4 changed files with 84 additions and 25 deletions

View file

@ -131,7 +131,7 @@ type
nkFormalParams, # formal parameters nkFormalParams, # formal parameters
nkOfInherit, # inherited from symbol nkOfInherit, # inherited from symbol
nkModule, # the syntax tree of a module nkImportAs, # a 'as' b in an import statement
nkProcDef, # a proc nkProcDef, # a proc
nkMethodDef, # a method nkMethodDef, # a method
nkConverterDef, # a converter nkConverterDef, # a converter
@ -641,6 +641,11 @@ type
# this is because in incremental compilation, when a module is about to # this is because in incremental compilation, when a module is about to
# be replaced with a newer version, we must decrement the usage count # be replaced with a newer version, we must decrement the usage count
# of all previously used generics. # 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] usedGenerics*: seq[PInstantiation]
tab*: TStrTable # interface table for modules tab*: TStrTable # interface table for modules
else: nil else: nil
@ -1106,7 +1111,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
proc copySym(s: PSym, keepId: bool = false): PSym = proc copySym(s: PSym, keepId: bool = false): PSym =
result = newSym(s.kind, s.name, s.owner, s.info) 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 result.typ = s.typ
if keepId: if keepId:
result.id = s.id result.id = s.id
@ -1121,6 +1126,20 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
result.position = s.position result.position = s.position
result.loc = s.loc result.loc = s.loc
result.annex = s.annex # BUGFIX 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, proc newSym(symKind: TSymKind, Name: PIdent, owner: PSym,
info: TLineInfo): PSym = info: TLineInfo): PSym =

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2013 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -27,12 +27,24 @@ proc getModuleName*(n: PNode): string =
result = n.ident.s result = n.ident.s
of nkSym: of nkSym:
result = n.sym.name.s 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': # hacky way to implement 'x / y /../ z':
result = renderTree(n, {renderNoComments}).replace(" ") result = renderTree(n, {renderNoComments}).replace(" ")
#localError(n.info, errGenerated, of nkDotExpr:
# "invalide module name: '$1'" % renderTree(n)) result = renderTree(n, {renderNoComments}).replace(".")
#result = "" of nkImportAs:
result = getModuleName(n.sons[0])
else:
localError(n.info, errGenerated,
"invalid module name: '$1'" % renderTree(n))
result = ""
proc checkModuleName*(n: PNode): int32 = proc checkModuleName*(n: PNode): int32 =
# This returns the full canonical path for a given module import # 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: for i in 0 ..safeLen(n)-1:
importForwarded(c, n.sons[i], exceptSet) 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 = proc evalImport(c: PContext, n: PNode): PNode =
result = n result = n
var emptySet: TIntSet var emptySet: TIntSet
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var f = checkModuleName(n.sons[i]) var m = myImportModule(c, n.sons[i])
if f != InvalidFileIDX: if m != nil:
var m = gImportModule(c.module, f)
if sfDeprecated in m.flags:
Message(n.sons[i].info, warnDeprecated, m.name.s)
# ``addDecl`` needs to be done before ``importAllSymbols``! # ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m) # add symbol to symbol table of module addDecl(c, m) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, emptySet) importAllSymbolsExcept(c, m, emptySet)
@ -152,21 +177,19 @@ proc evalImport(c: PContext, n: PNode): PNode =
proc evalFrom(c: PContext, n: PNode): PNode = proc evalFrom(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
var f = checkModuleName(n.sons[0]) var m = myImportModule(c, n.sons[0])
if f != InvalidFileIDX: if m != nil:
var m = gImportModule(c.module, f)
n.sons[0] = newSymNode(m) n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module 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: if n.sons[i].kind != nkNilLit:
importSymbol(c, n.sons[i], m) importSymbol(c, n.sons[i], m)
proc evalImportExcept*(c: PContext, n: PNode): PNode = proc evalImportExcept*(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
var f = checkModuleName(n.sons[0]) var m = myImportModule(c, n.sons[0])
if f != InvalidFileIDX: if m != nil:
var m = gImportModule(c.module, f)
n.sons[0] = newSymNode(m) n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module addDecl(c, m) # add symbol to symbol table of module
var exceptSet = initIntSet() var exceptSet = initIntSet()

View file

@ -1088,6 +1088,17 @@ proc parseExprStmt(p: var TParser): PNode =
addSon(result, b) addSon(result, b)
if b.kind == nkElse: break 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 = proc parseImport(p: var TParser, kind: TNodeKind): PNode =
#| importStmt = 'import' optInd expr #| importStmt = 'import' optInd expr
#| ((comma expr)* #| ((comma expr)*
@ -1095,7 +1106,7 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
getTok(p) # skip `import` or `export` getTok(p) # skip `import` or `export`
optInd(p, result) optInd(p, result)
var a = parseExpr(p) var a = parseModuleName(p, kind)
addSon(result, a) addSon(result, a)
if p.tok.tokType in {tkComma, tkExcept}: if p.tok.tokType in {tkComma, tkExcept}:
if p.tok.tokType == tkExcept: if p.tok.tokType == tkExcept:
@ -1104,10 +1115,10 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode =
optInd(p, result) optInd(p, result)
while true: while true:
# was: while p.tok.tokType notin {tkEof, tkSad, tkDed}: # was: while p.tok.tokType notin {tkEof, tkSad, tkDed}:
a = parseExpr(p) a = parseModuleName(p, kind)
if a.kind == nkEmpty: break if a.kind == nkEmpty: break
addSon(result, a) addSon(result, a)
if p.tok.tokType != tkComma: break if p.tok.tokType != tkComma: break
getTok(p) getTok(p)
optInd(p, a) optInd(p, a)
#expectNl(p) #expectNl(p)
@ -1128,11 +1139,11 @@ proc parseIncludeStmt(p: var TParser): PNode =
#expectNl(p) #expectNl(p)
proc parseFromStmt(p: var TParser): PNode = 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) result = newNodeP(nkFromStmt, p)
getTok(p) # skip `from` getTok(p) # skip `from`
optInd(p, result) optInd(p, result)
var a = parseExpr(p) var a = parseModuleName(p, nkImportStmt)
addSon(result, a) #optInd(p, a); addSon(result, a) #optInd(p, a);
eat(p, tkImport) eat(p, tkImport)
optInd(p, result) optInd(p, result)

View file

@ -448,6 +448,7 @@ proc lsub(n: PNode): int =
of nkPragma: result = lcomma(n) + 4 of nkPragma: result = lcomma(n) + 4
of nkCommentStmt: result = len(n.comment) of nkCommentStmt: result = len(n.comment)
of nkOfBranch: result = lcomma(n, 0, - 2) + lsub(lastSon(n)) + len("of_:_") 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 nkElifBranch: result = lsons(n) + len("elif_:_")
of nkElse: result = lsub(n.sons[0]) + len("else:_") of nkElse: result = lsub(n.sons[0]) + len("else:_")
of nkFinally: result = lsub(n.sons[0]) + len("finally:_") 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, ":") putWithSpace(g, tkColon, ":")
gcoms(g) gcoms(g)
gstmts(g, lastSon(n), c) 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: of nkBindStmt:
putWithSpace(g, tkBind, "bind") putWithSpace(g, tkBind, "bind")
gcomma(g, n, c) gcomma(g, n, c)