summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/patterns.nim30
-rwxr-xr-xcompiler/semtempl.nim16
-rwxr-xr-xcompiler/semtypes.nim13
3 files changed, 38 insertions, 21 deletions
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index 1a2f9b761..7f3bf1556 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -17,11 +17,20 @@ import
 type
   TPatternContext = object
     owner: PSym
-    mapping: TIdNodeTable  # maps formal parameters to nodes
+    mapping: seq[PNode]  # maps formal parameters to nodes
+    formals: int
     c: PContext
-    subMatch: bool         # subnode matches are special
+    subMatch: bool       # subnode matches are special
   PPatternContext = var TPatternContext
 
+proc getLazy(c: PPatternContext, sym: PSym): PNode =
+  if not isNil(c.mapping):
+    result = c.mapping[sym.position]
+
+proc putLazy(c: PPatternContext, sym: PSym, n: PNode) =
+  if isNil(c.mapping): newSeq(c.mapping, c.formals)
+  c.mapping[sym.position] = n
+
 proc matches(c: PPatternContext, p, n: PNode): bool
 
 proc canonKind(n: PNode): TNodeKind =
@@ -78,22 +87,22 @@ proc matchChoice(c: PPatternContext, p, n: PNode): bool =
     if matches(c, p.sons[i], n): return true
 
 proc bindOrCheck(c: PPatternContext, param: PSym, n: PNode): bool =
-  var pp = IdNodeTableGetLazy(c.mapping, param)
+  var pp = GetLazy(c, param)
   if pp != nil:
     # check if we got the same pattern (already unified):
     result = sameTrees(pp, n) #matches(c, pp, n)
   elif n.kind == nkArgList or checkTypes(c, param, n):
-    IdNodeTablePutLazy(c.mapping, param, n)
+    PutLazy(c, param, n)
     result = true
 
 proc gather(c: PPatternContext, param: PSym, n: PNode) =
-  var pp = IdNodeTableGetLazy(c.mapping, param)
+  var pp = GetLazy(c, param)
   if pp != nil and pp.kind == nkArgList:
     pp.add(n)
   else:
     pp = newNodeI(nkArgList, n.info, 1)
     pp.sons[0] = n
-    IdNodeTablePutLazy(c.mapping, param, pp)
+    PutLazy(c, param, pp)
 
 proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
   # match ``op * param`` or ``op *| param``
@@ -112,6 +121,9 @@ proc matchNested(c: PPatternContext, p, n: PNode, rpn: bool): bool =
       add(arglist, n)
     else:
       result = false
+      debug p.sons[2].sym.typ
+      debug n.typ
+      echo "type check failed!"
     
   if n.kind notin nkCallKinds: return false
   if matches(c, p.sons[1], n.sons[0]):
@@ -198,7 +210,7 @@ proc matchStmtList(c: PPatternContext, p, n: PNode): PNode =
     for j in 0 .. <p.len:
       if not matches(c, p.sons[j], n.sons[i+j]):
         # we need to undo any bindings:
-        if not isNil(c.mapping.data): reset(c.mapping)
+        if not isNil(c.mapping): c.mapping = nil
         return false
     result = true
   
@@ -233,7 +245,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
   var ctx: TPatternContext
   ctx.owner = s
   ctx.c = c
-  # we perform 'initIdNodeTable' lazily for performance
+  ctx.formals = sonsLen(s.typ)-1
   var m = matchStmtList(ctx, s.ast.sons[patternPos], n)
   if isNil(m): return nil
   # each parameter should have been bound; we simply setup a call and
@@ -247,7 +259,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
     args = newNodeI(nkArgList, n.info)
   for i in 1 .. < params.len:
     let param = params.sons[i].sym
-    let x = IdNodeTableGetLazy(ctx.mapping, param)
+    let x = GetLazy(ctx, param)
     # couldn't bind parameter:
     if isNil(x): return nil
     result.add(x)
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index fa15f8ede..ef935e346 100755
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -422,12 +422,21 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
   template templToExpand(s: expr): expr =
     s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags)
   
+  proc newParam(c: var TemplCtx, n: PNode, s: PSym): PNode =
+    # the param added in the current scope is actually wrong here for
+    # macros because they have a shadowed param of type 'PNimNode' (see
+    # semtypes.addParamOrResult). Within the pattern we have to ensure
+    # to use the param with the proper type though:
+    incl(s.flags, sfUsed)
+    let x = c.owner.typ.n.sons[s.position+1].sym
+    assert x.name == s.name
+    result = newSymNode(x, n.info)
+  
   proc handleSym(c: var TemplCtx, n: PNode, s: PSym): PNode =
     result = n
     if s != nil:
       if s.owner == c.owner and s.kind == skParam:
-        incl(s.flags, sfUsed)
-        result = newSymNode(s, n.info)
+        result = newParam(c, n, s)
       elif Contains(c.toBind, s.id):
         result = symChoice(c.c, n, s, scClosed)
       elif templToExpand(s):
@@ -440,8 +449,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
   proc expectParam(c: var TemplCtx, n: PNode): PNode =
     let s = QualifiedLookUp(c.c, n, {})
     if s != nil and s.owner == c.owner and s.kind == skParam:
-      incl(s.flags, sfUsed)
-      result = newSymNode(s, n.info)
+      result = newParam(c, n, s)
     else:
       localError(n.info, errInvalidExpression)
       result = n
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index ff745dc36..7c1318ada 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -554,15 +554,12 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
   if kind == skMacro:
     # within a macro, every param has the type PNimrodNode!
     # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
-    # We used to copySym(param) here, but this is not possible for term
-    # rewriting macros; so we simply overwrite param.typ here and hope for
-    # the best ...
     let nn = getSysSym"PNimrodNode"
-    #var a = copySym(param)
-    #a.typ = nn.typ
-    param.typ = nn.typ
-    #if sfGenSym notin a.flags: addDecl(c, a)
-  if sfGenSym notin param.flags: addDecl(c, param)
+    var a = copySym(param)
+    a.typ = nn.typ
+    if sfGenSym notin a.flags: addDecl(c, a)
+  else:
+    if sfGenSym notin param.flags: addDecl(c, param)
 
 proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
   tuple[typ: PType, id: PIdent] =