semdata.nim 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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, rodread, vmdef,
  15. modulegraphs
  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. otherPragmas*: PNode # every pragma can be pushed
  23. POptionEntry* = ref TOptionEntry
  24. PProcCon* = ref TProcCon
  25. TProcCon* = object # procedure context; also used for top-level
  26. # statements
  27. owner*: PSym # the symbol this context belongs to
  28. resultSym*: PSym # the result symbol (if we are in a proc)
  29. selfSym*: PSym # the 'self' symbol (if available)
  30. nestedLoopCounter*: int # whether we are in a loop or not
  31. nestedBlockCounter*: int # whether we are in a block or not
  32. inTryStmt*: int # whether we are in a try statement; works also
  33. # in standalone ``except`` and ``finally``
  34. next*: PProcCon # used for stacking procedure contexts
  35. wasForwarded*: bool # whether the current proc has a separate header
  36. bracketExpr*: PNode # current bracket expression (for ^ support)
  37. mapping*: TIdTable
  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. efNoProcvarCheck, efNoEvaluateGeneric, efInCall, efFromHlo,
  61. TExprFlags* = set[TExprFlag]
  62. TTypeAttachedOp* = enum
  63. attachedAsgn,
  64. attachedSink,
  65. attachedDeepCopy,
  66. attachedDestructor
  67. PContext* = ref TContext
  68. TContext* = object of TPassContext # a context represents a module
  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. inUnrolledContext*: int # > 0 if we are unrolling a loop
  83. compilesContextId*: int # > 0 if we are in a ``compiles`` magic
  84. compilesContextIdGenerator*: int
  85. inGenericInst*: int # > 0 if we are instantiating a generic
  86. converters*: TSymSeq # sequence of converters
  87. patterns*: TSymSeq # sequence of pattern matchers
  88. optionStack*: seq[POptionEntry]
  89. symMapping*: TIdTable # every gensym'ed symbol needs to be mapped
  90. # to some new symbol in a generic instantiation
  91. libs*: seq[PLib] # all libs used by this module
  92. semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
  93. semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  94. semTryExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  95. semTryConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.}
  96. semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
  97. semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
  98. semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
  99. filter: TSymKinds, flags: TExprFlags): PNode {.nimcall.}
  100. semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.}
  101. semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode
  102. semGenerateInstance*: proc (c: PContext, fn: PSym, pt: TIdTable,
  103. info: TLineInfo): PSym
  104. includedFiles*: IntSet # used to detect recursive include files
  105. pureEnumFields*: TStrTable # pure enum fields that can be used unambiguously
  106. userPragmas*: TStrTable
  107. evalContext*: PEvalContext
  108. unknownIdents*: IntSet # ids of all unknown identifiers to prevent
  109. # naming it multiple times
  110. generics*: seq[TInstantiationPair] # pending list of instantiated generics to compile
  111. topStmts*: int # counts the number of encountered top level statements
  112. lastGenericIdx*: int # used for the generics stack
  113. hloLoopDetector*: int # used to prevent endless loops in the HLO
  114. inParallelStmt*: int
  115. instTypeBoundOp*: proc (c: PContext; dc: PSym; t: PType; info: TLineInfo;
  116. op: TTypeAttachedOp; col: int): PSym {.nimcall.}
  117. selfName*: PIdent
  118. cache*: IdentCache
  119. graph*: ModuleGraph
  120. signatures*: TStrTable
  121. recursiveDep*: string
  122. suggestionsMade*: bool
  123. inTypeContext*: int
  124. typesWithOps*: seq[(PType, PType)] #\
  125. # We need to instantiate the type bound ops lazily after
  126. # the generic type has been constructed completely. See
  127. # tests/destructor/topttree.nim for an example that
  128. # would otherwise fail.
  129. proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
  130. result.genericSym = s
  131. result.inst = inst
  132. proc filename*(c: PContext): string =
  133. # the module's filename
  134. return c.module.filename
  135. proc scopeDepth*(c: PContext): int {.inline.} =
  136. result = if c.currentScope != nil: c.currentScope.depthLevel
  137. else: 0
  138. proc getCurrOwner*(c: PContext): PSym =
  139. # owner stack (used for initializing the
  140. # owner field of syms)
  141. # the documentation comment always gets
  142. # assigned to the current owner
  143. result = c.graph.owners[^1]
  144. proc pushOwner*(c: PContext; owner: PSym) =
  145. add(c.graph.owners, owner)
  146. proc popOwner*(c: PContext) =
  147. var length = len(c.graph.owners)
  148. if length > 0: setLen(c.graph.owners, length - 1)
  149. else: internalError("popOwner")
  150. proc lastOptionEntry*(c: PContext): POptionEntry =
  151. result = c.optionStack[^1]
  152. proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
  153. proc put*(p: PProcCon; key, val: PSym) =
  154. if p.mapping.data == nil: initIdTable(p.mapping)
  155. #echo "put into table ", key.info
  156. p.mapping.idTablePut(key, val)
  157. proc get*(p: PProcCon; key: PSym): PSym =
  158. if p.mapping.data == nil: return nil
  159. result = PSym(p.mapping.idTableGet(key))
  160. proc getGenSym*(c: PContext; s: PSym): PSym =
  161. if sfGenSym notin s.flags: return s
  162. var it = c.p
  163. while it != nil:
  164. result = get(it, s)
  165. if result != nil:
  166. #echo "got from table ", result.name.s, " ", result.info
  167. return result
  168. it = it.next
  169. result = s
  170. proc considerGenSyms*(c: PContext; n: PNode) =
  171. if n.kind == nkSym:
  172. let s = getGenSym(c, n.sym)
  173. if n.sym != s:
  174. n.sym = s
  175. else:
  176. for i in 0..<n.safeLen:
  177. considerGenSyms(c, n.sons[i])
  178. proc newOptionEntry*(): POptionEntry =
  179. new(result)
  180. result.options = gOptions
  181. result.defaultCC = ccDefault
  182. result.dynlib = nil
  183. result.notes = gNotes
  184. proc newContext*(graph: ModuleGraph; module: PSym; cache: IdentCache): PContext =
  185. new(result)
  186. result.ambiguousSymbols = initIntSet()
  187. result.optionStack = @[]
  188. result.libs = @[]
  189. result.optionStack.add(newOptionEntry())
  190. result.module = module
  191. result.friendModules = @[module]
  192. result.converters = @[]
  193. result.patterns = @[]
  194. result.includedFiles = initIntSet()
  195. initStrTable(result.pureEnumFields)
  196. initStrTable(result.userPragmas)
  197. result.generics = @[]
  198. result.unknownIdents = initIntSet()
  199. result.cache = cache
  200. result.graph = graph
  201. initStrTable(result.signatures)
  202. result.typesWithOps = @[]
  203. proc inclSym(sq: var TSymSeq, s: PSym) =
  204. var L = len(sq)
  205. for i in countup(0, L - 1):
  206. if sq[i].id == s.id: return
  207. setLen(sq, L + 1)
  208. sq[L] = s
  209. proc addConverter*(c: PContext, conv: PSym) =
  210. inclSym(c.converters, conv)
  211. proc addPattern*(c: PContext, p: PSym) =
  212. inclSym(c.patterns, p)
  213. proc newLib*(kind: TLibKind): PLib =
  214. new(result)
  215. result.kind = kind #initObjectSet(result.syms)
  216. proc addToLib*(lib: PLib, sym: PSym) =
  217. #if sym.annex != nil and not isGenericRoutine(sym):
  218. # LocalError(sym.info, errInvalidPragma)
  219. sym.annex = lib
  220. proc newTypeS*(kind: TTypeKind, c: PContext): PType =
  221. result = newType(kind, getCurrOwner(c))
  222. proc makePtrType*(c: PContext, baseType: PType): PType =
  223. result = newTypeS(tyPtr, c)
  224. addSonSkipIntLit(result, baseType.assertNotNil)
  225. proc makeTypeWithModifier*(c: PContext,
  226. modifier: TTypeKind,
  227. baseType: PType): PType =
  228. assert modifier in {tyVar, tyPtr, tyRef, tyStatic, tyTypeDesc}
  229. if modifier in {tyVar, tyTypeDesc} and baseType.kind == modifier:
  230. result = baseType
  231. else:
  232. result = newTypeS(modifier, c)
  233. addSonSkipIntLit(result, baseType.assertNotNil)
  234. proc makeVarType*(c: PContext, baseType: PType): PType =
  235. if baseType.kind == tyVar:
  236. result = baseType
  237. else:
  238. result = newTypeS(tyVar, c)
  239. addSonSkipIntLit(result, baseType.assertNotNil)
  240. proc makeTypeDesc*(c: PContext, typ: PType): PType =
  241. if typ.kind == tyTypeDesc:
  242. result = typ
  243. else:
  244. result = newTypeS(tyTypeDesc, c)
  245. result.addSonSkipIntLit(typ.assertNotNil)
  246. proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
  247. let typedesc = makeTypeDesc(c, typ)
  248. let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info).linkTo(typedesc)
  249. return newSymNode(sym, info)
  250. proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
  251. result = newTypeS(tyFromExpr, c)
  252. assert n != nil
  253. result.n = n
  254. proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]): PType =
  255. result = newType(kind, owner)
  256. result.sons = sons
  257. proc newTypeWithSons*(c: PContext, kind: TTypeKind,
  258. sons: seq[PType]): PType =
  259. result = newType(kind, getCurrOwner(c))
  260. result.sons = sons
  261. proc makeStaticExpr*(c: PContext, n: PNode): PNode =
  262. result = newNodeI(nkStaticExpr, n.info)
  263. result.sons = @[n]
  264. result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ
  265. else: newTypeWithSons(c, tyStatic, @[n.typ])
  266. proc makeAndType*(c: PContext, t1, t2: PType): PType =
  267. result = newTypeS(tyAnd, c)
  268. result.sons = @[t1, t2]
  269. propagateToOwner(result, t1)
  270. propagateToOwner(result, t2)
  271. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  272. result.flags.incl tfHasMeta
  273. proc makeOrType*(c: PContext, t1, t2: PType): PType =
  274. result = newTypeS(tyOr, c)
  275. if t1.kind != tyOr and t2.kind != tyOr:
  276. result.sons = @[t1, t2]
  277. else:
  278. template addOr(t1) =
  279. if t1.kind == tyOr:
  280. for x in t1.sons: result.rawAddSon x
  281. else:
  282. result.rawAddSon t1
  283. addOr(t1)
  284. addOr(t2)
  285. propagateToOwner(result, t1)
  286. propagateToOwner(result, t2)
  287. result.flags.incl((t1.flags + t2.flags) * {tfHasStatic})
  288. result.flags.incl tfHasMeta
  289. proc makeNotType*(c: PContext, t1: PType): PType =
  290. result = newTypeS(tyNot, c)
  291. result.sons = @[t1]
  292. propagateToOwner(result, t1)
  293. result.flags.incl(t1.flags * {tfHasStatic})
  294. result.flags.incl tfHasMeta
  295. proc nMinusOne*(n: PNode): PNode =
  296. result = newNode(nkCall, n.info, @[
  297. newSymNode(getSysMagic("<", mUnaryLt)),
  298. n])
  299. # Remember to fix the procs below this one when you make changes!
  300. proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType =
  301. let intType = getSysType(tyInt)
  302. result = newTypeS(tyRange, c)
  303. result.sons = @[intType]
  304. if n.typ != nil and n.typ.n == nil:
  305. result.flags.incl tfUnresolved
  306. result.n = newNode(nkRange, n.info, @[
  307. newIntTypeNode(nkIntLit, 0, intType),
  308. makeStaticExpr(c, n.nMinusOne)])
  309. template rangeHasUnresolvedStatic*(t: PType): bool =
  310. tfUnresolved in t.flags
  311. proc errorType*(c: PContext): PType =
  312. ## creates a type representing an error state
  313. result = newTypeS(tyError, c)
  314. proc errorNode*(c: PContext, n: PNode): PNode =
  315. result = newNodeI(nkEmpty, n.info)
  316. result.typ = errorType(c)
  317. proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
  318. dest.kind = kind
  319. dest.owner = getCurrOwner(c)
  320. dest.size = - 1
  321. proc makeRangeType*(c: PContext; first, last: BiggestInt;
  322. info: TLineInfo; intType = getSysType(tyInt)): PType =
  323. var n = newNodeI(nkRange, info)
  324. addSon(n, newIntTypeNode(nkIntLit, first, intType))
  325. addSon(n, newIntTypeNode(nkIntLit, last, intType))
  326. result = newTypeS(tyRange, c)
  327. result.n = n
  328. addSonSkipIntLit(result, intType) # basetype of range
  329. proc markIndirect*(c: PContext, s: PSym) {.inline.} =
  330. if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:
  331. incl(s.flags, sfAddrTaken)
  332. # XXX add to 'c' for global analysis
  333. proc illFormedAst*(n: PNode) =
  334. globalError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  335. proc illFormedAstLocal*(n: PNode) =
  336. localError(n.info, errIllFormedAstX, renderTree(n, {renderNoComments}))
  337. proc checkSonsLen*(n: PNode, length: int) =
  338. if sonsLen(n) != length: illFormedAst(n)
  339. proc checkMinSonsLen*(n: PNode, length: int) =
  340. if sonsLen(n) < length: illFormedAst(n)
  341. proc isTopLevel*(c: PContext): bool {.inline.} =
  342. result = c.currentScope.depthLevel <= 2
  343. proc experimentalMode*(c: PContext): bool {.inline.} =
  344. result = gExperimentalMode or sfExperimental in c.module.flags