semstmts.nim 105 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764
  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 used (or 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 '$1'"
  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. errRecursiveDependencyIteratorX = "recursion is not supported in iterators: '$1'"
  36. errPragmaOnlyInHeaderOfProcX = "pragmas are only allowed in the header of a proc; redefinition of $1"
  37. errCannotAssignToGlobal = "cannot assign local to global variable"
  38. proc implicitlyDiscardable(n: PNode): bool
  39. proc hasEmpty(typ: PType): bool =
  40. if typ.kind in {tySequence, tyArray, tySet}:
  41. result = typ.elementType.kind == tyEmpty
  42. elif typ.kind == tyTuple:
  43. result = false
  44. for s in typ.kids:
  45. result = result or hasEmpty(s)
  46. else:
  47. result = false
  48. proc semDiscard(c: PContext, n: PNode): PNode =
  49. result = n
  50. checkSonsLen(n, 1, c.config)
  51. if n[0].kind != nkEmpty:
  52. n[0] = semExprWithType(c, n[0])
  53. let sonType = n[0].typ
  54. let sonKind = n[0].kind
  55. if isEmptyType(sonType) or hasEmpty(sonType) or
  56. sonType.kind in {tyNone, tyTypeDesc} or
  57. sonKind == nkTypeOfExpr:
  58. localError(c.config, n.info, errInvalidDiscard)
  59. if sonType.kind == tyProc and sonKind notin nkCallKinds:
  60. # tyProc is disallowed to prevent ``discard foo`` to be valid, when ``discard foo()`` is meant.
  61. localError(c.config, n.info, "illegal discard proc, did you mean: " & $n[0] & "()")
  62. proc semBreakOrContinue(c: PContext, n: PNode): PNode =
  63. result = n
  64. checkSonsLen(n, 1, c.config)
  65. if n[0].kind != nkEmpty:
  66. if n.kind != nkContinueStmt:
  67. var s: PSym = nil
  68. case n[0].kind
  69. of nkIdent: s = lookUp(c, n[0])
  70. of nkSym: s = n[0].sym
  71. else: illFormedAst(n, c.config)
  72. s = getGenSym(c, s)
  73. if s.kind == skLabel and s.owner.id == c.p.owner.id:
  74. var x = newSymNode(s)
  75. x.info = n.info
  76. incl(s.flags, sfUsed)
  77. n[0] = x
  78. suggestSym(c.graph, x.info, s, c.graph.usageSym)
  79. onUse(x.info, s)
  80. else:
  81. localError(c.config, n.info, errInvalidControlFlowX % s.name.s)
  82. else:
  83. localError(c.config, n.info, errGenerated, "'continue' cannot have a label")
  84. elif c.p.nestedBlockCounter > 0 and n.kind == nkBreakStmt and not c.p.breakInLoop:
  85. localError(c.config, n.info, warnUnnamedBreak)
  86. elif (c.p.nestedLoopCounter <= 0) and ((c.p.nestedBlockCounter <= 0) or n.kind == nkContinueStmt):
  87. localError(c.config, n.info, errInvalidControlFlowX %
  88. renderTree(n, {renderNoComments}))
  89. proc semAsm(c: PContext, n: PNode): PNode =
  90. checkSonsLen(n, 2, c.config)
  91. var marker = pragmaAsm(c, n[0])
  92. if marker == '\0': marker = '`' # default marker
  93. result = semAsmOrEmit(c, n, marker)
  94. proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
  95. result = n
  96. checkSonsLen(n, 2, c.config)
  97. openScope(c)
  98. n[0] = forceBool(c, semExprWithType(c, n[0], expectedType = getSysType(c.graph, n.info, tyBool)))
  99. inc(c.p.nestedLoopCounter)
  100. let oldBreakInLoop = c.p.breakInLoop
  101. c.p.breakInLoop = true
  102. n[1] = semStmt(c, n[1], flags)
  103. c.p.breakInLoop = oldBreakInLoop
  104. dec(c.p.nestedLoopCounter)
  105. closeScope(c)
  106. if n[1].typ == c.enforceVoidContext:
  107. result.typ = c.enforceVoidContext
  108. elif efInTypeof in flags:
  109. result.typ = n[1].typ
  110. elif implicitlyDiscardable(n[1]):
  111. result[1].typ = c.enforceVoidContext
  112. proc semProc(c: PContext, n: PNode): PNode
  113. proc semExprBranch(c: PContext, n: PNode; flags: TExprFlags = {}; expectedType: PType = nil): PNode =
  114. result = semExpr(c, n, flags, expectedType)
  115. if result.typ != nil:
  116. # XXX tyGenericInst here?
  117. if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
  118. proc semExprBranchScope(c: PContext, n: PNode; expectedType: PType = nil): PNode =
  119. openScope(c)
  120. result = semExprBranch(c, n, expectedType = expectedType)
  121. closeScope(c)
  122. const
  123. skipForDiscardable = {nkIfStmt, nkIfExpr, nkCaseStmt, nkOfBranch,
  124. nkElse, nkStmtListExpr, nkTryStmt, nkFinally, nkExceptBranch,
  125. nkElifBranch, nkElifExpr, nkElseExpr, nkBlockStmt, nkBlockExpr,
  126. nkHiddenStdConv, nkHiddenDeref}
  127. proc implicitlyDiscardable(n: PNode): bool =
  128. var n = n
  129. while n.kind in skipForDiscardable: n = n.lastSon
  130. result = n.kind in nkLastBlockStmts or
  131. (isCallExpr(n) and n[0].kind == nkSym and
  132. sfDiscardable in n[0].sym.flags)
  133. proc fixNilType(c: PContext; n: PNode) =
  134. if isAtom(n):
  135. if n.kind != nkNilLit and n.typ != nil:
  136. localError(c.config, n.info, errDiscardValueX % n.typ.typeToString)
  137. elif n.kind in {nkStmtList, nkStmtListExpr}:
  138. n.transitionSonsKind(nkStmtList)
  139. for it in n: fixNilType(c, it)
  140. n.typ = nil
  141. proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
  142. if c.matchedConcept != nil or efInTypeof in flags: return
  143. if result.typ != nil and result.typ.kind notin {tyTyped, tyVoid}:
  144. if implicitlyDiscardable(result):
  145. var n = newNodeI(nkDiscardStmt, result.info, 1)
  146. n[0] = result
  147. elif result.typ.kind != tyError and c.config.cmd != cmdInteractive:
  148. if result.typ.kind == tyNone:
  149. localError(c.config, result.info, "expression has no type: " &
  150. renderTree(result, {renderNoComments}))
  151. else:
  152. var n = result
  153. while n.kind in skipForDiscardable:
  154. if n.kind == nkTryStmt: n = n[0]
  155. else: n = n.lastSon
  156. # Ignore noreturn procs since they don't have a type
  157. if n.endsInNoReturn:
  158. return
  159. var s = "expression '" & $n & "' is of type '" &
  160. result.typ.typeToString & "' and has to be used (or discarded)"
  161. if result.info.line != n.info.line or
  162. result.info.fileIndex != n.info.fileIndex:
  163. s.add "; start of expression here: " & c.config$result.info
  164. if result.typ.kind == tyProc:
  165. s.add "; for a function call use ()"
  166. localError(c.config, n.info, s)
  167. proc semIf(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
  168. result = n
  169. var typ = commonTypeBegin
  170. var expectedType = expectedType
  171. var hasElse = false
  172. for i in 0..<n.len:
  173. var it = n[i]
  174. if it.len == 2:
  175. openScope(c)
  176. it[0] = forceBool(c, semExprWithType(c, it[0], expectedType = getSysType(c.graph, n.info, tyBool)))
  177. it[1] = semExprBranch(c, it[1], flags, expectedType)
  178. typ = commonType(c, typ, it[1])
  179. if not endsInNoReturn(it[1]):
  180. expectedType = typ
  181. closeScope(c)
  182. elif it.len == 1:
  183. hasElse = true
  184. it[0] = semExprBranchScope(c, it[0], expectedType)
  185. typ = commonType(c, typ, it[0])
  186. if not endsInNoReturn(it[0]):
  187. expectedType = typ
  188. else: illFormedAst(it, c.config)
  189. if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or
  190. (not hasElse and efInTypeof notin flags):
  191. for it in n: discardCheck(c, it.lastSon, flags)
  192. result.transitionSonsKind(nkIfStmt)
  193. # propagate any enforced VoidContext:
  194. if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
  195. else:
  196. for it in n:
  197. let j = it.len-1
  198. if not endsInNoReturn(it[j]):
  199. it[j] = fitNode(c, typ, it[j], it[j].info)
  200. result.transitionSonsKind(nkIfExpr)
  201. result.typ = typ
  202. proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
  203. var check = initIntSet()
  204. template semExceptBranchType(typeNode: PNode): bool =
  205. # returns true if exception type is imported type
  206. let typ = semTypeNode(c, typeNode, nil).toObject()
  207. var isImported = false
  208. if isImportedException(typ, c.config):
  209. isImported = true
  210. elif not isException(typ):
  211. localError(c.config, typeNode.info, errExprCannotBeRaised)
  212. elif not isDefectOrCatchableError(typ):
  213. message(c.config, a.info, warnBareExcept, "catch a more precise Exception deriving from CatchableError or Defect.")
  214. if containsOrIncl(check, typ.id):
  215. localError(c.config, typeNode.info, errExceptionAlreadyHandled)
  216. typeNode = newNodeIT(nkType, typeNode.info, typ)
  217. isImported
  218. result = n
  219. checkMinSonsLen(n, 2, c.config)
  220. var typ = commonTypeBegin
  221. var expectedType = expectedType
  222. n[0] = semExprBranchScope(c, n[0], expectedType)
  223. if not endsInNoReturn(n[0]):
  224. typ = commonType(c, typ, n[0].typ)
  225. expectedType = typ
  226. var last = n.len - 1
  227. var catchAllExcepts = 0
  228. for i in 1..last:
  229. let a = n[i]
  230. checkMinSonsLen(a, 1, c.config)
  231. openScope(c)
  232. if a.kind == nkExceptBranch:
  233. if a.len == 2 and a[0].kind == nkBracket:
  234. # rewrite ``except [a, b, c]: body`` -> ```except a, b, c: body```
  235. a.sons[0..0] = move a[0].sons
  236. if a.len == 2 and a[0].isInfixAs():
  237. # support ``except Exception as ex: body``
  238. let isImported = semExceptBranchType(a[0][1])
  239. let symbol = newSymG(skLet, a[0][2], c)
  240. symbol.typ = if isImported: a[0][1].typ
  241. else: a[0][1].typ.toRef(c.idgen)
  242. addDecl(c, symbol)
  243. # Overwrite symbol in AST with the symbol in the symbol table.
  244. a[0][2] = newSymNode(symbol, a[0][2].info)
  245. elif a.len == 1:
  246. # count number of ``except: body`` blocks
  247. inc catchAllExcepts
  248. message(c.config, a.info, warnBareExcept,
  249. "The bare except clause is deprecated; use `except CatchableError:` instead")
  250. else:
  251. # support ``except KeyError, ValueError, ... : body``
  252. if catchAllExcepts > 0:
  253. # if ``except: body`` already encountered,
  254. # cannot be followed by a ``except KeyError, ... : body`` block
  255. inc catchAllExcepts
  256. var isNative, isImported: bool = false
  257. for j in 0..<a.len-1:
  258. let tmp = semExceptBranchType(a[j])
  259. if tmp: isImported = true
  260. else: isNative = true
  261. if isNative and isImported:
  262. localError(c.config, a[0].info, "Mix of imported and native exception types is not allowed in one except branch")
  263. elif a.kind == nkFinally:
  264. if i != n.len-1:
  265. localError(c.config, a.info, "Only one finally is allowed after all other branches")
  266. else:
  267. illFormedAst(n, c.config)
  268. if catchAllExcepts > 1:
  269. # if number of ``except: body`` blocks is greater than 1
  270. # or more specific exception follows a general except block, it is invalid
  271. localError(c.config, a.info, "Only one general except clause is allowed after more specific exceptions")
  272. # last child of an nkExcept/nkFinally branch is a statement:
  273. if a.kind != nkFinally:
  274. a[^1] = semExprBranchScope(c, a[^1], expectedType)
  275. typ = commonType(c, typ, a[^1])
  276. if not endsInNoReturn(a[^1]):
  277. expectedType = typ
  278. else:
  279. a[^1] = semExprBranchScope(c, a[^1])
  280. dec last
  281. closeScope(c)
  282. if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped}:
  283. discardCheck(c, n[0], flags)
  284. for i in 1..<n.len: discardCheck(c, n[i].lastSon, flags)
  285. if typ == c.enforceVoidContext:
  286. result.typ = c.enforceVoidContext
  287. else:
  288. if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
  289. if not endsInNoReturn(n[0]):
  290. n[0] = fitNode(c, typ, n[0], n[0].info)
  291. for i in 1..last:
  292. var it = n[i]
  293. let j = it.len-1
  294. if not endsInNoReturn(it[j]):
  295. it[j] = fitNode(c, typ, it[j], it[j].info)
  296. result.typ = typ
  297. proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
  298. result = fitNode(c, typ, n, n.info)
  299. if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
  300. let r1 = result[1]
  301. if r1.kind in {nkCharLit..nkUInt64Lit} and typ.skipTypes(abstractRange).kind in {tyFloat..tyFloat128}:
  302. result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal)
  303. result.info = n.info
  304. result.typ = typ
  305. if not floatRangeCheck(result.floatVal, typ):
  306. localError(c.config, n.info, errFloatToString % [$result.floatVal, typeToString(typ)])
  307. elif r1.kind == nkSym and typ.skipTypes(abstractRange).kind == tyCstring:
  308. discard "keep nkHiddenStdConv for cstring conversions"
  309. else:
  310. changeType(c, r1, typ, check=true)
  311. result = r1
  312. elif not sameType(result.typ, typ):
  313. changeType(c, result, typ, check=false)
  314. proc findShadowedVar(c: PContext, v: PSym): PSym =
  315. result = nil
  316. for scope in localScopesFrom(c, c.currentScope.parent):
  317. let shadowed = strTableGet(scope.symbols, v.name)
  318. if shadowed != nil and shadowed.kind in skLocalVars:
  319. return shadowed
  320. proc identWithin(n: PNode, s: PIdent): bool =
  321. for i in 0..n.safeLen-1:
  322. if identWithin(n[i], s): return true
  323. result = n.kind == nkSym and n.sym.name.id == s.id
  324. proc semIdentDef(c: PContext, n: PNode, kind: TSymKind, reportToNimsuggest = true): PSym =
  325. if isTopLevel(c):
  326. result = semIdentWithPragma(c, kind, n, {sfExported})
  327. incl(result.flags, sfGlobal)
  328. #if kind in {skVar, skLet}:
  329. # echo "global variable here ", n.info, " ", result.name.s
  330. else:
  331. result = semIdentWithPragma(c, kind, n, {})
  332. if result.owner.kind == skModule:
  333. incl(result.flags, sfGlobal)
  334. result.options = c.config.options
  335. proc getLineInfo(n: PNode): TLineInfo =
  336. case n.kind
  337. of nkPostfix:
  338. if len(n) > 1:
  339. return getLineInfo(n[1])
  340. of nkAccQuoted, nkPragmaExpr:
  341. if len(n) > 0:
  342. return getLineInfo(n[0])
  343. else:
  344. discard
  345. result = n.info
  346. let info = getLineInfo(n)
  347. if reportToNimsuggest:
  348. suggestSym(c.graph, info, result, c.graph.usageSym)
  349. proc checkNilable(c: PContext; v: PSym) =
  350. if {sfGlobal, sfImportc} * v.flags == {sfGlobal} and v.typ.requiresInit:
  351. if v.astdef.isNil:
  352. message(c.config, v.info, warnProveInit, v.name.s)
  353. elif tfNotNil in v.typ.flags and not v.astdef.typ.isNil and tfNotNil notin v.astdef.typ.flags:
  354. message(c.config, v.info, warnProveInit, v.name.s)
  355. #include liftdestructors
  356. proc addToVarSection(c: PContext; result: var PNode; n: PNode) =
  357. if result.kind != nkStmtList:
  358. result = makeStmtList(result)
  359. result.add n
  360. proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
  361. if result.kind == nkStmtList:
  362. let o = copyNode(orig)
  363. o.add identDefs
  364. result.add o
  365. else:
  366. result.add identDefs
  367. proc isDiscardUnderscore(v: PSym): bool =
  368. if v.name.id == ord(wUnderscore):
  369. v.flags.incl(sfGenSym)
  370. result = true
  371. else:
  372. result = false
  373. proc semUsing(c: PContext; n: PNode): PNode =
  374. result = c.graph.emptyNode
  375. if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "using")
  376. for i in 0..<n.len:
  377. var a = n[i]
  378. if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
  379. if a.kind == nkCommentStmt: continue
  380. if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
  381. checkMinSonsLen(a, 3, c.config)
  382. if a[^2].kind != nkEmpty:
  383. let typ = semTypeNode(c, a[^2], nil)
  384. for j in 0..<a.len-2:
  385. let v = semIdentDef(c, a[j], skParam)
  386. styleCheckDef(c, v)
  387. onDef(a[j].info, v)
  388. v.typ = typ
  389. strTableIncl(c.signatures, v)
  390. else:
  391. localError(c.config, a.info, "'using' section must have a type")
  392. var def: PNode
  393. if a[^1].kind != nkEmpty:
  394. localError(c.config, a.info, "'using' sections cannot contain assignments")
  395. proc hasUnresolvedParams(n: PNode; flags: TExprFlags): bool =
  396. result = tfUnresolved in n.typ.flags
  397. when false:
  398. case n.kind
  399. of nkSym:
  400. result = isGenericRoutineStrict(n.sym)
  401. of nkSymChoices:
  402. for ch in n:
  403. if hasUnresolvedParams(ch, flags):
  404. return true
  405. result = false
  406. else:
  407. result = false
  408. if efOperand in flags:
  409. if tfUnresolved notin n.typ.flags:
  410. result = false
  411. proc makeDeref(n: PNode): PNode =
  412. var t = n.typ
  413. if t.kind in tyUserTypeClasses and t.isResolvedUserTypeClass:
  414. t = t.last
  415. t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned})
  416. result = n
  417. if t.kind in {tyVar, tyLent}:
  418. result = newNodeIT(nkHiddenDeref, n.info, t.elementType)
  419. result.add n
  420. t = skipTypes(t.elementType, {tyGenericInst, tyAlias, tySink, tyOwned})
  421. while t.kind in {tyPtr, tyRef}:
  422. var a = result
  423. let baseTyp = t.elementType
  424. result = newNodeIT(nkHiddenDeref, n.info, baseTyp)
  425. result.add a
  426. t = skipTypes(baseTyp, {tyGenericInst, tyAlias, tySink, tyOwned})
  427. proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
  428. if n.len == 2:
  429. let x = semExprWithType(c, n[0])
  430. let y = considerQuotedIdent(c, n[1])
  431. let obj = x.typ.skipTypes(abstractPtrs)
  432. if obj.kind == tyObject and tfPartial in obj.flags:
  433. let field = newSym(skField, getIdent(c.cache, y.s), c.idgen, obj.sym, n[1].info)
  434. field.typ = skipIntLit(typ, c.idgen)
  435. field.position = obj.n.len
  436. obj.n.add newSymNode(field)
  437. n[0] = makeDeref x
  438. n[1] = newSymNode(field)
  439. n.typ = field.typ
  440. else:
  441. localError(c.config, n.info, "implicit object field construction " &
  442. "requires a .partial object, but got " & typeToString(obj))
  443. else:
  444. localError(c.config, n.info, "nkDotNode requires 2 children")
  445. proc setVarType(c: PContext; v: PSym, typ: PType) =
  446. if v.typ != nil and not sameTypeOrNil(v.typ, typ):
  447. localError(c.config, v.info, "inconsistent typing for reintroduced symbol '" &
  448. v.name.s & "': previous type was: " & typeToString(v.typ, preferDesc) &
  449. "; new type is: " & typeToString(typ, preferDesc))
  450. v.typ = typ
  451. proc isPossibleMacroPragma(c: PContext, it: PNode, key: PNode): bool =
  452. # make sure it's not a normal pragma, and calls an identifier
  453. # considerQuotedIdent below will fail on non-identifiers
  454. result = whichPragma(it) == wInvalid and key.kind in nkIdentKinds
  455. if result:
  456. # make sure it's not a user pragma
  457. let ident = considerQuotedIdent(c, key)
  458. result = strTableGet(c.userPragmas, ident) == nil
  459. if result:
  460. # make sure it's not a custom pragma
  461. var amb = false
  462. let sym = searchInScopes(c, ident, amb)
  463. result = sym == nil or sfCustomPragma notin sym.flags
  464. proc copyExcept(n: PNode, i: int): PNode =
  465. result = copyNode(n)
  466. for j in 0..<n.len:
  467. if j != i: result.add(n[j])
  468. proc semVarMacroPragma(c: PContext, a: PNode, n: PNode): PNode =
  469. # Mirrored with semProcAnnotation
  470. result = nil
  471. # a, b {.prag.}: int = 3 not allowed
  472. const lhsPos = 0
  473. if a.len == 3 and a[lhsPos].kind == nkPragmaExpr:
  474. var b = a[lhsPos]
  475. const
  476. namePos = 0
  477. pragmaPos = 1
  478. let pragmas = b[pragmaPos]
  479. for i in 0 ..< pragmas.len:
  480. let it = pragmas[i]
  481. let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
  482. trySuggestPragmas(c, key)
  483. if isPossibleMacroPragma(c, it, key):
  484. # we transform ``var p {.m, rest.}`` into ``m(do: var p {.rest.})`` and
  485. # let the semantic checker deal with it:
  486. var x = newNodeI(nkCall, key.info)
  487. x.add(key)
  488. if it.kind in nkPragmaCallKinds and it.len > 1:
  489. # pass pragma arguments to the macro too:
  490. for i in 1..<it.len:
  491. x.add(it[i])
  492. # Drop the pragma from the list, this prevents getting caught in endless
  493. # recursion when the nkCall is semanticized
  494. let oldExpr = a[lhsPos]
  495. let newPragmas = copyExcept(pragmas, i)
  496. if newPragmas.kind != nkEmpty and newPragmas.len == 0:
  497. a[lhsPos] = oldExpr[namePos]
  498. else:
  499. a[lhsPos] = copyNode(oldExpr)
  500. a[lhsPos].add(oldExpr[namePos])
  501. a[lhsPos].add(newPragmas)
  502. var unarySection = newNodeI(n.kind, a.info)
  503. unarySection.add(a)
  504. x.add(unarySection)
  505. # recursion assures that this works for multiple macro annotations too:
  506. var r = semOverloadedCall(c, x, x, {skMacro, skTemplate}, {efNoUndeclared})
  507. if r == nil:
  508. # Restore the old list of pragmas since we couldn't process this
  509. a[lhsPos] = oldExpr
  510. # No matching macro was found but there's always the possibility this may
  511. # be a .pragma. template instead
  512. continue
  513. doAssert r[0].kind == nkSym
  514. let m = r[0].sym
  515. case m.kind
  516. of skMacro: result = semMacroExpr(c, r, r, m, {})
  517. of skTemplate: result = semTemplateExpr(c, r, m, {})
  518. else:
  519. a[lhsPos] = oldExpr
  520. continue
  521. doAssert result != nil
  522. return result
  523. template isLocalSym(sym: PSym): bool =
  524. sym.kind in {skVar, skLet, skParam} and not
  525. ({sfGlobal, sfPure} * sym.flags != {} or
  526. sym.typ.kind == tyTypeDesc or
  527. sfCompileTime in sym.flags) or
  528. sym.kind in {skProc, skFunc, skIterator} and
  529. sfGlobal notin sym.flags
  530. template isLocalVarSym(n: PNode): bool =
  531. n.kind == nkSym and isLocalSym(n.sym)
  532. proc usesLocalVar(n: PNode): bool =
  533. result = false
  534. for z in 1 ..< n.len:
  535. if n[z].isLocalVarSym:
  536. return true
  537. elif n[z].kind in nkCallKinds:
  538. if usesLocalVar(n[z]):
  539. return true
  540. proc globalVarInitCheck(c: PContext, n: PNode) =
  541. if n.isLocalVarSym or n.kind in nkCallKinds and usesLocalVar(n):
  542. localError(c.config, n.info, errCannotAssignToGlobal)
  543. const
  544. errTupleUnpackingTupleExpected = "tuple expected for tuple unpacking, but got '$1'"
  545. errTupleUnpackingDifferentLengths = "tuple with $1 elements expected, but got '$2' with $3 elements"
  546. proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSymKind, origResult: var PNode): PNode =
  547. ## expand tuple unpacking assignments into new var/let/const section
  548. ##
  549. ## mirrored with semexprs.makeTupleAssignments
  550. if typ.kind != tyTuple:
  551. localError(c.config, a.info, errTupleUnpackingTupleExpected %
  552. [typeToString(typ, preferDesc)])
  553. elif a.len-2 != typ.len:
  554. localError(c.config, a.info, errTupleUnpackingDifferentLengths %
  555. [$(a.len-2), typeToString(typ, preferDesc), $typ.len])
  556. var
  557. tempNode: PNode = nil
  558. lastDef: PNode
  559. let defkind = if symkind == skConst: nkConstDef else: nkIdentDefs
  560. # temporary not needed if not const and RHS is tuple literal
  561. # const breaks with seqs without temporary
  562. let useTemp = def.kind notin {nkPar, nkTupleConstr} or symkind == skConst
  563. if useTemp:
  564. # use same symkind for compatibility with original section
  565. let temp = newSym(symkind, getIdent(c.cache, "tmpTuple"), c.idgen, getCurrOwner(c), n.info)
  566. temp.typ = typ
  567. temp.flags.incl(sfGenSym)
  568. lastDef = newNodeI(defkind, a.info)
  569. newSons(lastDef, 3)
  570. lastDef[0] = newSymNode(temp)
  571. # NOTE: at the moment this is always ast.emptyNode, see parser.nim
  572. lastDef[1] = a[^2]
  573. lastDef[2] = def
  574. temp.ast = lastDef
  575. addToVarSection(c, origResult, n, lastDef)
  576. tempNode = newSymNode(temp)
  577. result = newNodeI(n.kind, a.info)
  578. for j in 0..<a.len-2:
  579. let name = a[j]
  580. if useTemp and name.kind == nkIdent and name.ident.id == ord(wUnderscore):
  581. # skip _ assignments if we are using a temp as they are already evaluated
  582. continue
  583. if name.kind == nkVarTuple:
  584. # nested tuple
  585. lastDef = newNodeI(nkVarTuple, name.info)
  586. newSons(lastDef, name.len)
  587. for k in 0..<name.len-2:
  588. lastDef[k] = name[k]
  589. else:
  590. lastDef = newNodeI(defkind, name.info)
  591. newSons(lastDef, 3)
  592. lastDef[0] = name
  593. lastDef[^2] = c.graph.emptyNode
  594. if useTemp:
  595. lastDef[^1] = newTupleAccessRaw(tempNode, j)
  596. else:
  597. var val = def[j]
  598. if val.kind == nkExprColonExpr: val = val[1]
  599. lastDef[^1] = val
  600. result.add(lastDef)
  601. proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
  602. var b: PNode
  603. result = copyNode(n)
  604. # transform var x, y = 12 into var x = 12; var y = 12
  605. # bug #18104; transformation should be finished before templates expansion
  606. # TODO: move warnings for tuple here
  607. var transformed = copyNode(n)
  608. for i in 0..<n.len:
  609. var a = n[i]
  610. if a.kind == nkIdentDefs and a.len > 3 and a[^1].kind != nkEmpty:
  611. for j in 0..<a.len-2:
  612. var b = newNodeI(nkIdentDefs, a.info)
  613. b.add a[j]
  614. b.add a[^2]
  615. b.add copyTree(a[^1])
  616. transformed.add b
  617. else:
  618. transformed.add a
  619. let n = transformed
  620. for i in 0..<n.len:
  621. var a = n[i]
  622. if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
  623. if a.kind == nkCommentStmt: continue
  624. if a.kind notin {nkIdentDefs, nkVarTuple}: illFormedAst(a, c.config)
  625. checkMinSonsLen(a, 3, c.config)
  626. b = semVarMacroPragma(c, a, n)
  627. if b != nil:
  628. addToVarSection(c, result, b)
  629. continue
  630. var hasUserSpecifiedType = false
  631. var typ: PType = nil
  632. if a[^2].kind != nkEmpty:
  633. typ = semTypeNode(c, a[^2], nil)
  634. hasUserSpecifiedType = true
  635. var typFlags: TTypeAllowedFlags = {}
  636. var def: PNode = c.graph.emptyNode
  637. if a[^1].kind != nkEmpty:
  638. def = semExprWithType(c, a[^1], {efTypeAllowed}, typ)
  639. if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
  640. typFlags.incl taIsTemplateOrMacro
  641. elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
  642. typFlags.incl taProcContextIsNotMacro
  643. if typ != nil:
  644. if typ.isMetaType:
  645. def = inferWithMetatype(c, typ, def)
  646. typ = def.typ
  647. else:
  648. # BUGFIX: ``fitNode`` is needed here!
  649. # check type compatibility between def.typ and typ
  650. def = fitNodeConsiderViewType(c, typ, def, def.info)
  651. #changeType(def.skipConv, typ, check=true)
  652. else:
  653. typ = def.typ.skipTypes({tyStatic, tySink}).skipIntLit(c.idgen)
  654. if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass:
  655. typ = typ.last
  656. if hasEmpty(typ):
  657. localError(c.config, def.info, errCannotInferTypeOfTheLiteral % typ.kind.toHumanStr)
  658. elif typ.kind == tyProc and def.kind == nkSym and isGenericRoutine(def.sym.ast):
  659. let owner = typ.owner
  660. let err =
  661. # consistent error message with evaltempl/semMacroExpr
  662. if owner != nil and owner.kind in {skTemplate, skMacro}:
  663. errMissingGenericParamsForTemplate % def.renderTree
  664. else:
  665. errProcHasNoConcreteType % def.renderTree
  666. localError(c.config, def.info, err)
  667. when false:
  668. # XXX This typing rule is neither documented nor complete enough to
  669. # justify it. Instead use the newer 'unowned x' until we figured out
  670. # a more general solution.
  671. if symkind == skVar and typ.kind == tyOwned and def.kind notin nkCallKinds:
  672. # special type inference rule: 'var it = ownedPointer' is turned
  673. # into an unowned pointer.
  674. typ = typ.lastSon
  675. # this can only happen for errornous var statements:
  676. if typ == nil: continue
  677. if c.matchedConcept != nil:
  678. typFlags.incl taConcept
  679. typeAllowedCheck(c, a.info, typ, symkind, typFlags)
  680. var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink})
  681. if a.kind == nkVarTuple:
  682. # generate new section from tuple unpacking and embed it into this one
  683. let assignments = makeVarTupleSection(c, n, a, def, tup, symkind, result)
  684. let resSection = semVarOrLet(c, assignments, symkind)
  685. for resDef in resSection:
  686. addToVarSection(c, result, n, resDef)
  687. else:
  688. if tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
  689. a.len > 3:
  690. # var a, b = (1, 2)
  691. message(c.config, a.info, warnEachIdentIsTuple)
  692. for j in 0..<a.len-2:
  693. if a[j].kind == nkDotExpr:
  694. fillPartialObject(c, a[j], typ)
  695. addToVarSection(c, result, n, a)
  696. continue
  697. var v = semIdentDef(c, a[j], symkind, false)
  698. when defined(nimsuggest):
  699. v.hasUserSpecifiedType = hasUserSpecifiedType
  700. styleCheckDef(c, v)
  701. onDef(a[j].info, v)
  702. if sfGenSym notin v.flags:
  703. if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
  704. else:
  705. if v.owner == nil: v.owner = c.p.owner
  706. when oKeepVariableNames:
  707. if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
  708. else:
  709. let shadowed = findShadowedVar(c, v)
  710. if shadowed != nil:
  711. shadowed.flags.incl(sfShadowed)
  712. if shadowed.kind == skResult and sfGenSym notin v.flags:
  713. message(c.config, a.info, warnResultShadowed)
  714. if def.kind != nkEmpty:
  715. if sfThread in v.flags: localError(c.config, def.info, errThreadvarCannotInit)
  716. setVarType(c, v, typ)
  717. # this is needed for the evaluation pass, guard checking
  718. # and custom pragmas:
  719. b = newNodeI(nkIdentDefs, a.info)
  720. if importantComments(c.config):
  721. # keep documentation information:
  722. b.comment = a.comment
  723. # postfix not generated here (to generate, get rid of it in transf)
  724. if a[j].kind == nkPragmaExpr:
  725. var p = newNodeI(nkPragmaExpr, a.info)
  726. p.add newSymNode(v)
  727. p.add a[j][1]
  728. b.add p
  729. else:
  730. b.add newSymNode(v)
  731. # keep type desc for doc generator
  732. b.add a[^2]
  733. b.add copyTree(def)
  734. addToVarSection(c, result, n, b)
  735. v.ast = b
  736. if def.kind == nkEmpty:
  737. let actualType = v.typ.skipTypes({tyGenericInst, tyAlias,
  738. tyUserTypeClassInst})
  739. if actualType.kind in {tyObject, tyDistinct} and
  740. actualType.requiresInit:
  741. defaultConstructionError(c, v.typ, v.info)
  742. else:
  743. checkNilable(c, v)
  744. # allow let to not be initialised if imported from C:
  745. if v.kind == skLet and sfImportc notin v.flags and (strictDefs notin c.features or not isLocalSym(v)):
  746. localError(c.config, a.info, errLetNeedsInit)
  747. if sfCompileTime in v.flags:
  748. var x = newNodeI(result.kind, v.info)
  749. x.add result[i]
  750. vm.setupCompileTimeVar(c.module, c.idgen, c.graph, x)
  751. if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
  752. message(c.config, v.info, hintGlobalVar)
  753. if {sfGlobal, sfPure} <= v.flags:
  754. globalVarInitCheck(c, def)
  755. suggestSym(c.graph, v.info, v, c.graph.usageSym)
  756. proc semConst(c: PContext, n: PNode): PNode =
  757. result = copyNode(n)
  758. inc c.inStaticContext
  759. var b: PNode
  760. for i in 0..<n.len:
  761. var a = n[i]
  762. if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
  763. if a.kind == nkCommentStmt: continue
  764. if a.kind notin {nkConstDef, nkVarTuple}: illFormedAst(a, c.config)
  765. checkMinSonsLen(a, 3, c.config)
  766. b = semVarMacroPragma(c, a, n)
  767. if b != nil:
  768. addToVarSection(c, result, b)
  769. continue
  770. var hasUserSpecifiedType = false
  771. var typ: PType = nil
  772. if a[^2].kind != nkEmpty:
  773. typ = semTypeNode(c, a[^2], nil)
  774. hasUserSpecifiedType = true
  775. var typFlags: TTypeAllowedFlags = {}
  776. # don't evaluate here since the type compatibility check below may add a converter
  777. var def = semExprWithType(c, a[^1], {efTypeAllowed}, typ)
  778. if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
  779. typFlags.incl taIsTemplateOrMacro
  780. elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
  781. typFlags.incl taProcContextIsNotMacro
  782. # check type compatibility between def.typ and typ:
  783. if typ != nil:
  784. if typ.isMetaType:
  785. def = inferWithMetatype(c, typ, def)
  786. typ = def.typ
  787. else:
  788. def = fitRemoveHiddenConv(c, typ, def)
  789. else:
  790. typ = def.typ
  791. # evaluate the node
  792. def = semConstExpr(c, def)
  793. if def == nil:
  794. localError(c.config, a[^1].info, errConstExprExpected)
  795. continue
  796. if def.kind != nkNilLit:
  797. if c.matchedConcept != nil:
  798. typFlags.incl taConcept
  799. typeAllowedCheck(c, a.info, typ, skConst, typFlags)
  800. if a.kind == nkVarTuple:
  801. # generate new section from tuple unpacking and embed it into this one
  802. let assignments = makeVarTupleSection(c, n, a, def, typ, skConst, result)
  803. let resSection = semConst(c, assignments)
  804. for resDef in resSection:
  805. addToVarSection(c, result, n, resDef)
  806. else:
  807. for j in 0..<a.len-2:
  808. var v = semIdentDef(c, a[j], skConst)
  809. when defined(nimsuggest):
  810. v.hasUserSpecifiedType = hasUserSpecifiedType
  811. if sfGenSym notin v.flags: addInterfaceDecl(c, v)
  812. elif v.owner == nil: v.owner = getCurrOwner(c)
  813. styleCheckDef(c, v)
  814. onDef(a[j].info, v)
  815. var fillSymbol = true
  816. if v.typ != nil:
  817. # symbol already has type and probably value
  818. # don't mutate
  819. fillSymbol = false
  820. else:
  821. setVarType(c, v, typ)
  822. b = newNodeI(nkConstDef, a.info)
  823. if importantComments(c.config): b.comment = a.comment
  824. # postfix not generated here (to generate, get rid of it in transf)
  825. if a[j].kind == nkPragmaExpr:
  826. var p = newNodeI(nkPragmaExpr, a.info)
  827. p.add newSymNode(v)
  828. p.add a[j][1].copyTree
  829. b.add p
  830. else:
  831. b.add newSymNode(v)
  832. b.add a[1]
  833. b.add copyTree(def)
  834. if fillSymbol:
  835. v.ast = b
  836. addToVarSection(c, result, n, b)
  837. dec c.inStaticContext
  838. include semfields
  839. proc symForVar(c: PContext, n: PNode): PSym =
  840. let m = if n.kind == nkPragmaExpr: n[0] else: n
  841. result = newSymG(skForVar, m, c)
  842. styleCheckDef(c, result)
  843. onDef(n.info, result)
  844. if n.kind == nkPragmaExpr:
  845. pragma(c, result, n[1], forVarPragmas)
  846. proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
  847. result = n
  848. let iterBase = n[^2].typ
  849. var iter = skipTypes(iterBase, {tyGenericInst, tyAlias, tySink, tyOwned})
  850. var iterAfterVarLent = iter.skipTypes({tyGenericInst, tyAlias, tyLent, tyVar})
  851. # n.len == 3 means that there is one for loop variable
  852. # and thus no tuple unpacking:
  853. if iterAfterVarLent.kind == tyEmpty:
  854. localError(c.config, n[^2].info, "cannot infer element type of $1" %
  855. renderTree(n[^2], {renderNoComments}))
  856. if iterAfterVarLent.kind != tyTuple or n.len == 3:
  857. if n.len == 3:
  858. if n[0].kind == nkVarTuple:
  859. if iterAfterVarLent.kind != tyTuple:
  860. return localErrorNode(c, n, n[0].info, errTupleUnpackingTupleExpected %
  861. [typeToString(n[1].typ, preferDesc)])
  862. elif n[0].len-1 != iterAfterVarLent.len:
  863. return localErrorNode(c, n, n[0].info, errWrongNumberOfVariables)
  864. for i in 0..<n[0].len-1:
  865. var v = symForVar(c, n[0][i])
  866. if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
  867. case iter.kind
  868. of tyVar, tyLent:
  869. v.typ = newTypeS(iter.kind, c)
  870. v.typ.add iterAfterVarLent[i]
  871. if tfVarIsPtr in iter.flags:
  872. v.typ.flags.incl tfVarIsPtr
  873. else:
  874. v.typ = iter[i]
  875. n[0][i] = newSymNode(v)
  876. if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v)
  877. elif v.owner == nil: v.owner = getCurrOwner(c)
  878. else:
  879. var v = symForVar(c, n[0])
  880. if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
  881. # BUGFIX: don't use `iter` here as that would strip away
  882. # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
  883. # for an example:
  884. v.typ = iterBase
  885. n[0] = newSymNode(v)
  886. if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v)
  887. elif v.owner == nil: v.owner = getCurrOwner(c)
  888. else:
  889. localError(c.config, n.info, errWrongNumberOfVariables)
  890. elif n.len-2 != iterAfterVarLent.len:
  891. localError(c.config, n.info, errWrongNumberOfVariables)
  892. else:
  893. for i in 0..<n.len - 2:
  894. if n[i].kind == nkVarTuple:
  895. var mutable = false
  896. var isLent = false
  897. case iter[i].kind
  898. of tyVar:
  899. mutable = true
  900. iter[i] = iter[i].skipTypes({tyVar})
  901. of tyLent:
  902. isLent = true
  903. iter[i] = iter[i].skipTypes({tyLent})
  904. else: discard
  905. if n[i].len-1 != iter[i].len:
  906. localError(c.config, n[i].info, errWrongNumberOfVariables)
  907. for j in 0..<n[i].len-1:
  908. var v = symForVar(c, n[i][j])
  909. if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
  910. if mutable:
  911. v.typ = newTypeS(tyVar, c)
  912. v.typ.add iter[i][j]
  913. elif isLent:
  914. v.typ = newTypeS(tyLent, c)
  915. v.typ.add iter[i][j]
  916. else:
  917. v.typ = iter[i][j]
  918. n[i][j] = newSymNode(v)
  919. if not isDiscardUnderscore(v): addDecl(c, v)
  920. elif v.owner == nil: v.owner = getCurrOwner(c)
  921. else:
  922. var v = symForVar(c, n[i])
  923. if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
  924. case iter.kind
  925. of tyVar, tyLent:
  926. v.typ = newTypeS(iter.kind, c)
  927. v.typ.add iterAfterVarLent[i]
  928. if tfVarIsPtr in iter.flags:
  929. v.typ.flags.incl tfVarIsPtr
  930. else:
  931. v.typ = iter[i]
  932. n[i] = newSymNode(v)
  933. if sfGenSym notin v.flags:
  934. if not isDiscardUnderscore(v): addDecl(c, v)
  935. elif v.owner == nil: v.owner = getCurrOwner(c)
  936. inc(c.p.nestedLoopCounter)
  937. let oldBreakInLoop = c.p.breakInLoop
  938. c.p.breakInLoop = true
  939. openScope(c)
  940. n[^1] = semExprBranch(c, n[^1], flags)
  941. if efInTypeof notin flags:
  942. discardCheck(c, n[^1], flags)
  943. closeScope(c)
  944. c.p.breakInLoop = oldBreakInLoop
  945. dec(c.p.nestedLoopCounter)
  946. proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
  947. result = newNodeI(nkCall, arg.info)
  948. result.add(newIdentNode(getIdent(c.cache, it), arg.info))
  949. if arg.typ != nil and arg.typ.kind in {tyVar, tyLent}:
  950. result.add newDeref(arg)
  951. else:
  952. result.add arg
  953. result = semExprNoDeref(c, result, {efWantIterator})
  954. proc isTrivalStmtExpr(n: PNode): bool =
  955. for i in 0..<n.len-1:
  956. if n[i].kind notin {nkEmpty, nkCommentStmt}:
  957. return false
  958. result = true
  959. proc handleStmtMacro(c: PContext; n, selector: PNode; magicType: string;
  960. flags: TExprFlags): PNode =
  961. if selector.kind in nkCallKinds:
  962. # we transform
  963. # n := for a, b, c in m(x, y, z): Y
  964. # to
  965. # m(n)
  966. let maType = magicsys.getCompilerProc(c.graph, magicType)
  967. if maType == nil: return
  968. let headSymbol = selector[0]
  969. var o: TOverloadIter
  970. var match: PSym = nil
  971. var symx = initOverloadIter(o, c, headSymbol)
  972. while symx != nil:
  973. if symx.kind in {skTemplate, skMacro}:
  974. if symx.typ.len == 2 and symx.typ.firstParamType == maType.typ:
  975. if match == nil:
  976. match = symx
  977. else:
  978. localError(c.config, n.info, errAmbiguousCallXYZ % [
  979. getProcHeader(c.config, match),
  980. getProcHeader(c.config, symx), $selector])
  981. symx = nextOverloadIter(o, c, headSymbol)
  982. if match == nil: return
  983. var callExpr = newNodeI(nkCall, n.info)
  984. callExpr.add newSymNode(match)
  985. callExpr.add n
  986. case match.kind
  987. of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, flags)
  988. of skTemplate: result = semTemplateExpr(c, callExpr, match, flags)
  989. else: result = nil
  990. else:
  991. result = nil
  992. proc handleForLoopMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
  993. result = handleStmtMacro(c, n, n[^2], "ForLoopStmt", flags)
  994. proc handleCaseStmtMacro(c: PContext; n: PNode; flags: TExprFlags): PNode =
  995. # n[0] has been sem'checked and has a type. We use this to resolve
  996. # '`case`(n[0])' but then we pass 'n' to the `case` macro. This seems to
  997. # be the best solution.
  998. var toResolve = newNodeI(nkCall, n.info)
  999. toResolve.add newIdentNode(getIdent(c.cache, "case"), n.info)
  1000. toResolve.add n[0]
  1001. var errors: CandidateErrors
  1002. var r = resolveOverloads(c, toResolve, toResolve, {skTemplate, skMacro}, {efNoDiagnostics},
  1003. errors, false)
  1004. if r.state == csMatch:
  1005. var match = r.calleeSym
  1006. markUsed(c, n[0].info, match)
  1007. onUse(n[0].info, match)
  1008. # but pass 'n' to the `case` macro, not 'n[0]':
  1009. r.call[1] = n
  1010. let toExpand = semResolvedCall(c, r, r.call, {})
  1011. case match.kind
  1012. of skMacro: result = semMacroExpr(c, toExpand, toExpand, match, flags)
  1013. of skTemplate: result = semTemplateExpr(c, toExpand, match, flags)
  1014. else: result = errorNode(c, n[0])
  1015. elif r.state == csNoMatch:
  1016. result = errorNode(c, n[0])
  1017. else:
  1018. result = errorNode(c, n[0])
  1019. if result.kind == nkEmpty:
  1020. localError(c.config, n[0].info, errSelectorMustBeOfCertainTypes)
  1021. # this would be the perfectly consistent solution with 'for loop macros',
  1022. # but it kinda sucks for pattern matching as the matcher is not attached to
  1023. # a type then:
  1024. when false:
  1025. result = handleStmtMacro(c, n, n[0], "CaseStmt")
  1026. proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
  1027. checkMinSonsLen(n, 3, c.config)
  1028. result = handleForLoopMacro(c, n, flags)
  1029. if result != nil: return result
  1030. openScope(c)
  1031. result = n
  1032. n[^2] = semExprNoDeref(c, n[^2], {efWantIterator})
  1033. var call = n[^2]
  1034. if call.kind == nkStmtListExpr and (isTrivalStmtExpr(call) or (call.lastSon.kind in nkCallKinds and call.lastSon[0].sym.kind == skIterator)):
  1035. call = call.lastSon
  1036. n[^2] = call
  1037. let isCallExpr = call.kind in nkCallKinds
  1038. if isCallExpr and call[0].kind == nkSym and
  1039. call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}:
  1040. if call[0].sym.magic == mOmpParFor:
  1041. result = semForVars(c, n, flags)
  1042. result.transitionSonsKind(nkParForStmt)
  1043. else:
  1044. result = semForFields(c, n, call[0].sym.magic)
  1045. elif isCallExpr and isClosureIterator(call[0].typ.skipTypes(abstractInst)):
  1046. # first class iterator:
  1047. result = semForVars(c, n, flags)
  1048. elif not isCallExpr or call[0].kind != nkSym or
  1049. call[0].sym.kind != skIterator:
  1050. if n.len == 3:
  1051. n[^2] = implicitIterator(c, "items", n[^2])
  1052. elif n.len == 4:
  1053. n[^2] = implicitIterator(c, "pairs", n[^2])
  1054. else:
  1055. localError(c.config, n[^2].info, "iterator within for loop context expected")
  1056. result = semForVars(c, n, flags)
  1057. else:
  1058. result = semForVars(c, n, flags)
  1059. # propagate any enforced VoidContext:
  1060. if n[^1].typ == c.enforceVoidContext:
  1061. result.typ = c.enforceVoidContext
  1062. elif efInTypeof in flags:
  1063. result.typ = result.lastSon.typ
  1064. closeScope(c)
  1065. proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
  1066. result = n
  1067. checkMinSonsLen(n, 2, c.config)
  1068. openScope(c)
  1069. pushCaseContext(c, n)
  1070. n[0] = semExprWithType(c, n[0])
  1071. var covered: Int128 = toInt128(0)
  1072. var typ = commonTypeBegin
  1073. var expectedType = expectedType
  1074. var hasElse = false
  1075. let caseTyp = skipTypes(n[0].typ, abstractVar-{tyTypeDesc})
  1076. var chckCovered = caseTyp.shouldCheckCaseCovered()
  1077. case caseTyp.kind
  1078. of tyFloat..tyFloat128, tyString, tyCstring, tyError, shouldChckCovered, tyRange:
  1079. discard
  1080. else:
  1081. popCaseContext(c)
  1082. closeScope(c)
  1083. return handleCaseStmtMacro(c, n, flags)
  1084. template invalidOrderOfBranches(n: PNode) =
  1085. localError(c.config, n.info, "invalid order of case branches")
  1086. break
  1087. for i in 1..<n.len:
  1088. setCaseContextIdx(c, i)
  1089. var x = n[i]
  1090. when defined(nimsuggest):
  1091. if c.config.ideCmd == ideSug and exactEquals(c.config.m.trackPos, x.info) and caseTyp.kind == tyEnum:
  1092. suggestEnum(c, x, caseTyp)
  1093. case x.kind
  1094. of nkOfBranch:
  1095. if hasElse: invalidOrderOfBranches(x)
  1096. checkMinSonsLen(x, 2, c.config)
  1097. semCaseBranch(c, n, x, i, covered)
  1098. var last = x.len-1
  1099. x[last] = semExprBranchScope(c, x[last], expectedType)
  1100. typ = commonType(c, typ, x[last])
  1101. if not endsInNoReturn(x[last]):
  1102. expectedType = typ
  1103. of nkElifBranch:
  1104. if hasElse: invalidOrderOfBranches(x)
  1105. chckCovered = false
  1106. checkSonsLen(x, 2, c.config)
  1107. openScope(c)
  1108. x[0] = forceBool(c, semExprWithType(c, x[0], expectedType = getSysType(c.graph, n.info, tyBool)))
  1109. x[1] = semExprBranch(c, x[1], expectedType = expectedType)
  1110. typ = commonType(c, typ, x[1])
  1111. if not endsInNoReturn(x[1]):
  1112. expectedType = typ
  1113. closeScope(c)
  1114. of nkElse:
  1115. checkSonsLen(x, 1, c.config)
  1116. x[0] = semExprBranchScope(c, x[0], expectedType)
  1117. typ = commonType(c, typ, x[0])
  1118. if not endsInNoReturn(x[0]):
  1119. expectedType = typ
  1120. if (chckCovered and covered == toCover(c, n[0].typ)) or hasElse:
  1121. message(c.config, x.info, warnUnreachableElse)
  1122. hasElse = true
  1123. chckCovered = false
  1124. else:
  1125. illFormedAst(x, c.config)
  1126. if chckCovered:
  1127. if covered == toCover(c, n[0].typ):
  1128. hasElse = true
  1129. elif n[0].typ.skipTypes(abstractRange).kind in {tyEnum, tyChar}:
  1130. localError(c.config, n.info, "not all cases are covered; missing: $1" %
  1131. formatMissingEnums(c, n))
  1132. else:
  1133. localError(c.config, n.info, "not all cases are covered")
  1134. popCaseContext(c)
  1135. closeScope(c)
  1136. if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or
  1137. (not hasElse and efInTypeof notin flags):
  1138. for i in 1..<n.len: discardCheck(c, n[i].lastSon, flags)
  1139. # propagate any enforced VoidContext:
  1140. if typ == c.enforceVoidContext:
  1141. result.typ = c.enforceVoidContext
  1142. else:
  1143. for i in 1..<n.len:
  1144. var it = n[i]
  1145. let j = it.len-1
  1146. if not endsInNoReturn(it[j]):
  1147. it[j] = fitNode(c, typ, it[j], it[j].info)
  1148. result.typ = typ
  1149. proc semRaise(c: PContext, n: PNode): PNode =
  1150. result = n
  1151. checkSonsLen(n, 1, c.config)
  1152. if n[0].kind != nkEmpty:
  1153. n[0] = semExprWithType(c, n[0])
  1154. var typ = n[0].typ
  1155. if not isImportedException(typ, c.config):
  1156. typ = typ.skipTypes({tyAlias, tyGenericInst, tyOwned})
  1157. if typ.kind != tyRef:
  1158. localError(c.config, n.info, errExprCannotBeRaised)
  1159. if typ.len > 0 and not isException(typ.elementType):
  1160. localError(c.config, n.info, "raised object of type $1 does not inherit from Exception" % typeToString(typ))
  1161. proc addGenericParamListToScope(c: PContext, n: PNode) =
  1162. if n.kind != nkGenericParams: illFormedAst(n, c.config)
  1163. for i in 0..<n.len:
  1164. var a = n[i]
  1165. if a.kind == nkSym: addDecl(c, a.sym)
  1166. else: illFormedAst(a, c.config)
  1167. proc typeSectionTypeName(c: PContext; n: PNode): PNode =
  1168. if n.kind == nkPragmaExpr:
  1169. if n.len == 0: illFormedAst(n, c.config)
  1170. result = n[0]
  1171. else:
  1172. result = n
  1173. if result.kind == nkPostfix:
  1174. if result.len != 2: illFormedAst(n, c.config)
  1175. result = result[1]
  1176. if result.kind != nkSym: illFormedAst(n, c.config)
  1177. proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) =
  1178. let typeDef = typeSection[i]
  1179. checkSonsLen(typeDef, 3, c.config)
  1180. var name = typeDef[0]
  1181. var s: PSym = nil
  1182. if name.kind == nkDotExpr and typeDef[2].kind == nkObjectTy:
  1183. let pkgName = considerQuotedIdent(c, name[0])
  1184. let typName = considerQuotedIdent(c, name[1])
  1185. let pkg = c.graph.packageSyms.strTableGet(pkgName)
  1186. if pkg.isNil or pkg.kind != skPackage:
  1187. localError(c.config, name.info, "unknown package name: " & pkgName.s)
  1188. else:
  1189. let typsym = c.graph.packageTypes.strTableGet(typName)
  1190. if typsym.isNil:
  1191. s = semIdentDef(c, name[1], skType)
  1192. onDef(name[1].info, s)
  1193. s.typ = newTypeS(tyObject, c)
  1194. s.typ.sym = s
  1195. s.flags.incl sfForward
  1196. c.graph.packageTypes.strTableAdd s
  1197. addInterfaceDecl(c, s)
  1198. elif typsym.kind == skType and sfForward in typsym.flags:
  1199. s = typsym
  1200. addInterfaceDecl(c, s)
  1201. # PRTEMP no onDef here?
  1202. else:
  1203. localError(c.config, name.info, typsym.name.s & " is not a type that can be forwarded")
  1204. s = typsym
  1205. else:
  1206. s = semIdentDef(c, name, skType)
  1207. onDef(name.info, s)
  1208. s.typ = newTypeS(tyForward, c)
  1209. s.typ.sym = s # process pragmas:
  1210. if name.kind == nkPragmaExpr:
  1211. let rewritten = applyTypeSectionPragmas(c, name[1], typeDef)
  1212. if rewritten != nil:
  1213. case rewritten.kind
  1214. of nkTypeDef:
  1215. typeSection[i] = rewritten
  1216. of nkTypeSection:
  1217. typeSection.sons[i .. i] = rewritten.sons
  1218. else: illFormedAst(rewritten, c.config)
  1219. typeDefLeftSidePass(c, typeSection, i)
  1220. return
  1221. pragma(c, s, name[1], typePragmas)
  1222. if sfForward in s.flags:
  1223. # check if the symbol already exists:
  1224. let pkg = c.module.owner
  1225. if not isTopLevel(c) or pkg.isNil:
  1226. localError(c.config, name.info, "only top level types in a package can be 'package'")
  1227. else:
  1228. let typsym = c.graph.packageTypes.strTableGet(s.name)
  1229. if typsym != nil:
  1230. if sfForward notin typsym.flags or sfNoForward notin typsym.flags:
  1231. typeCompleted(typsym)
  1232. typsym.info = s.info
  1233. else:
  1234. localError(c.config, name.info, "cannot complete type '" & s.name.s & "' twice; " &
  1235. "previous type completion was here: " & c.config$typsym.info)
  1236. s = typsym
  1237. # add it here, so that recursive types are possible:
  1238. if sfGenSym notin s.flags: addInterfaceDecl(c, s)
  1239. elif s.owner == nil: s.owner = getCurrOwner(c)
  1240. if name.kind == nkPragmaExpr:
  1241. if name[0].kind == nkPostfix:
  1242. typeDef[0][0][1] = newSymNode(s)
  1243. else:
  1244. typeDef[0][0] = newSymNode(s)
  1245. else:
  1246. if name.kind == nkPostfix:
  1247. typeDef[0][1] = newSymNode(s)
  1248. else:
  1249. typeDef[0] = newSymNode(s)
  1250. proc typeSectionLeftSidePass(c: PContext, n: PNode) =
  1251. # process the symbols on the left side for the whole type section, before
  1252. # we even look at the type definitions on the right
  1253. var i = 0
  1254. while i < n.len: # n may grow due to type pragma macros
  1255. var a = n[i]
  1256. when defined(nimsuggest):
  1257. if c.config.cmd == cmdIdeTools:
  1258. inc c.inTypeContext
  1259. suggestStmt(c, a)
  1260. dec c.inTypeContext
  1261. case a.kind
  1262. of nkCommentStmt: discard
  1263. of nkTypeDef: typeDefLeftSidePass(c, n, i)
  1264. else: illFormedAst(a, c.config)
  1265. inc i
  1266. proc checkCovariantParamsUsages(c: PContext; genericType: PType) =
  1267. var body = genericType.typeBodyImpl
  1268. proc traverseSubTypes(c: PContext; t: PType): bool =
  1269. template error(msg) = localError(c.config, genericType.sym.info, msg)
  1270. result = false
  1271. template subresult(r) =
  1272. let sub = r
  1273. result = result or sub
  1274. case t.kind
  1275. of tyGenericParam:
  1276. t.flags.incl tfWeakCovariant
  1277. return true
  1278. of tyObject:
  1279. for field in t.n:
  1280. subresult traverseSubTypes(c, field.typ)
  1281. of tyArray:
  1282. return traverseSubTypes(c, t.elementType)
  1283. of tyProc:
  1284. for subType in t.signature:
  1285. if subType != nil:
  1286. subresult traverseSubTypes(c, subType)
  1287. if result:
  1288. error("non-invariant type param used in a proc type: " & $t)
  1289. of tySequence:
  1290. return traverseSubTypes(c, t.elementType)
  1291. of tyGenericInvocation:
  1292. let targetBody = t.genericHead
  1293. for i in 1..<t.len:
  1294. let param = t[i]
  1295. if param.kind == tyGenericParam:
  1296. if tfCovariant in param.flags:
  1297. let formalFlags = targetBody[i-1].flags
  1298. if tfCovariant notin formalFlags:
  1299. error("covariant param '" & param.sym.name.s &
  1300. "' used in a non-covariant position")
  1301. elif tfWeakCovariant in formalFlags:
  1302. param.flags.incl tfWeakCovariant
  1303. result = true
  1304. elif tfContravariant in param.flags:
  1305. let formalParam = targetBody[i-1].sym
  1306. if tfContravariant notin formalParam.typ.flags:
  1307. error("contravariant param '" & param.sym.name.s &
  1308. "' used in a non-contravariant position")
  1309. result = true
  1310. else:
  1311. subresult traverseSubTypes(c, param)
  1312. of tyAnd, tyOr, tyNot, tyStatic, tyBuiltInTypeClass, tyCompositeTypeClass:
  1313. error("non-invariant type parameters cannot be used with types such '" & $t & "'")
  1314. of tyUserTypeClass, tyUserTypeClassInst:
  1315. error("non-invariant type parameters are not supported in concepts")
  1316. of tyTuple:
  1317. for fieldType in t.kids:
  1318. subresult traverseSubTypes(c, fieldType)
  1319. of tyPtr, tyRef, tyVar, tyLent:
  1320. if t.elementType.kind == tyGenericParam: return true
  1321. return traverseSubTypes(c, t.elementType)
  1322. of tyDistinct, tyAlias, tySink, tyOwned:
  1323. return traverseSubTypes(c, t.skipModifier)
  1324. of tyGenericInst:
  1325. internalAssert c.config, false
  1326. else:
  1327. discard
  1328. discard traverseSubTypes(c, body)
  1329. proc typeSectionRightSidePass(c: PContext, n: PNode) =
  1330. for i in 0..<n.len:
  1331. var a = n[i]
  1332. if a.kind == nkCommentStmt: continue
  1333. if a.kind != nkTypeDef: illFormedAst(a, c.config)
  1334. checkSonsLen(a, 3, c.config)
  1335. let name = typeSectionTypeName(c, a[0])
  1336. var s = name.sym
  1337. if s.magic == mNone and a[2].kind == nkEmpty:
  1338. localError(c.config, a.info, errImplOfXexpected % s.name.s)
  1339. if s.magic != mNone: processMagicType(c, s)
  1340. let oldFlags = s.typ.flags
  1341. if a[1].kind != nkEmpty:
  1342. # We have a generic type declaration here. In generic types,
  1343. # symbol lookup needs to be done here.
  1344. openScope(c)
  1345. pushOwner(c, s)
  1346. if s.magic == mNone: s.typ.kind = tyGenericBody
  1347. # XXX for generic type aliases this is not correct! We need the
  1348. # underlying Id really:
  1349. #
  1350. # type
  1351. # TGObj[T] = object
  1352. # TAlias[T] = TGObj[T]
  1353. #
  1354. s.typ.n = semGenericParamList(c, a[1], s.typ)
  1355. a[1] = s.typ.n
  1356. s.typ.size = -1 # could not be computed properly
  1357. # we fill it out later. For magic generics like 'seq', it won't be filled
  1358. # so we use tyNone instead of nil to not crash for strange conversions
  1359. # like: mydata.seq
  1360. if s.typ.kind in {tyOpenArray, tyVarargs} and s.typ.len == 1:
  1361. # XXX investigate why `tySequence` cannot be added here for now.
  1362. discard
  1363. else:
  1364. rawAddSon(s.typ, newTypeS(tyNone, c))
  1365. s.ast = a
  1366. inc c.inGenericContext
  1367. var body = semTypeNode(c, a[2], s.typ)
  1368. dec c.inGenericContext
  1369. if body != nil:
  1370. body.sym = s
  1371. body.size = -1 # could not be computed properly
  1372. if body.kind == tyObject:
  1373. # add flags applied to generic type to object (nominal) type
  1374. incl(body.flags, oldFlags)
  1375. # {.inheritable, final.} is already disallowed, but
  1376. # object might have been assumed to be final
  1377. if tfInheritable in oldFlags and tfFinal in body.flags:
  1378. excl(body.flags, tfFinal)
  1379. s.typ[^1] = body
  1380. if tfCovariant in s.typ.flags:
  1381. checkCovariantParamsUsages(c, s.typ)
  1382. # XXX: This is a temporary limitation:
  1383. # The codegen currently produces various failures with
  1384. # generic imported types that have fields, but we need
  1385. # the fields specified in order to detect weak covariance.
  1386. # The proper solution is to teach the codegen how to handle
  1387. # such types, because this would offer various interesting
  1388. # possibilities such as instantiating C++ generic types with
  1389. # garbage collected Nim types.
  1390. if sfImportc in s.flags:
  1391. var body = s.typ.last
  1392. if body.kind == tyObject:
  1393. # erases all declared fields
  1394. body.n.sons = @[]
  1395. popOwner(c)
  1396. closeScope(c)
  1397. elif a[2].kind != nkEmpty:
  1398. # process the type's body:
  1399. pushOwner(c, s)
  1400. var t = semTypeNode(c, a[2], s.typ)
  1401. if s.typ == nil:
  1402. s.typ = t
  1403. elif t != s.typ and (s.typ == nil or s.typ.kind != tyAlias):
  1404. # this can happen for e.g. tcan_alias_specialised_generic:
  1405. assignType(s.typ, t)
  1406. #debug s.typ
  1407. s.ast = a
  1408. popOwner(c)
  1409. # If the right hand side expression was a macro call we replace it with
  1410. # its evaluated result here so that we don't execute it once again in the
  1411. # final pass
  1412. if a[2].kind in nkCallKinds:
  1413. incl a[2].flags, nfSem # bug #10548
  1414. if sfExportc in s.flags:
  1415. if s.typ.kind == tyAlias:
  1416. localError(c.config, name.info, "{.exportc.} not allowed for type aliases")
  1417. elif s.typ.kind == tyGenericBody:
  1418. localError(c.config, name.info, "{.exportc.} not allowed for generic types")
  1419. if tfBorrowDot in s.typ.flags:
  1420. let body = s.typ.skipTypes({tyGenericBody})
  1421. if body.kind != tyDistinct:
  1422. # flag might be copied from alias/instantiation:
  1423. let t = body.skipTypes({tyAlias, tyGenericInst})
  1424. if not (t.kind == tyDistinct and tfBorrowDot in t.flags):
  1425. excl s.typ.flags, tfBorrowDot
  1426. localError(c.config, name.info, "only a 'distinct' type can borrow `.`")
  1427. let aa = a[2]
  1428. if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
  1429. aa[0].kind == nkObjectTy:
  1430. # give anonymous object a dummy symbol:
  1431. var st = s.typ
  1432. if st.kind == tyGenericBody: st = st.typeBodyImpl
  1433. internalAssert c.config, st.kind in {tyPtr, tyRef}
  1434. internalAssert c.config, st.last.sym == nil
  1435. incl st.flags, tfRefsAnonObj
  1436. let objTy = st.last
  1437. # add flags for `ref object` etc to underlying `object`
  1438. incl(objTy.flags, oldFlags)
  1439. # {.inheritable, final.} is already disallowed, but
  1440. # object might have been assumed to be final
  1441. if tfInheritable in oldFlags and tfFinal in objTy.flags:
  1442. excl(objTy.flags, tfFinal)
  1443. let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
  1444. c.idgen, getCurrOwner(c), s.info)
  1445. obj.flags.incl sfGeneratedType
  1446. let symNode = newSymNode(obj)
  1447. obj.ast = a.shallowCopy
  1448. case a[0].kind
  1449. of nkSym: obj.ast[0] = symNode
  1450. of nkPragmaExpr:
  1451. obj.ast[0] = a[0].shallowCopy
  1452. if a[0][0].kind == nkPostfix:
  1453. obj.ast[0][0] = a[0][0].shallowCopy
  1454. obj.ast[0][0][1] = symNode
  1455. else:
  1456. obj.ast[0][0] = symNode
  1457. obj.ast[0][1] = a[0][1]
  1458. of nkPostfix:
  1459. obj.ast[0] = a[0].shallowCopy
  1460. obj.ast[0][1] = symNode
  1461. else: assert(false)
  1462. obj.ast[1] = a[1]
  1463. obj.ast[2] = a[2][0]
  1464. if sfPure in s.flags:
  1465. obj.flags.incl sfPure
  1466. obj.typ = objTy
  1467. objTy.sym = obj
  1468. for sk in c.skipTypes:
  1469. discard semTypeNode(c, sk, nil)
  1470. c.skipTypes = @[]
  1471. proc checkForMetaFields(c: PContext; n: PNode) =
  1472. proc checkMeta(c: PContext; n: PNode; t: PType) =
  1473. if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
  1474. if t.kind == tyBuiltInTypeClass and t.len == 1 and t.elementType.kind == tyProc:
  1475. localError(c.config, n.info, ("'$1' is not a concrete type; " &
  1476. "for a callback without parameters use 'proc()'") % t.typeToString)
  1477. else:
  1478. localError(c.config, n.info, errTIsNotAConcreteType % t.typeToString)
  1479. if n.isNil: return
  1480. case n.kind
  1481. of nkRecList, nkRecCase:
  1482. for s in n: checkForMetaFields(c, s)
  1483. of nkOfBranch, nkElse:
  1484. checkForMetaFields(c, n.lastSon)
  1485. of nkSym:
  1486. let t = n.sym.typ
  1487. case t.kind
  1488. of tySequence, tySet, tyArray, tyOpenArray, tyVar, tyLent, tyPtr, tyRef,
  1489. tyProc, tyGenericInvocation, tyGenericInst, tyAlias, tySink, tyOwned:
  1490. let start = ord(t.kind in {tyGenericInvocation, tyGenericInst})
  1491. for i in start..<t.len:
  1492. checkMeta(c, n, t[i])
  1493. else:
  1494. checkMeta(c, n, t)
  1495. else:
  1496. internalAssert c.config, false
  1497. proc typeSectionFinalPass(c: PContext, n: PNode) =
  1498. for i in 0..<n.len:
  1499. var a = n[i]
  1500. if a.kind == nkCommentStmt: continue
  1501. let name = typeSectionTypeName(c, a[0])
  1502. var s = name.sym
  1503. # check the style here after the pragmas have been processed:
  1504. styleCheckDef(c, s)
  1505. # compute the type's size and check for illegal recursions:
  1506. if a[1].kind == nkEmpty:
  1507. var x = a[2]
  1508. if x.kind in nkCallKinds and nfSem in x.flags:
  1509. discard "already semchecked, see line marked with bug #10548"
  1510. else:
  1511. while x.kind in {nkStmtList, nkStmtListExpr} and x.len > 0:
  1512. x = x.lastSon
  1513. # we need the 'safeSkipTypes' here because illegally recursive types
  1514. # can enter at this point, see bug #13763
  1515. if x.kind notin {nkObjectTy, nkDistinctTy, nkEnumTy, nkEmpty} and
  1516. s.typ.safeSkipTypes(abstractPtrs).kind notin {tyObject, tyEnum}:
  1517. # type aliases are hard:
  1518. var t = semTypeNode(c, x, nil)
  1519. assert t != nil
  1520. if s.typ != nil and s.typ.kind notin {tyAlias, tySink}:
  1521. if t.kind in {tyProc, tyGenericInst} and not t.isMetaType:
  1522. assignType(s.typ, t)
  1523. s.typ.itemId = t.itemId
  1524. elif t.kind in {tyObject, tyEnum, tyDistinct}:
  1525. assert s.typ != nil
  1526. assignType(s.typ, t)
  1527. s.typ.itemId = t.itemId # same id
  1528. checkConstructedType(c.config, s.info, s.typ)
  1529. if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
  1530. checkForMetaFields(c, s.typ.n)
  1531. # fix bug #5170, bug #17162, bug #15526: ensure locally scoped types get a unique name:
  1532. if s.typ.kind in {tyEnum, tyRef, tyObject} and not isTopLevel(c):
  1533. incl(s.flags, sfGenSym)
  1534. #instAllTypeBoundOp(c, n.info)
  1535. proc semAllTypeSections(c: PContext; n: PNode): PNode =
  1536. proc gatherStmts(c: PContext; n: PNode; result: PNode) {.nimcall.} =
  1537. case n.kind
  1538. of nkIncludeStmt:
  1539. for i in 0..<n.len:
  1540. var f = checkModuleName(c.config, n[i])
  1541. if f != InvalidFileIdx:
  1542. if containsOrIncl(c.includedFiles, f.int):
  1543. localError(c.config, n.info, errRecursiveDependencyX % toMsgFilename(c.config, f))
  1544. else:
  1545. let code = c.graph.includeFileCallback(c.graph, c.module, f)
  1546. gatherStmts c, code, result
  1547. excl(c.includedFiles, f.int)
  1548. of nkStmtList:
  1549. for i in 0..<n.len:
  1550. gatherStmts(c, n[i], result)
  1551. of nkTypeSection:
  1552. incl n.flags, nfSem
  1553. typeSectionLeftSidePass(c, n)
  1554. result.add n
  1555. else:
  1556. result.add n
  1557. result = newNodeI(nkStmtList, n.info)
  1558. gatherStmts(c, n, result)
  1559. template rec(name) =
  1560. for i in 0..<result.len:
  1561. if result[i].kind == nkTypeSection:
  1562. name(c, result[i])
  1563. rec typeSectionRightSidePass
  1564. rec typeSectionFinalPass
  1565. when false:
  1566. # too beautiful to delete:
  1567. template rec(name; setbit=false) =
  1568. proc `name rec`(c: PContext; n: PNode) {.nimcall.} =
  1569. if n.kind == nkTypeSection:
  1570. when setbit: incl n.flags, nfSem
  1571. name(c, n)
  1572. elif n.kind == nkStmtList:
  1573. for i in 0..<n.len:
  1574. `name rec`(c, n[i])
  1575. `name rec`(c, n)
  1576. rec typeSectionLeftSidePass, true
  1577. rec typeSectionRightSidePass
  1578. rec typeSectionFinalPass
  1579. proc semTypeSection(c: PContext, n: PNode): PNode =
  1580. ## Processes a type section. This must be done in separate passes, in order
  1581. ## to allow the type definitions in the section to reference each other
  1582. ## without regard for the order of their definitions.
  1583. if sfNoForward notin c.module.flags or nfSem notin n.flags:
  1584. inc c.inTypeContext
  1585. typeSectionLeftSidePass(c, n)
  1586. typeSectionRightSidePass(c, n)
  1587. typeSectionFinalPass(c, n)
  1588. dec c.inTypeContext
  1589. result = n
  1590. proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
  1591. s.typ = semProcTypeNode(c, n, genericParams, nil, s.kind)
  1592. proc addParams(c: PContext, n: PNode, kind: TSymKind) =
  1593. for i in 1..<n.len:
  1594. if n[i].kind == nkSym: addParamOrResult(c, n[i].sym, kind)
  1595. else: illFormedAst(n, c.config)
  1596. proc semBorrow(c: PContext, n: PNode, s: PSym) =
  1597. # search for the correct alias:
  1598. var (b, state) = searchForBorrowProc(c, c.currentScope.parent, s)
  1599. case state
  1600. of bsMatch:
  1601. # store the alias:
  1602. n[bodyPos] = newSymNode(b)
  1603. # Carry over the original symbol magic, this is necessary in order to ensure
  1604. # the semantic pass is correct
  1605. s.magic = b.magic
  1606. if b.typ != nil and b.typ.len > 0:
  1607. s.typ.n[0] = b.typ.n[0]
  1608. s.typ.flags = b.typ.flags
  1609. of bsNoDistinct:
  1610. localError(c.config, n.info, "borrow proc without distinct type parameter is meaningless")
  1611. of bsReturnNotMatch:
  1612. localError(c.config, n.info, "borrow from proc return type mismatch: '$1'" % typeToString(b.typ.returnType))
  1613. of bsGeneric:
  1614. localError(c.config, n.info, "borrow with generic parameter is not supported")
  1615. of bsNotSupported:
  1616. localError(c.config, n.info, "borrow from '$1' is not supported" % $b.name.s)
  1617. else:
  1618. localError(c.config, n.info, errNoSymbolToBorrowFromFound)
  1619. proc swapResult(n: PNode, sRes: PSym, dNode: PNode) =
  1620. ## Swap nodes that are (skResult) symbols to d(estination)Node.
  1621. for i in 0..<n.safeLen:
  1622. if n[i].kind == nkSym and n[i].sym == sRes:
  1623. n[i] = dNode
  1624. swapResult(n[i], sRes, dNode)
  1625. proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) =
  1626. template genResSym(s) =
  1627. var s = newSym(skResult, getIdent(c.cache, "result"), c.idgen,
  1628. getCurrOwner(c), n.info)
  1629. s.typ = t
  1630. incl(s.flags, sfUsed)
  1631. if owner == skMacro or t != nil:
  1632. if n.len > resultPos and n[resultPos] != nil:
  1633. if n[resultPos].sym.kind != skResult:
  1634. localError(c.config, n.info, "incorrect result proc symbol")
  1635. if n[resultPos].sym.owner != getCurrOwner(c):
  1636. # re-write result with new ownership, and re-write the proc accordingly
  1637. let sResSym = n[resultPos].sym
  1638. genResSym(s)
  1639. n[resultPos] = newSymNode(s)
  1640. swapResult(n, sResSym, n[resultPos])
  1641. c.p.resultSym = n[resultPos].sym
  1642. else:
  1643. genResSym(s)
  1644. c.p.resultSym = s
  1645. n.add newSymNode(c.p.resultSym)
  1646. addParamOrResult(c, c.p.resultSym, owner)
  1647. proc semProcAnnotation(c: PContext, prc: PNode;
  1648. validPragmas: TSpecialWords): PNode =
  1649. # Mirrored with semVarMacroPragma
  1650. result = nil
  1651. var n = prc[pragmasPos]
  1652. if n == nil or n.kind == nkEmpty: return
  1653. for i in 0..<n.len:
  1654. let it = n[i]
  1655. let key = if it.kind in nkPragmaCallKinds and it.len >= 1: it[0] else: it
  1656. trySuggestPragmas(c, key)
  1657. if isPossibleMacroPragma(c, it, key):
  1658. # we transform ``proc p {.m, rest.}`` into ``m(do: proc p {.rest.})`` and
  1659. # let the semantic checker deal with it:
  1660. var x = newNodeI(nkCall, key.info)
  1661. x.add(key)
  1662. if it.kind in nkPragmaCallKinds and it.len > 1:
  1663. # pass pragma arguments to the macro too:
  1664. for i in 1..<it.len:
  1665. x.add(it[i])
  1666. # Drop the pragma from the list, this prevents getting caught in endless
  1667. # recursion when the nkCall is semanticized
  1668. prc[pragmasPos] = copyExcept(n, i)
  1669. if prc[pragmasPos].kind != nkEmpty and prc[pragmasPos].len == 0:
  1670. prc[pragmasPos] = c.graph.emptyNode
  1671. x.add(prc)
  1672. # recursion assures that this works for multiple macro annotations too:
  1673. var r = semOverloadedCall(c, x, x, {skMacro, skTemplate}, {efNoUndeclared})
  1674. if r == nil:
  1675. # Restore the old list of pragmas since we couldn't process this
  1676. prc[pragmasPos] = n
  1677. # No matching macro was found but there's always the possibility this may
  1678. # be a .pragma. template instead
  1679. continue
  1680. doAssert r[0].kind == nkSym
  1681. let m = r[0].sym
  1682. case m.kind
  1683. of skMacro: result = semMacroExpr(c, r, r, m, {})
  1684. of skTemplate: result = semTemplateExpr(c, r, m, {})
  1685. else:
  1686. prc[pragmasPos] = n
  1687. continue
  1688. doAssert result != nil
  1689. return result
  1690. proc semInferredLambda(c: PContext, pt: TypeMapping, n: PNode): PNode =
  1691. ## used for resolving 'auto' in lambdas based on their callsite
  1692. var n = n
  1693. let original = n[namePos].sym
  1694. let s = original #copySym(original, false)
  1695. #incl(s.flags, sfFromGeneric)
  1696. #s.owner = original
  1697. n = replaceTypesInBody(c, pt, n, original)
  1698. result = n
  1699. s.ast = result
  1700. n[namePos].sym = s
  1701. n[genericParamsPos] = c.graph.emptyNode
  1702. # for LL we need to avoid wrong aliasing
  1703. let params = copyTree n.typ.n
  1704. s.typ = n.typ
  1705. for i in 1..<params.len:
  1706. if params[i].typ.kind in {tyTypeDesc, tyGenericParam,
  1707. tyFromExpr}+tyTypeClasses:
  1708. localError(c.config, params[i].info, "cannot infer type of parameter: " &
  1709. params[i].sym.name.s)
  1710. #params[i].sym.owner = s
  1711. openScope(c)
  1712. pushOwner(c, s)
  1713. addParams(c, params, skProc)
  1714. pushProcCon(c, s)
  1715. addResult(c, n, n.typ.returnType, skProc)
  1716. s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], n.typ.returnType))
  1717. trackProc(c, s, s.ast[bodyPos])
  1718. popProcCon(c)
  1719. popOwner(c)
  1720. closeScope(c)
  1721. if optOwnedRefs in c.config.globalOptions and result.typ != nil:
  1722. result.typ = makeVarType(c, result.typ, tyOwned)
  1723. # alternative variant (not quite working):
  1724. # var prc = arg[0].sym
  1725. # let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
  1726. # result = inferred.ast
  1727. # result.kind = arg.kind
  1728. proc activate(c: PContext, n: PNode) =
  1729. # XXX: This proc is part of my plan for getting rid of
  1730. # forward declarations. stay tuned.
  1731. when false:
  1732. # well for now it breaks code ...
  1733. case n.kind
  1734. of nkLambdaKinds:
  1735. discard semLambda(c, n, {})
  1736. of nkCallKinds:
  1737. for i in 1..<n.len: activate(c, n[i])
  1738. else:
  1739. discard
  1740. proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
  1741. if s.kind == skMacro:
  1742. let resultType = sysTypeFromName(c.graph, n.info, "NimNode")
  1743. addResult(c, n, resultType, s.kind)
  1744. elif s.typ.returnType != nil and not isInlineIterator(s.typ):
  1745. addResult(c, n, s.typ.returnType, s.kind)
  1746. proc canonType(c: PContext, t: PType): PType =
  1747. if t.kind == tySequence:
  1748. result = c.graph.sysTypes[tySequence]
  1749. else:
  1750. result = t
  1751. proc prevDestructor(c: PContext; prevOp: PSym; obj: PType; info: TLineInfo) =
  1752. var msg = "cannot bind another '" & prevOp.name.s & "' to: " & typeToString(obj)
  1753. if sfOverridden notin prevOp.flags:
  1754. msg.add "; previous declaration was constructed here implicitly: " & (c.config $ prevOp.info)
  1755. else:
  1756. msg.add "; previous declaration was here: " & (c.config $ prevOp.info)
  1757. localError(c.config, info, errGenerated, msg)
  1758. proc whereToBindTypeHook(c: PContext; t: PType): PType =
  1759. result = t
  1760. while true:
  1761. if result.kind in {tyGenericBody, tyGenericInst}: result = result.skipModifier
  1762. elif result.kind == tyGenericInvocation: result = result[0]
  1763. else: break
  1764. if result.kind in {tyObject, tyDistinct, tySequence, tyString}:
  1765. result = canonType(c, result)
  1766. proc bindDupHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp) =
  1767. let t = s.typ
  1768. var noError = false
  1769. let cond = t.len == 2 and t.returnType != nil
  1770. if cond:
  1771. var obj = t.firstParamType
  1772. while true:
  1773. incl(obj.flags, tfHasAsgn)
  1774. if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.skipModifier
  1775. elif obj.kind == tyGenericInvocation: obj = obj.genericHead
  1776. else: break
  1777. var res = t.returnType
  1778. while true:
  1779. if res.kind in {tyGenericBody, tyGenericInst}: res = res.skipModifier
  1780. elif res.kind == tyGenericInvocation: res = res.genericHead
  1781. else: break
  1782. if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, res):
  1783. obj = canonType(c, obj)
  1784. let ao = getAttachedOp(c.graph, obj, op)
  1785. if ao == s:
  1786. discard "forward declared destructor"
  1787. elif ao.isNil and tfCheckedForDestructor notin obj.flags:
  1788. setAttachedOp(c.graph, c.module.position, obj, op, s)
  1789. else:
  1790. prevDestructor(c, ao, obj, n.info)
  1791. noError = true
  1792. if obj.owner.getModule != s.getModule:
  1793. localError(c.config, n.info, errGenerated,
  1794. "type bound operation `" & s.name.s & "` can be defined only in the same module with its type (" & obj.typeToString() & ")")
  1795. if not noError and sfSystemModule notin s.owner.flags:
  1796. localError(c.config, n.info, errGenerated,
  1797. "signature for '=dup' must be proc[T: object](x: T): T")
  1798. incl(s.flags, sfUsed)
  1799. incl(s.flags, sfOverridden)
  1800. proc bindTypeHook(c: PContext; s: PSym; n: PNode; op: TTypeAttachedOp; suppressVarDestructorWarning = false) =
  1801. let t = s.typ
  1802. var noError = false
  1803. let cond = case op
  1804. of attachedWasMoved:
  1805. t.len == 2 and t.returnType == nil and t.firstParamType.kind == tyVar
  1806. of attachedTrace:
  1807. t.len == 3 and t.returnType == nil and t.firstParamType.kind == tyVar and t[2].kind == tyPointer
  1808. of attachedDestructor:
  1809. if c.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
  1810. t.len == 2 and t.returnType == nil
  1811. else:
  1812. t.len == 2 and t.returnType == nil and t.firstParamType.kind == tyVar
  1813. else:
  1814. t.len >= 2 and t.returnType == nil
  1815. if cond:
  1816. var obj = t.firstParamType.skipTypes({tyVar})
  1817. while true:
  1818. incl(obj.flags, tfHasAsgn)
  1819. if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.skipModifier
  1820. elif obj.kind == tyGenericInvocation: obj = obj.genericHead
  1821. else: break
  1822. if obj.kind in {tyObject, tyDistinct, tySequence, tyString}:
  1823. if (not suppressVarDestructorWarning) and op == attachedDestructor and t.firstParamType.kind == tyVar and
  1824. c.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
  1825. message(c.config, n.info, warnDeprecated, "A custom '=destroy' hook which takes a 'var T' parameter is deprecated; it should take a 'T' parameter")
  1826. obj = canonType(c, obj)
  1827. let ao = getAttachedOp(c.graph, obj, op)
  1828. if ao == s:
  1829. discard "forward declared destructor"
  1830. elif ao.isNil and tfCheckedForDestructor notin obj.flags:
  1831. setAttachedOp(c.graph, c.module.position, obj, op, s)
  1832. else:
  1833. prevDestructor(c, ao, obj, n.info)
  1834. noError = true
  1835. if obj.owner.getModule != s.getModule:
  1836. localError(c.config, n.info, errGenerated,
  1837. "type bound operation `" & s.name.s & "` can be defined only in the same module with its type (" & obj.typeToString() & ")")
  1838. if not noError and sfSystemModule notin s.owner.flags:
  1839. case op
  1840. of attachedTrace:
  1841. localError(c.config, n.info, errGenerated,
  1842. "signature for '=trace' must be proc[T: object](x: var T; env: pointer)")
  1843. of attachedDestructor:
  1844. if c.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
  1845. localError(c.config, n.info, errGenerated,
  1846. "signature for '=destroy' must be proc[T: object](x: var T) or proc[T: object](x: T)")
  1847. else:
  1848. localError(c.config, n.info, errGenerated,
  1849. "signature for '=destroy' must be proc[T: object](x: var T)")
  1850. else:
  1851. localError(c.config, n.info, errGenerated,
  1852. "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
  1853. incl(s.flags, sfUsed)
  1854. incl(s.flags, sfOverridden)
  1855. proc semOverride(c: PContext, s: PSym, n: PNode) =
  1856. let name = s.name.s.normalize
  1857. case name
  1858. of "=destroy":
  1859. bindTypeHook(c, s, n, attachedDestructor)
  1860. if s.ast != nil:
  1861. if s.ast[pragmasPos].kind == nkEmpty:
  1862. s.ast[pragmasPos] = newNodeI(nkPragma, s.info)
  1863. s.ast[pragmasPos].add newTree(nkExprColonExpr,
  1864. newIdentNode(c.cache.getIdent("raises"), s.info), newNodeI(nkBracket, s.info))
  1865. of "deepcopy", "=deepcopy":
  1866. if s.typ.len == 2 and
  1867. s.typ.firstParamType.skipTypes(abstractInst).kind in {tyRef, tyPtr} and
  1868. sameType(s.typ.firstParamType, s.typ.returnType):
  1869. # Note: we store the deepCopy in the base of the pointer to mitigate
  1870. # the problem that pointers are structural types:
  1871. var t = s.typ.firstParamType.skipTypes(abstractInst).elementType.skipTypes(abstractInst)
  1872. while true:
  1873. if t.kind == tyGenericBody: t = t.typeBodyImpl
  1874. elif t.kind == tyGenericInvocation: t = t.genericHead
  1875. else: break
  1876. if t.kind in {tyObject, tyDistinct, tyEnum, tySequence, tyString}:
  1877. if getAttachedOp(c.graph, t, attachedDeepCopy).isNil:
  1878. setAttachedOp(c.graph, c.module.position, t, attachedDeepCopy, s)
  1879. else:
  1880. localError(c.config, n.info, errGenerated,
  1881. "cannot bind another 'deepCopy' to: " & typeToString(t))
  1882. else:
  1883. localError(c.config, n.info, errGenerated,
  1884. "cannot bind 'deepCopy' to: " & typeToString(t))
  1885. if t.owner.getModule != s.getModule:
  1886. localError(c.config, n.info, errGenerated,
  1887. "type bound operation `" & name & "` can be defined only in the same module with its type (" & t.typeToString() & ")")
  1888. else:
  1889. localError(c.config, n.info, errGenerated,
  1890. "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
  1891. incl(s.flags, sfUsed)
  1892. incl(s.flags, sfOverridden)
  1893. of "=", "=copy", "=sink":
  1894. if s.magic == mAsgn: return
  1895. incl(s.flags, sfUsed)
  1896. incl(s.flags, sfOverridden)
  1897. if name == "=":
  1898. message(c.config, n.info, warnDeprecated, "Overriding `=` hook is deprecated; Override `=copy` hook instead")
  1899. let t = s.typ
  1900. if t.len == 3 and t.returnType == nil and t.firstParamType.kind == tyVar:
  1901. var obj = t.firstParamType.elementType
  1902. while true:
  1903. incl(obj.flags, tfHasAsgn)
  1904. if obj.kind == tyGenericBody: obj = obj.skipModifier
  1905. elif obj.kind == tyGenericInvocation: obj = obj.genericHead
  1906. else: break
  1907. var objB = t[2]
  1908. while true:
  1909. if objB.kind == tyGenericBody: objB = objB.skipModifier
  1910. elif objB.kind in {tyGenericInvocation, tyGenericInst}:
  1911. objB = objB.genericHead
  1912. else: break
  1913. if obj.kind in {tyObject, tyDistinct, tySequence, tyString} and sameType(obj, objB):
  1914. # attach these ops to the canonical tySequence
  1915. obj = canonType(c, obj)
  1916. #echo "ATTACHING TO ", obj.id, " ", s.name.s, " ", cast[int](obj)
  1917. let k = if name == "=" or name == "=copy": attachedAsgn else: attachedSink
  1918. let ao = getAttachedOp(c.graph, obj, k)
  1919. if ao == s:
  1920. discard "forward declared op"
  1921. elif ao.isNil and tfCheckedForDestructor notin obj.flags:
  1922. setAttachedOp(c.graph, c.module.position, obj, k, s)
  1923. else:
  1924. prevDestructor(c, ao, obj, n.info)
  1925. if obj.owner.getModule != s.getModule:
  1926. localError(c.config, n.info, errGenerated,
  1927. "type bound operation `" & name & "` can be defined only in the same module with its type (" & obj.typeToString() & ")")
  1928. return
  1929. if sfSystemModule notin s.owner.flags:
  1930. localError(c.config, n.info, errGenerated,
  1931. "signature for '" & s.name.s & "' must be proc[T: object](x: var T; y: T)")
  1932. of "=trace":
  1933. if s.magic != mTrace:
  1934. bindTypeHook(c, s, n, attachedTrace)
  1935. of "=wasmoved":
  1936. if s.magic != mWasMoved:
  1937. bindTypeHook(c, s, n, attachedWasMoved)
  1938. of "=dup":
  1939. if s.magic != mDup:
  1940. bindDupHook(c, s, n, attachedDup)
  1941. else:
  1942. if sfOverridden in s.flags:
  1943. localError(c.config, n.info, errGenerated,
  1944. "'destroy' or 'deepCopy' expected for 'override'")
  1945. proc cursorInProcAux(conf: ConfigRef; n: PNode): bool =
  1946. result = false
  1947. if inCheckpoint(n.info, conf.m.trackPos) != cpNone: return true
  1948. for i in 0..<n.safeLen:
  1949. if cursorInProcAux(conf, n[i]): return true
  1950. proc cursorInProc(conf: ConfigRef; n: PNode): bool =
  1951. if n.info.fileIndex == conf.m.trackPos.fileIndex:
  1952. result = cursorInProcAux(conf, n)
  1953. else:
  1954. result = false
  1955. proc hasObjParam(s: PSym): bool =
  1956. result = false
  1957. var t = s.typ
  1958. for col in 1..<t.len:
  1959. if skipTypes(t[col], skipPtrs).kind == tyObject:
  1960. return true
  1961. proc finishMethod(c: PContext, s: PSym) =
  1962. if hasObjParam(s):
  1963. methodDef(c.graph, c.idgen, s)
  1964. proc semCppMember(c: PContext; s: PSym; n: PNode) =
  1965. if sfImportc notin s.flags:
  1966. let isVirtual = sfVirtual in s.flags
  1967. let isCtor = sfConstructor in s.flags
  1968. let pragmaName = if isVirtual: "virtual" elif isCtor: "constructor" else: "member"
  1969. if c.config.backend == backendCpp:
  1970. if s.typ.len < 2 and not isCtor:
  1971. localError(c.config, n.info, pragmaName & " must have at least one parameter")
  1972. for son in s.typ.signature:
  1973. if son!=nil and son.isMetaType:
  1974. localError(c.config, n.info, pragmaName & " unsupported for generic routine")
  1975. var typ: PType
  1976. if isCtor:
  1977. typ = s.typ.returnType
  1978. if typ == nil or typ.kind != tyObject:
  1979. localError(c.config, n.info, "constructor must return an object")
  1980. if sfImportc in typ.sym.flags:
  1981. localError(c.config, n.info, "constructor in an imported type needs importcpp pragma")
  1982. else:
  1983. typ = s.typ.firstParamType
  1984. if typ.kind == tyPtr and not isCtor:
  1985. typ = typ.elementType
  1986. if typ.kind != tyObject:
  1987. localError(c.config, n.info, pragmaName & " must be either ptr to object or object type.")
  1988. if typ.owner.id == s.owner.id and c.module.id == s.owner.id:
  1989. c.graph.memberProcsPerType.mgetOrPut(typ.itemId, @[]).add s
  1990. else:
  1991. localError(c.config, n.info,
  1992. pragmaName & " procs must be defined in the same scope as the type they are virtual for and it must be a top level scope")
  1993. else:
  1994. localError(c.config, n.info, pragmaName & " procs are only supported in C++")
  1995. else:
  1996. var typ = s.typ.returnType
  1997. if typ != nil and typ.kind == tyObject and typ.itemId notin c.graph.initializersPerType:
  1998. var initializerCall = newTree(nkCall, newSymNode(s))
  1999. var isInitializer = n[paramsPos].len > 1
  2000. for i in 1..<n[paramsPos].len:
  2001. let p = n[paramsPos][i]
  2002. let val = p[^1]
  2003. if val.kind == nkEmpty:
  2004. isInitializer = false
  2005. break
  2006. var j = 0
  2007. while p[j].sym.kind == skParam:
  2008. initializerCall.add val
  2009. inc j
  2010. if isInitializer:
  2011. c.graph.initializersPerType[typ.itemId] = initializerCall
  2012. proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
  2013. if s.isGenericRoutine:
  2014. let tt = s.typ
  2015. var foundObj = false
  2016. # we start at 1 for now so that tparsecombnum continues to compile.
  2017. # XXX Revisit this problem later.
  2018. for col in 1..<tt.len:
  2019. let t = tt[col]
  2020. if t != nil and t.kind == tyGenericInvocation:
  2021. var x = skipTypes(t.genericHead, {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
  2022. tyGenericInvocation, tyGenericBody,
  2023. tyAlias, tySink, tyOwned})
  2024. if x.kind == tyObject and t.len-1 == n[genericParamsPos].len:
  2025. foundObj = true
  2026. addMethodToGeneric(c.graph, c.module.position, x, col, s)
  2027. message(c.config, n.info, warnDeprecated, "generic methods are deprecated")
  2028. #if not foundObj:
  2029. # message(c.config, n.info, warnDeprecated, "generic method not attachable to object type is deprecated")
  2030. else:
  2031. # why check for the body? bug #2400 has none. Checking for sfForward makes
  2032. # no sense either.
  2033. # and result[bodyPos].kind != nkEmpty:
  2034. if hasObjParam(s):
  2035. methodDef(c.graph, c.idgen, s)
  2036. else:
  2037. localError(c.config, n.info, "'method' needs a parameter that has an object type")
  2038. proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
  2039. validPragmas: TSpecialWords, flags: TExprFlags = {}): PNode =
  2040. result = semProcAnnotation(c, n, validPragmas)
  2041. if result != nil: return result
  2042. result = n
  2043. checkMinSonsLen(n, bodyPos + 1, c.config)
  2044. let
  2045. isAnon = n[namePos].kind == nkEmpty
  2046. isHighlight = c.config.ideCmd == ideHighlight
  2047. var s: PSym
  2048. case n[namePos].kind
  2049. of nkEmpty:
  2050. s = newSym(kind, c.cache.idAnon, c.idgen, c.getCurrOwner, n.info)
  2051. s.flags.incl sfUsed
  2052. n[namePos] = newSymNode(s)
  2053. of nkSym:
  2054. s = n[namePos].sym
  2055. s.owner = c.getCurrOwner
  2056. else:
  2057. # Highlighting needs to be done early so the position for
  2058. # name isn't changed (see taccent_highlight). We don't want to check if this is the
  2059. # defintion yet since we are missing some info (comments, side effects)
  2060. s = semIdentDef(c, n[namePos], kind, reportToNimsuggest=isHighlight)
  2061. n[namePos] = newSymNode(s)
  2062. when false:
  2063. # disable for now
  2064. if sfNoForward in c.module.flags and
  2065. sfSystemModule notin c.module.flags:
  2066. addInterfaceOverloadableSymAt(c, c.currentScope, s)
  2067. s.flags.incl sfForward
  2068. return
  2069. assert s.kind in skProcKinds
  2070. s.ast = n
  2071. s.options = c.config.options
  2072. #s.scope = c.currentScope
  2073. if s.kind in {skMacro, skTemplate}:
  2074. # push noalias flag at first to prevent unwanted recursive calls:
  2075. incl(s.flags, sfNoalias)
  2076. # before compiling the proc params & body, set as current the scope
  2077. # where the proc was declared
  2078. let declarationScope = c.currentScope
  2079. pushOwner(c, s)
  2080. openScope(c)
  2081. # process parameters:
  2082. # generic parameters, parameters, and also the implicit generic parameters
  2083. # within are analysed. This is often the entirety of their semantic analysis
  2084. # but later we will have to do a check for forward declarations, which can by
  2085. # way of pragmas, default params, and so on invalidate this parsing.
  2086. # Nonetheless, we need to carry out this analysis to perform the search for a
  2087. # potential forward declaration.
  2088. setGenericParamsMisc(c, n)
  2089. if n[paramsPos].kind != nkEmpty:
  2090. semParamList(c, n[paramsPos], n[genericParamsPos], s)
  2091. else:
  2092. s.typ = newProcType(c, n.info)
  2093. if n[genericParamsPos].safeLen == 0:
  2094. # if there exist no explicit or implicit generic parameters, then this is
  2095. # at most a nullary generic (generic with no type params). Regardless of
  2096. # whether it's a nullary generic or non-generic, we restore the original.
  2097. # In the case of `nkEmpty` it's non-generic and an empty `nkGeneircParams`
  2098. # is a nullary generic.
  2099. #
  2100. # Remarks about nullary generics vs non-generics:
  2101. # The difference between a non-generic and nullary generic is minor in
  2102. # most cases but there are subtle and significant differences as well.
  2103. # Due to instantiation that generic procs go through, a static echo in the
  2104. # body of a nullary generic will not be executed immediately, as it's
  2105. # instantiated and not immediately evaluated.
  2106. n[genericParamsPos] = n[miscPos][1]
  2107. n[miscPos] = c.graph.emptyNode
  2108. if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
  2109. if n[patternPos].kind != nkEmpty:
  2110. n[patternPos] = semPattern(c, n[patternPos], s)
  2111. if s.kind == skIterator:
  2112. s.typ.flags.incl(tfIterator)
  2113. elif s.kind == skFunc:
  2114. incl(s.flags, sfNoSideEffect)
  2115. incl(s.typ.flags, tfNoSideEffect)
  2116. var (proto, comesFromShadowScope) =
  2117. if isAnon: (nil, false)
  2118. else: searchForProc(c, declarationScope, s)
  2119. if proto == nil and sfForward in s.flags and n[bodyPos].kind != nkEmpty:
  2120. ## In cases such as a macro generating a proc with a gensymmed name we
  2121. ## know `searchForProc` will not find it and sfForward will be set. In
  2122. ## such scenarios the sym is shared between forward declaration and we
  2123. ## can treat the `s` as the proto.
  2124. ## To differentiate between that happening and a macro just returning a
  2125. ## forward declaration that has been typed before we check if the body
  2126. ## is not empty. This has the sideeffect of allowing multiple forward
  2127. ## declarations if they share the same sym.
  2128. ## See the "doubly-typed forward decls" case in tmacros_issues.nim
  2129. proto = s
  2130. let hasProto = proto != nil
  2131. # set the default calling conventions
  2132. case s.kind
  2133. of skIterator:
  2134. if s.typ.callConv != ccClosure:
  2135. s.typ.callConv = if isAnon: ccClosure else: ccInline
  2136. of skMacro, skTemplate:
  2137. # we don't bother setting calling conventions for macros and templates
  2138. discard
  2139. else:
  2140. # NB: procs with a forward decl have theirs determined by the forward decl
  2141. if not hasProto:
  2142. # in this case we're either a forward declaration or we're an impl without
  2143. # a forward decl. We set the calling convention or will be set during
  2144. # pragma analysis further down.
  2145. s.typ.callConv = lastOptionEntry(c).defaultCC
  2146. if not hasProto and sfGenSym notin s.flags: #and not isAnon:
  2147. if s.kind in OverloadableSyms:
  2148. addInterfaceOverloadableSymAt(c, declarationScope, s)
  2149. else:
  2150. addInterfaceDeclAt(c, declarationScope, s)
  2151. pragmaCallable(c, s, n, validPragmas)
  2152. if not hasProto:
  2153. implicitPragmas(c, s, n.info, validPragmas)
  2154. if n[pragmasPos].kind != nkEmpty and sfBorrow notin s.flags:
  2155. setEffectsForProcType(c.graph, s.typ, n[pragmasPos], s)
  2156. s.typ.flags.incl tfEffectSystemWorkaround
  2157. # To ease macro generation that produce forwarded .async procs we now
  2158. # allow a bit redundancy in the pragma declarations. The rule is
  2159. # a prototype's pragma list must be a superset of the current pragma
  2160. # list.
  2161. # XXX This needs more checks eventually, for example that external
  2162. # linking names do agree:
  2163. if hasProto and (
  2164. # calling convention mismatch
  2165. tfExplicitCallConv in s.typ.flags and proto.typ.callConv != s.typ.callConv or
  2166. # implementation has additional pragmas
  2167. proto.typ.flags < s.typ.flags):
  2168. localError(c.config, n[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
  2169. ("'" & proto.name.s & "' from " & c.config$proto.info &
  2170. " '" & s.name.s & "' from " & c.config$s.info))
  2171. styleCheckDef(c, s)
  2172. if hasProto:
  2173. onDefResolveForward(n[namePos].info, proto)
  2174. else:
  2175. onDef(n[namePos].info, s)
  2176. if hasProto:
  2177. if sfForward notin proto.flags and proto.magic == mNone:
  2178. wrongRedefinition(c, n.info, proto.name.s, proto.info)
  2179. if not comesFromShadowScope:
  2180. excl(proto.flags, sfForward)
  2181. incl(proto.flags, sfWasForwarded)
  2182. suggestSym(c.graph, s.info, proto, c.graph.usageSym)
  2183. closeScope(c) # close scope with wrong parameter symbols
  2184. openScope(c) # open scope for old (correct) parameter symbols
  2185. if proto.ast[genericParamsPos].isGenericParams:
  2186. addGenericParamListToScope(c, proto.ast[genericParamsPos])
  2187. addParams(c, proto.typ.n, proto.kind)
  2188. proto.info = s.info # more accurate line information
  2189. proto.options = s.options
  2190. s = proto
  2191. n[genericParamsPos] = proto.ast[genericParamsPos]
  2192. n[paramsPos] = proto.ast[paramsPos]
  2193. n[pragmasPos] = proto.ast[pragmasPos]
  2194. if n[namePos].kind != nkSym: internalError(c.config, n.info, "semProcAux")
  2195. n[namePos].sym = proto
  2196. if importantComments(c.config) and proto.ast.comment.len > 0:
  2197. n.comment = proto.ast.comment
  2198. proto.ast = n # needed for code generation
  2199. popOwner(c)
  2200. pushOwner(c, s)
  2201. if not isAnon:
  2202. if sfOverridden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
  2203. elif s.name.s[0] in {'.', '('}:
  2204. if s.name.s in [".", ".()", ".="] and {Feature.destructor, dotOperators} * c.features == {}:
  2205. localError(c.config, n.info, "the overloaded " & s.name.s &
  2206. " operator has to be enabled with {.experimental: \"dotOperators\".}")
  2207. elif s.name.s == "()" and callOperator notin c.features:
  2208. localError(c.config, n.info, "the overloaded " & s.name.s &
  2209. " operator has to be enabled with {.experimental: \"callOperator\".}")
  2210. if sfBorrow in s.flags and c.config.cmd notin cmdDocLike:
  2211. result[bodyPos] = c.graph.emptyNode
  2212. if sfCppMember * s.flags != {}:
  2213. semCppMember(c, s, n)
  2214. if n[bodyPos].kind != nkEmpty and sfError notin s.flags:
  2215. # for DLL generation we allow sfImportc to have a body, for use in VM
  2216. if c.config.ideCmd in {ideSug, ideCon} and s.kind notin {skMacro, skTemplate} and not
  2217. cursorInProc(c.config, n[bodyPos]):
  2218. # speed up nimsuggest
  2219. if s.kind == skMethod: semMethodPrototype(c, s, n)
  2220. elif isAnon:
  2221. let gp = n[genericParamsPos]
  2222. if gp.kind == nkEmpty or (gp.len == 1 and tfRetType in gp[0].typ.flags):
  2223. # absolutely no generics (empty) or a single generic return type are
  2224. # allowed, everything else, including a nullary generic is an error.
  2225. pushProcCon(c, s)
  2226. addResult(c, n, s.typ.returnType, skProc)
  2227. s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], s.typ.returnType))
  2228. trackProc(c, s, s.ast[bodyPos])
  2229. popProcCon(c)
  2230. elif efOperand notin flags:
  2231. localError(c.config, n.info, errGenericLambdaNotAllowed)
  2232. else:
  2233. pushProcCon(c, s)
  2234. if n[genericParamsPos].kind == nkEmpty or s.kind in {skMacro, skTemplate}:
  2235. # Macros and Templates can have generic parameters, but they are only
  2236. # used for overload resolution (there is no instantiation of the symbol)
  2237. if s.kind notin {skMacro, skTemplate} and s.magic == mNone: paramsTypeCheck(c, s.typ)
  2238. maybeAddResult(c, s, n)
  2239. let resultType =
  2240. if s.kind == skMacro:
  2241. sysTypeFromName(c.graph, n.info, "NimNode")
  2242. elif not isInlineIterator(s.typ):
  2243. s.typ.returnType
  2244. else:
  2245. nil
  2246. # semantic checking also needed with importc in case used in VM
  2247. s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos], resultType))
  2248. # unfortunately we cannot skip this step when in 'system.compiles'
  2249. # context as it may even be evaluated in 'system.compiles':
  2250. trackProc(c, s, s.ast[bodyPos])
  2251. else:
  2252. if (s.typ.returnType != nil and s.kind != skIterator):
  2253. addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), c.idgen, s, n.info))
  2254. openScope(c)
  2255. n[bodyPos] = semGenericStmt(c, n[bodyPos])
  2256. closeScope(c)
  2257. if s.magic == mNone:
  2258. fixupInstantiatedSymbols(c, s)
  2259. if s.kind == skMethod: semMethodPrototype(c, s, n)
  2260. popProcCon(c)
  2261. else:
  2262. if s.kind == skMethod: semMethodPrototype(c, s, n)
  2263. if hasProto: localError(c.config, n.info, errImplOfXexpected % proto.name.s)
  2264. if {sfImportc, sfBorrow, sfError} * s.flags == {} and s.magic == mNone:
  2265. # this is a forward declaration and we're building the prototype
  2266. if s.kind in {skProc, skFunc} and s.typ.returnType != nil and s.typ.returnType.kind == tyAnything:
  2267. localError(c.config, n[paramsPos][0].info, "return type 'auto' cannot be used in forward declarations")
  2268. incl(s.flags, sfForward)
  2269. incl(s.flags, sfWasForwarded)
  2270. elif sfBorrow in s.flags: semBorrow(c, n, s)
  2271. sideEffectsCheck(c, s)
  2272. closeScope(c) # close scope for parameters
  2273. # c.currentScope = oldScope
  2274. popOwner(c)
  2275. if n[patternPos].kind != nkEmpty:
  2276. c.patterns.add(s)
  2277. if isAnon:
  2278. n.transitionSonsKind(nkLambda)
  2279. result.typ = s.typ
  2280. if optOwnedRefs in c.config.globalOptions:
  2281. result.typ = makeVarType(c, result.typ, tyOwned)
  2282. elif isTopLevel(c) and s.kind != skIterator and s.typ.callConv == ccClosure:
  2283. localError(c.config, s.info, "'.closure' calling convention for top level routines is invalid")
  2284. # Prevent double highlights. We already highlighted before.
  2285. # When not highlighting we still need to allow for suggestions though
  2286. if not isHighlight:
  2287. suggestSym(c.graph, s.info, s, c.graph.usageSym)
  2288. proc determineType(c: PContext, s: PSym) =
  2289. if s.typ != nil: return
  2290. #if s.magic != mNone: return
  2291. #if s.ast.isNil: return
  2292. discard semProcAux(c, s.ast, s.kind, {})
  2293. proc semIterator(c: PContext, n: PNode): PNode =
  2294. # gensym'ed iterator?
  2295. if n[namePos].kind == nkSym:
  2296. # gensym'ed iterators might need to become closure iterators:
  2297. n[namePos].sym.owner = getCurrOwner(c)
  2298. n[namePos].sym.transitionRoutineSymKind(skIterator)
  2299. result = semProcAux(c, n, skIterator, iteratorPragmas)
  2300. # bug #7093: if after a macro transformation we don't have an
  2301. # nkIteratorDef aynmore, return. The iterator then might have been
  2302. # sem'checked already. (Or not, if the macro skips it.)
  2303. if result.kind != n.kind: return
  2304. var s = result[namePos].sym
  2305. var t = s.typ
  2306. if t.returnType == nil and s.typ.callConv != ccClosure:
  2307. localError(c.config, n.info, "iterator needs a return type")
  2308. # iterators are either 'inline' or 'closure'; for backwards compatibility,
  2309. # we require first class iterators to be marked with 'closure' explicitly
  2310. # -- at least for 0.9.2.
  2311. if s.typ.callConv == ccClosure:
  2312. incl(s.typ.flags, tfCapturesEnv)
  2313. else:
  2314. s.typ.callConv = ccInline
  2315. if n[bodyPos].kind == nkEmpty and s.magic == mNone and c.inConceptDecl == 0:
  2316. localError(c.config, n.info, errImplOfXexpected % s.name.s)
  2317. if optOwnedRefs in c.config.globalOptions and result.typ != nil:
  2318. result.typ = makeVarType(c, result.typ, tyOwned)
  2319. result.typ.callConv = ccClosure
  2320. proc semProc(c: PContext, n: PNode): PNode =
  2321. result = semProcAux(c, n, skProc, procPragmas)
  2322. proc semFunc(c: PContext, n: PNode): PNode =
  2323. let validPragmas = if n[namePos].kind != nkEmpty: procPragmas
  2324. else: lambdaPragmas
  2325. result = semProcAux(c, n, skFunc, validPragmas)
  2326. proc semMethod(c: PContext, n: PNode): PNode =
  2327. if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "method")
  2328. result = semProcAux(c, n, skMethod, methodPragmas)
  2329. # macros can transform converters to nothing:
  2330. if namePos >= result.safeLen: return result
  2331. # bug #7093: if after a macro transformation we don't have an
  2332. # nkIteratorDef aynmore, return. The iterator then might have been
  2333. # sem'checked already. (Or not, if the macro skips it.)
  2334. if result.kind != nkMethodDef: return
  2335. var s = result[namePos].sym
  2336. # we need to fix the 'auto' return type for the dispatcher here (see tautonotgeneric
  2337. # test case):
  2338. let disp = getDispatcher(s)
  2339. # auto return type?
  2340. if disp != nil and disp.typ.returnType != nil and disp.typ.returnType.kind == tyUntyped:
  2341. let ret = s.typ.returnType
  2342. disp.typ.setReturnType ret
  2343. if disp.ast[resultPos].kind == nkSym:
  2344. if isEmptyType(ret): disp.ast[resultPos] = c.graph.emptyNode
  2345. else: disp.ast[resultPos].sym.typ = ret
  2346. proc semConverterDef(c: PContext, n: PNode): PNode =
  2347. if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "converter")
  2348. result = semProcAux(c, n, skConverter, converterPragmas)
  2349. # macros can transform converters to nothing:
  2350. if namePos >= result.safeLen: return result
  2351. # bug #7093: if after a macro transformation we don't have an
  2352. # nkIteratorDef aynmore, return. The iterator then might have been
  2353. # sem'checked already. (Or not, if the macro skips it.)
  2354. if result.kind != nkConverterDef: return
  2355. var s = result[namePos].sym
  2356. var t = s.typ
  2357. if t.returnType == nil: localError(c.config, n.info, errXNeedsReturnType % "converter")
  2358. if t.len != 2: localError(c.config, n.info, "a converter takes exactly one argument")
  2359. addConverterDef(c, LazySym(sym: s))
  2360. proc semMacroDef(c: PContext, n: PNode): PNode =
  2361. result = semProcAux(c, n, skMacro, macroPragmas)
  2362. # macros can transform macros to nothing:
  2363. if namePos >= result.safeLen: return result
  2364. # bug #7093: if after a macro transformation we don't have an
  2365. # nkIteratorDef aynmore, return. The iterator then might have been
  2366. # sem'checked already. (Or not, if the macro skips it.)
  2367. if result.kind != nkMacroDef: return
  2368. var s = result[namePos].sym
  2369. var t = s.typ
  2370. var allUntyped = true
  2371. var nullary = true
  2372. for i in 1..<t.n.len:
  2373. let param = t.n[i].sym
  2374. if param.typ.kind != tyUntyped: allUntyped = false
  2375. # no default value, parameters required in call
  2376. if param.ast == nil: nullary = false
  2377. if allUntyped: incl(s.flags, sfAllUntyped)
  2378. if nullary and n[genericParamsPos].kind == nkEmpty:
  2379. # macro can be called with alias syntax, remove pushed noalias flag
  2380. excl(s.flags, sfNoalias)
  2381. if n[bodyPos].kind == nkEmpty:
  2382. localError(c.config, n.info, errImplOfXexpected % s.name.s)
  2383. proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
  2384. var f = checkModuleName(c.config, it)
  2385. if f != InvalidFileIdx:
  2386. addIncludeFileDep(c, f)
  2387. onProcessing(c.graph, f, "include", c.module)
  2388. if containsOrIncl(c.includedFiles, f.int):
  2389. localError(c.config, n.info, errRecursiveDependencyX % toMsgFilename(c.config, f))
  2390. else:
  2391. includeStmtResult.add semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {})
  2392. excl(c.includedFiles, f.int)
  2393. proc evalInclude(c: PContext, n: PNode): PNode =
  2394. result = newNodeI(nkStmtList, n.info)
  2395. result.add n
  2396. for i in 0..<n.len:
  2397. var imp: PNode
  2398. let it = n[i]
  2399. if it.kind == nkInfix and it.len == 3 and it[0].ident.s != "/":
  2400. localError(c.config, it.info, "Cannot use '" & it[0].ident.s & "' in 'include'.")
  2401. if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
  2402. let sep = it[0]
  2403. let dir = it[1]
  2404. imp = newNodeI(nkInfix, it.info)
  2405. imp.add sep
  2406. imp.add dir
  2407. imp.add sep # dummy entry, replaced in the loop
  2408. for x in it[2]:
  2409. imp[2] = x
  2410. incMod(c, n, imp, result)
  2411. else:
  2412. incMod(c, n, it, result)
  2413. proc recursiveSetFlag(n: PNode, flag: TNodeFlag) =
  2414. if n != nil:
  2415. for i in 0..<n.safeLen: recursiveSetFlag(n[i], flag)
  2416. incl(n.flags, flag)
  2417. proc semPragmaBlock(c: PContext, n: PNode; expectedType: PType = nil): PNode =
  2418. checkSonsLen(n, 2, c.config)
  2419. let pragmaList = n[0]
  2420. pragma(c, nil, pragmaList, exprPragmas, isStatement = true)
  2421. var inUncheckedAssignSection = 0
  2422. for p in pragmaList:
  2423. if whichPragma(p) == wCast:
  2424. case whichPragma(p[1])
  2425. of wGcSafe, wNoSideEffect, wTags, wForbids, wRaises:
  2426. discard "handled in sempass2"
  2427. of wUncheckedAssign:
  2428. inUncheckedAssignSection = 1
  2429. else:
  2430. localError(c.config, p.info, "invalid pragma block: " & $p)
  2431. inc c.inUncheckedAssignSection, inUncheckedAssignSection
  2432. n[1] = semExpr(c, n[1], expectedType = expectedType)
  2433. dec c.inUncheckedAssignSection, inUncheckedAssignSection
  2434. result = n
  2435. result.typ = n[1].typ
  2436. for i in 0..<pragmaList.len:
  2437. case whichPragma(pragmaList[i])
  2438. of wLine: setInfoRecursive(result, pragmaList[i].info)
  2439. of wNoRewrite: recursiveSetFlag(result, nfNoRewrite)
  2440. else: discard
  2441. proc semStaticStmt(c: PContext, n: PNode): PNode =
  2442. #echo "semStaticStmt"
  2443. #writeStackTrace()
  2444. inc c.inStaticContext
  2445. openScope(c)
  2446. let a = semStmt(c, n[0], {})
  2447. closeScope(c)
  2448. dec c.inStaticContext
  2449. n[0] = a
  2450. evalStaticStmt(c.module, c.idgen, c.graph, a, c.p.owner)
  2451. when false:
  2452. # for incremental replays, keep the AST as required for replays:
  2453. result = n
  2454. else:
  2455. result = newNodeI(nkDiscardStmt, n.info, 1)
  2456. result[0] = c.graph.emptyNode
  2457. proc usesResult(n: PNode): bool =
  2458. # nkStmtList(expr) properly propagates the void context,
  2459. # so we don't need to process that all over again:
  2460. if n.kind notin {nkStmtList, nkStmtListExpr,
  2461. nkMacroDef, nkTemplateDef} + procDefs:
  2462. if isAtom(n):
  2463. result = n.kind == nkSym and n.sym.kind == skResult
  2464. elif n.kind == nkReturnStmt:
  2465. result = true
  2466. else:
  2467. result = false
  2468. for c in n:
  2469. if usesResult(c): return true
  2470. else:
  2471. result = false
  2472. proc inferConceptStaticParam(c: PContext, inferred, n: PNode) =
  2473. var typ = inferred.typ
  2474. let res = semConstExpr(c, n)
  2475. if not sameType(res.typ, typ.base):
  2476. localError(c.config, n.info,
  2477. "cannot infer the concept parameter '%s', due to a type mismatch. " &
  2478. "attempt to equate '%s' and '%s'." % [inferred.renderTree, $res.typ, $typ.base])
  2479. typ.n = res
  2480. proc semStmtList(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType = nil): PNode =
  2481. result = n
  2482. result.transitionSonsKind(nkStmtList)
  2483. var voidContext = false
  2484. var last = n.len-1
  2485. # by not allowing for nkCommentStmt etc. we ensure nkStmtListExpr actually
  2486. # really *ends* in the expression that produces the type: The compiler now
  2487. # relies on this fact and it's too much effort to change that. And arguably
  2488. # 'R(); #comment' shouldn't produce R's type anyway.
  2489. #while last > 0 and n[last].kind in {nkPragma, nkCommentStmt,
  2490. # nkNilLit, nkEmpty}:
  2491. # dec last
  2492. for i in 0..<n.len:
  2493. var x = semExpr(c, n[i], flags, if i == n.len - 1: expectedType else: nil)
  2494. n[i] = x
  2495. if c.matchedConcept != nil and x.typ != nil and
  2496. (nfFromTemplate notin n.flags or i != last):
  2497. case x.typ.kind
  2498. of tyBool:
  2499. if x.kind == nkInfix and
  2500. x[0].kind == nkSym and
  2501. x[0].sym.name.s == "==":
  2502. if x[1].typ.isUnresolvedStatic:
  2503. inferConceptStaticParam(c, x[1], x[2])
  2504. continue
  2505. elif x[2].typ.isUnresolvedStatic:
  2506. inferConceptStaticParam(c, x[2], x[1])
  2507. continue
  2508. let verdict = semConstExpr(c, n[i])
  2509. if verdict == nil or verdict.kind != nkIntLit or verdict.intVal == 0:
  2510. localError(c.config, result.info, "concept predicate failed")
  2511. of tyUnknown: continue
  2512. else: discard
  2513. if n[i].typ == c.enforceVoidContext: #or usesResult(n[i]):
  2514. voidContext = true
  2515. n.typ = c.enforceVoidContext
  2516. if i == last and (n.len == 1 or ({efWantValue, efInTypeof} * flags != {})):
  2517. n.typ = n[i].typ
  2518. if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
  2519. elif i != last or voidContext:
  2520. discardCheck(c, n[i], flags)
  2521. else:
  2522. n.typ = n[i].typ
  2523. if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
  2524. var m = n[i]
  2525. while m.kind in {nkStmtListExpr, nkStmtList} and m.len > 0: # from templates
  2526. m = m.lastSon
  2527. if endsInNoReturn(m):
  2528. for j in i + 1..<n.len:
  2529. case n[j].kind
  2530. of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkState: discard
  2531. else: message(c.config, n[j].info, warnUnreachableCode)
  2532. else: discard
  2533. if result.len == 1 and
  2534. # concept bodies should be preserved as a stmt list:
  2535. c.matchedConcept == nil and
  2536. # also, don't make life complicated for macros.
  2537. # they will always expect a proper stmtlist:
  2538. nfBlockArg notin n.flags and
  2539. result[0].kind != nkDefer:
  2540. result = result[0]
  2541. proc semStmt(c: PContext, n: PNode; flags: TExprFlags): PNode =
  2542. if efInTypeof notin flags:
  2543. result = semExprNoType(c, n)
  2544. else:
  2545. result = semExpr(c, n, flags)