Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq 2012-12-02 11:13:05 +01:00
commit 6ce15652d3
16 changed files with 252 additions and 133 deletions

View file

@ -585,8 +585,9 @@ proc StrTableContains(t: TStrTable, n: PSym): bool =
proc StrTableRawInsert(data: var TSymSeq, n: PSym) =
var h: THash = n.name.h and high(data)
while data[h] != nil:
if data[h] == n:
InternalError(n.info, "StrTableRawInsert: " & n.name.s)
if data[h] == n:
# allowed for 'export' feature:
#InternalError(n.info, "StrTableRawInsert: " & n.name.s)
return
h = nextTry(h, high(data))
assert(data[h] == nil)
@ -617,23 +618,23 @@ proc StrTableAdd(t: var TStrTable, n: PSym) =
StrTableRawInsert(t.data, n)
inc(t.counter)
proc StrTableIncl*(t: var TStrTable, n: PSym): bool =
proc StrTableIncl*(t: var TStrTable, n: PSym): bool {.discardable.} =
# returns true if n is already in the string table:
# It is essential that `n` is written nevertheless!
# This way the newest redefinition is picked by the semantic analyses!
assert n.name != nil
var h: THash = n.name.h and high(t.data)
while true:
while true:
var it = t.data[h]
if it == nil: break
if it.name.id == n.name.id:
if it == nil: break
if it.name.id == n.name.id:
t.data[h] = n # overwrite it with newer definition!
return true # found it
h = nextTry(h, high(t.data))
if mustRehash(len(t.data), t.counter):
if mustRehash(len(t.data), t.counter):
StrTableEnlarge(t)
StrTableRawInsert(t.data, n)
else:
else:
assert(t.data[h] == nil)
t.data[h] = n
inc(t.counter)

View file

@ -15,7 +15,6 @@ import
proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode
proc importAllSymbols*(c: PContext, fromMod: PSym)
proc getModuleName*(n: PNode): string =
# This returns a short relative module name without the nim extension
@ -29,9 +28,11 @@ proc getModuleName*(n: PNode): string =
of nkSym:
result = n.sym.name.s
else:
localError(n.info, errGenerated,
"invalide module name: '$1'" % renderTree(n))
result = ""
# hacky way to implement 'x / y /../ z':
result = renderTree(n, {renderNoComments}).replace(" ")
#localError(n.info, errGenerated,
# "invalide module name: '$1'" % renderTree(n))
#result = ""
proc checkModuleName*(n: PNode): string =
# This returns the full canonical path for a given module import
@ -40,42 +41,43 @@ proc checkModuleName*(n: PNode): string =
if result.len == 0:
LocalError(n.info, errCannotOpenFile, modulename)
proc rawImportSymbol(c: PContext, s: PSym) =
proc rawImportSymbol(c: PContext, s: PSym) =
# This does not handle stubs, because otherwise loading on demand would be
# pointless in practice. So importing stubs is fine here!
var copy = s # do not copy symbols when importing!
# check if we have already a symbol of the same name:
var check = StrTableGet(c.tab.stack[importTablePos], s.name)
if check != nil and check.id != copy.id:
if s.kind notin OverloadableSyms:
if check != nil and check.id != s.id:
if s.kind notin OverloadableSyms:
# s and check need to be qualified:
Incl(c.AmbiguousSymbols, copy.id)
Incl(c.AmbiguousSymbols, s.id)
Incl(c.AmbiguousSymbols, check.id)
StrTableAdd(c.tab.stack[importTablePos], copy)
if s.kind == skType:
# thanks to 'export' feature, it could be we import the same symbol from
# multiple sources, so we need to call 'StrTableAdd' here:
StrTableAdd(c.tab.stack[importTablePos], s)
if s.kind == skType:
var etyp = s.typ
if etyp.kind in {tyBool, tyEnum} and sfPure notin s.flags:
for j in countup(0, sonsLen(etyp.n) - 1):
if etyp.kind in {tyBool, tyEnum} and sfPure notin s.flags:
for j in countup(0, sonsLen(etyp.n) - 1):
var e = etyp.n.sons[j].sym
if (e.Kind != skEnumField):
if e.Kind != skEnumField:
InternalError(s.info, "rawImportSymbol")
# BUGFIX: because of aliases for enums the symbol may already
# have been put into the symbol table
# BUGFIX: but only iff they are the same symbols!
var it: TIdentIter
check = InitIdentIter(it, c.tab.stack[importTablePos], e.name)
while check != nil:
if check.id == e.id:
while check != nil:
if check.id == e.id:
e = nil
break
break
check = NextIdentIter(it, c.tab.stack[importTablePos])
if e != nil:
if e != nil:
rawImportSymbol(c, e)
else:
# rodgen assures that converters and patterns are no stubs
if s.kind == skConverter: addConverter(c, s)
if hasPattern(s): addPattern(c, s)
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
let ident = lookups.considerAcc(n)
let s = StrTableGet(fromMod.tab, ident)
@ -96,17 +98,6 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
rawImportSymbol(c, e)
e = NextIdentIter(it, fromMod.tab)
else: rawImportSymbol(c, s)
proc importAllSymbols(c: PContext, fromMod: PSym) =
var i: TTabIter
var s = InitTabIter(i, fromMod.tab)
while s != nil:
if s.kind != skModule:
if s.kind != skEnumField:
if s.Kind notin ExportableSymKinds:
InternalError(s.info, "importAllSymbols: " & $s.kind)
rawImportSymbol(c, s) # this is correct!
s = NextIter(i, fromMod.tab)
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: TIntSet) =
var i: TTabIter
@ -116,12 +107,34 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: TIntSet) =
if s.kind != skEnumField:
if s.Kind notin ExportableSymKinds:
InternalError(s.info, "importAllSymbols: " & $s.kind)
if s.name.id notin exceptSet:
if exceptSet.empty or s.name.id notin exceptSet:
rawImportSymbol(c, s)
s = NextIter(i, fromMod.tab)
proc importAllSymbols*(c: PContext, fromMod: PSym) =
var exceptSet: TIntSet
importAllSymbolsExcept(c, fromMod, exceptSet)
proc importForwarded(c: PContext, n: PNode, exceptSet: TIntSet) =
if n.isNil: return
case n.kind
of nkExportStmt:
for a in n:
assert a.kind == nkSym
let s = a.sym
if s.kind == skModule:
importAllSymbolsExcept(c, s, exceptSet)
elif exceptSet.empty or s.name.id notin exceptSet:
rawImportSymbol(c, s)
of nkExportExceptStmt:
localError(n.info, errGenerated, "'export except' not implemented")
else:
for i in 0 ..safeLen(n)-1:
importForwarded(c, n.sons[i], exceptSet)
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.len > 0:
@ -130,7 +143,8 @@ proc evalImport(c: PContext, n: PNode): PNode =
Message(n.sons[i].info, warnDeprecated, m.name.s)
# ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m) # add symbol to symbol table of module
importAllSymbols(c, m)
importAllSymbolsExcept(c, m, emptySet)
importForwarded(c, m.ast, emptySet)
proc evalFrom(c: PContext, n: PNode): PNode =
result = n
@ -155,3 +169,4 @@ proc evalImportExcept*(c: PContext, n: PNode): PNode =
let ident = lookups.considerAcc(n.sons[i])
exceptSet.incl(ident.id)
importAllSymbolsExcept(c, m, exceptSet)
importForwarded(c, m.ast, exceptSet)

View file

@ -1659,6 +1659,26 @@ proc fixImmediateParams(n: PNode): PNode =
result = n
proc semExport(c: PContext, n: PNode): PNode =
var x = newNodeI(n.kind, n.info)
#let L = if n.kind == nkExportExceptStmt: L = 1 else: n.len
for i in 0.. <n.len:
let a = n.sons[i]
var o: TOverloadIter
var s = initOverloadIter(o, c, a)
if s == nil:
localError(a.info, errGenerated, "invalid expr for 'export': " &
renderTree(a))
while s != nil:
if s.kind in ExportableSymKinds+{skModule}:
x.add(newSymNode(s, a.info))
s = nextOverloadIter(o, c, a)
if c.module.ast.isNil:
c.module.ast = newNodeI(nkStmtList, n.info)
assert c.module.ast.kind == nkStmtList
c.module.ast.add x
result = n
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = n
if gCmd == cmdIdeTools: suggestExpr(c, n)
@ -1861,6 +1881,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkIncludeStmt:
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "include")
result = evalInclude(c, n)
of nkExportStmt, nkExportExceptStmt:
if not isTopLevel(c): LocalError(n.info, errXOnlyAtModuleScope, "export")
result = semExport(c, n)
of nkPragmaBlock:
result = semPragmaBlock(c, n)
of nkStaticStmt: