semdata.nim 16 KB

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