semdata.nim 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. TExprFlags* = set[TExprFlag]
  63. TTypeAttachedOp* = enum
  64. attachedAsgn,
  65. attachedSink,
  66. attachedDeepCopy,
  67. attachedDestructor
  68. PContext* = ref TContext
  69. TContext* = object of TPassContext # a context represents a module
  70. enforceVoidContext*: PType
  71. module*: PSym # the module sym belonging to the context
  72. currentScope*: PScope # current scope
  73. importTable*: PScope # scope for all imported symbols
  74. topLevelScope*: PScope # scope for all top-level symbols
  75. p*: PProcCon # procedure context
  76. matchedConcept*: ptr TMatchedConcept # the current concept being matched
  77. friendModules*: seq[PSym] # friend modules; may access private data;
  78. # this is used so that generic instantiations
  79. # can access private object fields
  80. instCounter*: int # to prevent endless instantiations
  81. ambiguousSymbols*: IntSet # ids of all ambiguous symbols (cannot
  82. # store this info in the syms themselves!)
  83. inGenericContext*: int # > 0 if we are in a generic type
  84. inStaticContext*: int # > 0 if we are inside a static: block
  85. inUnrolledContext*: int # > 0 if we are unrolling a loop
  86. compilesContextId*: int # > 0 if we are in a ``compiles`` magic
  87. compilesContextIdGenerator*: int
  88. inGenericInst*: int # > 0 if we are instantiating a generic
  89. converters*: TSymSeq # sequence of converters
  90. patterns*: TSymSeq # sequence of pattern matchers
  91. optionStack*: seq[POptionEntry]
  92. symMapping*: TIdTable # every gensym'ed symbol needs to be mapped
  93. # to some new symbol in a generic instantiation
  94. libs*: seq[PLib] # all libs used by this module
  95. semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
  96. semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  97. semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  98. semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.}
  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. template config*(c: PContext): ConfigRef = c.graph.config
  134. proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
  135. result.genericSym = s
  136. result.inst = inst
  137. proc filename*(c: PContext): string =
  138. # the module's filename
  139. return toFilename(c.config, FileIndex c.module.position)
  140. proc scopeDepth*(c: PContext): int {.inline.} =
  141. result = if c.currentScope != nil: c.currentScope.depthLevel
  142. else: 0
  143. proc getCurrOwner*(c: PContext): PSym =
  144. # owner stack (used for initializing the
  145. # owner field of syms)
  146. # the documentation comment always gets
  147. # assigned to the current owner
  148. result = c.graph.owners[^1]
  149. proc pushOwner*(c: PContext; owner: PSym) =
  150. add(c.graph.owners, owner)
  151. proc popOwner*(c: PContext) =
  152. var length = len(c.graph.owners)
  153. if length > 0: setLen(c.graph.owners, length - 1)
  154. else: internalError(c.config, "popOwner")
  155. proc lastOptionEntry*(c: PContext): POptionEntry =
  156. result = c.optionStack[^1]
  157. proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
  158. proc put*(p: PProcCon; key, val: PSym) =
  159. if not p.mappingExists:
  160. initIdTable(p.mapping)
  161. p.mappingExists = true
  162. #echo "put into table ", key.info
  163. p.mapping.idTablePut(key, val)
  164. proc get*(p: PProcCon; key: PSym): PSym =
  165. if not p.mappingExists: return nil
  166. result = PSym(p.mapping.idTableGet(key))
  167. proc getGenSym*(c: PContext; s: PSym): PSym =
  168. if sfGenSym notin s.flags: return s
  169. var it = c.p
  170. while it != nil:
  171. result = get(it, s)
  172. if result != nil:
  173. #echo "got from table ", result.name.s, " ", result.info
  174. return result
  175. it = it.next
  176. result = s
  177. proc considerGenSyms*(c: PContext; n: PNode) =
  178. if n.kind == nkSym:
  179. let s = getGenSym(c, n.sym)
  180. if n.sym != s:
  181. n.sym = s
  182. else:
  183. for i in 0..<n.safeLen:
  184. considerGenSyms(c, n.sons[i])
  185. proc newOptionEntry*(conf: ConfigRef): POptionEntry =
  186. new(result)
  187. result.options = conf.options
  188. result.defaultCC = ccDefault
  189. result.dynlib = nil
  190. result.notes = conf.notes
  191. proc newContext*(graph: ModuleGraph; module: PSym): PContext =
  192. new(result)
  193. result.enforceVoidContext = PType(kind: tyStmt)
  194. result.ambiguousSymbols = initIntSet()
  195. result.optionStack = @[]
  196. result.libs = @[]
  197. result.optionStack.add(newOptionEntry(graph.config))
  198. result.module = module
  199. result.friendModules = @[module]
  200. result.converters = @[]
  201. result.patterns = @[]
  202. result.includedFiles = initIntSet()
  203. initStrTable(result.pureEnumFields)
  204. initStrTable(result.userPragmas)
  205. result.generics = @[]
  206. result.unknownIdents = initIntSet()
  207. result.cache = graph.cache
  208. result.graph = graph
  209. initStrTable(result.signatures)
  210. result.typesWithOps = @[]
  211. result.features = graph.config.features
  212. proc inclSym(sq: var TSymSeq, s: PSym) =
  213. var L = len(sq)
  214. for i in countup(0, L - 1):
  215. if sq[i].id == s.id: return
  216. setLen(sq, L + 1)
  217. sq[L] = s
  218. proc addConverter*(c: PContext, conv: PSym) =
  219. inclSym(c.converters, conv)
  220. proc addPattern*(c: PContext, p: PSym) =
  221. inclSym(c.patterns, p)
  222. proc newLib*(kind: TLibKind): PLib =
  223. new(result)
  224. result.kind = kind #initObjectSet(result.syms)
  225. proc addToLib*(lib: PLib, sym: PSym) =
  226. #if sym.annex != nil and not isGenericRoutine(sym):
  227. # LocalError(sym.info, errInvalidPragma)
  228. sym.annex = lib
  229. proc newTypeS*(kind: TTypeKind, c: PContext): PType =
  230. result = newType(kind, getCurrOwner(c))
  231. proc makePtrType*(c: PContext, baseType: PType): PType =
  232. result = newTypeS(tyPtr, c)
  233. addSonSkipIntLit(result, baseType)
  234. proc makeTypeWithModifier*(c: PContext,
  235. modifier: TTypeKind,
  236. baseType: PType): PType =
  237. assert modifier in {tyVar, tyLent, tyPtr, tyRef, tyStatic, tyTypeDesc}
  238. if modifier in {tyVar, tyLent, tyTypeDesc} and baseType.kind == modifier:
  239. result = baseType
  240. else:
  241. result = newTypeS(modifier, c)
  242. addSonSkipIntLit(result, baseType)
  243. proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType =
  244. if baseType.kind == kind:
  245. result = baseType
  246. else:
  247. result = newTypeS(kind, c)
  248. addSonSkipIntLit(result, baseType)
  249. proc makeTypeDesc*(c: PContext, typ: PType): PType =
  250. if typ.kind == tyTypeDesc:
  251. result = typ
  252. else:
  253. result = newTypeS(tyTypeDesc, c)
  254. result.addSonSkipIntLit(typ)
  255. proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
  256. let typedesc = newTypeS(tyTypeDesc, c)
  257. typedesc.addSonSkipIntLit(assertNotNil(c.config, typ))
  258. let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info,
  259. c.config.options).linkTo(typedesc)
  260. return newSymNode(sym, info)
  261. proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
  262. result = newTypeS(tyFromExpr, c)
  263. assert n != nil
  264. result.n = n
  265. proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]): PType =
  266. result = newType(kind, owner)
  267. result.sons = sons
  268. proc newTypeWithSons*(c: PContext, kind: TTypeKind,
  269. sons: seq[PType]): PType =
  270. result = newType(kind, getCurrOwner(c))
  271. result.sons = sons
  272. proc makeStaticExpr*(c: PContext, n: PNode): PNode =
  273. result = newNodeI(nkStaticExpr, n.info)
  274. result.sons = @[n]
  275. result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ
  276. else: newTypeWithSons(c, tyStatic, @[n.typ])
  277. proc makeAndType*(c: PContext, t1, t2: PType): PType =
  278. result = newTypeS(tyAnd, c)
  279. result.sons = @[t1, t2]
  280. propagateToOwner(result, t1)
  281. propagateToOwner(result, t2)
  282. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  283. result.flags.incl tfHasMeta
  284. proc makeOrType*(c: PContext, t1, t2: PType): PType =
  285. result = newTypeS(tyOr, c)
  286. if t1.kind != tyOr and t2.kind != tyOr:
  287. result.sons = @[t1, t2]
  288. else:
  289. template addOr(t1) =
  290. if t1.kind == tyOr:
  291. for x in t1.sons: result.rawAddSon x
  292. else:
  293. result.rawAddSon t1
  294. addOr(t1)
  295. addOr(t2)
  296. propagateToOwner(result, t1)
  297. propagateToOwner(result, t2)
  298. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  299. result.flags.incl tfHasMeta
  300. proc makeNotType*(c: PContext, t1: PType): PType =
  301. result = newTypeS(tyNot, c)
  302. result.sons = @[t1]
  303. propagateToOwner(result, t1)
  304. result.flags.incl(t1.flags * {tfHasStatic})
  305. result.flags.incl tfHasMeta
  306. proc nMinusOne(c: PContext; n: PNode): PNode =
  307. result = newNode(nkCall, n.info, @[
  308. newSymNode(getSysMagic(c.graph, n.info, "pred", mPred)), n])
  309. # Remember to fix the procs below this one when you make changes!
  310. proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
  311. let intType = getSysType(c.graph, n.info, tyInt)
  312. result = newTypeS(tyRange, c)
  313. result.sons = @[intType]
  314. if n.typ != nil and n.typ.n == nil:
  315. result.flags.incl tfUnresolved
  316. result.n = newNode(nkRange, n.info, @[
  317. newIntTypeNode(nkIntLit, 0, intType),
  318. makeStaticExpr(c, nMinusOne(c, n))])
  319. template rangeHasUnresolvedStatic*(t: PType): bool =
  320. tfUnresolved in t.flags
  321. proc errorType*(c: PContext): PType =
  322. ## creates a type representing an error state
  323. result = newTypeS(tyError, c)
  324. proc errorNode*(c: PContext, n: PNode): PNode =
  325. result = newNodeI(nkEmpty, n.info)
  326. result.typ = errorType(c)
  327. proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
  328. dest.kind = kind
  329. dest.owner = getCurrOwner(c)
  330. dest.size = - 1
  331. proc makeRangeType*(c: PContext; first, last: BiggestInt;
  332. info: TLineInfo; intType: PType = nil): PType =
  333. let intType = if intType != nil: intType else: getSysType(c.graph, info, tyInt)
  334. var n = newNodeI(nkRange, info)
  335. addSon(n, newIntTypeNode(nkIntLit, first, intType))
  336. addSon(n, newIntTypeNode(nkIntLit, last, intType))
  337. result = newTypeS(tyRange, c)
  338. result.n = n
  339. addSonSkipIntLit(result, intType) # basetype of range
  340. proc markIndirect*(c: PContext, s: PSym) {.inline.} =
  341. if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:
  342. incl(s.flags, sfAddrTaken)
  343. # XXX add to 'c' for global analysis
  344. proc illFormedAst*(n: PNode; conf: ConfigRef) =
  345. globalError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  346. proc illFormedAstLocal*(n: PNode; conf: ConfigRef) =
  347. localError(conf, n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  348. proc checkSonsLen*(n: PNode, length: int; conf: ConfigRef) =
  349. if sonsLen(n) != length: illFormedAst(n, conf)
  350. proc checkMinSonsLen*(n: PNode, length: int; conf: ConfigRef) =
  351. if sonsLen(n) < length: illFormedAst(n, conf)
  352. proc isTopLevel*(c: PContext): bool {.inline.} =
  353. result = c.currentScope.depthLevel <= 2