From b2cb5f55ac5208c5db879d7905f6552cc63e02ed Mon Sep 17 00:00:00 2001 From: metagn Date: Thu, 14 Sep 2023 07:22:22 +0300 Subject: [PATCH] refactor semtempl ident declarations, some special word use (#22693) `semtempl` is refactored to combine the uses of `getIdentNode`, `onlyReplaceParams`, `isTemplParam` and most of `replaceIdentBySym` into a single `getIdentReplaceParams` proc. This might fix possible problems with injections of `nkAccQuoted`. Some special word comparison in `ast` and `semtempl` are also made more efficient. (cherry picked from commit ac1804aba665b34a01cb014183f8fff0ba6db738) --- compiler/ast.nim | 4 +- compiler/semtempl.nim | 104 +++++++++++++++++------------------------- 2 files changed, 44 insertions(+), 64 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 970a544868..64505e7530 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -10,7 +10,7 @@ # abstract syntax tree + symbol table import - lineinfos, hashes, options, ropes, idents, int128, tables + lineinfos, hashes, options, ropes, idents, int128, tables, wordrecg from strutils import toLowerAscii when defined(nimPreviewSlimSystem): @@ -2016,7 +2016,7 @@ proc isImportedException*(t: PType; conf: ConfigRef): bool = result = true proc isInfixAs*(n: PNode): bool = - return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s == "as" + return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.id == ord(wAs) proc skipColon*(n: PNode): PNode = result = n diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 04c003b36d..f6f26a6cb2 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -135,24 +135,32 @@ type noGenSym: int inTemplateHeader: int -proc getIdentNode(c: var TemplCtx, n: PNode): PNode = +proc isTemplParam(c: TemplCtx, s: PSym): bool {.inline.} = + result = s.kind == skParam and + s.owner == c.owner and sfTemplateParam in s.flags + +proc getIdentReplaceParams(c: var TemplCtx, n: var PNode): tuple[node: PNode, hasParam: bool] = case n.kind - of nkPostfix: result = getIdentNode(c, n[1]) - of nkPragmaExpr: result = getIdentNode(c, n[0]) + of nkPostfix: result = getIdentReplaceParams(c, n[1]) + of nkPragmaExpr: result = getIdentReplaceParams(c, n[0]) of nkIdent: - result = n + result = (n, false) let s = qualifiedLookUp(c.c, n, {}) - if s != nil: - if s.owner == c.owner and s.kind == skParam: - result = newSymNode(s, n.info) - of nkAccQuoted, nkSym: result = n + if s != nil and isTemplParam(c, s): + n = newSymNode(s, n.info) + result = (n, true) + of nkSym: + result = (n, isTemplParam(c, n.sym)) + of nkAccQuoted: + result = (n, false) + for i in 0..= 2 and n[1].kind == nkPragma): let pragmaNode = n[1] @@ -218,15 +199,15 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) = var found = false if ni.kind == nkIdent: for a in templatePragmas: - if ni.ident == getIdent(c.c.cache, $a): + if ni.ident.id == ord(a): found = true break if not found: openScope(c) pragmaNode[i] = semTemplBody(c, pragmaNode[i]) closeScope(c) - let ident = getIdentNode(c, n) - if not isTemplParam(c, ident): + let (ident, hasParam) = getIdentReplaceParams(c, n) + if not hasParam: if n.kind != nkSym and not (n.kind == nkIdent and n.ident.id == ord(wUnderscore)): let local = newGenSym(k, ident, c) addPrelimDecl(c.c, local) @@ -235,8 +216,6 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) = replaceIdentBySym(c.c, n, newSymNode(local, n.info)) if k == skParam and c.inTemplateHeader > 0: local.flags.incl sfTemplateParam - else: - replaceIdentBySym(c.c, n, ident) proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode = incl(s.flags, sfUsed) @@ -292,20 +271,21 @@ proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode = proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode = result = n checkSonsLen(n, bodyPos + 1, c.c.config) - # routines default to 'inject': - if n.kind notin nkLambdaKinds and symBinding(n[pragmasPos]) == spGenSym: - let ident = getIdentNode(c, n[namePos]) - if not isTemplParam(c, ident): - var s = newGenSym(k, ident, c) - s.ast = n - addPrelimDecl(c.c, s) - styleCheckDef(c.c, n.info, s) - onDef(n.info, s) - n[namePos] = newSymNode(s, n[namePos].info) + if n.kind notin nkLambdaKinds: + # routines default to 'inject': + if symBinding(n[pragmasPos]) == spGenSym: + let (ident, hasParam) = getIdentReplaceParams(c, n[namePos]) + if not hasParam: + var s = newGenSym(k, ident, c) + s.ast = n + addPrelimDecl(c.c, s) + styleCheckDef(c.c, n.info, s) + onDef(n.info, s) + n[namePos] = newSymNode(s, n[namePos].info) + else: + n[namePos] = ident else: - n[namePos] = ident - else: - n[namePos] = semRoutineInTemplName(c, n[namePos]) + n[namePos] = semRoutineInTemplName(c, n[namePos]) # open scope for parameters openScope(c) for i in patternPos..paramsPos-1: