diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-03-26 04:36:26 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-03-26 04:36:26 +0300 |
commit | 6216046bc6b2794d15705f5d2621f602bda636c4 (patch) | |
tree | 8a70def0c70dc634ee92d1144c4b12e661042343 /compiler | |
parent | bc2eb0ea9b8a806ddafdb7726c94363fbd2c2f20 (diff) | |
download | Nim-6216046bc6b2794d15705f5d2621f602bda636c4.tar.gz |
genSym support for hygienic macros and templates.
example: template hygienic(val: expr) = var `*x` = val echo `*x` *x was chosen as mnemonic for "opposite of public" and thus private
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/evals.nim | 15 | ||||
-rw-r--r-- | compiler/idgen.nim | 7 | ||||
-rwxr-xr-x | compiler/lookups.nim | 7 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 2 | ||||
-rwxr-xr-x | compiler/semtempl.nim | 61 |
5 files changed, 22 insertions, 70 deletions
diff --git a/compiler/evals.nim b/compiler/evals.nim index 72c37a5d9..84d3023a5 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -16,7 +16,7 @@ import strutils, magicsys, lists, options, ast, astalgo, trees, treetab, nimsets, msgs, os, condsyms, idents, renderer, types, passes, semfold, transf, - parser, ropes, rodread + parser, ropes, rodread, idgen type PStackFrame* = ref TStackFrame @@ -843,6 +843,7 @@ proc evalParseStmt(c: PEvalContext, n: PNode): PNode = result.typ = newType(tyStmt, c.module) proc evalTemplateAux*(templ, actual: PNode, sym: PSym): PNode = + inc genSymBaseId case templ.kind of nkSym: var p = templ.sym @@ -866,26 +867,29 @@ proc evalTemplateArgs(n: PNode, s: PSym): PNode = of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: a = sonsLen(n) else: a = 0 - var f = sonsLen(s.typ) + var f = s.typ.sonsLen if a > f: GlobalError(n.info, errWrongNumberOfArguments) result = copyNode(n) for i in countup(1, f - 1): var arg = if i < a: n.sons[i] else: copyTree(s.typ.n.sons[i].sym.ast) + if arg == nil or arg.kind == nkEmpty: + LocalError(n.info, errWrongNumberOfArguments) addSon(result, arg) -var evalTemplateCounter = 0 +var evalTemplateCounter* = 0 # to prevent endless recursion in templates instantation -proc evalTemplate(n: PNode, sym: PSym): PNode = +proc evalTemplate*(n: PNode, sym: PSym): PNode = inc(evalTemplateCounter) if evalTemplateCounter > 100: GlobalError(n.info, errTemplateInstantiationTooNested) + result = n # replace each param by the corresponding node: var args = evalTemplateArgs(n, sym) result = evalTemplateAux(sym.getBody, args, sym) - + dec(evalTemplateCounter) proc evalExpandToAst(c: PEvalContext, original: PNode): PNode = @@ -1312,6 +1316,7 @@ proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode = if evalTemplateCounter > 100: GlobalError(n.info, errTemplateInstantiationTooNested) + inc genSymBaseId var s = newStackFrame() s.call = n setlen(s.params, 2) diff --git a/compiler/idgen.nim b/compiler/idgen.nim index 6dc19474d..d2e322796 100644 --- a/compiler/idgen.nim +++ b/compiler/idgen.nim @@ -11,7 +11,7 @@ import idents, strutils, os, options -var gFrontEndId, gBackendId*: int +var gFrontEndId, gBackendId*, genSymBaseId*: int const debugIds* = false @@ -25,7 +25,7 @@ proc registerID*(id: PIdObj) = when debugIDs: if id.id == -1 or ContainsOrIncl(usedIds, id.id): InternalError("ID already used: " & $id.id) - + proc getID*(): int {.inline.} = result = gFrontEndId inc(gFrontEndId) @@ -34,6 +34,9 @@ proc backendId*(): int {.inline.} = result = gBackendId inc(gBackendId) +proc genSym*(basename: string): PIdent = + result = getIdent(basename & $genSymBaseId) + proc setId*(id: int) {.inline.} = gFrontEndId = max(gFrontEndId, id + 1) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index ee77b3633..62f4a3391 100755 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -11,7 +11,7 @@ import intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, - renderer + renderer, wordrecg, idgen proc considerAcc*(n: PNode): PIdent = case n.kind @@ -21,6 +21,11 @@ proc considerAcc*(n: PNode): PIdent = case n.len of 0: GlobalError(n.info, errIdentifierExpected, renderTree(n)) of 1: result = considerAcc(n.sons[0]) + of 2: + if n[0].ident.id == ord(wStar): + result = genSym(n[1].ident.s) + else: + result = getIdent(n[0].ident.s & n[1].ident.s) else: var id = "" for i in 0.. <n.len: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 147f38abb..f5ceee7c0 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -13,7 +13,7 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = markUsed(n, s) pushInfoContext(n.info) - result = evalTemplate(c, n, s) + result = evalTemplate(n, s) if semCheck: result = semAfterMacroCall(c, result, s) popInfoContext() diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 2600d80cb..b0debc75b 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -9,67 +9,6 @@ # included from sem.nim -proc isExpr(n: PNode): bool = - # returns true if ``n`` looks like an expression - case n.kind - of nkIdent..nkNilLit: - result = true - of nkCall..pred(nkAsgn): - for i in countup(0, sonsLen(n) - 1): - if not isExpr(n.sons[i]): - return false - result = true - else: result = false - -proc isTypeDesc(n: PNode): bool = - # returns true if ``n`` looks like a type desc - case n.kind - of nkIdent, nkSym, nkType: - result = true - of nkDotExpr, nkBracketExpr: - for i in countup(0, sonsLen(n) - 1): - if not isTypeDesc(n.sons[i]): - return false - result = true - of nkTypeOfExpr..nkEnumTy: - result = true - else: result = false - -var evalTemplateCounter: int = 0 - # to prevend endless recursion in templates instantation - -proc evalTemplateArgs(c: PContext, n: PNode, s: PSym): PNode = - var - f, a: int - arg: PNode - f = sonsLen(s.typ) - # if the template has zero arguments, it can be called without ``()`` - # `n` is then a nkSym or something similar - case n.kind - of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: - a = sonsLen(n) - else: a = 0 - if a > f: LocalError(n.info, errWrongNumberOfArguments) - result = copyNode(n) - for i in countup(1, f - 1): - if i < a: arg = n.sons[i] - else: arg = copyTree(s.typ.n.sons[i].sym.ast) - if arg == nil or arg.kind == nkEmpty: - LocalError(n.info, errWrongNumberOfArguments) - addSon(result, arg) - -proc evalTemplate*(c: PContext, n: PNode, sym: PSym): PNode = - var args: PNode - inc(evalTemplateCounter) - if evalTemplateCounter <= 100: - # replace each param by the corresponding node: - args = evalTemplateArgs(c, n, sym) - result = evalTemplateAux(sym.getBody, args, sym) - dec(evalTemplateCounter) - else: - GlobalError(n.info, errTemplateInstantiationTooNested) - result = n - proc symChoice(c: PContext, n: PNode, s: PSym): PNode = var a: PSym |