diff options
-rwxr-xr-x | compiler/parser.nim | 9 | ||||
-rwxr-xr-x | compiler/semtempl.nim | 52 | ||||
-rwxr-xr-x | doc/grammar.txt | 2 | ||||
-rw-r--r-- | tests/run/tstempl.nim | 24 | ||||
-rwxr-xr-x | todo.txt | 3 | ||||
-rwxr-xr-x | web/news.txt | 3 |
6 files changed, 61 insertions, 32 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 7f11ddb2b..88edcd967 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -1412,13 +1412,12 @@ proc parseBind(p: var TParser): PNode = result = newNodeP(nkBindStmt, p) getTok(p) optInd(p, result) - while p.tok.tokType == tkSymbol: - var a = newIdentNodeP(p.tok.ident, p) - getTok(p) + while true: + var a = qualifiedIdent(p) addSon(result, a) - if p.tok.tokType != tkComma: break + if p.tok.tokType != tkComma: break getTok(p) - optInd(p, a) + optInd(p, a) expectNl(p) proc parseStmtPragma(p: var TParser): PNode = diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index b09f50306..98c4aff53 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -13,12 +13,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode = var a: PSym o: TOverloadIter - i: int - i = 0 + var i = 0 a = initOverloadIter(o, c, n) while a != nil: a = nextOverloadIter(o, c, n) inc(i) + if i > 1: break if i <= 1: result = newSymNode(s) result.info = n.info @@ -36,41 +36,45 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode = proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode = for i in 0 .. < n.len: var a = n.sons[i] - if a.kind == nkIdent: - var s = SymtabGet(c.Tab, a.ident) - if s != nil: - toBind.incl(s.name.id) - else: - localError(a.info, errUndeclaredIdentifier, a.ident.s) - else: + # If 'a' is an overloaded symbol, we use the first symbol as a 'witness' + # and use the fact that subsequent lookups will yield the same symbol! + # This is currently the case due to the hash table's implementation... + let s = QualifiedLookUp(c, a) + if s != nil: + toBind.incl(s.id) + else: illFormedAst(a) result = newNodeI(nkEmpty, n.info) -proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool, +proc resolveTemplateParams(c: PContext, n: PNode, owner: PSym, toBind: var TIntSet): PNode = var s: PSym case n.kind - of nkIdent: - if not withinBind and not Contains(toBind, n.ident.id): - s = SymTabLocalGet(c.Tab, n.ident) - if s != nil: + of nkIdent, nkAccQuoted: + result = n + let s = QualifiedLookUp(c, n, {}) + if s != nil: + if s.owner == owner and s.kind == skParam: result = newSymNode(s) result.info = n.info - else: - result = n - else: - Incl(toBind, n.ident.id) - result = symChoice(c, n, lookup(c, n)) + elif Contains(toBind, s.id): + result = symChoice(c, n, s) of nkEmpty, nkSym..nkNilLit: # atom result = n - of nkBind: - result = resolveTemplateParams(c, n.sons[0], true, toBind) + of nkBind: + result = resolveTemplateParams(c, n.sons[0], owner, toBind) of nkBindStmt: result = semBindStmt(c, n, toBind) - else: + else: + # dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam', + # so we use the generic code for nkDotExpr too + if n.kind == nkDotExpr: + let s = QualifiedLookUp(c, n, {}) + if s != nil and Contains(toBind, s.id): + return symChoice(c, n, s) result = n for i in countup(0, sonsLen(n) - 1): - result.sons[i] = resolveTemplateParams(c, n.sons[i], withinBind, toBind) + result.sons[i] = resolveTemplateParams(c, n.sons[i], owner, toBind) proc transformToExpr(n: PNode): PNode = var realStmt: int @@ -122,7 +126,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = s.typ.sons[0] = newTypeS(tyStmt, c) s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0]) var toBind = initIntSet() - n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], false, toBind) + n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], s, toBind) if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}: n.sons[bodyPos] = transformToExpr(n.sons[bodyPos]) # only parameters are resolved, no type checking is performed diff --git a/doc/grammar.txt b/doc/grammar.txt index f378cd140..1e54d1116 100755 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -137,7 +137,7 @@ staticStmt ::= 'static' ':' stmt filename ::= symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT importStmt ::= 'import' filename (comma filename)* includeStmt ::= 'include' filename (comma filename)* -bindStmt ::= 'bind' IDENT (comma IDENT)* +bindStmt ::= 'bind' qualifiedIdent (comma qualifiedIdent)* fromStmt ::= 'from' filename 'import' symbol (comma symbol)* pragma ::= '{.' optInd (colonExpr [comma])* optPar ('.}' | '}') diff --git a/tests/run/tstempl.nim b/tests/run/tstempl.nim new file mode 100644 index 000000000..2b4a8baa0 --- /dev/null +++ b/tests/run/tstempl.nim @@ -0,0 +1,24 @@ +discard """ + output: '''global = levB, arg = levA, test = false +levB''' +""" + +# tstempl.nim +import strutils + +type + TLev = enum + levA, + levB + +var abclev = levB + +template tstLev(abclev: TLev) = + bind tstempl.abclev, `%` + writeln(stdout, "global = $1, arg = $2, test = $3" % [ + $tstempl.abclev, $abclev, $(tstempl.abclev == abclev)]) + # evaluates to true, but must be false + + +tstLev(levA) +writeln(stdout, $abclev) diff --git a/todo.txt b/todo.txt index 15a26f75d..34cd89ae5 100755 --- a/todo.txt +++ b/todo.txt @@ -2,7 +2,6 @@ version 0.9.0 ============= - fix DLLs -- fix 'bind' for templates - implicit deref for parameter matching - deprecate ``var x, y = 0`` as it's confusing for tuple consistency @@ -35,7 +34,7 @@ Bugs but this can lead to compilation errors - bug: the parser is not strict enough with newlines: 'echo "a" echo "b"' compiles - +- bug: blocks can "export" an identifier but the CCG generates {} for them ... version 0.9.XX ============== diff --git a/web/news.txt b/web/news.txt index df81b952c..fc879f474 100755 --- a/web/news.txt +++ b/web/news.txt @@ -95,6 +95,8 @@ Changes affecting backwards compatibility conversions from ``int`` to ``int32`` are now forbidden. - ``system.byte`` is now an alias for ``uint8``; it used to be an alias to ``int8``. +- ``bind`` expressions in templates are not properly supported anymore. Use + the declarative ``bind`` statement instead. Compiler Additions @@ -136,6 +138,7 @@ Language Additions readability: ``proc divmod(a, b: int; resA, resB: var int)``. - A semicolon can now be used to have multiple simple statements on a single line: ``inc i; inc j``. +- ``bind`` supports overloaded symbols and operators. 2012-02-09 Version 0.8.14 released |