1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#
#
# The Nimrod Compiler
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This module implements the symbol importing mechanism.
import
intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
semdata, passes
proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode
proc importAllSymbols*(c: PContext, fromMod: PSym)
proc getModuleFile*(n: PNode): string
# implementation
proc findModule(info: TLineInfo, modulename: string): string =
# returns path to module
result = options.FindFile(AddFileExt(modulename, nimExt))
if result == "": Fatal(info, errCannotOpenFile, modulename)
proc getModuleFile(n: PNode): string =
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
result = findModule(n.info, UnixToNativePath(n.strVal))
of nkIdent:
result = findModule(n.info, n.ident.s)
of nkSym:
result = findModule(n.info, n.sym.name.s)
else:
internalError(n.info, "getModuleFile()")
result = ""
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 not (s.kind in OverloadableSyms):
# s and check need to be qualified:
Incl(c.AmbiguousSymbols, copy.id)
Incl(c.AmbiguousSymbols, check.id)
StrTableAdd(c.tab.stack[importTablePos], copy)
if s.kind == skType:
var etyp = s.typ
if etyp.kind in {tyBool, tyEnum}:
for j in countup(0, sonsLen(etyp.n) - 1):
var e = etyp.n.sons[j].sym
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:
e = nil
break
check = NextIdentIter(it, c.tab.stack[importTablePos])
if e != nil:
rawImportSymbol(c, e)
elif s.kind == skConverter:
addConverter(c, s) # rodgen assures that converters are no stubs
proc importSymbol(c: PContext, ident: PNode, fromMod: PSym) =
if (ident.kind != nkIdent): InternalError(ident.info, "importSymbol")
var s = StrTableGet(fromMod.tab, ident.ident)
if s == nil: GlobalError(ident.info, errUndeclaredIdentifier, ident.ident.s)
if s.kind == skStub: loadStub(s)
if not (s.Kind in ExportableSymKinds):
InternalError(ident.info, "importSymbol: 2")
# for an enumeration we have to add all identifiers
case s.Kind
of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
# for a overloadable syms add all overloaded routines
var it: TIdentIter
var e = InitIdentIter(it, fromMod.tab, s.name)
while e != nil:
if (e.name.id != s.Name.id): InternalError(ident.info, "importSymbol: 3")
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 not (s.Kind in ExportableSymKinds):
InternalError(s.info, "importAllSymbols: " & $s.kind)
rawImportSymbol(c, s) # this is correct!
s = NextIter(i, fromMod.tab)
proc evalImport(c: PContext, n: PNode): PNode =
result = n
for i in countup(0, sonsLen(n) - 1):
var f = getModuleFile(n.sons[i])
var m = gImportModule(f)
if sfDeprecated in m.flags:
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)
proc evalFrom(c: PContext, n: PNode): PNode =
result = n
checkMinSonsLen(n, 2)
var f = getModuleFile(n.sons[0])
var m = gImportModule(f)
n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module
for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m)
|