semgnrc.nim 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This implements the first pass over the generic body; it resolves some
  10. # symbols. Thus for generics there is a two-phase symbol lookup just like
  11. # in C++.
  12. # A problem is that it cannot be detected if the symbol is introduced
  13. # as in ``var x = ...`` or used because macros/templates can hide this!
  14. # So we have to eval templates/macros right here so that symbol
  15. # lookup can be accurate.
  16. # included from sem.nim
  17. proc getIdentNode(n: PNode): PNode =
  18. case n.kind
  19. of nkPostfix: result = getIdentNode(n.sons[1])
  20. of nkPragmaExpr: result = getIdentNode(n.sons[0])
  21. of nkIdent, nkAccQuoted, nkSym: result = n
  22. else:
  23. illFormedAst(n)
  24. result = n
  25. type
  26. GenericCtx = object
  27. toMixin: IntSet
  28. cursorInBody: bool # only for nimsuggest
  29. bracketExpr: PNode
  30. type
  31. TSemGenericFlag = enum
  32. withinBind, withinTypeDesc, withinMixin, withinConcept
  33. TSemGenericFlags = set[TSemGenericFlag]
  34. proc semGenericStmt(c: PContext, n: PNode,
  35. flags: TSemGenericFlags, ctx: var GenericCtx): PNode
  36. proc semGenericStmtScope(c: PContext, n: PNode,
  37. flags: TSemGenericFlags,
  38. ctx: var GenericCtx): PNode =
  39. openScope(c)
  40. result = semGenericStmt(c, n, flags, ctx)
  41. closeScope(c)
  42. template macroToExpand(s): untyped =
  43. s.kind in {skMacro, skTemplate} and (s.typ.len == 1 or sfAllUntyped in s.flags)
  44. template macroToExpandSym(s): untyped =
  45. s.kind in {skMacro, skTemplate} and (s.typ.len == 1) and not fromDotExpr
  46. proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
  47. ctx: var GenericCtx; fromDotExpr=false): PNode =
  48. semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
  49. incl(s.flags, sfUsed)
  50. case s.kind
  51. of skUnknown:
  52. # Introduced in this pass! Leave it as an identifier.
  53. result = n
  54. of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
  55. result = symChoice(c, n, s, scOpen)
  56. of skTemplate:
  57. if macroToExpandSym(s):
  58. styleCheckUse(n.info, s)
  59. result = semTemplateExpr(c, n, s, {efNoSemCheck})
  60. result = semGenericStmt(c, result, {}, ctx)
  61. else:
  62. result = symChoice(c, n, s, scOpen)
  63. of skMacro:
  64. if macroToExpandSym(s):
  65. styleCheckUse(n.info, s)
  66. result = semMacroExpr(c, n, n, s, {efNoSemCheck})
  67. result = semGenericStmt(c, result, {}, ctx)
  68. else:
  69. result = symChoice(c, n, s, scOpen)
  70. of skGenericParam:
  71. if s.typ != nil and s.typ.kind == tyStatic:
  72. if s.typ.n != nil:
  73. result = s.typ.n
  74. else:
  75. result = n
  76. else:
  77. result = newSymNodeTypeDesc(s, n.info)
  78. styleCheckUse(n.info, s)
  79. of skParam:
  80. result = n
  81. styleCheckUse(n.info, s)
  82. of skType:
  83. if (s.typ != nil) and
  84. (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
  85. result = newSymNodeTypeDesc(s, n.info)
  86. else:
  87. result = n
  88. styleCheckUse(n.info, s)
  89. else:
  90. result = newSymNode(s, n.info)
  91. styleCheckUse(n.info, s)
  92. proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
  93. ctx: var GenericCtx): PNode =
  94. result = n
  95. let ident = considerQuotedIdent(n)
  96. var s = searchInScopes(c, ident).skipAlias(n)
  97. if s == nil:
  98. s = strTableGet(c.pureEnumFields, ident)
  99. if s != nil and contains(c.ambiguousSymbols, s.id):
  100. s = nil
  101. if s == nil:
  102. if ident.id notin ctx.toMixin and withinMixin notin flags:
  103. errorUndeclaredIdentifier(c, n.info, ident.s)
  104. else:
  105. if withinBind in flags:
  106. result = symChoice(c, n, s, scClosed)
  107. elif s.name.id in ctx.toMixin:
  108. result = symChoice(c, n, s, scForceOpen)
  109. else:
  110. result = semGenericStmtSymbol(c, n, s, ctx)
  111. # else: leave as nkIdent
  112. proc newDot(n, b: PNode): PNode =
  113. result = newNodeI(nkDotExpr, n.info)
  114. result.add(n.sons[0])
  115. result.add(b)
  116. proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
  117. ctx: var GenericCtx; isMacro: var bool): PNode =
  118. assert n.kind == nkDotExpr
  119. semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
  120. let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule}
  121. var s = qualifiedLookUp(c, n, luf)
  122. if s != nil:
  123. result = semGenericStmtSymbol(c, n, s, ctx)
  124. else:
  125. n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
  126. result = n
  127. let n = n[1]
  128. let ident = considerQuotedIdent(n)
  129. var s = searchInScopes(c, ident).skipAlias(n)
  130. if s != nil and s.kind in routineKinds:
  131. isMacro = s.kind in {skTemplate, skMacro}
  132. if withinBind in flags:
  133. result = newDot(result, symChoice(c, n, s, scClosed))
  134. elif s.name.id in ctx.toMixin:
  135. result = newDot(result, symChoice(c, n, s, scForceOpen))
  136. else:
  137. let syms = semGenericStmtSymbol(c, n, s, ctx, fromDotExpr=true)
  138. if syms.kind == nkSym:
  139. let choice = symChoice(c, n, s, scForceOpen)
  140. choice.kind = nkClosedSymChoice
  141. result = newDot(result, choice)
  142. else:
  143. result = newDot(result, syms)
  144. proc addTempDecl(c: PContext; n: PNode; kind: TSymKind) =
  145. let s = newSymS(skUnknown, getIdentNode(n), c)
  146. addPrelimDecl(c, s)
  147. styleCheckDef(n.info, s, kind)
  148. proc semGenericStmt(c: PContext, n: PNode,
  149. flags: TSemGenericFlags, ctx: var GenericCtx): PNode =
  150. result = n
  151. when defined(nimsuggest):
  152. if withinTypeDesc in flags: inc c.inTypeContext
  153. #if gCmd == cmdIdeTools: suggestStmt(c, n)
  154. semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
  155. case n.kind
  156. of nkIdent, nkAccQuoted:
  157. result = lookup(c, n, flags, ctx)
  158. of nkDotExpr:
  159. #let luf = if withinMixin notin flags: {checkUndeclared} else: {}
  160. #var s = qualifiedLookUp(c, n, luf)
  161. #if s != nil: result = semGenericStmtSymbol(c, n, s)
  162. # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
  163. var dummy: bool
  164. result = fuzzyLookup(c, n, flags, ctx, dummy)
  165. of nkSym:
  166. let a = n.sym
  167. let b = getGenSym(c, a)
  168. if b != a: n.sym = b
  169. of nkEmpty, succ(nkSym)..nkNilLit:
  170. # see tests/compile/tgensymgeneric.nim:
  171. # We need to open the gensym'ed symbol again so that the instantiation
  172. # creates a fresh copy; but this is wrong the very first reason for gensym
  173. # is that scope rules cannot be used! So simply removing 'sfGenSym' does
  174. # not work. Copying the symbol does not work either because we're already
  175. # the owner of the symbol! What we need to do is to copy the symbol
  176. # in the generic instantiation process...
  177. discard
  178. of nkBind:
  179. result = semGenericStmt(c, n.sons[0], flags+{withinBind}, ctx)
  180. of nkMixinStmt:
  181. result = semMixinStmt(c, n, ctx.toMixin)
  182. of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit:
  183. # check if it is an expression macro:
  184. checkMinSonsLen(n, 1)
  185. let fn = n.sons[0]
  186. var s = qualifiedLookUp(c, fn, {})
  187. if s == nil and
  188. {withinMixin, withinConcept}*flags == {} and
  189. fn.kind in {nkIdent, nkAccQuoted} and
  190. considerQuotedIdent(fn).id notin ctx.toMixin:
  191. errorUndeclaredIdentifier(c, n.info, fn.renderTree)
  192. var first = ord(withinConcept in flags)
  193. var mixinContext = false
  194. if s != nil:
  195. incl(s.flags, sfUsed)
  196. mixinContext = s.magic in {mDefined, mDefinedInScope, mCompiles}
  197. let sc = symChoice(c, fn, s,
  198. if s.name.id in ctx.toMixin: scForceOpen else: scOpen)
  199. case s.kind
  200. of skMacro:
  201. if macroToExpand(s) and sc.safeLen <= 1:
  202. styleCheckUse(fn.info, s)
  203. result = semMacroExpr(c, n, n, s, {efNoSemCheck})
  204. result = semGenericStmt(c, result, flags, ctx)
  205. else:
  206. n.sons[0] = sc
  207. result = n
  208. mixinContext = true
  209. of skTemplate:
  210. if macroToExpand(s) and sc.safeLen <= 1:
  211. styleCheckUse(fn.info, s)
  212. result = semTemplateExpr(c, n, s, {efNoSemCheck})
  213. result = semGenericStmt(c, result, flags, ctx)
  214. else:
  215. n.sons[0] = sc
  216. result = n
  217. # BUGFIX: we must not return here, we need to do first phase of
  218. # symbol lookup. Also since templates and macros can do scope injections
  219. # we need to put the ``c`` in ``t(c)`` in a mixin context to prevent
  220. # the famous "undeclared identifier: it" bug:
  221. mixinContext = true
  222. of skUnknown, skParam:
  223. # Leave it as an identifier.
  224. discard
  225. of skProc, skFunc, skMethod, skIterator, skConverter, skModule:
  226. result.sons[0] = sc
  227. # do not check of 's.magic==mRoof' here because it might be some
  228. # other '^' but after overload resolution the proper one:
  229. if ctx.bracketExpr != nil and n.len == 2 and s.name.s == "^":
  230. result.add ctx.bracketExpr
  231. first = 1
  232. of skGenericParam:
  233. result.sons[0] = newSymNodeTypeDesc(s, fn.info)
  234. styleCheckUse(fn.info, s)
  235. first = 1
  236. of skType:
  237. # bad hack for generics:
  238. if (s.typ != nil) and (s.typ.kind != tyGenericParam):
  239. result.sons[0] = newSymNodeTypeDesc(s, fn.info)
  240. styleCheckUse(fn.info, s)
  241. first = 1
  242. else:
  243. result.sons[0] = newSymNode(s, fn.info)
  244. styleCheckUse(fn.info, s)
  245. first = 1
  246. elif fn.kind == nkDotExpr:
  247. result.sons[0] = fuzzyLookup(c, fn, flags, ctx, mixinContext)
  248. first = 1
  249. # Consider 'when declared(globalsSlot): ThreadVarSetValue(globalsSlot, ...)'
  250. # in threads.nim: the subtle preprocessing here binds 'globalsSlot' which
  251. # is not exported and yet the generic 'threadProcWrapper' works correctly.
  252. let flags = if mixinContext: flags+{withinMixin} else: flags
  253. for i in countup(first, sonsLen(result) - 1):
  254. result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
  255. of nkCurlyExpr:
  256. result = newNodeI(nkCall, n.info)
  257. result.add newIdentNode(getIdent("{}"), n.info)
  258. for i in 0 ..< n.len: result.add(n[i])
  259. result = semGenericStmt(c, result, flags, ctx)
  260. of nkBracketExpr:
  261. result = newNodeI(nkCall, n.info)
  262. result.add newIdentNode(getIdent("[]"), n.info)
  263. for i in 0 ..< n.len: result.add(n[i])
  264. withBracketExpr ctx, n.sons[0]:
  265. result = semGenericStmt(c, result, flags, ctx)
  266. of nkAsgn, nkFastAsgn:
  267. checkSonsLen(n, 2)
  268. let a = n.sons[0]
  269. let b = n.sons[1]
  270. let k = a.kind
  271. case k
  272. of nkCurlyExpr:
  273. result = newNodeI(nkCall, n.info)
  274. result.add newIdentNode(getIdent("{}="), n.info)
  275. for i in 0 ..< a.len: result.add(a[i])
  276. result.add(b)
  277. result = semGenericStmt(c, result, flags, ctx)
  278. of nkBracketExpr:
  279. result = newNodeI(nkCall, n.info)
  280. result.add newIdentNode(getIdent("[]="), n.info)
  281. for i in 0 ..< a.len: result.add(a[i])
  282. result.add(b)
  283. withBracketExpr ctx, a.sons[0]:
  284. result = semGenericStmt(c, result, flags, ctx)
  285. else:
  286. for i in countup(0, sonsLen(n) - 1):
  287. result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
  288. of nkIfStmt:
  289. for i in countup(0, sonsLen(n)-1):
  290. n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
  291. of nkWhenStmt:
  292. for i in countup(0, sonsLen(n)-1):
  293. n.sons[i] = semGenericStmt(c, n.sons[i], flags+{withinMixin}, ctx)
  294. of nkWhileStmt:
  295. openScope(c)
  296. for i in countup(0, sonsLen(n)-1):
  297. n.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
  298. closeScope(c)
  299. of nkCaseStmt:
  300. openScope(c)
  301. n.sons[0] = semGenericStmt(c, n.sons[0], flags, ctx)
  302. for i in countup(1, sonsLen(n)-1):
  303. var a = n.sons[i]
  304. checkMinSonsLen(a, 1)
  305. var L = sonsLen(a)
  306. for j in countup(0, L-2):
  307. a.sons[j] = semGenericStmt(c, a.sons[j], flags, ctx)
  308. a.sons[L - 1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
  309. closeScope(c)
  310. of nkForStmt, nkParForStmt:
  311. var L = sonsLen(n)
  312. openScope(c)
  313. n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
  314. for i in countup(0, L - 3):
  315. addTempDecl(c, n.sons[i], skForVar)
  316. n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
  317. closeScope(c)
  318. of nkBlockStmt, nkBlockExpr, nkBlockType:
  319. checkSonsLen(n, 2)
  320. openScope(c)
  321. if n.sons[0].kind != nkEmpty:
  322. addTempDecl(c, n.sons[0], skLabel)
  323. n.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
  324. closeScope(c)
  325. of nkTryStmt:
  326. checkMinSonsLen(n, 2)
  327. n.sons[0] = semGenericStmtScope(c, n.sons[0], flags, ctx)
  328. for i in countup(1, sonsLen(n)-1):
  329. var a = n.sons[i]
  330. checkMinSonsLen(a, 1)
  331. var L = sonsLen(a)
  332. openScope(c)
  333. for j in countup(0, L-2):
  334. if a.sons[j].isInfixAs():
  335. addTempDecl(c, getIdentNode(a.sons[j][2]), skLet)
  336. a.sons[j].sons[1] = semGenericStmt(c, a.sons[j][1], flags+{withinTypeDesc}, ctx)
  337. else:
  338. a.sons[j] = semGenericStmt(c, a.sons[j], flags+{withinTypeDesc}, ctx)
  339. a.sons[L-1] = semGenericStmtScope(c, a.sons[L-1], flags, ctx)
  340. closeScope(c)
  341. of nkVarSection, nkLetSection:
  342. for i in countup(0, sonsLen(n) - 1):
  343. var a = n.sons[i]
  344. if a.kind == nkCommentStmt: continue
  345. if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a)
  346. checkMinSonsLen(a, 3)
  347. var L = sonsLen(a)
  348. a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
  349. a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
  350. for j in countup(0, L-3):
  351. addTempDecl(c, getIdentNode(a.sons[j]), skVar)
  352. of nkGenericParams:
  353. for i in countup(0, sonsLen(n) - 1):
  354. var a = n.sons[i]
  355. if (a.kind != nkIdentDefs): illFormedAst(a)
  356. checkMinSonsLen(a, 3)
  357. var L = sonsLen(a)
  358. a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
  359. # do not perform symbol lookup for default expressions
  360. for j in countup(0, L-3):
  361. addTempDecl(c, getIdentNode(a.sons[j]), skType)
  362. of nkConstSection:
  363. for i in countup(0, sonsLen(n) - 1):
  364. var a = n.sons[i]
  365. if a.kind == nkCommentStmt: continue
  366. if (a.kind != nkConstDef): illFormedAst(a)
  367. checkSonsLen(a, 3)
  368. addTempDecl(c, getIdentNode(a.sons[0]), skConst)
  369. a.sons[1] = semGenericStmt(c, a.sons[1], flags+{withinTypeDesc}, ctx)
  370. a.sons[2] = semGenericStmt(c, a.sons[2], flags, ctx)
  371. of nkTypeSection:
  372. for i in countup(0, sonsLen(n) - 1):
  373. var a = n.sons[i]
  374. if a.kind == nkCommentStmt: continue
  375. if (a.kind != nkTypeDef): illFormedAst(a)
  376. checkSonsLen(a, 3)
  377. addTempDecl(c, getIdentNode(a.sons[0]), skType)
  378. for i in countup(0, sonsLen(n) - 1):
  379. var a = n.sons[i]
  380. if a.kind == nkCommentStmt: continue
  381. if (a.kind != nkTypeDef): illFormedAst(a)
  382. checkSonsLen(a, 3)
  383. if a.sons[1].kind != nkEmpty:
  384. openScope(c)
  385. a.sons[1] = semGenericStmt(c, a.sons[1], flags, ctx)
  386. a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
  387. closeScope(c)
  388. else:
  389. a.sons[2] = semGenericStmt(c, a.sons[2], flags+{withinTypeDesc}, ctx)
  390. of nkEnumTy:
  391. if n.sonsLen > 0:
  392. if n.sons[0].kind != nkEmpty:
  393. n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
  394. for i in countup(1, sonsLen(n) - 1):
  395. var a: PNode
  396. case n.sons[i].kind
  397. of nkEnumFieldDef: a = n.sons[i].sons[0]
  398. of nkIdent: a = n.sons[i]
  399. else: illFormedAst(n)
  400. addDecl(c, newSymS(skUnknown, getIdentNode(a), c))
  401. of nkObjectTy, nkTupleTy, nkTupleClassTy:
  402. discard
  403. of nkFormalParams:
  404. checkMinSonsLen(n, 1)
  405. if n.sons[0].kind != nkEmpty:
  406. n.sons[0] = semGenericStmt(c, n.sons[0], flags+{withinTypeDesc}, ctx)
  407. for i in countup(1, sonsLen(n) - 1):
  408. var a = n.sons[i]
  409. if (a.kind != nkIdentDefs): illFormedAst(a)
  410. checkMinSonsLen(a, 3)
  411. var L = sonsLen(a)
  412. a.sons[L-2] = semGenericStmt(c, a.sons[L-2], flags+{withinTypeDesc}, ctx)
  413. a.sons[L-1] = semGenericStmt(c, a.sons[L-1], flags, ctx)
  414. for j in countup(0, L-3):
  415. addTempDecl(c, getIdentNode(a.sons[j]), skParam)
  416. of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
  417. nkFuncDef, nkIteratorDef, nkLambdaKinds:
  418. checkSonsLen(n, bodyPos + 1)
  419. if n.sons[namePos].kind != nkEmpty:
  420. addTempDecl(c, getIdentNode(n.sons[0]), skProc)
  421. openScope(c)
  422. n.sons[genericParamsPos] = semGenericStmt(c, n.sons[genericParamsPos],
  423. flags, ctx)
  424. if n.sons[paramsPos].kind != nkEmpty:
  425. if n.sons[paramsPos].sons[0].kind != nkEmpty:
  426. addPrelimDecl(c, newSym(skUnknown, getIdent("result"), nil, n.info))
  427. n.sons[paramsPos] = semGenericStmt(c, n.sons[paramsPos], flags, ctx)
  428. n.sons[pragmasPos] = semGenericStmt(c, n.sons[pragmasPos], flags, ctx)
  429. var body: PNode
  430. if n.sons[namePos].kind == nkSym:
  431. let s = n.sons[namePos].sym
  432. if sfGenSym in s.flags and s.ast == nil:
  433. body = n.sons[bodyPos]
  434. else:
  435. body = s.getBody
  436. else: body = n.sons[bodyPos]
  437. n.sons[bodyPos] = semGenericStmtScope(c, body, flags, ctx)
  438. closeScope(c)
  439. of nkPragma, nkPragmaExpr: discard
  440. of nkExprColonExpr, nkExprEqExpr:
  441. checkMinSonsLen(n, 2)
  442. result.sons[1] = semGenericStmt(c, n.sons[1], flags, ctx)
  443. else:
  444. for i in countup(0, sonsLen(n) - 1):
  445. result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
  446. when defined(nimsuggest):
  447. if withinTypeDesc in flags: dec c.inTypeContext
  448. proc semGenericStmt(c: PContext, n: PNode): PNode =
  449. var ctx: GenericCtx
  450. ctx.toMixin = initIntset()
  451. result = semGenericStmt(c, n, {}, ctx)
  452. semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)
  453. proc semConceptBody(c: PContext, n: PNode): PNode =
  454. var ctx: GenericCtx
  455. ctx.toMixin = initIntset()
  456. result = semGenericStmt(c, n, {withinConcept}, ctx)
  457. semIdeForTemplateOrGeneric(c, result, ctx.cursorInBody)