semdata.nim 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2017 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## This module contains the data structures for the semantic checking phase.
  10. import
  11. strutils, intsets, options, lexer, ast, astalgo, trees, treetab,
  12. wordrecg,
  13. ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
  14. magicsys, nversion, nimsets, parser, times, passes, vmdef,
  15. modulegraphs, lineinfos
  16. type
  17. TOptionEntry* = object # entries to put on a stack for pragma parsing
  18. options*: TOptions
  19. defaultCC*: TCallingConvention
  20. dynlib*: PLib
  21. notes*: TNoteKinds
  22. features*: set[Feature]
  23. otherPragmas*: PNode # every pragma can be pushed
  24. POptionEntry* = ref TOptionEntry
  25. PProcCon* = ref TProcCon
  26. TProcCon* = object # procedure context; also used for top-level
  27. # statements
  28. owner*: PSym # the symbol this context belongs to
  29. resultSym*: PSym # the result symbol (if we are in a proc)
  30. selfSym*: PSym # the 'self' symbol (if available)
  31. nestedLoopCounter*: int # whether we are in a loop or not
  32. nestedBlockCounter*: int # whether we are in a block or not
  33. inTryStmt*: int # whether we are in a try statement; works also
  34. # in standalone ``except`` and ``finally``
  35. next*: PProcCon # used for stacking procedure contexts
  36. wasForwarded*: bool # whether the current proc has a separate header
  37. mappingExists*: bool
  38. mapping*: TIdTable
  39. TMatchedConcept* = object
  40. candidateType*: PType
  41. prev*: ptr TMatchedConcept
  42. depth*: int
  43. TInstantiationPair* = object
  44. genericSym*: PSym
  45. inst*: PInstantiation
  46. TExprFlag* = enum
  47. efLValue, efWantIterator, efInTypeof,
  48. efNeedStatic,
  49. # Use this in contexts where a static value is mandatory
  50. efPreferStatic,
  51. # Use this in contexts where a static value could bring more
  52. # information, but it's not strictly mandatory. This may become
  53. # the default with implicit statics in the future.
  54. efPreferNilResult,
  55. # Use this if you want a certain result (e.g. static value),
  56. # but you don't want to trigger a hard error. For example,
  57. # you may be in position to supply a better error message
  58. # to the user.
  59. efWantStmt, efAllowStmt, efDetermineType, efExplain,
  60. efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
  61. efNoEvaluateGeneric, efInCall, efFromHlo,
  62. efNoUndeclared
  63. # Use this if undeclared identifiers should not raise an error during
  64. # overload resolution.
  65. TExprFlags* = set[TExprFlag]
  66. TTypeAttachedOp* = enum
  67. attachedAsgn,
  68. attachedSink,
  69. attachedDeepCopy,
  70. attachedDestructor
  71. PContext* = ref TContext
  72. TContext* = object of TPassContext # a context represents a module
  73. enforceVoidContext*: PType
  74. module*: PSym # the module sym belonging to the context
  75. currentScope*: PScope # current scope
  76. importTable*: PScope # scope for all imported symbols
  77. topLevelScope*: PScope # scope for all top-level symbols
  78. p*: PProcCon # procedure context
  79. matchedConcept*: ptr TMatchedConcept # the current concept being matched
  80. friendModules*: seq[PSym] # friend modules; may access private data;
  81. # this is used so that generic instantiations
  82. # can access private object fields
  83. instCounter*: int # to prevent endless instantiations
  84. ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot
  85. # store this info in the syms themselves!)
  86. inGenericContext*: int # > 0 if we are in a generic type
  87. inStaticContext*: int # > 0 if we are inside a static: block
  88. inUnrolledContext*: int # > 0 if we are unrolling a loop
  89. compilesContextId*: int # > 0 if we are in a ``compiles`` magic
  90. compilesContextIdGenerator*: int
  91. inGenericInst*: int # > 0 if we are instantiating a generic
  92. converters*: seq[PSym]
  93. patterns*: seq[PSym] # sequence of pattern matchers
  94. optionStack*: seq[POptionEntry]
  95. symMapping*: TIdTable # every gensym'ed symbol needs to be mapped
  96. # to some new symbol in a generic instantiation
  97. libs*: seq[PLib] # all libs used by this module
  98. semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
  99. semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  100. semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  101. semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.}
  102. semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  103. semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
  104. semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
  105. filter: TSymKinds, flags: TExprFlags): PNode {.nimcall.}
  106. semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.}
  107. semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode
  108. semGenerateInstance*: proc (c: PContext, fn: PSym, pt: TIdTable,
  109. info: TLineInfo): PSym
  110. includedFiles*: IntSet # used to detect recursive include files
  111. pureEnumFields*: TStrTable # pure enum fields that can be used unambiguously
  112. userPragmas*: TStrTable
  113. evalContext*: PEvalContext
  114. unknownIdents*: IntSet # ids of all unknown identifiers to prevent
  115. # naming it multiple times
  116. generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
  117. topStmts*: int # counts the number of encountered top level statements
  118. lastGenericIdx*: int # used for the generics stack
  119. hloLoopDetector*: int # used to prevent endless loops in the HLO
  120. inParallelStmt*: int
  121. instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo;
  122. op: TTypeAttachedOp; col: int): PSym {.nimcall.}
  123. selfName*: PIdent
  124. cache*: IdentCache
  125. graph*: ModuleGraph
  126. signatures*: TStrTable
  127. recursiveDep*: string
  128. suggestionsMade*: bool
  129. features*: set[Feature]
  130. inTypeContext*: int
  131. typesWithOps*: seq[(PType, PType)] #\
  132. # We need to instantiate the type bound ops lazily after
  133. # the generic type has been constructed completely. See
  134. # tests/destructor/topttree.nim for an example that
  135. # would otherwise fail.
  136. template config*(c: PContext): ConfigRef = c.graph.config
  137. proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
  138. result.genericSym = s
  139. result.inst = inst
  140. proc filename*(c: PContext): string =
  141. # the module's filename
  142. return toFilename(c.config, FileIndex c.module.position)
  143. proc scopeDepth*(c: PContext): int {.inline.} =
  144. result = if c.currentScope != nil: c.currentScope.depthLevel
  145. else: 0
  146. proc getCurrOwner*(c: PContext): PSym =
  147. # owner stack (used for initializing the
  148. # owner field of syms)
  149. # the documentation comment always gets
  150. # assigned to the current owner
  151. result = c.graph.owners[^1]
  152. proc pushOwner*(c: PContext; owner: PSym) =
  153. add(c.graph.owners, owner)
  154. proc popOwner*(c: PContext) =
  155. var length = len(c.graph.owners)
  156. if length > 0: setLen(c.graph.owners, length - 1)
  157. else: internalError(c.config, "popOwner")
  158. proc lastOptionEntry*(c: PContext): POptionEntry =
  159. result = c.optionStack[^1]
  160. proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
  161. proc put*(p: PProcCon; key, val: PSym) =
  162. if not p.mappingExists:
  163. initIdTable(p.mapping)
  164. p.mappingExists = true
  165. #echo "put into table ", key.info
  166. p.mapping.idTablePut(key, val)
  167. proc get*(p: PProcCon; key: PSym): PSym =
  168. if not p.mappingExists: return nil
  169. result = PSym(p.mapping.idTableGet(key))
  170. proc getGenSym*(c: PContext; s: PSym): PSym =
  171. if sfGenSym notin s.flags: return s
  172. var it = c.p
  173. while it != nil:
  174. result = get(it, s)
  175. if result != nil:
  176. #echo "got from table ", result.name.s, " ", result.info
  177. return result
  178. it = it.next
  179. result = s
  180. proc considerGenSyms*(c: PContext; n: PNode) =
  181. if n.kind == nkSym:
  182. let s = getGenSym(c, n.sym)
  183. if n.sym != s:
  184. n.sym = s
  185. else:
  186. for i in 0..<n.safeLen:
  187. considerGenSyms(c, n.sons[i])
  188. proc newOptionEntry*(conf: ConfigRef): POptionEntry =
  189. new(result)
  190. result.options = conf.options
  191. result.defaultCC = ccDefault
  192. result.dynlib = nil
  193. result.notes = conf.notes
  194. proc newContext*(graph: ModuleGraph; module: PSym): PContext =
  195. new(result)
  196. result.enforceVoidContext = PType(kind: tyStmt)
  197. result.ambiguousSymbols = initIntSet()
  198. result.optionStack = @[]
  199. result.libs = @[]
  200. result.optionStack.add(newOptionEntry(graph.config))
  201. result.module = module
  202. result.friendModules = @[module]
  203. result.converters = @[]
  204. result.patterns = @[]
  205. result.includedFiles = initIntSet()
  206. initStrTable(result.pureEnumFields)
  207. initStrTable(result.userPragmas)
  208. result.generics = @[]
  209. result.unknownIdents = initIntSet()
  210. result.cache = graph.cache
  211. result.graph = graph
  212. initStrTable(result.signatures)
  213. result.typesWithOps = @[]
  214. result.features = graph.config.features
  215. proc inclSym(sq: var seq[PSym], s: PSym) =
  216. var L = len(sq)
  217. for i in countup(0, L - 1):
  218. if sq[i].id == s.id: return
  219. setLen(sq, L + 1)
  220. sq[L] = s
  221. proc addConverter*(c: PContext, conv: PSym) =
  222. inclSym(c.converters, conv)
  223. proc addPattern*(c: PContext, p: PSym) =
  224. inclSym(c.patterns, p)
  225. proc newLib*(kind: TLibKind): PLib =
  226. new(result)
  227. result.kind = kind #initObjectSet(result.syms)
  228. proc addToLib*(lib: PLib, sym: PSym) =
  229. #if sym.annex != nil and not isGenericRoutine(sym):
  230. # LocalError(sym.info, errInvalidPragma)
  231. sym.annex = lib
  232. proc newTypeS*(kind: TTypeKind, c: PContext): PType =
  233. result = newType(kind, getCurrOwner(c))
  234. proc makePtrType*(c: PContext, baseType: PType): PType =
  235. result = newTypeS(tyPtr, c)
  236. addSonSkipIntLit(result, baseType)
  237. proc makeTypeWithModifier*(c: PContext,
  238. modifier: TTypeKind,
  239. baseType: PType): PType =
  240. assert modifier in {tyVar, tyLent, tyPtr, tyRef, tyStatic, tyTypeDesc}
  241. if modifier in {tyVar, tyLent, tyTypeDesc} and baseType.kind == modifier:
  242. result = baseType
  243. else:
  244. result = newTypeS(modifier, c)
  245. addSonSkipIntLit(result, baseType)
  246. proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType =
  247. if baseType.kind == kind:
  248. result = baseType
  249. else:
  250. result = newTypeS(kind, c)
  251. addSonSkipIntLit(result, baseType)
  252. proc makeTypeDesc*(c: PContext, typ: PType): PType =
  253. if typ.kind == tyTypeDesc:
  254. result = typ
  255. else:
  256. result = newTypeS(tyTypeDesc, c)
  257. result.addSonSkipIntLit(typ)
  258. proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
  259. let typedesc = newTypeS(tyTypeDesc, c)
  260. typedesc.addSonSkipIntLit(assertNotNil(c.config, typ))
  261. let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info,
  262. c.config.options).linkTo(typedesc)
  263. return newSymNode(sym, info)
  264. proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
  265. result = newTypeS(tyFromExpr, c)
  266. assert n != nil
  267. result.n = n
  268. proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]): PType =
  269. result = newType(kind, owner)
  270. result.sons = sons
  271. proc newTypeWithSons*(c: PContext, kind: TTypeKind,
  272. sons: seq[PType]): PType =
  273. result = newType(kind, getCurrOwner(c))
  274. result.sons = sons
  275. proc makeStaticExpr*(c: PContext, n: PNode): PNode =
  276. result = newNodeI(nkStaticExpr, n.info)
  277. result.sons = @[n]
  278. result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ
  279. else: newTypeWithSons(c, tyStatic, @[n.typ])
  280. proc makeAndType*(c: PContext, t1, t2: PType): PType =
  281. result = newTypeS(tyAnd, c)
  282. result.sons = @[t1, t2]
  283. propagateToOwner(result, t1)
  284. propagateToOwner(result, t2)
  285. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  286. result.flags.incl tfHasMeta
  287. proc makeOrType*(c: PContext, t1, t2: PType): PType =
  288. result = newTypeS(tyOr, c)
  289. if t1.kind != tyOr and t2.kind != tyOr:
  290. result.sons = @[t1, t2]
  291. else:
  292. template addOr(t1) =
  293. if t1.kind == tyOr:
  294. for x in t1.sons: result.rawAddSon x
  295. else:
  296. result.rawAddSon t1
  297. addOr(t1)
  298. addOr(t2)
  299. propagateToOwner(result, t1)
  300. propagateToOwner(result, t2)
  301. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  302. result.flags.incl tfHasMeta
  303. proc makeNotType*(c: PContext, t1: PType): PType =
  304. result = newTypeS(tyNot, c)
  305. result.sons = @[t1]
  306. propagateToOwner(result, t1)
  307. result.flags.incl(t1.flags * {tfHasStatic})
  308. result.flags.incl tfHasMeta
  309. proc nMinusOne(c: PContext; n: PNode): PNode =
  310. result = newNode(nkCall, n.info, @[
  311. newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n])
  312. # Remember to fix the procs below this one when you make changes!
  313. proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
  314. let intType = getSysType(c.graph, n.info, tyInt)
  315. result = newTypeS(tyRange, c)
  316. result.sons = @[intType]
  317. if n.typ != nil and n.typ.n == nil:
  318. result.flags.incl tfUnresolved
  319. result.n = newNode(nkRange, n.info, @[
  320. newIntTypeNode(nkIntLit, 0, intType),
  321. makeStaticExpr(c, nMinusOne(c, n))])
  322. template rangeHasUnresolvedStatic*(t: PType): bool =
  323. tfUnresolved in t.flags
  324. proc errorType*(c: PContext): PType =
  325. ## creates a type representing an error state
  326. result = newTypeS(tyError, c)
  327. proc errorNode*(c: PContext, n: PNode): PNode =
  328. result = newNodeI(nkEmpty, n.info)
  329. result.typ = errorType(c)
  330. proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
  331. dest.kind = kind
  332. dest.owner = getCurrOwner(c)
  333. dest.size = - 1
  334. proc makeRangeType*(c: PContext; first, last: BiggestInt;
  335. info: TLineInfo; intType: PType = nil): PType =
  336. let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt)
  337. var n = newNodeI(nkRange, info)
  338. addSon(n, newIntTypeNode(nkIntLit, first, intType))
  339. addSon(n, newIntTypeNode(nkIntLit, last, intType))
  340. result = newTypeS(tyRange, c)
  341. result.n = n
  342. addSonSkipIntLit(result, intType) # basetype of range
  343. proc markIndirect*(c: PContext, s: PSym) {.inline.} =
  344. if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:
  345. incl(s.flags, sfAddrTaken)
  346. # XXX add to 'c' for global analysis
  347. proc illFormedAst*(n: PNode; conf: ConfigRef) =
  348. globalError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  349. proc illFormedAstLocal*(n: PNode; conf: ConfigRef) =
  350. localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  351. proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) =
  352. if sonsLen(n) != length: illFormedAst(n, conf)
  353. proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) =
  354. if sonsLen(n) < length: illFormedAst(n, conf)
  355. proc isTopLevel*(c: PContext): bool {.inline.} =
  356. result = c.currentScope.depthLevel <= 2