diff options
-rw-r--r-- | compiler/patterns.nim | 30 | ||||
-rwxr-xr-x | compiler/semtempl.nim | 16 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 13 | ||||
-rw-r--r-- | tests/patterns/tmatrix.nim | 4 | ||||
-rwxr-xr-x | todo.txt | 1 |
5 files changed, 40 insertions, 24 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] = diff --git a/tests/patterns/tmatrix.nim b/tests/patterns/tmatrix.nim index 067c4cd5a..5074e068d 100644 --- a/tests/patterns/tmatrix.nim +++ b/tests/patterns/tmatrix.nim @@ -13,8 +13,8 @@ proc `+`(a, b: TMat): TMat = nil proc `-`(a, b: TMat): TMat = nil proc `$`(a: TMat): string = result = $a.dummy -macro optOps{ (`+`|`-`|`*`) *| a }(a: varargs[TMat]): expr = - result = newIntLitNode(21) +macro optOps{ (`+`|`-`|`*`) *| a }(a: TMat): expr = + result = callsite() #macro optPlus{ `+` * a }(a: varargs[TMat]): expr = # result = newIntLitNode(21) diff --git a/todo.txt b/todo.txt index a50c776c7..3ea45b9b8 100755 --- a/todo.txt +++ b/todo.txt @@ -2,7 +2,6 @@ version 0.9.0 ============= - make 'm: stmt' use overloading resolution -- finish, test and document tmatrix - document pattern matching - make 'bind' default for templates and introduce 'mixin' |