semstmts.nim 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## this module does the semantic checking of statements
  10. # included from sem.nim
  11. const
  12. errNoSymbolToBorrowFromFound = "no symbol to borrow from found"
  13. errDiscardValueX = "value of type '$1' has to be discarded"
  14. errInvalidDiscard = "statement returns no value that can be discarded"
  15. errInvalidControlFlowX = "invalid control flow: $1"
  16. errSelectorMustBeOfCertainTypes = "selector must be of an ordinal type, float or string"
  17. errExprCannotBeRaised = "only a 'ref object' can be raised"
  18. errBreakOnlyInLoop = "'break' only allowed in loop construct"
  19. errExceptionAlreadyHandled = "exception already handled"
  20. errYieldNotAllowedHere = "'yield' only allowed in an iterator"
  21. errYieldNotAllowedInTryStmt = "'yield' cannot be used within 'try' in a non-inlined iterator"
  22. errInvalidNumberOfYieldExpr = "invalid number of 'yield' expressions"
  23. errCannotReturnExpr = "current routine cannot return an expression"
  24. errGenericLambdaNotAllowed = "A nested proc can have generic parameters only when " &
  25. "it is used as an operand to another routine and the types " &
  26. "of the generic paramers can be inferred from the expected signature."
  27. errCannotInferTypeOfTheLiteral = "cannot infer the type of the $1"
  28. errCannotInferReturnType = "cannot infer the return type of the proc"
  29. errCannotInferStaticParam = "cannot infer the value of the static param '$1'"
  30. errProcHasNoConcreteType = "'$1' doesn't have a concrete type, due to unspecified generic parameters."
  31. errLetNeedsInit = "'let' symbol requires an initialization"
  32. errThreadvarCannotInit = "a thread var cannot be initialized explicitly; this would only run for the main thread"
  33. errImplOfXexpected = "implementation of '$1' expected"
  34. errRecursiveDependencyX = "recursive dependency: '$1'"
  35. errPragmaOnlyInHeaderOfProcX = "pragmas are only allowed in the header of a proc; redefinition of $1"
  36. proc semDiscard(c: PContext, n: PNode): PNode =
  37. result = n
  38. checkSonsLen(n, 1, c.config)
  39. if n.sons[0].kind != nkEmpty:
  40. n.sons[0] = semExprWithType(c, n.sons[0])
  41. let sonType = n.sons[0].typ
  42. let sonKind = n.sons[0].kind
  43. if isEmptyType(sonType) or sonType.kind == tyNone or n.sons[0].kind == nkTypeOfExpr:
  44. localError(c.config, n.info, errInvalidDiscard)
  45. if sonType.kind == tyProc and sonKind notin nkCallKinds:
  46. # tyProc is disallowed to prevent ``discard foo`` to be valid, when ``discard foo()`` is meant.
  47. localError(c.config, n.info, "illegal discard proc, did you mean: " & $n[0] & "()")
  48. proc semBreakOrContinue(c: PContext, n: PNode): PNode =
  49. result = n
  50. checkSonsLen(n, 1, c.config)
  51. if n.sons[0].kind != nkEmpty:
  52. if n.kind != nkContinueStmt:
  53. var s: PSym
  54. case n.sons[0].kind
  55. of nkIdent: s = lookUp(c, n.sons[0])
  56. of nkSym: s = n.sons[0].sym
  57. else: illFormedAst(n, c.config)
  58. s = getGenSym(c, s)
  59. if s.kind == skLabel and s.owner.id == c.p.owner.id:
  60. var x = newSymNode(s)
  61. x.info = n.info
  62. incl(s.flags, sfUsed)
  63. n.sons[0] = x
  64. suggestSym(c.config, x.info, s, c.graph.usageSym)
  65. onUse(x.info, s)
  66. else:
  67. localError(c.config, n.info, errInvalidControlFlowX % s.name.s)
  68. else:
  69. localError(c.config, n.info, errGenerated, "'continue' cannot have a label")
  70. elif (c.p.nestedLoopCounter <= 0) and ((c.p.nestedBlockCounter <= 0) or n.kind == nkContinueStmt):
  71. localError(c.config, n.info, errInvalidControlFlowX %
  72. renderTree(n, {renderNoComments}))
  73. proc semAsm(c: PContext, n: PNode): PNode =
  74. checkSonsLen(n, 2, c.config)
  75. var marker = pragmaAsm(c, n.sons[0])
  76. if marker == '\0': marker = '`' # default marker
  77. result = semAsmOrEmit(c, n, marker)
  78. proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
  79. result = n
  80. checkSonsLen(n, 2, c.config)
  81. openScope(c)
  82. n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0]))
  83. inc(c.p.nestedLoopCounter)
  84. n.sons[1] = semStmt(c, n.sons[1], flags)
  85. dec(c.p.nestedLoopCounter)
  86. closeScope(c)
  87. if n.sons[1].typ == c.enforceVoidContext:
  88. result.typ = c.enforceVoidContext
  89. elif efInTypeof in flags:
  90. result.typ = n[1].typ
  91. proc semProc(c: PContext, n: PNode): PNode
  92. proc semExprBranch(c: PContext, n: PNode; flags: TExprFlags = {}): PNode =
  93. result = semExpr(c, n, flags)
  94. if result.typ != nil:
  95. # XXX tyGenericInst here?
  96. if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
  97. proc semExprBranchScope(c: PContext, n: PNode): PNode =
  98. openScope(c)
  99. result = semExprBranch(c, n)
  100. closeScope(c)
  101. const
  102. skipForDiscardable = {nkIfStmt, nkIfExpr, nkCaseStmt, nkOfBranch,
  103. nkElse, nkStmtListExpr, nkTryStmt, nkFinally, nkExceptBranch,
  104. nkElifBranch, nkElifExpr, nkElseExpr, nkBlockStmt, nkBlockExpr,
  105. nkHiddenStdConv, nkHiddenDeref}
  106. proc implicitlyDiscardable(n: PNode): bool =
  107. var n = n
  108. while n.kind in skipForDiscardable: n = n.lastSon
  109. result = n.kind == nkRaiseStmt or
  110. (isCallExpr(n) and n.sons[0].kind == nkSym and
  111. sfDiscardable in n.sons[0].sym.flags)
  112. proc fixNilType(c: PContext; n: PNode) =
  113. if isAtom(n):
  114. if n.kind != nkNilLit and n.typ != nil:
  115. localError(c.config, n.info, errDiscardValueX % n.typ.typeToString)
  116. elif n.kind in {nkStmtList, nkStmtListExpr}:
  117. n.kind = nkStmtList
  118. for it in n: fixNilType(c, it)
  119. n.typ = nil
  120. proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
  121. if c.matchedConcept != nil or efInTypeof in flags: return
  122. if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}:
  123. if implicitlyDiscardable(result):
  124. var n = newNodeI(nkDiscardStmt, result.info, 1)
  125. n[0] = result
  126. elif result.typ.kind != tyError and c.config.cmd != cmdInteractive:
  127. var n = result
  128. while n.kind in skipForDiscardable: n = n.lastSon
  129. var s = "expression '" & $n & "' is of type '" &
  130. result.typ.typeToString & "' and has to be discarded"
  131. if result.info.line != n.info.line or
  132. result.info.fileIndex != n.info.fileIndex:
  133. s.add "; start of expression here: " & c.config$result.info
  134. if result.typ.kind == tyProc:
  135. s.add "; for a function call use ()"
  136. localError(c.config, n.info, s)
  137. proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
  138. result = n
  139. var typ = commonTypeBegin
  140. var hasElse = false
  141. for i in countup(0, sonsLen(n) - 1):
  142. var it = n.sons[i]
  143. if it.len == 2:
  144. openScope(c)
  145. it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
  146. it.sons[1] = semExprBranch(c, it.sons[1])
  147. typ = commonType(typ, it.sons[1])
  148. closeScope(c)
  149. elif it.len == 1:
  150. hasElse = true
  151. it.sons[0] = semExprBranchScope(c, it.sons[0])
  152. typ = commonType(typ, it.sons[0])
  153. else: illFormedAst(it, c.config)
  154. if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
  155. (not hasElse and efInTypeof notin flags):
  156. for it in n: discardCheck(c, it.lastSon, flags)
  157. result.kind = nkIfStmt
  158. # propagate any enforced VoidContext:
  159. if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
  160. else:
  161. for it in n:
  162. let j = it.len-1
  163. if not endsInNoReturn(it.sons[j]):
  164. it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
  165. result.kind = nkIfExpr
  166. result.typ = typ
  167. proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
  168. var check = initIntSet()
  169. template semExceptBranchType(typeNode: PNode): bool =
  170. # returns true if exception type is imported type
  171. let typ = semTypeNode(c, typeNode, nil).toObject()
  172. var is_imported = false
  173. if isImportedException(typ, c.config):
  174. is_imported = true
  175. elif not isException(typ):
  176. localError(c.config, typeNode.info, errExprCannotBeRaised)
  177. if containsOrIncl(check, typ.id):
  178. localError(c.config, typeNode.info, errExceptionAlreadyHandled)
  179. typeNode = newNodeIT(nkType, typeNode.info, typ)
  180. is_imported
  181. result = n
  182. inc c.p.inTryStmt
  183. checkMinSonsLen(n, 2, c.config)
  184. var typ = commonTypeBegin
  185. n[0] = semExprBranchScope(c, n[0])
  186. typ = commonType(typ, n[0].typ)
  187. var last = sonsLen(n) - 1
  188. var catchAllExcepts = 0
  189. for i in countup(1, last):
  190. let a = n.sons[i]
  191. checkMinSonsLen(a, 1, c.config)
  192. openScope(c)
  193. if a.kind == nkExceptBranch:
  194. if a.len == 2 and a[0].kind == nkBracket:
  195. # rewrite ``except [a, b, c]: body`` -> ```except a, b, c: body```
  196. a.sons[0..0] = a[0].sons
  197. if a.len == 2 and a[0].isInfixAs():
  198. # support ``except Exception as ex: body``
  199. let is_imported = semExceptBranchType(a[0][1])
  200. let symbol = newSymG(skLet, a[0][2], c)
  201. symbol.typ = if is_imported: a[0][1].typ
  202. else: a[0][1].typ.toRef()
  203. addDecl(c, symbol)
  204. # Overwrite symbol in AST with the symbol in the symbol table.
  205. a[0][2] = newSymNode(symbol, a[0][2].info)
  206. elif a.len == 1:
  207. # count number of ``except: body`` blocks
  208. inc catchAllExcepts
  209. else:
  210. # support ``except KeyError, ValueError, ... : body``
  211. if catchAllExcepts > 0:
  212. # if ``except: body`` already encountered,
  213. # cannot be followed by a ``except KeyError, ... : body`` block
  214. inc catchAllExcepts
  215. var is_native, is_imported: bool
  216. for j in 0..a.len-2:
  217. let tmp = semExceptBranchType(a[j])
  218. if tmp: is_imported = true
  219. else: is_native = true
  220. if is_native and is_imported:
  221. localError(c.config, a[0].info, "Mix of imported and native exception types is not allowed in one except branch")
  222. elif a.kind == nkFinally:
  223. if i != n.len-1:
  224. localError(c.config, a.info, "Only one finally is allowed after all other branches")
  225. else:
  226. illFormedAst(n, c.config)
  227. if catchAllExcepts > 1:
  228. # if number of ``except: body`` blocks is greater than 1
  229. # or more specific exception follows a general except block, it is invalid
  230. localError(c.config, a.info, "Only one general except clause is allowed after more specific exceptions")
  231. # last child of an nkExcept/nkFinally branch is a statement:
  232. a[^1] = semExprBranchScope(c, a[^1])
  233. if a.kind != nkFinally: typ = commonType(typ, a[^1])
  234. else: dec last
  235. closeScope(c)
  236. dec c.p.inTryStmt
  237. if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}:
  238. discardCheck(c, n.sons[0], flags)
  239. for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
  240. if typ == c.enforceVoidContext:
  241. result.typ = c.enforceVoidContext
  242. else:
  243. if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
  244. n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info)
  245. for i in 1..last:
  246. var it = n.sons[i]
  247. let j = it.len-1
  248. it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
  249. result.typ = typ
  250. proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
  251. result = fitNode(c, typ, n, n.info)
  252. if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
  253. let r1 = result.sons[1]
  254. if r1.kind in {nkCharLit..nkUInt64Lit} and typ.skipTypes(abstractRange).kind in {tyFloat..tyFloat128}:
  255. result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal)
  256. result.info = n.info
  257. result.typ = typ
  258. else:
  259. changeType(c, r1, typ, check=true)
  260. result = r1
  261. elif not sameType(result.typ, typ):
  262. changeType(c, result, typ, check=false)
  263. proc findShadowedVar(c: PContext, v: PSym): PSym =
  264. for scope in walkScopes(c.currentScope.parent):
  265. if scope == c.topLevelScope: break
  266. let shadowed = strTableGet(scope.symbols, v.name)
  267. if shadowed != nil and shadowed.kind in skLocalVars:
  268. return shadowed
  269. proc identWithin(n: PNode, s: PIdent): bool =
  270. for i in 0 .. n.safeLen-1:
  271. if identWithin(n.sons[i], s): return true
  272. result = n.kind == nkSym and n.sym.name.id == s.id
  273. proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
  274. if isTopLevel(c):
  275. result = semIdentWithPragma(c, kind, n, {sfExported})
  276. incl(result.flags, sfGlobal)
  277. #if kind in {skVar, skLet}:
  278. # echo "global variable here ", n.info, " ", result.name.s
  279. else:
  280. result = semIdentWithPragma(c, kind, n, {})
  281. if result.owner.kind == skModule:
  282. incl(result.flags, sfGlobal)
  283. let info = case n.kind
  284. of nkPostfix:
  285. n.sons[1].info
  286. of nkPragmaExpr:
  287. if n.sons[0].kind == nkPostfix:
  288. n.sons[0].sons[1].info
  289. else:
  290. n.sons[0].info
  291. else:
  292. n.info
  293. suggestSym(c.config, info, result, c.graph.usageSym)
  294. proc checkNilable(c: PContext; v: PSym) =
  295. if {sfGlobal, sfImportC} * v.flags == {sfGlobal} and
  296. {tfNotNil, tfNeedsInit} * v.typ.flags != {}:
  297. if v.ast.isNil:
  298. message(c.config, v.info, warnProveInit, v.name.s)
  299. elif tfNotNil in v.typ.flags and tfNotNil notin v.ast.typ.flags:
  300. message(c.config, v.info, warnProveInit, v.name.s)
  301. include semasgn
  302. proc addToVarSection(c: PContext; result: PNode; orig, identDefs: PNode) =
  303. let L = identDefs.len
  304. let value = identDefs[L-1]
  305. if result.kind == nkStmtList:
  306. let o = copyNode(orig)
  307. o.add identDefs
  308. result.add o
  309. else:
  310. result.add identDefs
  311. proc isDiscardUnderscore(v: PSym): bool =
  312. if v.name.s == "_":
  313. v.flags.incl(sfGenSym)
  314. result = true
  315. proc semUsing(c: PContext; n: PNode): PNode =
  316. result = c.graph.emptyNode
  317. if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "using")
  318. for i in countup(0, sonsLen(n)-1):
  319. var a = n.sons[i]
  320. if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
  321. if a.kind == nkCommentStmt: continue
  322. if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
  323. checkMinSonsLen(a, 3, c.config)
  324. var length = sonsLen(a)
  325. if a.sons[length-2].kind != nkEmpty:
  326. let typ = semTypeNode(c, a.sons[length-2], nil)
  327. for j in countup(0, length-3):
  328. let v = semIdentDef(c, a.sons[j], skParam)
  329. styleCheckDef(c.config, v)
  330. onDef(a[j].info, v)
  331. v.typ = typ
  332. strTableIncl(c.signatures, v)
  333. else:
  334. localError(c.config, a.info, "'using' section must have a type")
  335. var def: PNode
  336. if a.sons[length-1].kind != nkEmpty:
  337. localError(c.config, a.info, "'using' sections cannot contain assignments")
  338. proc hasEmpty(typ: PType): bool =
  339. if typ.kind in {tySequence, tyArray, tySet}:
  340. result = typ.lastSon.kind == tyEmpty
  341. elif typ.kind == tyTuple:
  342. for s in typ.sons:
  343. result = result or hasEmpty(s)
  344. proc makeDeref(n: PNode): PNode =
  345. var t = n.typ
  346. if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass:
  347. t = t.lastSon
  348. t = skipTypes(t, {tyGenericInst, tyAlias, tySink})
  349. result = n
  350. if t.kind in {tyVar, tyLent}:
  351. result = newNodeIT(nkHiddenDeref, n.info, t.sons[0])
  352. addSon(result, n)
  353. t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink})
  354. while t.kind in {tyPtr, tyRef}:
  355. var a = result
  356. let baseTyp = t.lastSon
  357. result = newNodeIT(nkHiddenDeref, n.info, baseTyp)
  358. addSon(result, a)
  359. t = skipTypes(baseTyp, {tyGenericInst, tyAlias, tySink})
  360. proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
  361. if n.len == 2:
  362. let x = semExprWithType(c, n[0])
  363. let y = considerQuotedIdent(c, n[1])
  364. let obj = x.typ.skipTypes(abstractPtrs)
  365. if obj.kind == tyObject and tfPartial in obj.flags:
  366. let field = newSym(skField, getIdent(c.cache, y.s), obj.sym, n[1].info)
  367. field.typ = skipIntLit(typ)
  368. field.position = sonsLen(obj.n)
  369. addSon(obj.n, newSymNode(field))
  370. n.sons[0] = makeDeref x
  371. n.sons[1] = newSymNode(field)
  372. n.typ = field.typ
  373. else:
  374. localError(c.config, n.info, "implicit object field construction " &
  375. "requires a .partial object, but got " & typeToString(obj))
  376. else:
  377. localError(c.config, n.info, "nkDotNode requires 2 children")
  378. proc setVarType(c: PContext; v: PSym, typ: PType) =
  379. if v.typ != nil and not sameTypeOrNil(v.typ, typ):
  380. localError(c.config, v.info, "inconsistent typing for reintroduced symbol '" &
  381. v.name.s & "': previous type was: " & typeToString(v.typ) &
  382. "; new type is: " & typeToString(typ))
  383. v.typ = typ
  384. proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
  385. var b: PNode
  386. result = copyNode(n)
  387. var hasCompileTime = false
  388. for i in countup(0, sonsLen(n)-1):
  389. var a = n.sons[i]
  390. if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
  391. if a.kind == nkCommentStmt: continue
  392. if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
  393. checkMinSonsLen(a, 3, c.config)
  394. var length = sonsLen(a)
  395. var typ: PType
  396. if a.sons[length-2].kind != nkEmpty:
  397. typ = semTypeNode(c, a.sons[length-2], nil)
  398. else:
  399. typ = nil
  400. var def: PNode = c.graph.emptyNode
  401. if a.sons[length-1].kind != nkEmpty:
  402. def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
  403. if def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
  404. # prevent the all too common 'var x = int' bug:
  405. localError(c.config, def.info, "'typedesc' metatype is not valid here; typed '=' instead of ':'?")
  406. def.typ = errorType(c)
  407. if typ != nil:
  408. if typ.isMetaType:
  409. def = inferWithMetatype(c, typ, def)
  410. typ = def.typ
  411. else:
  412. # BUGFIX: ``fitNode`` is needed here!
  413. # check type compatibility between def.typ and typ
  414. def = fitNode(c, typ, def, def.info)
  415. #changeType(def.skipConv, typ, check=true)
  416. else:
  417. typ = def.typ.skipTypes({tyStatic}).skipIntLit
  418. if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass:
  419. typ = typ.lastSon
  420. if hasEmpty(typ):
  421. localError(c.config, def.info, errCannotInferTypeOfTheLiteral %
  422. ($typ.kind).substr(2).toLowerAscii)
  423. elif typ.kind == tyProc and tfUnresolved in typ.flags:
  424. localError(c.config, def.info, errProcHasNoConcreteType % def.renderTree)
  425. else:
  426. if symkind == skLet: localError(c.config, a.info, errLetNeedsInit)
  427. # this can only happen for errornous var statements:
  428. if typ == nil: continue
  429. typeAllowedCheck(c.config, a.info, typ, symkind, if c.matchedConcept != nil: {taConcept} else: {})
  430. liftTypeBoundOps(c, typ, a.info)
  431. var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink})
  432. if a.kind == nkVarTuple:
  433. if tup.kind != tyTuple:
  434. localError(c.config, a.info, errXExpected, "tuple")
  435. elif length-2 != sonsLen(tup):
  436. localError(c.config, a.info, errWrongNumberOfVariables)
  437. b = newNodeI(nkVarTuple, a.info)
  438. newSons(b, length)
  439. # keep type desc for doc generator
  440. # NOTE: at the moment this is always ast.emptyNode, see parser.nim
  441. b.sons[length-2] = a.sons[length-2]
  442. b.sons[length-1] = def
  443. addToVarSection(c, result, n, b)
  444. elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
  445. a.kind == nkIdentDefs and a.len > 3:
  446. message(c.config, a.info, warnEachIdentIsTuple)
  447. for j in countup(0, length-3):
  448. if a[j].kind == nkDotExpr:
  449. fillPartialObject(c, a[j],
  450. if a.kind != nkVarTuple: typ else: tup.sons[j])
  451. addToVarSection(c, result, n, a)
  452. continue
  453. var v = semIdentDef(c, a.sons[j], symkind)
  454. styleCheckDef(c.config, v)
  455. onDef(a[j].info, v)
  456. if sfGenSym notin v.flags:
  457. if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
  458. else:
  459. if v.owner == nil: v.owner = c.p.owner
  460. when oKeepVariableNames:
  461. if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
  462. else:
  463. let shadowed = findShadowedVar(c, v)
  464. if shadowed != nil:
  465. shadowed.flags.incl(sfShadowed)
  466. if shadowed.kind == skResult and sfGenSym notin v.flags:
  467. message(c.config, a.info, warnResultShadowed)
  468. # a shadowed variable is an error unless it appears on the right
  469. # side of the '=':
  470. if warnShadowIdent in c.config.notes and not identWithin(def, v.name):
  471. message(c.config, a.info, warnShadowIdent, v.name.s)
  472. if a.kind != nkVarTuple:
  473. if def.kind != nkEmpty:
  474. # this is needed for the evaluation pass and for the guard checking:
  475. v.ast = def
  476. if sfThread in v.flags: localError(c.config, def.info, errThreadvarCannotInit)
  477. setVarType(c, v, typ)
  478. b = newNodeI(nkIdentDefs, a.info)
  479. if importantComments(c.config):
  480. # keep documentation information:
  481. b.comment = a.comment
  482. addSon(b, newSymNode(v))
  483. # keep type desc for doc generator
  484. addSon(b, a.sons[length-2])
  485. addSon(b, copyTree(def))
  486. addToVarSection(c, result, n, b)
  487. else:
  488. if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
  489. # bug #7663, for 'nim check' this can be a non-tuple:
  490. if tup.kind == tyTuple: setVarType(c, v, tup.sons[j])
  491. else: v.typ = tup
  492. b.sons[j] = newSymNode(v)
  493. checkNilable(c, v)
  494. if sfCompileTime in v.flags: hasCompileTime = true
  495. if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
  496. message(c.config, v.info, hintGlobalVar)
  497. if hasCompileTime:
  498. vm.setupCompileTimeVar(c.module, c.graph, result)
  499. # handled by the VM codegen:
  500. #c.graph.recordStmt(c.graph, c.module, result)
  501. proc semConst(c: PContext, n: PNode): PNode =
  502. result = copyNode(n)
  503. inc c.inStaticContext
  504. for i in countup(0, sonsLen(n) - 1):
  505. var a = n.sons[i]
  506. if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
  507. if a.kind == nkCommentStmt: continue
  508. if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
  509. checkMinSonsLen(a, 3, c.config)
  510. var length = sonsLen(a)
  511. var typ: PType = nil
  512. if a.sons[length-2].kind != nkEmpty:
  513. typ = semTypeNode(c, a.sons[length-2], nil)
  514. var def = semConstExpr(c, a.sons[length-1])
  515. if def == nil:
  516. localError(c.config, a.sons[length-1].info, errConstExprExpected)
  517. continue
  518. # check type compatibility between def.typ and typ:
  519. if typ != nil:
  520. def = fitRemoveHiddenConv(c, typ, def)
  521. else:
  522. typ = def.typ
  523. if typ == nil:
  524. localError(c.config, a.sons[length-1].info, errConstExprExpected)
  525. continue
  526. if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit:
  527. localError(c.config, a.info, "invalid type for const: " & typeToString(typ))
  528. continue
  529. var b: PNode
  530. if a.kind == nkVarTuple:
  531. if typ.kind != tyTuple:
  532. localError(c.config, a.info, errXExpected, "tuple")
  533. elif length-2 != sonsLen(typ):
  534. localError(c.config, a.info, errWrongNumberOfVariables)
  535. b = newNodeI(nkVarTuple, a.info)
  536. newSons(b, length)
  537. b.sons[length-2] = a.sons[length-2]
  538. b.sons[length-1] = def
  539. for j in countup(0, length-3):
  540. var v = semIdentDef(c, a.sons[j], skConst)
  541. if sfGenSym notin v.flags: addInterfaceDecl(c, v)
  542. elif v.owner == nil: v.owner = getCurrOwner(c)
  543. styleCheckDef(c.config, v)
  544. onDef(a[j].info, v)
  545. if a.kind != nkVarTuple:
  546. setVarType(c, v, typ)
  547. v.ast = def # no need to copy
  548. b = newNodeI(nkConstDef, a.info)
  549. if importantComments(c.config): b.comment = a.comment
  550. addSon(b, newSymNode(v))
  551. addSon(b, a.sons[1])
  552. addSon(b, copyTree(def))
  553. else:
  554. setVarType(c, v, typ.sons[j])
  555. v.ast = def[j]
  556. b.sons[j] = newSymNode(v)
  557. addSon(result,b)
  558. dec c.inStaticContext
  559. include semfields
  560. proc addForVarDecl(c: PContext, v: PSym) =
  561. if warnShadowIdent in c.config.notes:
  562. let shadowed = findShadowedVar(c, v)
  563. if shadowed != nil:
  564. # XXX should we do this here?
  565. #shadowed.flags.incl(sfShadowed)
  566. message(c.config, v.info, warnShadowIdent, v.name.s)
  567. addDecl(c, v)
  568. proc symForVar(c: PContext, n: PNode): PSym =
  569. let m = if n.kind == nkPragmaExpr: n.sons[0] else: n
  570. result = newSymG(skForVar, m, c)
  571. styleCheckDef(c.config, result)
  572. onDef(n.info, result)
  573. if n.kind == nkPragmaExpr:
  574. pragma(c, result, n.sons[1], forVarPragmas)
  575. proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
  576. result = n
  577. var length = sonsLen(n)
  578. let iterBase = n.sons[length-2].typ
  579. var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink})
  580. # length == 3 means that there is one for loop variable
  581. # and thus no tuple unpacking:
  582. if iter.kind != tyTuple or length == 3:
  583. if length == 3:
  584. var v = symForVar(c, n.sons[0])
  585. if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
  586. # BUGFIX: don't use `iter` here as that would strip away
  587. # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
  588. # for an example:
  589. v.typ = iterBase
  590. n.sons[0] = newSymNode(v)
  591. if sfGenSym notin v.flags: addForVarDecl(c, v)
  592. elif v.owner == nil: v.owner = getCurrOwner(c)
  593. else:
  594. localError(c.config, n.info, errWrongNumberOfVariables)
  595. elif length-2 != sonsLen(iter):
  596. localError(c.config, n.info, errWrongNumberOfVariables)
  597. else:
  598. for i in countup(0, length - 3):
  599. var v = symForVar(c, n.sons[i])
  600. if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
  601. v.typ = iter.sons[i]
  602. n.sons[i] = newSymNode(v)
  603. if sfGenSym notin v.flags:
  604. if not isDiscardUnderscore(v): addForVarDecl(c, v)
  605. elif v.owner == nil: v.owner = getCurrOwner(c)
  606. inc(c.p.nestedLoopCounter)
  607. openScope(c)
  608. n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
  609. if efInTypeof notin flags:
  610. discardCheck(c, n.sons[length-1], flags)
  611. closeScope(c)
  612. dec(c.p.nestedLoopCounter)
  613. proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
  614. result = newNodeI(nkCall, arg.info)
  615. result.add(newIdentNode(getIdent(c.cache, it), arg.info))
  616. if arg.typ != nil and arg.typ.kind in {tyVar, tyLent}:
  617. result.add newDeref(arg)
  618. else:
  619. result.add arg
  620. result = semExprNoDeref(c, result, {efWantIterator})
  621. proc isTrivalStmtExpr(n: PNode): bool =
  622. for i in 0 .. n.len-2:
  623. if n[i].kind notin {nkEmpty, nkCommentStmt}:
  624. return false
  625. result = true
  626. proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string): PNode =
  627. if selector.kind in nkCallKinds:
  628. # we transform
  629. # n := for a, b, c in m(x, y, z): Y
  630. # to
  631. # m(n)
  632. let maType = magicsys.getCompilerProc(c.graph, magicType)
  633. if maType == nil: return
  634. let headSymbol = selector[0]
  635. var o: TOverloadIter
  636. var match: PSym = nil
  637. var symx = initOverloadIter(o, c, headSymbol)
  638. while symx != nil:
  639. if symx.kind in {skTemplate, skMacro}:
  640. if symx.typ.len == 2 and symx.typ[1] == maType.typ:
  641. if match == nil:
  642. match = symx
  643. else:
  644. localError(c.config, n.info, errAmbiguousCallXYZ % [
  645. getProcHeader(c.config, match),
  646. getProcHeader(c.config, symx), $selector])
  647. symx = nextOverloadIter(o, c, headSymbol)
  648. if match == nil: return
  649. var callExpr = newNodeI(nkCall, n.info)
  650. callExpr.add newSymNode(match)
  651. callExpr.add n
  652. case match.kind
  653. of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, {})
  654. of skTemplate: result = semTemplateExpr(c, callExpr, match, {})
  655. else: result = nil
  656. proc handleForLoopMacro(c: PContext; n: PNode): PNode =
  657. result = handleStmtMacro(c, n, n[^2], "ForLoopStmt")
  658. proc handleCaseStmtMacro(c: PContext; n: PNode): PNode =
  659. # n[0] has been sem'checked and has a type. We use this to resolve
  660. # 'match(n[0])' but then we pass 'n' to the 'match' macro. This seems to
  661. # be the best solution.
  662. var toResolve = newNodeI(nkCall, n.info)
  663. toResolve.add newIdentNode(getIdent(c.cache, "match"), n.info)
  664. toResolve.add n[0]
  665. var errors: CandidateErrors
  666. var r = resolveOverloads(c, toResolve, toResolve, {skTemplate, skMacro}, {},
  667. errors, false)
  668. if r.state == csMatch:
  669. var match = r.calleeSym
  670. markUsed(c.config, n[0].info, match, c.graph.usageSym)
  671. onUse(n[0].info, match)
  672. # but pass 'n' to the 'match' macro, not 'n[0]':
  673. r.call.sons[1] = n
  674. let toExpand = semResolvedCall(c, r, r.call, {})
  675. case match.kind
  676. of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, {})
  677. of skTemplate: result = semTemplateExpr(c, toExpand, match, {})
  678. else: result = nil
  679. # this would be the perfectly consistent solution with 'for loop macros',
  680. # but it kinda sucks for pattern matching as the matcher is not attached to
  681. # a type then:
  682. when false:
  683. result = handleStmtMacro(c, n, n[0], "CaseStmt")
  684. proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
  685. checkMinSonsLen(n, 3, c.config)
  686. var length = sonsLen(n)
  687. if forLoopMacros in c.features:
  688. result = handleForLoopMacro(c, n)
  689. if result != nil: return result
  690. openScope(c)
  691. result = n
  692. n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator})
  693. var call = n.sons[length-2]
  694. if call.kind == nkStmtListExpr and isTrivalStmtExpr(call):
  695. call = call.lastSon
  696. n.sons[length-2] = call
  697. let isCallExpr = call.kind in nkCallKinds
  698. if isCallExpr and call[0].kind == nkSym and
  699. call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}:
  700. if call.sons[0].sym.magic == mOmpParFor:
  701. result = semForVars(c, n, flags)
  702. result.kind = nkParForStmt
  703. else:
  704. result = semForFields(c, n, call.sons[0].sym.magic)
  705. elif isCallExpr and call.sons[0].typ.callConv == ccClosure and
  706. tfIterator in call.sons[0].typ.flags:
  707. # first class iterator:
  708. result = semForVars(c, n, flags)
  709. elif not isCallExpr or call.sons[0].kind != nkSym or
  710. call.sons[0].sym.kind != skIterator:
  711. if length == 3:
  712. n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
  713. elif length == 4:
  714. n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
  715. else:
  716. localError(c.config, n.sons[length-2].info, "iterator within for loop context expected")
  717. result = semForVars(c, n, flags)
  718. else:
  719. result = semForVars(c, n, flags)
  720. # propagate any enforced VoidContext:
  721. if n.sons[length-1].typ == c.enforceVoidContext:
  722. result.typ = c.enforceVoidContext
  723. elif efInTypeof in flags:
  724. result.typ = result.lastSon.typ
  725. closeScope(c)
  726. proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
  727. result = n
  728. checkMinSonsLen(n, 2, c.config)
  729. openScope(c)
  730. n.sons[0] = semExprWithType(c, n.sons[0])
  731. var chckCovered = false
  732. var covered: BiggestInt = 0
  733. var typ = commonTypeBegin
  734. var hasElse = false
  735. let caseTyp = skipTypes(n.sons[0].typ, abstractVarRange-{tyTypeDesc})
  736. case caseTyp.kind
  737. of tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool:
  738. chckCovered = true
  739. of tyFloat..tyFloat128, tyString, tyError:
  740. discard
  741. else:
  742. if caseStmtMacros in c.features:
  743. result = handleCaseStmtMacro(c, n)
  744. if result != nil: return result
  745. localError(c.config, n.info, errSelectorMustBeOfCertainTypes)
  746. return
  747. for i in countup(1, sonsLen(n) - 1):
  748. var x = n.sons[i]
  749. when defined(nimsuggest):
  750. if c.config.ideCmd == ideSug and exactEquals(c.config.m.trackPos, x.info) and caseTyp.kind == tyEnum:
  751. suggestEnum(c, x, caseTyp)
  752. case x.kind
  753. of nkOfBranch:
  754. checkMinSonsLen(x, 2, c.config)
  755. semCaseBranch(c, n, x, i, covered)
  756. var last = sonsLen(x)-1
  757. x.sons[last] = semExprBranchScope(c, x.sons[last])
  758. typ = commonType(typ, x.sons[last])
  759. of nkElifBranch:
  760. chckCovered = false
  761. checkSonsLen(x, 2, c.config)
  762. openScope(c)
  763. x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0]))
  764. x.sons[1] = semExprBranch(c, x.sons[1])
  765. typ = commonType(typ, x.sons[1])
  766. closeScope(c)
  767. of nkElse:
  768. checkSonsLen(x, 1, c.config)
  769. x.sons[0] = semExprBranchScope(c, x.sons[0])
  770. typ = commonType(typ, x.sons[0])
  771. hasElse = true
  772. if chckCovered and covered == toCover(c, n.sons[0].typ):
  773. localError(c.config, x.info, "invalid else, all cases are already covered")
  774. chckCovered = false
  775. else:
  776. illFormedAst(x, c.config)
  777. if chckCovered:
  778. if covered == toCover(c, n.sons[0].typ):
  779. hasElse = true
  780. else:
  781. localError(c.config, n.info, "not all cases are covered")
  782. closeScope(c)
  783. if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
  784. (not hasElse and efInTypeof notin flags):
  785. for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
  786. # propagate any enforced VoidContext:
  787. if typ == c.enforceVoidContext:
  788. result.typ = c.enforceVoidContext
  789. else:
  790. for i in 1..n.len-1:
  791. var it = n.sons[i]
  792. let j = it.len-1
  793. if not endsInNoReturn(it.sons[j]):
  794. it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
  795. result.typ = typ
  796. proc semRaise(c: PContext, n: PNode): PNode =
  797. result = n
  798. checkSonsLen(n, 1, c.config)
  799. if n[0].kind != nkEmpty:
  800. n[0] = semExprWithType(c, n[0])
  801. var typ = n[0].typ
  802. if not isImportedException(typ, c.config):
  803. typ = typ.skipTypes({tyAlias, tyGenericInst})
  804. if typ.kind != tyRef:
  805. localError(c.config, n.info, errExprCannotBeRaised)
  806. if typ.len > 0 and not isException(typ.lastSon):
  807. localError(c.config, n.info, "raised object of type $1 does not inherit from Exception",
  808. [typeToString(typ)])
  809. proc addGenericParamListToScope(c: PContext, n: PNode) =
  810. if n.kind != nkGenericParams: illFormedAst(n, c.config)
  811. for i in countup(0, sonsLen(n)-1):
  812. var a = n.sons[i]
  813. if a.kind == nkSym: addDecl(c, a.sym)
  814. else: illFormedAst(a, c.config)
  815. proc typeSectionTypeName(c: PContext; n: PNode): PNode =
  816. if n.kind == nkPragmaExpr:
  817. if n.len == 0: illFormedAst(n, c.config)
  818. result = n.sons[0]
  819. else:
  820. result = n
  821. if result.kind != nkSym: illFormedAst(n, c.config)
  822. proc typeSectionLeftSidePass(c: PContext, n: PNode) =
  823. # process the symbols on the left side for the whole type section, before
  824. # we even look at the type definitions on the right
  825. for i in countup(0, sonsLen(n) - 1):
  826. var a = n.sons[i]
  827. when defined(nimsuggest):
  828. if c.config.cmd == cmdIdeTools:
  829. inc c.inTypeContext
  830. suggestStmt(c, a)
  831. dec c.inTypeContext
  832. if a.kind == nkCommentStmt: continue
  833. if a.kind != nkTypeDef: illFormedAst(a, c.config)
  834. checkSonsLen(a, 3, c.config)
  835. let name = a.sons[0]
  836. var s: PSym
  837. if name.kind == nkDotExpr and a[2].kind == nkObjectTy:
  838. let pkgName = considerQuotedIdent(c, name[0])
  839. let typName = considerQuotedIdent(c, name[1])
  840. let pkg = c.graph.packageSyms.strTableGet(pkgName)
  841. if pkg.isNil or pkg.kind != skPackage:
  842. localError(c.config, name.info, "unknown package name: " & pkgName.s)
  843. else:
  844. let typsym = pkg.tab.strTableGet(typName)
  845. if typsym.isNil:
  846. s = semIdentDef(c, name[1], skType)
  847. styleCheckDef(c.config, s)
  848. onDef(name[1].info, s)
  849. s.typ = newTypeS(tyObject, c)
  850. s.typ.sym = s
  851. s.flags.incl sfForward
  852. pkg.tab.strTableAdd s
  853. addInterfaceDecl(c, s)
  854. elif typsym.kind == skType and sfForward in typsym.flags:
  855. s = typsym
  856. addInterfaceDecl(c, s)
  857. else:
  858. localError(c.config, name.info, typsym.name.s & " is not a type that can be forwarded")
  859. s = typsym
  860. else:
  861. s = semIdentDef(c, name, skType)
  862. styleCheckDef(c.config, s)
  863. onDef(name.info, s)
  864. s.typ = newTypeS(tyForward, c)
  865. s.typ.sym = s # process pragmas:
  866. if name.kind == nkPragmaExpr:
  867. pragma(c, s, name.sons[1], typePragmas)
  868. if sfForward in s.flags:
  869. # check if the symbol already exists:
  870. let pkg = c.module.owner
  871. if not isTopLevel(c) or pkg.isNil:
  872. localError(c.config, name.info, "only top level types in a package can be 'package'")
  873. else:
  874. let typsym = pkg.tab.strTableGet(s.name)
  875. if typsym != nil:
  876. if sfForward notin typsym.flags or sfNoForward notin typsym.flags:
  877. typeCompleted(typsym)
  878. typsym.info = s.info
  879. else:
  880. localError(c.config, name.info, "cannot complete type '" & s.name.s & "' twice; " &
  881. "previous type completion was here: " & c.config$typsym.info)
  882. s = typsym
  883. # add it here, so that recursive types are possible:
  884. if sfGenSym notin s.flags: addInterfaceDecl(c, s)
  885. elif s.owner == nil: s.owner = getCurrOwner(c)
  886. if name.kind == nkPragmaExpr:
  887. a.sons[0].sons[0] = newSymNode(s)
  888. else:
  889. a.sons[0] = newSymNode(s)
  890. proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
  891. var body = genericType[^1]
  892. proc traverseSubTypes(c: PContext; t: PType): bool =
  893. template error(msg) = localError(c.config, genericType.sym.info, msg)
  894. result = false
  895. template subresult(r) =
  896. let sub = r
  897. result = result or sub
  898. case t.kind
  899. of tyGenericParam:
  900. t.flags.incl tfWeakCovariant
  901. return true
  902. of tyObject:
  903. for field in t.n:
  904. subresult traverseSubTypes(c, field.typ)
  905. of tyArray:
  906. return traverseSubTypes(c, t[1])
  907. of tyProc:
  908. for subType in t.sons:
  909. if subType != nil:
  910. subresult traverseSubTypes(c, subType)
  911. if result:
  912. error("non-invariant type param used in a proc type: " & $t)
  913. of tySequence:
  914. return traverseSubTypes(c, t[0])
  915. of tyGenericInvocation:
  916. let targetBody = t[0]
  917. for i in 1 ..< t.len:
  918. let param = t[i]
  919. if param.kind == tyGenericParam:
  920. if tfCovariant in param.flags:
  921. let formalFlags = targetBody[i-1].flags
  922. if tfCovariant notin formalFlags:
  923. error("covariant param '" & param.sym.name.s &
  924. "' used in a non-covariant position")
  925. elif tfWeakCovariant in formalFlags:
  926. param.flags.incl tfWeakCovariant
  927. result = true
  928. elif tfContravariant in param.flags:
  929. let formalParam = targetBody[i-1].sym
  930. if tfContravariant notin formalParam.typ.flags:
  931. error("contravariant param '" & param.sym.name.s &
  932. "' used in a non-contravariant position")
  933. result = true
  934. else:
  935. subresult traverseSubTypes(c, param)
  936. of tyAnd, tyOr, tyNot, tyStatic, tyBuiltInTypeClass, tyCompositeTypeClass:
  937. error("non-invariant type parameters cannot be used with types such '" & $t & "'")
  938. of tyUserTypeClass, tyUserTypeClassInst:
  939. error("non-invariant type parameters are not supported in concepts")
  940. of tyTuple:
  941. for fieldType in t.sons:
  942. subresult traverseSubTypes(c, fieldType)
  943. of tyPtr, tyRef, tyVar, tyLent:
  944. if t.base.kind == tyGenericParam: return true
  945. return traverseSubTypes(c, t.base)
  946. of tyDistinct, tyAlias, tySink:
  947. return traverseSubTypes(c, t.lastSon)
  948. of tyGenericInst:
  949. internalAssert c.config, false
  950. else:
  951. discard
  952. discard traverseSubTypes(c, body)
  953. proc typeSectionRightSidePass(c: PContext, n: PNode) =
  954. for i in countup(0, sonsLen(n) - 1):
  955. var a = n.sons[i]
  956. if a.kind == nkCommentStmt: continue
  957. if a.kind != nkTypeDef: illFormedAst(a, c.config)
  958. checkSonsLen(a, 3, c.config)
  959. let name = typeSectionTypeName(c, a.sons[0])
  960. var s = name.sym
  961. if s.magic == mNone and a.sons[2].kind == nkEmpty:
  962. localError(c.config, a.info, errImplOfXexpected % s.name.s)
  963. if s.magic != mNone: processMagicType(c, s)
  964. if a.sons[1].kind != nkEmpty:
  965. # We have a generic type declaration here. In generic types,
  966. # symbol lookup needs to be done here.
  967. openScope(c)
  968. pushOwner(c, s)
  969. if s.magic == mNone: s.typ.kind = tyGenericBody
  970. # XXX for generic type aliases this is not correct! We need the
  971. # underlying Id really:
  972. #
  973. # type
  974. # TGObj[T] = object
  975. # TAlias[T] = TGObj[T]
  976. #
  977. s.typ.n = semGenericParamList(c, a.sons[1], s.typ)
  978. a.sons[1] = s.typ.n
  979. s.typ.size = -1 # could not be computed properly
  980. # we fill it out later. For magic generics like 'seq', it won't be filled
  981. # so we use tyNone instead of nil to not crash for strange conversions
  982. # like: mydata.seq
  983. rawAddSon(s.typ, newTypeS(tyNone, c))
  984. s.ast = a
  985. inc c.inGenericContext
  986. var body = semTypeNode(c, a.sons[2], nil)
  987. dec c.inGenericContext
  988. if body != nil:
  989. body.sym = s
  990. body.size = -1 # could not be computed properly
  991. s.typ.sons[sonsLen(s.typ) - 1] = body
  992. if tfCovariant in s.typ.flags:
  993. checkCovariantParamsUsages(c, s.typ)
  994. # XXX: This is a temporary limitation:
  995. # The codegen currently produces various failures with
  996. # generic imported types that have fields, but we need
  997. # the fields specified in order to detect weak covariance.
  998. # The proper solution is to teach the codegen how to handle
  999. # such types, because this would offer various interesting
  1000. # possibilities such as instantiating C++ generic types with
  1001. # garbage collected Nim types.
  1002. if sfImportc in s.flags:
  1003. var body = s.typ.lastSon
  1004. if body.kind == tyObject:
  1005. # erases all declared fields
  1006. when defined(nimNoNilSeqs):
  1007. body.n.sons = @[]
  1008. else:
  1009. body.n.sons = nil
  1010. popOwner(c)
  1011. closeScope(c)
  1012. elif a.sons[2].kind != nkEmpty:
  1013. # process the type's body:
  1014. pushOwner(c, s)
  1015. var t = semTypeNode(c, a.sons[2], s.typ)
  1016. if s.typ == nil:
  1017. s.typ = t
  1018. elif t != s.typ and (s.typ == nil or s.typ.kind != tyAlias):
  1019. # this can happen for e.g. tcan_alias_specialised_generic:
  1020. assignType(s.typ, t)
  1021. #debug s.typ
  1022. s.ast = a
  1023. popOwner(c)
  1024. if sfExportc in s.flags and s.typ.kind == tyAlias:
  1025. localError(c.config, name.info, "{.exportc.} not allowed for type aliases")
  1026. let aa = a.sons[2]
  1027. if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
  1028. aa.sons[0].kind == nkObjectTy:
  1029. # give anonymous object a dummy symbol:
  1030. var st = s.typ
  1031. if st.kind == tyGenericBody: st = st.lastSon
  1032. internalAssert c.config, st.kind in {tyPtr, tyRef}
  1033. internalAssert c.config, st.lastSon.sym == nil
  1034. incl st.flags, tfRefsAnonObj
  1035. let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
  1036. getCurrOwner(c), s.info)
  1037. obj.typ = st.lastSon
  1038. st.lastSon.sym = obj
  1039. proc checkForMetaFields(c: PContext; n: PNode) =
  1040. proc checkMeta(c: PContext; n: PNode; t: PType) =
  1041. if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
  1042. if t.kind == tyBuiltInTypeClass and t.len == 1 and t.sons[0].kind == tyProc:
  1043. localError(c.config, n.info, ("'$1' is not a concrete type; " &
  1044. "for a callback without parameters use 'proc()'") % t.typeToString)
  1045. else:
  1046. localError(c.config, n.info, errTIsNotAConcreteType % t.typeToString)
  1047. if n.isNil: return
  1048. case n.kind
  1049. of nkRecList, nkRecCase:
  1050. for s in n: checkForMetaFields(c, s)
  1051. of nkOfBranch, nkElse:
  1052. checkForMetaFields(c, n.lastSon)
  1053. of nkSym:
  1054. let t = n.sym.typ
  1055. case t.kind
  1056. of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef,
  1057. tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink:
  1058. let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
  1059. for i in start ..< t.len:
  1060. checkMeta(c, n, t.sons[i])
  1061. else:
  1062. checkMeta(c, n, t)
  1063. else:
  1064. internalAssert c.config, false
  1065. proc typeSectionFinalPass(c: PContext, n: PNode) =
  1066. for i in countup(0, sonsLen(n) - 1):
  1067. var a = n.sons[i]
  1068. if a.kind == nkCommentStmt: continue
  1069. let name = typeSectionTypeName(c, a.sons[0])
  1070. var s = name.sym
  1071. # compute the type's size and check for illegal recursions:
  1072. if a.sons[1].kind == nkEmpty:
  1073. var x = a[2]
  1074. while x.kind in {nkStmtList, nkStmtListExpr} and x.len > 0:
  1075. x = x.lastSon
  1076. if x.kind notin {nkObjectTy, nkDistinctTy, nkEnumTy, nkEmpty} and
  1077. s.typ.kind notin {tyObject, tyEnum}:
  1078. # type aliases are hard:
  1079. var t = semTypeNode(c, x, nil)
  1080. assert t != nil
  1081. if s.typ != nil and s.typ.kind notin {tyAlias, tySink}:
  1082. if t.kind in {tyProc, tyGenericInst} and not t.isMetaType:
  1083. assignType(s.typ, t)
  1084. s.typ.id = t.id
  1085. elif t.kind in {tyObject, tyEnum, tyDistinct}:
  1086. assert s.typ != nil
  1087. assignType(s.typ, t)
  1088. s.typ.id = t.id # same id
  1089. checkConstructedType(c.config, s.info, s.typ)
  1090. if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
  1091. checkForMetaFields(c, s.typ.n)
  1092. instAllTypeBoundOp(c, n.info)
  1093. proc semAllTypeSections(c: PContext; n: PNode): PNode =
  1094. proc gatherStmts(c: PContext; n: PNode; result: PNode) {.nimcall.} =
  1095. case n.kind
  1096. of nkIncludeStmt:
  1097. for i in 0..<n.len:
  1098. var f = checkModuleName(c.config, n.sons[i])
  1099. if f != InvalidFileIDX:
  1100. if containsOrIncl(c.includedFiles, f.int):
  1101. localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f))
  1102. else:
  1103. let code = c.graph.includeFileCallback(c.graph, c.module, f)
  1104. gatherStmts c, code, result
  1105. excl(c.includedFiles, f.int)
  1106. of nkStmtList:
  1107. for i in 0 ..< n.len:
  1108. gatherStmts(c, n.sons[i], result)
  1109. of nkTypeSection:
  1110. incl n.flags, nfSem
  1111. typeSectionLeftSidePass(c, n)
  1112. result.add n
  1113. else:
  1114. result.add n
  1115. result = newNodeI(nkStmtList, n.info)
  1116. gatherStmts(c, n, result)
  1117. template rec(name) =
  1118. for i in 0 ..< result.len:
  1119. if result[i].kind == nkTypeSection:
  1120. name(c, result[i])
  1121. rec typeSectionRightSidePass
  1122. rec typeSectionFinalPass
  1123. when false:
  1124. # too beautiful to delete:
  1125. template rec(name; setbit=false) =
  1126. proc `name rec`(c: PContext; n: PNode) {.nimcall.} =
  1127. if n.kind == nkTypeSection:
  1128. when setbit: incl n.flags, nfSem
  1129. name(c, n)
  1130. elif n.kind == nkStmtList:
  1131. for i in 0 ..< n.len:
  1132. `name rec`(c, n.sons[i])
  1133. `name rec`(c, n)
  1134. rec typeSectionLeftSidePass, true
  1135. rec typeSectionRightSidePass
  1136. rec typeSectionFinalPass
  1137. proc semTypeSection(c: PContext, n: PNode): PNode =
  1138. ## Processes a type section. This must be done in separate passes, in order
  1139. ## to allow the type definitions in the section to reference each other
  1140. ## without regard for the order of their definitions.
  1141. if sfNoForward notin c.module.flags or nfSem notin n.flags:
  1142. inc c.inTypeContext
  1143. typeSectionLeftSidePass(c, n)
  1144. typeSectionRightSidePass(c, n)
  1145. typeSectionFinalPass(c, n)
  1146. dec c.inTypeContext
  1147. result = n
  1148. proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
  1149. s.typ = semProcTypeNode(c, n, genericParams, nil, s.kind)
  1150. if s.kind notin {skMacro, skTemplate}:
  1151. if s.typ.sons[0] != nil and s.typ.sons[0].kind == tyStmt:
  1152. localError(c.config, n.info, "invalid return type: 'stmt'")
  1153. proc addParams(c: PContext, n: PNode, kind: TSymKind) =
  1154. for i in countup(1, sonsLen(n)-1):
  1155. if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
  1156. else: illFormedAst(n, c.config)
  1157. proc semBorrow(c: PContext, n: PNode, s: PSym) =
  1158. # search for the correct alias:
  1159. var b = searchForBorrowProc(c, c.currentScope.parent, s)
  1160. if b != nil:
  1161. # store the alias:
  1162. n.sons[bodyPos] = newSymNode(b)
  1163. # Carry over the original symbol magic, this is necessary in order to ensure
  1164. # the semantic pass is correct
  1165. s.magic = b.magic
  1166. else:
  1167. localError(c.config, n.info, errNoSymbolToBorrowFromFound)
  1168. proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) =
  1169. if t != nil:
  1170. var s = newSym(skResult, getIdent(c.cache, "result"), getCurrOwner(c), info)
  1171. s.typ = t
  1172. incl(s.flags, sfUsed)
  1173. addParamOrResult(c, s, owner)
  1174. c.p.resultSym = s
  1175. proc addResultNode(c: PContext, n: PNode) =
  1176. if c.p.resultSym != nil: addSon(n, newSymNode(c.p.resultSym))
  1177. proc copyExcept(n: PNode, i: int): PNode =
  1178. result = copyNode(n)
  1179. for j in 0..<n.len:
  1180. if j != i: result.add(n.sons[j])
  1181. proc semProcAnnotation(c: PContext, prc: PNode;
  1182. validPragmas: TSpecialWords): PNode =
  1183. var n = prc.sons[pragmasPos]
  1184. if n == nil or n.kind == nkEmpty: return
  1185. for i in countup(0, n.len-1):
  1186. var it = n.sons[i]
  1187. var key = if it.kind in nkPragmaCallKinds and it.len >= 1: it.sons[0] else: it
  1188. if whichPragma(it) != wInvalid:
  1189. # Not a custom pragma
  1190. continue
  1191. elif strTableGet(c.userPragmas, considerQuotedIdent(c, key)) != nil:
  1192. # User-defined pragma
  1193. continue
  1194. # we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
  1195. # let the semantic checker deal with it:
  1196. var x = newNodeI(nkCall, key.info)
  1197. x.add(key)
  1198. if it.kind in nkPragmaCallKinds and it.len > 1:
  1199. # pass pragma arguments to the macro too:
  1200. for i in 1..<it.len:
  1201. x.add(it.sons[i])
  1202. # Drop the pragma from the list, this prevents getting caught in endless
  1203. # recursion when the nkCall is semanticized
  1204. prc.sons[pragmasPos] = copyExcept(n, i)
  1205. if prc[pragmasPos].kind != nkEmpty and prc[pragmasPos].len == 0:
  1206. prc.sons[pragmasPos] = c.graph.emptyNode
  1207. x.add(prc)
  1208. # recursion assures that this works for multiple macro annotations too:
  1209. var r = semOverloadedCall(c, x, x, {skMacro, skTemplate}, {efNoUndeclared})
  1210. if r == nil:
  1211. # Restore the old list of pragmas since we couldn't process this
  1212. prc.sons[pragmasPos] = n
  1213. # No matching macro was found but there's always the possibility this may
  1214. # be a .pragma. template instead
  1215. continue
  1216. doAssert r.sons[0].kind == nkSym
  1217. # Expand the macro here
  1218. result = semMacroExpr(c, r, r, r.sons[0].sym, {})
  1219. doAssert result != nil
  1220. # since a proc annotation can set pragmas, we process these here again.
  1221. # This is required for SqueakNim-like export pragmas.
  1222. if result.kind in procDefs and result[namePos].kind == nkSym and
  1223. result[pragmasPos].kind != nkEmpty:
  1224. pragma(c, result[namePos].sym, result[pragmasPos], validPragmas)
  1225. return
  1226. proc setGenericParamsMisc(c: PContext; n: PNode): PNode =
  1227. let orig = n.sons[genericParamsPos]
  1228. # we keep the original params around for better error messages, see
  1229. # issue https://github.com/nim-lang/Nim/issues/1713
  1230. result = semGenericParamList(c, orig)
  1231. if n.sons[miscPos].kind == nkEmpty:
  1232. n.sons[miscPos] = newTree(nkBracket, c.graph.emptyNode, orig)
  1233. else:
  1234. n.sons[miscPos].sons[1] = orig
  1235. n.sons[genericParamsPos] = result
  1236. proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
  1237. # XXX semProcAux should be good enough for this now, we will eventually
  1238. # remove semLambda
  1239. result = semProcAnnotation(c, n, lambdaPragmas)
  1240. if result != nil: return result
  1241. result = n
  1242. checkSonsLen(n, bodyPos + 1, c.config)
  1243. var s: PSym
  1244. if n[namePos].kind != nkSym:
  1245. s = newSym(skProc, c.cache.idAnon, getCurrOwner(c), n.info)
  1246. s.ast = n
  1247. n.sons[namePos] = newSymNode(s)
  1248. else:
  1249. s = n[namePos].sym
  1250. pushOwner(c, s)
  1251. openScope(c)
  1252. var gp: PNode
  1253. if n.sons[genericParamsPos].kind != nkEmpty:
  1254. gp = setGenericParamsMisc(c, n)
  1255. else:
  1256. gp = newNodeI(nkGenericParams, n.info)
  1257. if n.sons[paramsPos].kind != nkEmpty:
  1258. semParamList(c, n.sons[paramsPos], gp, s)
  1259. # paramsTypeCheck(c, s.typ)
  1260. if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
  1261. # we have a list of implicit type parameters:
  1262. n.sons[genericParamsPos] = gp
  1263. else:
  1264. s.typ = newProcType(c, n.info)
  1265. if n.sons[pragmasPos].kind != nkEmpty:
  1266. pragma(c, s, n.sons[pragmasPos], lambdaPragmas)
  1267. s.options = c.config.options
  1268. if n.sons[bodyPos].kind != nkEmpty:
  1269. if sfImportc in s.flags:
  1270. localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
  1271. #if efDetermineType notin flags:
  1272. # XXX not good enough; see tnamedparamanonproc.nim
  1273. if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags):
  1274. pushProcCon(c, s)
  1275. addResult(c, s.typ.sons[0], n.info, skProc)
  1276. addResultNode(c, n)
  1277. s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos]))
  1278. trackProc(c.graph, s, s.ast[bodyPos])
  1279. popProcCon(c)
  1280. elif efOperand notin flags:
  1281. localError(c.config, n.info, errGenericLambdaNotAllowed)
  1282. sideEffectsCheck(c, s)
  1283. else:
  1284. localError(c.config, n.info, errImplOfXexpected % s.name.s)
  1285. closeScope(c) # close scope for parameters
  1286. popOwner(c)
  1287. result.typ = s.typ
  1288. proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
  1289. var n = n
  1290. let original = n.sons[namePos].sym
  1291. let s = original #copySym(original, false)
  1292. #incl(s.flags, sfFromGeneric)
  1293. #s.owner = original
  1294. n = replaceTypesInBody(c, pt, n, original)
  1295. result = n
  1296. s.ast = result
  1297. n.sons[namePos].sym = s
  1298. n.sons[genericParamsPos] = c.graph.emptyNode
  1299. # for LL we need to avoid wrong aliasing
  1300. let params = copyTree n.typ.n
  1301. n.sons[paramsPos] = params
  1302. s.typ = n.typ
  1303. for i in 1..<params.len:
  1304. if params[i].typ.kind in {tyTypeDesc, tyGenericParam,
  1305. tyFromExpr}+tyTypeClasses:
  1306. localError(c.config, params[i].info, "cannot infer type of parameter: " &
  1307. params[i].sym.name.s)
  1308. #params[i].sym.owner = s
  1309. openScope(c)
  1310. pushOwner(c, s)
  1311. addParams(c, params, skProc)
  1312. pushProcCon(c, s)
  1313. addResult(c, n.typ.sons[0], n.info, skProc)
  1314. addResultNode(c, n)
  1315. s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos]))
  1316. trackProc(c.graph, s, s.ast[bodyPos])
  1317. popProcCon(c)
  1318. popOwner(c)
  1319. closeScope(c)
  1320. # alternative variant (not quite working):
  1321. # var prc = arg[0].sym
  1322. # let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
  1323. # result = inferred.ast
  1324. # result.kind = arg.kind
  1325. proc activate(c: PContext, n: PNode) =
  1326. # XXX: This proc is part of my plan for getting rid of
  1327. # forward declarations. stay tuned.
  1328. when false:
  1329. # well for now it breaks code ...
  1330. case n.kind
  1331. of nkLambdaKinds:
  1332. discard semLambda(c, n, {})
  1333. of nkCallKinds:
  1334. for i in 1 ..< n.len: activate(c, n[i])
  1335. else:
  1336. discard
  1337. proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
  1338. if s.typ.sons[0] != nil and not
  1339. (s.kind == skIterator and s.typ.callConv != ccClosure):
  1340. addResult(c, s.typ.sons[0], n.info, s.kind)
  1341. addResultNode(c, n)
  1342. proc canonType(c: PContext, t: PType): PType =
  1343. if t.kind == tySequence:
  1344. result = c.graph.sysTypes[tySequence]
  1345. else:
  1346. result = t
  1347. proc semOverride(c: PContext, s: PSym, n: PNode) =
  1348. case s.name.s.normalize
  1349. of "=destroy":
  1350. let t = s.typ
  1351. var noError = false
  1352. if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
  1353. var obj = t.sons[1].sons[0]
  1354. while true:
  1355. incl(obj.flags, tfHasAsgn)
  1356. if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon
  1357. elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
  1358. else: break
  1359. if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
  1360. obj = canonType(c, obj)
  1361. if obj.destructor.isNil:
  1362. obj.destructor = s
  1363. else:
  1364. localError(c.config, n.info, errGenerated,
  1365. "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
  1366. noError = true
  1367. if not noError and sfSystemModule notin s.owner.flags:
  1368. localError(c.config, n.info, errGenerated,
  1369. "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
  1370. incl(s.flags, sfUsed)
  1371. of "deepcopy", "=deepcopy":
  1372. if s.typ.len == 2 and
  1373. s.typ.sons[1].skipTypes(abstractInst).kind in {tyRef, tyPtr} and
  1374. sameType(s.typ.sons[1], s.typ.sons[0]):
  1375. # Note: we store the deepCopy in the base of the pointer to mitigate
  1376. # the problem that pointers are structural types:
  1377. var t = s.typ.sons[1].skipTypes(abstractInst).lastSon.skipTypes(abstractInst)
  1378. while true:
  1379. if t.kind == tyGenericBody: t = t.lastSon
  1380. elif t.kind == tyGenericInvocation: t = t.sons[0]
  1381. else: break
  1382. if t.kind in {tyObject, tyDistinct, tyEnum, tySequence, tyString}:
  1383. if t.deepCopy.isNil: t.deepCopy = s
  1384. else:
  1385. localError(c.config, n.info, errGenerated,
  1386. "cannot bind another 'deepCopy' to: " & typeToString(t))
  1387. else:
  1388. localError(c.config, n.info, errGenerated,
  1389. "cannot bind 'deepCopy' to: " & typeToString(t))
  1390. else:
  1391. localError(c.config, n.info, errGenerated,
  1392. "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
  1393. incl(s.flags, sfUsed)
  1394. of "=", "=sink":
  1395. if s.magic == mAsgn: return
  1396. incl(s.flags, sfUsed)
  1397. let t = s.typ
  1398. if t.len == 3 and t.sons[0] == nil and t.sons[1].kind == tyVar:
  1399. var obj = t.sons[1].sons[0]
  1400. while true:
  1401. incl(obj.flags, tfHasAsgn)
  1402. if obj.kind == tyGenericBody: obj = obj.lastSon
  1403. elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
  1404. else: break
  1405. var objB = t.sons[2]
  1406. while true:
  1407. if objB.kind == tyGenericBody: objB = objB.lastSon
  1408. elif objB.kind in {tyGenericInvocation, tyGenericInst}:
  1409. objB = objB.sons[0]
  1410. else: break
  1411. if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, objB):
  1412. # attach these ops to the canonical tySequence
  1413. obj = canonType(c, obj)
  1414. let opr = if s.name.s == "=": addr(obj.assignment) else: addr(obj.sink)
  1415. if opr[].isNil:
  1416. opr[] = s
  1417. else:
  1418. localError(c.config, n.info, errGenerated,
  1419. "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
  1420. return
  1421. if sfSystemModule notin s.owner.flags:
  1422. localError(c.config, n.info, errGenerated,
  1423. "signature for '" & s.name.s & "' must be proc[T: object](x: var T; y: T)")
  1424. else:
  1425. if sfOverriden in s.flags:
  1426. localError(c.config, n.info, errGenerated,
  1427. "'destroy' or 'deepCopy' expected for 'override'")
  1428. proc cursorInProcAux(conf: ConfigRef; n: PNode): bool =
  1429. if inCheckpoint(n.info, conf.m.trackPos) != cpNone: return true
  1430. for i in 0..<n.safeLen:
  1431. if cursorInProcAux(conf, n[i]): return true
  1432. proc cursorInProc(conf: ConfigRef; n: PNode): bool =
  1433. if n.info.fileIndex == conf.m.trackPos.fileIndex:
  1434. result = cursorInProcAux(conf, n)
  1435. type
  1436. TProcCompilationSteps = enum
  1437. stepRegisterSymbol,
  1438. stepDetermineType,
  1439. proc hasObjParam(s: PSym): bool =
  1440. var t = s.typ
  1441. for col in countup(1, sonsLen(t)-1):
  1442. if skipTypes(t.sons[col], skipPtrs).kind == tyObject:
  1443. return true
  1444. proc finishMethod(c: PContext, s: PSym) =
  1445. if hasObjParam(s):
  1446. methodDef(c.graph, s, false)
  1447. proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
  1448. if isGenericRoutine(s):
  1449. let tt = s.typ
  1450. var foundObj = false
  1451. # we start at 1 for now so that tparsecombnum continues to compile.
  1452. # XXX Revisit this problem later.
  1453. for col in countup(1, sonsLen(tt)-1):
  1454. let t = tt.sons[col]
  1455. if t != nil and t.kind == tyGenericInvocation:
  1456. var x = skipTypes(t.sons[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
  1457. tyGenericInvocation, tyGenericBody,
  1458. tyAlias, tySink})
  1459. if x.kind == tyObject and t.len-1 == n.sons[genericParamsPos].len:
  1460. foundObj = true
  1461. x.methods.add((col,s))
  1462. if not foundObj:
  1463. message(c.config, n.info, warnDeprecated, "generic method not attachable to object type is deprecated")
  1464. else:
  1465. # why check for the body? bug #2400 has none. Checking for sfForward makes
  1466. # no sense either.
  1467. # and result.sons[bodyPos].kind != nkEmpty:
  1468. if hasObjParam(s):
  1469. methodDef(c.graph, s, fromCache=false)
  1470. else:
  1471. localError(c.config, n.info, "'method' needs a parameter that has an object type")
  1472. proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
  1473. validPragmas: TSpecialWords,
  1474. phase = stepRegisterSymbol): PNode =
  1475. result = semProcAnnotation(c, n, validPragmas)
  1476. if result != nil: return result
  1477. result = n
  1478. checkSonsLen(n, bodyPos + 1, c.config)
  1479. var s: PSym
  1480. var typeIsDetermined = false
  1481. var isAnon = false
  1482. if n[namePos].kind != nkSym:
  1483. assert phase == stepRegisterSymbol
  1484. if n[namePos].kind == nkEmpty:
  1485. s = newSym(kind, c.cache.idAnon, getCurrOwner(c), n.info)
  1486. incl(s.flags, sfUsed)
  1487. isAnon = true
  1488. else:
  1489. s = semIdentDef(c, n.sons[0], kind)
  1490. n.sons[namePos] = newSymNode(s)
  1491. s.ast = n
  1492. #s.scope = c.currentScope
  1493. when false:
  1494. # disable for now
  1495. if sfNoForward in c.module.flags and
  1496. sfSystemModule notin c.module.flags:
  1497. addInterfaceOverloadableSymAt(c, c.currentScope, s)
  1498. s.flags.incl sfForward
  1499. return
  1500. else:
  1501. s = n[namePos].sym
  1502. s.owner = getCurrOwner(c)
  1503. typeIsDetermined = s.typ == nil
  1504. s.ast = n
  1505. #s.scope = c.currentScope
  1506. s.options = c.config.options
  1507. # before compiling the proc body, set as current the scope
  1508. # where the proc was declared
  1509. let oldScope = c.currentScope
  1510. #c.currentScope = s.scope
  1511. pushOwner(c, s)
  1512. openScope(c)
  1513. var gp: PNode
  1514. if n.sons[genericParamsPos].kind != nkEmpty:
  1515. gp = setGenericParamsMisc(c, n)
  1516. else:
  1517. gp = newNodeI(nkGenericParams, n.info)
  1518. # process parameters:
  1519. if n.sons[paramsPos].kind != nkEmpty:
  1520. semParamList(c, n.sons[paramsPos], gp, s)
  1521. if sonsLen(gp) > 0:
  1522. if n.sons[genericParamsPos].kind == nkEmpty:
  1523. # we have a list of implicit type parameters:
  1524. n.sons[genericParamsPos] = gp
  1525. # check for semantics again:
  1526. # semParamList(c, n.sons[ParamsPos], nil, s)
  1527. else:
  1528. s.typ = newProcType(c, n.info)
  1529. if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
  1530. if n.sons[patternPos].kind != nkEmpty:
  1531. n.sons[patternPos] = semPattern(c, n.sons[patternPos])
  1532. if s.kind == skIterator:
  1533. s.typ.flags.incl(tfIterator)
  1534. elif s.kind == skFunc:
  1535. incl(s.flags, sfNoSideEffect)
  1536. incl(s.typ.flags, tfNoSideEffect)
  1537. var proto = searchForProc(c, oldScope, s)
  1538. if proto == nil or isAnon:
  1539. if s.kind == skIterator:
  1540. if s.typ.callConv != ccClosure:
  1541. s.typ.callConv = if isAnon: ccClosure else: ccInline
  1542. else:
  1543. s.typ.callConv = lastOptionEntry(c).defaultCC
  1544. # add it here, so that recursive procs are possible:
  1545. if sfGenSym in s.flags:
  1546. if s.owner == nil: s.owner = getCurrOwner(c)
  1547. elif kind in OverloadableSyms:
  1548. if not typeIsDetermined:
  1549. addInterfaceOverloadableSymAt(c, oldScope, s)
  1550. else:
  1551. if not typeIsDetermined:
  1552. addInterfaceDeclAt(c, oldScope, s)
  1553. if n.sons[pragmasPos].kind != nkEmpty:
  1554. pragma(c, s, n.sons[pragmasPos], validPragmas)
  1555. else:
  1556. implicitPragmas(c, s, n, validPragmas)
  1557. styleCheckDef(c.config, s)
  1558. onDef(n[namePos].info, s)
  1559. else:
  1560. if n.sons[pragmasPos].kind != nkEmpty:
  1561. pragma(c, s, n.sons[pragmasPos], validPragmas)
  1562. # To ease macro generation that produce forwarded .async procs we now
  1563. # allow a bit redudancy in the pragma declarations. The rule is
  1564. # a prototype's pragma list must be a superset of the current pragma
  1565. # list.
  1566. # XXX This needs more checks eventually, for example that external
  1567. # linking names do agree:
  1568. if proto.typ.callConv != s.typ.callConv or proto.typ.flags < s.typ.flags:
  1569. localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
  1570. ("'" & proto.name.s & "' from " & c.config$proto.info))
  1571. styleCheckDef(c.config, s)
  1572. onDefResolveForward(n[namePos].info, proto)
  1573. if sfForward notin proto.flags and proto.magic == mNone:
  1574. wrongRedefinition(c, n.info, proto.name.s, proto.info)
  1575. excl(proto.flags, sfForward)
  1576. closeScope(c) # close scope with wrong parameter symbols
  1577. openScope(c) # open scope for old (correct) parameter symbols
  1578. if proto.ast.sons[genericParamsPos].kind != nkEmpty:
  1579. addGenericParamListToScope(c, proto.ast.sons[genericParamsPos])
  1580. addParams(c, proto.typ.n, proto.kind)
  1581. proto.info = s.info # more accurate line information
  1582. s.typ = proto.typ
  1583. proto.options = s.options
  1584. s = proto
  1585. n.sons[genericParamsPos] = proto.ast.sons[genericParamsPos]
  1586. n.sons[paramsPos] = proto.ast.sons[paramsPos]
  1587. n.sons[pragmasPos] = proto.ast.sons[pragmasPos]
  1588. if n.sons[namePos].kind != nkSym: internalError(c.config, n.info, "semProcAux")
  1589. n.sons[namePos].sym = proto
  1590. if importantComments(c.config) and proto.ast.comment.len > 0:
  1591. n.comment = proto.ast.comment
  1592. proto.ast = n # needed for code generation
  1593. popOwner(c)
  1594. pushOwner(c, s)
  1595. if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
  1596. if s.name.s[0] in {'.', '('}:
  1597. if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
  1598. localError(c.config, n.info, "the overloaded " & s.name.s &
  1599. " operator has to be enabled with {.experimental: \"dotOperators\".}")
  1600. elif s.name.s == "()" and callOperator notin c.features:
  1601. localError(c.config, n.info, "the overloaded " & s.name.s &
  1602. " operator has to be enabled with {.experimental: \"callOperator\".}")
  1603. if n.sons[bodyPos].kind != nkEmpty and sfError notin s.flags:
  1604. # for DLL generation it is annoying to check for sfImportc!
  1605. if sfBorrow in s.flags:
  1606. localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
  1607. let usePseudoGenerics = kind in {skMacro, skTemplate}
  1608. # Macros and Templates can have generic parameters, but they are
  1609. # only used for overload resolution (there is no instantiation of
  1610. # the symbol, so we must process the body now)
  1611. if not usePseudoGenerics and c.config.ideCmd in {ideSug, ideCon} and not
  1612. cursorInProc(c.config, n.sons[bodyPos]):
  1613. discard "speed up nimsuggest"
  1614. if s.kind == skMethod: semMethodPrototype(c, s, n)
  1615. else:
  1616. pushProcCon(c, s)
  1617. if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
  1618. if not usePseudoGenerics: paramsTypeCheck(c, s.typ)
  1619. c.p.wasForwarded = proto != nil
  1620. maybeAddResult(c, s, n)
  1621. if s.kind == skMethod: semMethodPrototype(c, s, n)
  1622. if lfDynamicLib notin s.loc.flags:
  1623. # no semantic checking for importc:
  1624. s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos]))
  1625. # unfortunately we cannot skip this step when in 'system.compiles'
  1626. # context as it may even be evaluated in 'system.compiles':
  1627. trackProc(c.graph, s, s.ast[bodyPos])
  1628. else:
  1629. if s.typ.sons[0] != nil and kind != skIterator:
  1630. addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nil, n.info))
  1631. openScope(c)
  1632. n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos])
  1633. closeScope(c)
  1634. if s.magic == mNone:
  1635. fixupInstantiatedSymbols(c, s)
  1636. if s.kind == skMethod: semMethodPrototype(c, s, n)
  1637. if sfImportc in s.flags:
  1638. # so we just ignore the body after semantic checking for importc:
  1639. n.sons[bodyPos] = c.graph.emptyNode
  1640. popProcCon(c)
  1641. else:
  1642. if s.kind == skMethod: semMethodPrototype(c, s, n)
  1643. if proto != nil: localError(c.config, n.info, errImplOfXexpected % proto.name.s)
  1644. if {sfImportc, sfBorrow, sfError} * s.flags == {} and s.magic == mNone:
  1645. incl(s.flags, sfForward)
  1646. elif sfBorrow in s.flags: semBorrow(c, n, s)
  1647. sideEffectsCheck(c, s)
  1648. closeScope(c) # close scope for parameters
  1649. # c.currentScope = oldScope
  1650. popOwner(c)
  1651. if n.sons[patternPos].kind != nkEmpty:
  1652. c.patterns.add(s)
  1653. if isAnon:
  1654. n.kind = nkLambda
  1655. result.typ = s.typ
  1656. if isTopLevel(c) and s.kind != skIterator and
  1657. s.typ.callConv == ccClosure:
  1658. localError(c.config, s.info, "'.closure' calling convention for top level routines is invalid")
  1659. proc determineType(c: PContext, s: PSym) =
  1660. if s.typ != nil: return
  1661. #if s.magic != mNone: return
  1662. #if s.ast.isNil: return
  1663. discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
  1664. proc semIterator(c: PContext, n: PNode): PNode =
  1665. # gensym'ed iterator?
  1666. let isAnon = n[namePos].kind == nkEmpty
  1667. if n[namePos].kind == nkSym:
  1668. # gensym'ed iterators might need to become closure iterators:
  1669. n[namePos].sym.owner = getCurrOwner(c)
  1670. n[namePos].sym.kind = skIterator
  1671. result = semProcAux(c, n, skIterator, iteratorPragmas)
  1672. # bug #7093: if after a macro transformation we don't have an
  1673. # nkIteratorDef aynmore, return. The iterator then might have been
  1674. # sem'checked already. (Or not, if the macro skips it.)
  1675. if result.kind != n.kind: return
  1676. var s = result.sons[namePos].sym
  1677. var t = s.typ
  1678. if t.sons[0] == nil and s.typ.callConv != ccClosure:
  1679. localError(c.config, n.info, "iterator needs a return type")
  1680. if isAnon and s.typ.callConv == ccInline:
  1681. localError(c.config, n.info, "inline iterators are not first-class / cannot be assigned to variables")
  1682. # iterators are either 'inline' or 'closure'; for backwards compatibility,
  1683. # we require first class iterators to be marked with 'closure' explicitly
  1684. # -- at least for 0.9.2.
  1685. if s.typ.callConv == ccClosure:
  1686. incl(s.typ.flags, tfCapturesEnv)
  1687. else:
  1688. s.typ.callConv = ccInline
  1689. if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
  1690. localError(c.config, n.info, errImplOfXexpected % s.name.s)
  1691. proc semProc(c: PContext, n: PNode): PNode =
  1692. result = semProcAux(c, n, skProc, procPragmas)
  1693. proc semFunc(c: PContext, n: PNode): PNode =
  1694. result = semProcAux(c, n, skFunc, procPragmas)
  1695. proc semMethod(c: PContext, n: PNode): PNode =
  1696. if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "method")
  1697. result = semProcAux(c, n, skMethod, methodPragmas)
  1698. # macros can transform converters to nothing:
  1699. if namePos >= result.safeLen: return result
  1700. # bug #7093: if after a macro transformation we don't have an
  1701. # nkIteratorDef aynmore, return. The iterator then might have been
  1702. # sem'checked already. (Or not, if the macro skips it.)
  1703. if result.kind != nkMethodDef: return
  1704. var s = result.sons[namePos].sym
  1705. # we need to fix the 'auto' return type for the dispatcher here (see tautonotgeneric
  1706. # test case):
  1707. let disp = getDispatcher(s)
  1708. # auto return type?
  1709. if disp != nil and disp.typ.sons[0] != nil and disp.typ.sons[0].kind == tyExpr:
  1710. let ret = s.typ.sons[0]
  1711. disp.typ.sons[0] = ret
  1712. if disp.ast[resultPos].kind == nkSym:
  1713. if isEmptyType(ret): disp.ast.sons[resultPos] = c.graph.emptyNode
  1714. else: disp.ast[resultPos].sym.typ = ret
  1715. proc semConverterDef(c: PContext, n: PNode): PNode =
  1716. if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "converter")
  1717. checkSonsLen(n, bodyPos + 1, c.config)
  1718. result = semProcAux(c, n, skConverter, converterPragmas)
  1719. # macros can transform converters to nothing:
  1720. if namePos >= result.safeLen: return result
  1721. # bug #7093: if after a macro transformation we don't have an
  1722. # nkIteratorDef aynmore, return. The iterator then might have been
  1723. # sem'checked already. (Or not, if the macro skips it.)
  1724. if result.kind != nkConverterDef: return
  1725. var s = result.sons[namePos].sym
  1726. var t = s.typ
  1727. if t.sons[0] == nil: localError(c.config, n.info, errXNeedsReturnType % "converter")
  1728. if sonsLen(t) != 2: localError(c.config, n.info, "a converter takes exactly one argument")
  1729. addConverter(c, s)
  1730. proc semMacroDef(c: PContext, n: PNode): PNode =
  1731. checkSonsLen(n, bodyPos + 1, c.config)
  1732. result = semProcAux(c, n, skMacro, macroPragmas)
  1733. # macros can transform macros to nothing:
  1734. if namePos >= result.safeLen: return result
  1735. # bug #7093: if after a macro transformation we don't have an
  1736. # nkIteratorDef aynmore, return. The iterator then might have been
  1737. # sem'checked already. (Or not, if the macro skips it.)
  1738. if result.kind != nkMacroDef: return
  1739. var s = result.sons[namePos].sym
  1740. var t = s.typ
  1741. var allUntyped = true
  1742. for i in 1 .. t.n.len-1:
  1743. let param = t.n.sons[i].sym
  1744. if param.typ.kind != tyExpr: allUntyped = false
  1745. if allUntyped: incl(s.flags, sfAllUntyped)
  1746. if t.sons[0] == nil: localError(c.config, n.info, "macro needs a return type")
  1747. if n.sons[bodyPos].kind == nkEmpty:
  1748. localError(c.config, n.info, errImplOfXexpected % s.name.s)
  1749. proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
  1750. var f = checkModuleName(c.config, it)
  1751. if f != InvalidFileIDX:
  1752. if containsOrIncl(c.includedFiles, f.int):
  1753. localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f))
  1754. else:
  1755. addSon(includeStmtResult, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {}))
  1756. excl(c.includedFiles, f.int)
  1757. proc evalInclude(c: PContext, n: PNode): PNode =
  1758. result = newNodeI(nkStmtList, n.info)
  1759. addSon(result, n)
  1760. for i in countup(0, sonsLen(n) - 1):
  1761. var imp: PNode
  1762. let it = n.sons[i]
  1763. if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
  1764. let sep = it[0]
  1765. let dir = it[1]
  1766. imp = newNodeI(nkInfix, it.info)
  1767. imp.add sep
  1768. imp.add dir
  1769. imp.add sep # dummy entry, replaced in the loop
  1770. for x in it[2]:
  1771. imp.sons[2] = x
  1772. incMod(c, n, imp, result)
  1773. else:
  1774. incMod(c, n, it, result)
  1775. proc setLine(n: PNode, info: TLineInfo) =
  1776. for i in 0 ..< safeLen(n): setLine(n.sons[i], info)
  1777. n.info = info
  1778. proc semPragmaBlock(c: PContext, n: PNode): PNode =
  1779. checkSonsLen(n, 2, c.config)
  1780. let pragmaList = n.sons[0]
  1781. pragma(c, nil, pragmaList, exprPragmas)
  1782. n[1] = semExpr(c, n[1])
  1783. result = n
  1784. result.typ = n[1].typ
  1785. for i in 0 ..< pragmaList.len:
  1786. case whichPragma(pragmaList.sons[i])
  1787. of wLine: setLine(result, pragmaList.sons[i].info)
  1788. of wNoRewrite: incl(result.flags, nfNoRewrite)
  1789. else: discard
  1790. proc semStaticStmt(c: PContext, n: PNode): PNode =
  1791. #echo "semStaticStmt"
  1792. #writeStackTrace()
  1793. inc c.inStaticContext
  1794. openScope(c)
  1795. let a = semStmt(c, n.sons[0], {})
  1796. closeScope(c)
  1797. dec c.inStaticContext
  1798. n.sons[0] = a
  1799. evalStaticStmt(c.module, c.graph, a, c.p.owner)
  1800. when false:
  1801. # for incremental replays, keep the AST as required for replays:
  1802. result = n
  1803. else:
  1804. result = newNodeI(nkDiscardStmt, n.info, 1)
  1805. result.sons[0] = c.graph.emptyNode
  1806. proc usesResult(n: PNode): bool =
  1807. # nkStmtList(expr) properly propagates the void context,
  1808. # so we don't need to process that all over again:
  1809. if n.kind notin {nkStmtList, nkStmtListExpr,
  1810. nkMacroDef, nkTemplateDef} + procDefs:
  1811. if isAtom(n):
  1812. result = n.kind == nkSym and n.sym.kind == skResult
  1813. elif n.kind == nkReturnStmt:
  1814. result = true
  1815. else:
  1816. for c in n:
  1817. if usesResult(c): return true
  1818. proc inferConceptStaticParam(c: PContext, inferred, n: PNode) =
  1819. var typ = inferred.typ
  1820. let res = semConstExpr(c, n)
  1821. if not sameType(res.typ, typ.base):
  1822. localError(c.config, n.info,
  1823. "cannot infer the concept parameter '%s', due to a type mismatch. " &
  1824. "attempt to equate '%s' and '%s'.",
  1825. [inferred.renderTree, $res.typ, $typ.base])
  1826. typ.n = res
  1827. proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
  1828. # these must be last statements in a block:
  1829. const
  1830. LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
  1831. result = n
  1832. result.kind = nkStmtList
  1833. var length = sonsLen(n)
  1834. var voidContext = false
  1835. var last = length-1
  1836. # by not allowing for nkCommentStmt etc. we ensure nkStmtListExpr actually
  1837. # really *ends* in the expression that produces the type: The compiler now
  1838. # relies on this fact and it's too much effort to change that. And arguably
  1839. # 'R(); #comment' shouldn't produce R's type anyway.
  1840. #while last > 0 and n.sons[last].kind in {nkPragma, nkCommentStmt,
  1841. # nkNilLit, nkEmpty}:
  1842. # dec last
  1843. for i in countup(0, length - 1):
  1844. var expr = semExpr(c, n.sons[i], flags)
  1845. n.sons[i] = expr
  1846. if c.matchedConcept != nil and expr.typ != nil and
  1847. (nfFromTemplate notin n.flags or i != last):
  1848. case expr.typ.kind
  1849. of tyBool:
  1850. if expr.kind == nkInfix and
  1851. expr[0].kind == nkSym and
  1852. expr[0].sym.name.s == "==":
  1853. if expr[1].typ.isUnresolvedStatic:
  1854. inferConceptStaticParam(c, expr[1], expr[2])
  1855. continue
  1856. elif expr[2].typ.isUnresolvedStatic:
  1857. inferConceptStaticParam(c, expr[2], expr[1])
  1858. continue
  1859. let verdict = semConstExpr(c, n[i])
  1860. if verdict.intVal == 0:
  1861. localError(c.config, result.info, "concept predicate failed")
  1862. of tyUnknown: continue
  1863. else: discard
  1864. if n.sons[i].typ == c.enforceVoidContext: #or usesResult(n.sons[i]):
  1865. voidContext = true
  1866. n.typ = c.enforceVoidContext
  1867. if i == last and (length == 1 or ({efWantValue, efInTypeof} * flags != {})):
  1868. n.typ = n.sons[i].typ
  1869. if not isEmptyType(n.typ): n.kind = nkStmtListExpr
  1870. elif i != last or voidContext:
  1871. discardCheck(c, n.sons[i], flags)
  1872. else:
  1873. n.typ = n.sons[i].typ
  1874. if not isEmptyType(n.typ): n.kind = nkStmtListExpr
  1875. if n.sons[i].kind in LastBlockStmts or
  1876. n.sons[i].kind in nkCallKinds and n.sons[i][0].kind == nkSym and
  1877. sfNoReturn in n.sons[i][0].sym.flags:
  1878. for j in countup(i + 1, length - 1):
  1879. case n.sons[j].kind
  1880. of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr,
  1881. nkBlockStmt, nkState: discard
  1882. else: localError(c.config, n.sons[j].info,
  1883. "unreachable statement after 'return' statement or '{.noReturn.}' proc")
  1884. else: discard
  1885. if result.len == 1 and
  1886. # concept bodies should be preserved as a stmt list:
  1887. c.matchedConcept == nil and
  1888. # also, don't make life complicated for macros.
  1889. # they will always expect a proper stmtlist:
  1890. nfBlockArg notin n.flags and
  1891. result.sons[0].kind != nkDefer:
  1892. result = result.sons[0]
  1893. when defined(nimfix):
  1894. if result.kind == nkCommentStmt and not result.comment.isNil and
  1895. not (result.comment[0] == '#' and result.comment[1] == '#'):
  1896. # it is an old-style comment statement: we replace it with 'discard ""':
  1897. prettybase.replaceComment(result.info)
  1898. proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode =
  1899. if efInTypeof notin flags:
  1900. result = semExprNoType(c, n)
  1901. else:
  1902. result = semExpr(c, n, flags)