tmatrix.nim works now

This commit is contained in:
Araq
2012-09-08 18:51:52 +02:00
parent e2ecfb8438
commit 46e9ff6139
5 changed files with 40 additions and 24 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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] =

View File

@@ -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)

View File

@@ -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'