summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/parser.nim9
-rwxr-xr-xcompiler/semtempl.nim52
-rwxr-xr-xdoc/grammar.txt2
-rw-r--r--tests/run/tstempl.nim24
-rwxr-xr-xtodo.txt3
-rwxr-xr-xweb/news.txt3
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