semdata.nim 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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. mappingExists*: bool
  35. mapping*: TIdTable
  36. caseContext*: seq[tuple[n: PNode, idx: int]]
  37. TMatchedConcept* = object
  38. candidateType*: PType
  39. prev*: ptr TMatchedConcept
  40. depth*: int
  41. TInstantiationPair* = object
  42. genericSym*: PSym
  43. inst*: PInstantiation
  44. TExprFlag* = enum
  45. efLValue, efWantIterator, efInTypeof,
  46. efNeedStatic,
  47. # Use this in contexts where a static value is mandatory
  48. efPreferStatic,
  49. # Use this in contexts where a static value could bring more
  50. # information, but it's not strictly mandatory. This may become
  51. # the default with implicit statics in the future.
  52. efPreferNilResult,
  53. # Use this if you want a certain result (e.g. static value),
  54. # but you don't want to trigger a hard error. For example,
  55. # you may be in position to supply a better error message
  56. # to the user.
  57. efWantStmt, efAllowStmt, efDetermineType, efExplain,
  58. efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
  59. efNoEvaluateGeneric, efInCall, efFromHlo, efNoSem2Check,
  60. efNoUndeclared
  61. # Use this if undeclared identifiers should not raise an error during
  62. # overload resolution.
  63. TExprFlags* = set[TExprFlag]
  64. PContext* = ref TContext
  65. TContext* = object of TPassContext # a context represents the module
  66. # that is currently being compiled
  67. enforceVoidContext*: PType
  68. module*: PSym # the module sym belonging to the context
  69. currentScope*: PScope # current scope
  70. importTable*: PScope # scope for all imported symbols
  71. topLevelScope*: PScope # scope for all top-level symbols
  72. p*: PProcCon # procedure context
  73. matchedConcept*: ptr TMatchedConcept # the current concept being matched
  74. friendModules*: seq[PSym] # friend modules; may access private data;
  75. # this is used so that generic instantiations
  76. # can access private object fields
  77. instCounter*: int # to prevent endless instantiations
  78. templInstCounter*: ref int # gives every template instantiation a unique id
  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. lastTLineInfo*: TLineInfo
  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. c.graph.owners.add(owner)
  154. proc popOwner*(c: PContext) =
  155. if c.graph.owners.len > 0: setLen(c.graph.owners, c.graph.owners.len - 1)
  156. else: internalError(c.config, "popOwner")
  157. proc lastOptionEntry*(c: PContext): POptionEntry =
  158. result = c.optionStack[^1]
  159. proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
  160. proc put*(p: PProcCon; key, val: PSym) =
  161. if not p.mappingExists:
  162. initIdTable(p.mapping)
  163. p.mappingExists = true
  164. #echo "put into table ", key.info
  165. p.mapping.idTablePut(key, val)
  166. proc get*(p: PProcCon; key: PSym): PSym =
  167. if not p.mappingExists: return nil
  168. result = PSym(p.mapping.idTableGet(key))
  169. proc getGenSym*(c: PContext; s: PSym): PSym =
  170. if sfGenSym notin s.flags: return s
  171. var it = c.p
  172. while it != nil:
  173. result = get(it, s)
  174. if result != nil:
  175. #echo "got from table ", result.name.s, " ", result.info
  176. return result
  177. it = it.next
  178. result = s
  179. proc considerGenSyms*(c: PContext; n: PNode) =
  180. if n.kind == nkSym:
  181. let s = getGenSym(c, n.sym)
  182. if n.sym != s:
  183. n.sym = s
  184. else:
  185. for i in 0..<n.safeLen:
  186. considerGenSyms(c, n[i])
  187. proc newOptionEntry*(conf: ConfigRef): POptionEntry =
  188. new(result)
  189. result.options = conf.options
  190. result.defaultCC = ccNimCall
  191. result.dynlib = nil
  192. result.notes = conf.notes
  193. result.warningAsErrors = conf.warningAsErrors
  194. proc pushOptionEntry*(c: PContext): POptionEntry =
  195. new(result)
  196. var prev = c.optionStack[^1]
  197. result.options = c.config.options
  198. result.defaultCC = prev.defaultCC
  199. result.dynlib = prev.dynlib
  200. result.notes = c.config.notes
  201. result.warningAsErrors = c.config.warningAsErrors
  202. result.features = c.features
  203. c.optionStack.add(result)
  204. proc popOptionEntry*(c: PContext) =
  205. c.config.options = c.optionStack[^1].options
  206. c.config.notes = c.optionStack[^1].notes
  207. c.config.warningAsErrors = c.optionStack[^1].warningAsErrors
  208. c.features = c.optionStack[^1].features
  209. c.optionStack.setLen(c.optionStack.len - 1)
  210. proc newContext*(graph: ModuleGraph; module: PSym): PContext =
  211. new(result)
  212. result.enforceVoidContext = PType(kind: tyTyped)
  213. result.ambiguousSymbols = initIntSet()
  214. result.optionStack = @[newOptionEntry(graph.config)]
  215. result.libs = @[]
  216. result.module = module
  217. result.friendModules = @[module]
  218. result.converters = @[]
  219. result.patterns = @[]
  220. result.includedFiles = initIntSet()
  221. initStrTable(result.pureEnumFields)
  222. initStrTable(result.userPragmas)
  223. result.generics = @[]
  224. result.unknownIdents = initIntSet()
  225. result.cache = graph.cache
  226. result.graph = graph
  227. initStrTable(result.signatures)
  228. result.typesWithOps = @[]
  229. result.features = graph.config.features
  230. proc inclSym(sq: var seq[PSym], s: PSym) =
  231. for i in 0..<sq.len:
  232. if sq[i].id == s.id: return
  233. sq.add s
  234. proc addConverter*(c: PContext, conv: PSym) =
  235. inclSym(c.converters, conv)
  236. proc addPattern*(c: PContext, p: PSym) =
  237. inclSym(c.patterns, p)
  238. proc newLib*(kind: TLibKind): PLib =
  239. new(result)
  240. result.kind = kind #initObjectSet(result.syms)
  241. proc addToLib*(lib: PLib, sym: PSym) =
  242. #if sym.annex != nil and not isGenericRoutine(sym):
  243. # LocalError(sym.info, errInvalidPragma)
  244. sym.annex = lib
  245. proc newTypeS*(kind: TTypeKind, c: PContext): PType =
  246. result = newType(kind, getCurrOwner(c))
  247. proc makePtrType*(owner: PSym, baseType: PType): PType =
  248. result = newType(tyPtr, owner)
  249. addSonSkipIntLit(result, baseType)
  250. proc makePtrType*(c: PContext, baseType: PType): PType =
  251. makePtrType(getCurrOwner(c), baseType)
  252. proc makeTypeWithModifier*(c: PContext,
  253. modifier: TTypeKind,
  254. baseType: PType): PType =
  255. assert modifier in {tyVar, tyLent, tyPtr, tyRef, tyStatic, tyTypeDesc}
  256. if modifier in {tyVar, tyLent, tyTypeDesc} and baseType.kind == modifier:
  257. result = baseType
  258. else:
  259. result = newTypeS(modifier, c)
  260. addSonSkipIntLit(result, baseType)
  261. proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType =
  262. if baseType.kind == kind:
  263. result = baseType
  264. else:
  265. result = newTypeS(kind, c)
  266. addSonSkipIntLit(result, baseType)
  267. proc makeVarType*(owner: PSym, baseType: PType; kind = tyVar): PType =
  268. if baseType.kind == kind:
  269. result = baseType
  270. else:
  271. result = newType(kind, owner)
  272. addSonSkipIntLit(result, baseType)
  273. proc makeTypeDesc*(c: PContext, typ: PType): PType =
  274. if typ.kind == tyTypeDesc:
  275. result = typ
  276. else:
  277. result = newTypeS(tyTypeDesc, c)
  278. incl result.flags, tfCheckedForDestructor
  279. result.addSonSkipIntLit(typ)
  280. proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
  281. let typedesc = newTypeS(tyTypeDesc, c)
  282. incl typedesc.flags, tfCheckedForDestructor
  283. internalAssert(c.config, typ != nil)
  284. typedesc.addSonSkipIntLit(typ)
  285. let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info,
  286. c.config.options).linkTo(typedesc)
  287. return newSymNode(sym, info)
  288. proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
  289. result = newTypeS(tyFromExpr, c)
  290. assert n != nil
  291. result.n = n
  292. proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]): PType =
  293. result = newType(kind, owner)
  294. result.sons = sons
  295. proc newTypeWithSons*(c: PContext, kind: TTypeKind,
  296. sons: seq[PType]): PType =
  297. result = newType(kind, getCurrOwner(c))
  298. result.sons = sons
  299. proc makeStaticExpr*(c: PContext, n: PNode): PNode =
  300. result = newNodeI(nkStaticExpr, n.info)
  301. result.sons = @[n]
  302. result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ
  303. else: newTypeWithSons(c, tyStatic, @[n.typ])
  304. proc makeAndType*(c: PContext, t1, t2: PType): PType =
  305. result = newTypeS(tyAnd, c)
  306. result.sons = @[t1, t2]
  307. propagateToOwner(result, t1)
  308. propagateToOwner(result, t2)
  309. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  310. result.flags.incl tfHasMeta
  311. proc makeOrType*(c: PContext, t1, t2: PType): PType =
  312. result = newTypeS(tyOr, c)
  313. if t1.kind != tyOr and t2.kind != tyOr:
  314. result.sons = @[t1, t2]
  315. else:
  316. template addOr(t1) =
  317. if t1.kind == tyOr:
  318. for x in t1.sons: result.rawAddSon x
  319. else:
  320. result.rawAddSon t1
  321. addOr(t1)
  322. addOr(t2)
  323. propagateToOwner(result, t1)
  324. propagateToOwner(result, t2)
  325. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  326. result.flags.incl tfHasMeta
  327. proc makeNotType*(c: PContext, t1: PType): PType =
  328. result = newTypeS(tyNot, c)
  329. result.sons = @[t1]
  330. propagateToOwner(result, t1)
  331. result.flags.incl(t1.flags * {tfHasStatic})
  332. result.flags.incl tfHasMeta
  333. proc nMinusOne(c: PContext; n: PNode): PNode =
  334. result = newTreeI(nkCall, n.info, 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 = newTreeI(nkRange, n.info, newIntTypeNode(0, intType),
  343. makeStaticExpr(c, nMinusOne(c, n)))
  344. template rangeHasUnresolvedStatic*(t: PType): bool =
  345. tfUnresolved in t.flags
  346. proc errorType*(c: PContext): PType =
  347. ## creates a type representing an error state
  348. result = newTypeS(tyError, c)
  349. result.flags.incl tfCheckedForDestructor
  350. proc errorNode*(c: PContext, n: PNode): PNode =
  351. result = newNodeI(nkEmpty, n.info)
  352. result.typ = errorType(c)
  353. proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
  354. dest.kind = kind
  355. dest.owner = getCurrOwner(c)
  356. dest.size = - 1
  357. proc makeRangeType*(c: PContext; first, last: BiggestInt;
  358. info: TLineInfo; intType: PType = nil): PType =
  359. let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt)
  360. var n = newNodeI(nkRange, info)
  361. n.add newIntTypeNode(first, intType)
  362. n.add newIntTypeNode(last, intType)
  363. result = newTypeS(tyRange, c)
  364. result.n = n
  365. addSonSkipIntLit(result, intType) # basetype of range
  366. proc markIndirect*(c: PContext, s: PSym) {.inline.} =
  367. if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:
  368. incl(s.flags, sfAddrTaken)
  369. # XXX add to 'c' for global analysis
  370. proc illFormedAst*(n: PNode; conf: ConfigRef) =
  371. globalError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  372. proc illFormedAstLocal*(n: PNode; conf: ConfigRef) =
  373. localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  374. proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) =
  375. if n.len != length: illFormedAst(n, conf)
  376. proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) =
  377. if n.len < length: illFormedAst(n, conf)
  378. proc isTopLevel*(c: PContext): bool {.inline.} =
  379. result = c.currentScope.depthLevel <= 2
  380. proc pushCaseContext*(c: PContext, caseNode: PNode) =
  381. c.p.caseContext.add((caseNode, 0))
  382. proc popCaseContext*(c: PContext) =
  383. discard pop(c.p.caseContext)
  384. proc setCaseContextIdx*(c: PContext, idx: int) =
  385. c.p.caseContext[^1].idx = idx