Selaa lähdekoodia

продвинулся в создании нового механизма интерпретации узлов

kpmy 10 vuotta sitten
vanhempi
commit
21bc567d47

+ 29 - 3
cp/node/class.go

@@ -97,9 +97,23 @@ type nodeFields struct {
 	adr               cp.ID
 }
 
-type stmt struct{}
+type stmt struct {
+	Statement
+}
+
+func (s *stmt) s() Statement { return s }
+
+type expr struct {
+	Expression
+}
 
-func (s *stmt) this() Statement { return s }
+func (e *expr) e() Expression { return e }
+
+type design struct {
+	Designator
+}
+
+func (x *design) d() Designator { return x }
 
 func (nf *nodeFields) Adr(a ...cp.ID) cp.ID {
 	assert.For(len(a) <= 1, 20)
@@ -127,8 +141,8 @@ func (nf *nodeFields) Object() object.Object { return nf.obj }
 
 type enterNode struct {
 	nodeFields
-	enter enter.Enter
 	stmt
+	enter enter.Enter
 }
 
 func (e *enterNode) SetEnter(enter enter.Enter) { e.enter = enter }
@@ -136,6 +150,7 @@ func (e *enterNode) Enter() enter.Enter         { return e.enter }
 
 type constantNode struct {
 	nodeFields
+	expr
 	typ      object.Type
 	data     interface{}
 	min, max *int
@@ -157,6 +172,7 @@ func (c *constantNode) Min() *int    { return c.min }
 type dyadicNode struct {
 	nodeFields
 	operation operation.Operation
+	expr
 }
 
 func (d *dyadicNode) SetOperation(op operation.Operation) { d.operation = op }
@@ -183,6 +199,8 @@ func (a *assignNode) Statement() statement.Statement { return a.stat }
 
 type variableNode struct {
 	nodeFields
+	design
+	expr
 }
 
 func (v *variableNode) self() VariableNode { return v }
@@ -190,6 +208,7 @@ func (v *variableNode) self() VariableNode { return v }
 type callNode struct {
 	nodeFields
 	stmt
+	expr
 }
 
 func (v *callNode) self() CallNode { return v }
@@ -201,6 +220,7 @@ func (c *callNode) String() string {
 type procedureNode struct {
 	nodeFields
 	super bool
+	design
 }
 
 func (v *procedureNode) self() ProcedureNode { return v }
@@ -213,6 +233,7 @@ func (v *procedureNode) Super(x ...string) bool {
 
 type parameterNode struct {
 	nodeFields
+	design
 }
 
 func (v *parameterNode) self() ParameterNode { return v }
@@ -229,6 +250,7 @@ type monadicNode struct {
 	operation operation.Operation
 	typ       object.Type
 	comp      object.ComplexType
+	expr
 }
 
 func (v *monadicNode) self() MonadicNode { return v }
@@ -295,6 +317,7 @@ func (v *loopNode) self() LoopNode { return v }
 type derefNode struct {
 	nodeFields
 	ptr bool
+	design
 }
 
 func (v *derefNode) self() DerefNode { return v }
@@ -308,6 +331,7 @@ func (c *derefNode) Ptr(x ...string) bool {
 
 type fieldNode struct {
 	nodeFields
+	design
 }
 
 func (v *fieldNode) self() FieldNode { return v }
@@ -328,6 +352,7 @@ func (v *compNode) self() CompNode { return v }
 
 type indexNode struct {
 	nodeFields
+	design
 }
 
 func (v *indexNode) self() IndexNode { return v }
@@ -349,6 +374,7 @@ func (v *withNode) self() WithNode { return v }
 type guardNode struct {
 	nodeFields
 	typ object.ComplexType
+	design
 }
 
 func (v *guardNode) self() GuardNode              { return v }

+ 21 - 1
cp/node/node.go

@@ -23,7 +23,16 @@ type Node interface {
 }
 
 type Statement interface {
-	this() Statement
+	s() Statement
+}
+
+type Expression interface {
+	e() Expression
+	Designator
+}
+
+type Designator interface {
+	d() Designator
 }
 
 type EnterNode interface {
@@ -49,6 +58,7 @@ type ConstantNode interface {
 	SetMin(int)
 	SetMax(int)
 	Node
+	Expression
 }
 
 // Self-designator for empty interfaces
@@ -63,23 +73,27 @@ type AssignNode interface {
 type VariableNode interface {
 	self() VariableNode
 	Node
+	Designator
 }
 
 type CallNode interface {
 	self() CallNode
 	Node
 	Statement
+	Expression
 }
 
 type ProcedureNode interface {
 	self() ProcedureNode
 	Super(...string) bool
 	Node
+	Designator
 }
 
 type ParameterNode interface {
 	Node
 	self() ParameterNode
+	Designator
 }
 
 type ReturnNode interface {
@@ -91,10 +105,12 @@ type ReturnNode interface {
 type DyadicNode interface {
 	OperationNode
 	self() DyadicNode
+	Expression
 }
 
 type MonadicNode interface {
 	OperationNode
+	Expression
 	SetType(typ object.Type)
 	Type() object.Type
 	self() MonadicNode
@@ -140,16 +156,19 @@ type DerefNode interface {
 	self() DerefNode
 	Node
 	Ptr(...string) bool
+	Designator
 }
 
 type FieldNode interface {
 	self() FieldNode
 	Node
+	Designator
 }
 
 type IndexNode interface {
 	self() IndexNode
 	Node
+	Designator
 }
 
 type TrapNode interface {
@@ -169,6 +188,7 @@ type GuardNode interface {
 	Node
 	Type() object.ComplexType
 	SetType(object.ComplexType)
+	Designator
 }
 
 type CaseNode interface {

+ 2 - 2
fw.go

@@ -35,11 +35,11 @@ func close() {
 
 func main() {
 	flag.Parse()
+	utils.Debug(debug)
 	if name == "" {
-		name = "Start3"
+		name = "XevDemo1"
 		utils.Debug(true)
 	}
-	utils.Debug(debug)
 	global := &stdDomain{god: true}
 	global.global = global
 	modList := rtm.New()

+ 1 - 0
rt2/context/ctx.go

@@ -11,6 +11,7 @@ const (
 
 	RETURN = "RETURN"
 	META   = "META"
+	KEY    = "eval:key"
 )
 
 type Factory interface {

+ 2 - 1
rt2/nodeframe/frame.go

@@ -133,7 +133,8 @@ func (f *nodeFrame) OnPop() {
 	utils.PrintFrame("_", "POP", reflect.TypeOf(f.ir))
 	f.seq = decision.EpilogueFor(f.ir)
 	if f.seq != nil {
-		_, _ = f.seq(f)
+		_, end := f.seq(f)
+		assert.For(end == frame.END || end == frame.STOP, 60, end)
 	}
 	if f.parent != nil {
 		ff, ok := f.parent.(*nodeFrame)

+ 119 - 4
rt2/rules2/wrap/eval/do.go

@@ -1,9 +1,124 @@
 package eval
 
-func BeginStatement(IN) OUT {
-	panic(0)
+import (
+	"fw/cp/constant/enter"
+	"fw/cp/node"
+	"fw/rt2"
+	"fw/rt2/context"
+	"fw/rt2/frame"
+	"fw/rt2/scope"
+	"reflect"
+	"ypk/assert"
+)
+
+import (
+	"ypk/halt"
+)
+
+func BeginExpression(in IN) (out OUT) {
+	switch e := in.IR.(type) {
+	case node.ConstantNode:
+		out = Now(getConst)
+	case node.DyadicNode:
+		out = Now(getDop)
+	case node.Designator:
+		out = Now(BeginDesignator)
+	default:
+		halt.As(100, reflect.TypeOf(e))
+	}
+	return
+}
+
+func BeginDesignator(in IN) (out OUT) {
+	switch e := in.IR.(type) {
+	case node.VariableNode:
+		out = Now(getVar)
+	default:
+		halt.As(100, reflect.TypeOf(e))
+	}
+	return
+}
+
+func GetExpression(in IN, key interface{}, expr node.Node, next Do) OUT {
+	assert.For(expr != nil, 20)
+	_, ok := expr.(node.Expression)
+	assert.For(ok, 21, reflect.TypeOf(expr))
+	assert.For(key != nil, 22)
+	nf := rt2.New(expr)
+	rt2.Push(nf, in.Frame)
+	rt2.RegOf(in.Frame)[context.KEY] = key
+	rt2.Assert(in.Frame, func(f frame.Frame) (bool, int) {
+		v := rt2.RegOf(f)[key]
+		return v != nil, 20
+	})
+	return Later(func(IN) OUT {
+		return Now(next)
+	})
+}
+
+func GetDesignator(in IN, key interface{}, design node.Node, next Do) OUT {
+	assert.For(design != nil, 20)
+	_, ok := design.(node.Designator)
+	assert.For(ok, 21)
+	assert.For(key != nil, 22)
+	nf := rt2.New(design)
+	rt2.Push(nf, in.Frame)
+	rt2.RegOf(in.Frame)[context.KEY] = key
+	rt2.Assert(in.Frame, func(f frame.Frame) (bool, int) {
+		v := rt2.RegOf(f)[key]
+		return v != nil, 20
+	})
+	return Later(func(IN) OUT {
+		return Now(next)
+	})
+}
+
+func BeginStatement(in IN) (out OUT) {
+	switch n := in.IR.(type) {
+	case node.EnterNode:
+		var tail Do
+		tail = func(in IN) OUT {
+			q := in.Frame.Root().Queue()
+			if q != nil {
+				in.Frame.Root().PushFor(q, nil)
+				return Later(tail)
+			} else {
+				return Now(doEnter)
+			}
+		}
+		out = Now(tail)
+	case node.AssignNode:
+		out = Now(doAssign)
+	case node.CallNode:
+		out = Now(doCall)
+	default:
+		halt.As(100, reflect.TypeOf(n))
+	}
+	return
 }
 
-func EndStatement(IN) OUT {
-	panic(0)
+func EndStatement(in IN) (out OUT) {
+	switch n := in.IR.(type) {
+	case node.EnterNode:
+		out = Now(func(in IN) OUT {
+			if n.Enter() == enter.PROCEDURE {
+				rt2.ThisScope(in.Frame).Target().(scope.ScopeAllocator).Dispose(n)
+			}
+			return End()
+		})
+	case node.AssignNode, node.CallNode:
+		out = Now(func(in IN) OUT {
+			next := n.Link()
+			if next != nil {
+				nf := rt2.New(next)
+				if nf != nil {
+					in.Frame.Root().PushFor(nf, in.Parent)
+				}
+			}
+			return End()
+		})
+	default:
+		halt.As(100, reflect.TypeOf(n))
+	}
+	return out.Do(in)
 }

+ 126 - 0
rt2/rules2/wrap/eval/expr.go

@@ -0,0 +1,126 @@
+package eval
+
+import (
+	"fw/cp/constant/operation"
+	"fw/cp/node"
+	"fw/rt2"
+	"fw/rt2/scope"
+	"ypk/assert"
+	"ypk/halt"
+)
+
+func getConst(in IN) OUT {
+	c := in.IR.(node.ConstantNode)
+	sc := rt2.ThisScope(in.Frame)
+	fn := sc.Provide(c)
+	assert.For(fn != nil, 40)
+	rt2.ValueOf(in.Parent)[c.Adr()] = fn(nil)
+	rt2.RegOf(in.Parent)[in.Key] = c.Adr()
+	return End()
+}
+
+func getVar(in IN) OUT {
+	v := in.IR.(node.VariableNode)
+	rt2.ScopeFor(in.Frame, v.Object().Adr(), func(val scope.Value) {
+		rt2.ValueOf(in.Parent)[v.Adr()] = val
+		rt2.RegOf(in.Parent)[in.Key] = v.Adr()
+	})
+	return End()
+}
+
+func getDop(in IN) OUT {
+	const (
+		left  = "dop:left"
+		right = "dop:right"
+	)
+	op := in.IR.(node.DyadicNode)
+
+	do := func(in IN) OUT {
+		var (
+			res scope.Value
+		)
+		l := rt2.ValueOf(in.Frame)[KeyOf(in, left)]
+		r := rt2.ValueOf(in.Frame)[KeyOf(in, right)]
+		switch op.Operation() {
+		case operation.PLUS:
+			res = scope.Ops.Sum(l, r)
+		case operation.MINUS:
+			res = scope.Ops.Sub(l, r)
+		case operation.EQUAL:
+			res = scope.Ops.Eq(l, r)
+		case operation.LESSER:
+			res = scope.Ops.Lss(l, r)
+		case operation.LESS_EQUAL:
+			res = scope.Ops.Leq(l, r)
+		case operation.LEN:
+			res = scope.Ops.Len(op.Left().Object(), l, r)
+		case operation.NOT_EQUAL:
+			res = scope.Ops.Neq(l, r)
+		case operation.GREATER:
+			res = scope.Ops.Gtr(l, r)
+		case operation.MAX:
+			res = scope.Ops.Max(l, r)
+		case operation.MIN:
+			res = scope.Ops.Min(l, r)
+		case operation.DIV:
+			res = scope.Ops.Div(l, r)
+		case operation.MOD:
+			res = scope.Ops.Mod(l, r)
+		case operation.ALIEN_MSK:
+			res = scope.Ops.Msk(l, r)
+		case operation.TIMES:
+			res = scope.Ops.Mult(l, r)
+		case operation.SLASH:
+			res = scope.Ops.Divide(l, r)
+		case operation.IN:
+			res = scope.Ops.In(l, r)
+		case operation.ASH:
+			res = scope.Ops.Ash(l, r)
+		case operation.AND:
+			res = scope.Ops.And(l, r)
+		case operation.OR:
+			res = scope.Ops.Or(l, r)
+		case operation.GREAT_EQUAL:
+			res = scope.Ops.Geq(l, r)
+		default:
+			halt.As(100, op.Operation())
+		}
+		assert.For(res != nil, 40)
+		rt2.ValueOf(in.Parent)[op.Adr()] = res
+		rt2.RegOf(in.Parent)[in.Key] = op.Adr()
+		return End()
+	}
+
+	next := func(IN) OUT {
+		return GetExpression(in, right, op.Right(), do)
+	}
+
+	short := func(IN) OUT {
+		id := KeyOf(in, left)
+		lv := rt2.ValueOf(in.Frame)[id]
+		switch op.Operation() {
+		case operation.AND:
+			val := scope.GoTypeFrom(lv).(bool)
+			if val {
+				return Now(next)
+			} else {
+				rt2.ValueOf(in.Parent)[op.Adr()] = scope.TypeFromGo(false)
+				rt2.RegOf(in.Parent)[in.Key] = op.Adr()
+				return End()
+			}
+		case operation.OR:
+			val := scope.GoTypeFrom(lv).(bool)
+			if !val {
+				return Now(next)
+			} else {
+				rt2.ValueOf(in.Parent)[op.Adr()] = scope.TypeFromGo(true)
+				rt2.RegOf(in.Parent)[in.Key] = op.Adr()
+				return End()
+			}
+		default:
+			return Now(next)
+		}
+	}
+
+	return GetExpression(in, left, op.Left(), short)
+}

+ 75 - 0
rt2/rules2/wrap/eval/stmt.go

@@ -0,0 +1,75 @@
+package eval
+
+import (
+	"fw/cp/constant/statement"
+	"fw/cp/node"
+	"fw/rt2"
+	"fw/rt2/scope"
+	"reflect"
+	"ypk/assert"
+	"ypk/halt"
+)
+
+func doEnter(in IN) OUT {
+	var next Do
+	tail := func(IN) (out OUT) {
+		body := in.IR.Right()
+		switch {
+		case body == nil:
+			return End()
+		case body != nil && in.Parent != nil:
+			panic(0)
+		case body != nil && in.Parent == nil: //секция BEGIN
+			rt2.Push(rt2.New(body), in.Frame)
+			end := in.IR.Link()
+			if end != nil { //секция CLOSE
+				out.Do = func(in IN) OUT {
+					in.Frame.Root().PushFor(rt2.New(end), in.Frame)
+					return OUT{Do: Tail(STOP), Next: LATER}
+				}
+			} else {
+				out.Do = Tail(STOP)
+			}
+			out.Next = BEGIN
+		}
+		return
+	}
+	sm := rt2.ThisScope(in.Frame)
+	if in.IR.Object() != nil { //параметры процедуры
+		panic(0)
+	} else {
+		sm.Target().(scope.ScopeAllocator).Allocate(in.IR, true)
+		next = tail
+	}
+	return Now(next)
+}
+
+func doAssign(in IN) (out OUT) {
+	const (
+		right = "assign:right"
+		left  = "assign:left"
+	)
+	a := in.IR.(node.AssignNode)
+	switch a.Statement() {
+	case statement.ASSIGN:
+		out = GetExpression(in, right, a.Right(), func(in IN) OUT {
+			id := KeyOf(in, right)
+			val := rt2.ValueOf(in.Frame)[id]
+			assert.For(val != nil, 40, id)
+			return GetDesignator(in, left, a.Left(), func(in IN) OUT {
+				id := KeyOf(in, left)
+				v, ok := rt2.ValueOf(in.Frame)[id].(scope.Variable)
+				assert.For(ok, 41, reflect.TypeOf(v))
+				v.Set(val)
+				return End()
+			})
+		})
+	default:
+		halt.As(100, "unsupported assign statement", a.Statement())
+	}
+	return
+}
+
+func doCall(in IN) OUT {
+	panic(0)
+}

+ 13 - 0
rt2/rules2/wrap/eval/utils.go

@@ -0,0 +1,13 @@
+package eval
+
+import (
+	"fw/cp"
+	"fw/rt2"
+	"ypk/assert"
+)
+
+func KeyOf(in IN, key interface{}) cp.ID {
+	id, ok := rt2.RegOf(in.Frame)[key].(cp.ID)
+	assert.For(ok, 40)
+	return id
+}

+ 11 - 0
rt2/rules2/wrap/eval/x.go

@@ -1,6 +1,7 @@
 package eval
 
 import (
+	"fw/cp/node"
 	"fw/rt2/frame"
 )
 
@@ -11,6 +12,8 @@ const (
 	STOP
 	LATER
 	NOW
+	BEGIN
+	END
 )
 
 func (n WAIT) Wait() frame.WAIT {
@@ -23,6 +26,10 @@ func (n WAIT) Wait() frame.WAIT {
 		return frame.LATER
 	case NOW:
 		return frame.NOW
+	case BEGIN:
+		return frame.BEGIN
+	case END:
+		return frame.END
 	default:
 		panic(n)
 	}
@@ -31,6 +38,10 @@ func (n WAIT) Wait() frame.WAIT {
 type Do func(IN) OUT
 
 type IN struct {
+	IR     node.Node
+	Frame  frame.Frame
+	Parent frame.Frame
+	Key    interface{}
 }
 
 type OUT struct {

+ 14 - 146
rt2/rules2/wrap/nodes.go

@@ -2,6 +2,8 @@ package wrap
 
 import (
 	"fw/cp/node"
+	"fw/rt2"
+	"fw/rt2/context"
 	"fw/rt2/decision"
 	"fw/rt2/frame"
 	"fw/rt2/rules2/wrap/eval"
@@ -25,112 +27,30 @@ func This(o eval.OUT) (seq frame.Sequence, ret frame.WAIT) {
 
 func Propose(a eval.Do) frame.Sequence {
 	return func(fr frame.Frame) (frame.Sequence, frame.WAIT) {
-		return This(a(eval.IN{}))
+		var key interface{}
+		if fr.Parent() != nil {
+			key = rt2.RegOf(fr.Parent())[context.KEY]
+		}
+		in := eval.IN{IR: rt2.NodeOf(fr), Frame: fr, Parent: fr.Parent(), Key: key}
+		return This(a(in))
 	}
 }
 
 func test(n node.Node) (bool, int) {
 	switch n.(type) {
-	case node.ConstantNode:
-		return false, -1
 	default:
 		return true, 0
 	}
-	panic(0)
 }
 
 func prologue(n node.Node) frame.Sequence {
-	/*	//fmt.Println(reflect.TypeOf(n))
-		switch next := n.(type) {
-		case node.EnterNode:
-			var tail frame.Sequence
-			tail = func(f frame.Frame) (frame.Sequence, frame.WAIT) {
-				q := f.Root().Queue()
-				if q != nil {
-					f.Root().PushFor(q, nil)
-					return tail, frame.NOW
-				} else {
-					return enterSeq, frame.NOW
-				}
-			}
-			return tail
-		case node.AssignNode:
-			return assignSeq
-		case node.OperationNode:
-			switch n.(type) {
-			case node.DyadicNode:
-				return dopSeq
-			case node.MonadicNode:
-				return mopSeq
-			default:
-				panic("no such op")
-			}
-		case node.CallNode:
-			return callSeq
-		case node.ReturnNode:
-			return returnSeq
-		case node.ConditionalNode:
-			return ifSeq
-		case node.IfNode:
-			return ifExpr
-		case node.WhileNode:
-			return whileSeq
-		case node.RepeatNode:
-			return repeatSeq
-		case node.LoopNode:
-			return loopSeq
-		case node.ExitNode:
-			return exitSeq
-		case node.DerefNode:
-			return derefSeq
-		case node.InitNode:
-			return frame.Tail(frame.STOP)
-		case node.IndexNode:
-			return indexSeq
-		case node.FieldNode:
-			return Propose(fieldSeq)
-		case node.TrapNode:
-			return func(f frame.Frame) (frame.Sequence, frame.WAIT) {
-				switch code := next.Left().(type) {
-				case node.ConstantNode:
-					log.Println("TRAP:", traps.This(code.Data()))
-					return frame.Tail(frame.WRONG), frame.NOW
-				default:
-					panic(fmt.Sprintln("unsupported code", reflect.TypeOf(code)))
-				}
-			}
-		case node.WithNode:
-			return withSeq
-		case node.GuardNode:
-			return guardSeq
-		case node.CaseNode:
-			return caseSeq
-		case node.RangeNode:
-			return rangeSeq
-		case node.CompNode:
-			return func(f frame.Frame) (frame.Sequence, frame.WAIT) {
-				right := func(f frame.Frame) (frame.Sequence, frame.WAIT) {
-					if next.Right() != nil {
-						rt2.Push(rt2.New(next.Right()), f)
-						return frame.Tail(frame.STOP), frame.LATER
-					}
-					return frame.End()
-				}
-				left := func(f frame.Frame) (frame.Sequence, frame.WAIT) {
-					if next.Left() != nil {
-						rt2.Push(rt2.New(next.Left()), f)
-						return right, frame.LATER
-					}
-					return right, frame.NOW
-				}
-				return left, frame.NOW
-			}
-		default:
-			panic(fmt.Sprintln("unknown node", reflect.TypeOf(n), n.Adr()))
-		}*/
 	switch n.(type) {
 	case node.Statement:
 		return Propose(eval.BeginStatement)
+	case node.Expression:
+		return Propose(eval.BeginExpression)
+	case node.Designator:
+		return Propose(eval.BeginDesignator)
 	default:
 		halt.As(100, reflect.TypeOf(n))
 	}
@@ -138,64 +58,12 @@ func prologue(n node.Node) frame.Sequence {
 }
 
 func epilogue(n node.Node) frame.Sequence {
-	/*	switch e := n.(type) {
-		case node.AssignNode, node.InitNode, node.CallNode, node.ConditionalNode, node.WhileNode,
-			node.RepeatNode, node.ExitNode, node.WithNode, node.CaseNode, node.CompNode:
-			return func(f frame.Frame) (frame.Sequence, frame.WAIT) {
-				next := n.Link()
-				//fmt.Println("from", reflect.TypeOf(n))
-				//fmt.Println("next", reflect.TypeOf(next))
-				if next != nil {
-					nf := rt2.New(next)
-					if nf != nil {
-						f.Root().PushFor(nf, f.Parent())
-					}
-				}
-				if _, ok := n.(node.CallNode); ok {
-					if f.Parent() != nil {
-						par := rt2.RegOf(f.Parent())
-						for k, v := range rt2.RegOf(f) {
-							par[k] = v
-						}
-						val := rt2.ValueOf(f.Parent())
-						for k, v := range rt2.ValueOf(f) {
-							val[k] = v
-						}
-					}
-				}
-				return frame.End()
-			}
-		case node.EnterNode:
-			return func(f frame.Frame) (seq frame.Sequence, ret frame.WAIT) {
-				//fmt.Println(rt_module.DomainModule(f.Domain()).Name)
-				if e.Enter() == enter.PROCEDURE {
-					rt2.ThisScope(f).Target().(scope.ScopeAllocator).Dispose(n)
-				}
-				//возвращаем результаты вызова функции
-				if f.Parent() != nil {
-					par := rt2.RegOf(f.Parent())
-					for k, v := range rt2.RegOf(f) {
-						par[k] = v
-					}
-					val := rt2.ValueOf(f.Parent())
-					for k, v := range rt2.ValueOf(f) {
-						val[k] = v
-					}
-				}
-				return frame.End()
-			}
-		case node.OperationNode, node.ReturnNode, node.IfNode, node.LoopNode,
-			node.DerefNode, node.IndexNode, node.TrapNode, node.GuardNode, node.RangeNode, node.FieldNode:
-			return nil
-		default:
-			fmt.Println(reflect.TypeOf(n))
-			panic("unhandled epilogue")
-		}*/
 	switch n.(type) {
 	case node.Statement:
 		return Propose(eval.EndStatement)
+	case node.ConstantNode, node.VariableNode, node.DyadicNode: //do nothing
 	default:
 		halt.As(100, reflect.TypeOf(n))
 	}
-	panic(0)
+	return nil
 }

+ 4 - 1
rt2/utils.go

@@ -24,7 +24,7 @@ func ThisScope(f frame.Frame) scope.Manager {
 	return f.Domain().Discover(context.VSCOPE, 0).(scope.Manager)
 }
 
-func ScopeFor(f frame.Frame, id cp.ID) (ret scope.Manager) {
+func ScopeFor(f frame.Frame, id cp.ID, fn ...scope.ValueOf) (ret scope.Manager) {
 	glob := f.Domain().Discover(context.UNIVERSE).(context.Domain)
 	ml := glob.Discover(context.MOD).(rtm.List)
 	for _, m := range ml.AsList() {
@@ -37,6 +37,9 @@ func ScopeFor(f frame.Frame, id cp.ID) (ret scope.Manager) {
 		}
 	}
 	assert.For(ret != nil, 60)
+	if len(fn) == 1 {
+		ret.Select(id, fn...)
+	}
 	return
 }