diff options
author | Araq <rumpf_a@web.de> | 2012-12-01 19:10:47 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-12-01 19:10:47 +0100 |
commit | c98e3d2c274ac4bd4227d4e3f7e0d2636827f88c (patch) | |
tree | c9b624562ae38f56d19e7ed190307caea8c61241 /compiler | |
parent | f503439e811d822f19daa9591cb3bd9e90edabe7 (diff) | |
download | Nim-c98e3d2c274ac4bd4227d4e3f7e0d2636827f88c.tar.gz |
implements 'export' feature
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/astalgo.nim | 17 | ||||
-rwxr-xr-x | compiler/importer.nim | 71 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 23 |
3 files changed, 74 insertions, 37 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index da0de3e94..9a2bebab4 100755 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -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) diff --git a/compiler/importer.nim b/compiler/importer.nim index 11fc45601..774bcea6a 100755 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -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 @@ -42,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) @@ -98,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 @@ -118,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: @@ -132,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 @@ -157,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) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9f2b431f6..7acfb830f 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1657,6 +1657,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) @@ -1859,6 +1879,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: |