]> Cypherpunks repositories - gostls13.git/commitdiff
s/vm/Thread/
authorRuss Cox <rsc@golang.org>
Wed, 2 Sep 2009 19:03:20 +0000 (12:03 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 2 Sep 2009 19:03:20 +0000 (12:03 -0700)
change eval functions from taking *Frame to *Thread

R=austin
DELTA=500  (7 added, 4 deleted, 489 changed)
OCL=34256
CL=34260

usr/austin/eval/abort.go
usr/austin/eval/bridge.go
usr/austin/eval/eval_test.go
usr/austin/eval/expr.go
usr/austin/eval/expr1.go
usr/austin/eval/func.go
usr/austin/eval/gen.go
usr/austin/eval/stmt.go
usr/austin/eval/value.go

index 0b8022e963e82e624f590680be345ca9ae305f00..521e51652b540d51c06315d1c487039c335cbed3 100644 (file)
@@ -39,49 +39,49 @@ func Try(f func()) os.Error {
        return res;
 }
 
-type DivByZero struct {}
+type DivByZeroError struct {}
 
-func (DivByZero) String() string {
+func (DivByZeroError) String() string {
        return "divide by zero";
 }
 
-type NilPointer struct {}
+type NilPointerError struct {}
 
-func (NilPointer) String() string {
+func (NilPointerError) String() string {
        return "nil pointer dereference";
 }
 
-type IndexOutOfBounds struct {
+type IndexError struct {
        Idx, Len int64;
 }
 
-func (e IndexOutOfBounds) String() string {
+func (e IndexError) String() string {
        if e.Idx < 0 {
                return fmt.Sprintf("negative index: %d", e.Idx);
        }
        return fmt.Sprintf("index %d exceeds length %d", e.Idx, e.Len);
 }
 
-type KeyNotFound struct {
+type KeyError struct {
        Key interface {};
 }
 
-func (e KeyNotFound) String() string {
+func (e KeyError) String() string {
        return fmt.Sprintf("key '%v' not found in map", e.Key);
 }
 
-type NegativeLength struct {
+type NegativeLengthError struct {
        Len int64;
 }
 
-func (e NegativeLength) String() string {
+func (e NegativeLengthError) String() string {
        return fmt.Sprintf("negative length: %d", e.Len);
 }
 
-type NegativeCapacity struct {
+type NegativeCapacityError struct {
        Len int64;
 }
 
-func (e NegativeCapacity) String() string {
+func (e NegativeCapacityError) String() string {
        return fmt.Sprintf("negative capacity: %d", e.Len);
 }
index f349135a0536ccf69a6306c5c65c1c761d74db47..41674860e280255d460a50e28423113eb4c7daae 100644 (file)
@@ -146,8 +146,8 @@ func (f *nativeFunc) NewFrame() *Frame {
        return &Frame{nil, vars};
 }
 
-func (f *nativeFunc) Call(fr *Frame) {
-       f.fn(fr.Vars[0:f.in], fr.Vars[f.in:f.in+f.out]);
+func (f *nativeFunc) Call(t *Thread) {
+       f.fn(t.f.Vars[0:f.in], t.f.Vars[f.in:f.in+f.out]);
 }
 
 // FuncFromNative creates an interpreter function from a native
index e8619e137bc3dd1aff73e0dba56989f071c0b505..847a6f2fa7b0c85d34788eab90d86cfbf998374b 100644 (file)
@@ -277,12 +277,12 @@ func (*testFunc) NewFrame() *Frame {
        return &Frame{nil, &[2]Value {}};
 }
 
-func (*testFunc) Call(fr *Frame) {
-       n := fr.Vars[0].(IntValue).Get();
+func (*testFunc) Call(t *Thread) {
+       n := t.f.Vars[0].(IntValue).Get();
 
        res := n + 1;
 
-       fr.Vars[1].(IntValue).Set(res);
+       t.f.Vars[1].(IntValue).Set(res);
 }
 
 type oneTwoFunc struct {};
@@ -291,9 +291,9 @@ func (*oneTwoFunc) NewFrame() *Frame {
        return &Frame{nil, &[2]Value {}};
 }
 
-func (*oneTwoFunc) Call(fr *Frame) {
-       fr.Vars[0].(IntValue).Set(1);
-       fr.Vars[1].(IntValue).Set(2);
+func (*oneTwoFunc) Call(t *Thread) {
+       t.f.Vars[0].(IntValue).Set(1);
+       t.f.Vars[1].(IntValue).Set(2);
 }
 
 type voidFunc struct {};
@@ -302,7 +302,7 @@ func (*voidFunc) NewFrame() *Frame {
        return &Frame{nil, []Value {}};
 }
 
-func (*voidFunc) Call(fr *Frame) {
+func (*voidFunc) Call(t *Thread) {
 }
 
 func newTestScope() *Scope {
index 7f959d93d78f0555f48bbe6ee0a3041dd4cf5195..4415c84ed28ba117a220f8fea25a2907a58a3f9c 100644 (file)
@@ -26,16 +26,16 @@ type expr struct {
 
        // Map index expressions permit special forms of assignment,
        // for which we need to know the Map and key.
-       evalMapValue func(f *Frame) (Map, interface{});
+       evalMapValue func(t *Thread) (Map, interface{});
 
        // Evaluate to the "address of" this value; that is, the
        // settable Value object.  nil for expressions whose address
        // cannot be taken.
-       evalAddr func(f *Frame) Value;
+       evalAddr func(t *Thread) Value;
 
        // Execute this expression as a statement.  Only expressions
        // that are valid expression statements should set this.
-       exec func(f *Frame);
+       exec func(t *Thread);
 
        // If this expression is a type, this is its compiled type.
        // This is only permitted in the function position of a call
@@ -126,12 +126,12 @@ func (a *expr) convertTo(t Type) *expr {
                n, d := rat.Value();
                f := n.Quo(bignum.MakeInt(false, d));
                v := f.Abs().Value();
-               res.eval = func(*Frame) uint64 { return v };
+               res.eval = func(*Thread) uint64 { return v };
        case *intType:
                n, d := rat.Value();
                f := n.Quo(bignum.MakeInt(false, d));
                v := f.Value();
-               res.eval = func(*Frame) int64 { return v };
+               res.eval = func(*Thread) int64 { return v };
        case *idealIntType:
                n, d := rat.Value();
                f := n.Quo(bignum.MakeInt(false, d));
@@ -139,7 +139,7 @@ func (a *expr) convertTo(t Type) *expr {
        case *floatType:
                n, d := rat.Value();
                v := float64(n.Value())/float64(d.Value());
-               res.eval = func(*Frame) float64 { return v };
+               res.eval = func(*Thread) float64 { return v };
        case *idealFloatType:
                res.eval = func() *bignum.Rational { return rat };
        default:
@@ -172,8 +172,8 @@ func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
                // Convert to int
                na := a.newExpr(IntType, a.desc);
                af := a.asUint();
-               na.eval = func(f *Frame) int64 {
-                       return int64(af(f));
+               na.eval = func(t *Thread) int64 {
+                       return int64(af(t));
                };
                return na;
 
@@ -302,7 +302,7 @@ func (a *assignCompiler) allowMapForms(nls int) {
 // a function that expects an l-value and the frame in which to
 // evaluate the RHS expressions.  The l-value must have exactly the
 // type given by lt.  Returns nil if type checking fails.
-func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
+func (a *assignCompiler) compile(b *block, lt Type) (func(Value, *Thread)) {
        lmt, isMT := lt.(*MultiType);
        rmt, isUnpack := a.rmt, a.isUnpack;
 
@@ -333,7 +333,7 @@ func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
        // multi-value and replace the RHS with expressions to pull
        // out values from the temporary.  Technically, this is only
        // necessary when we need to perform assignment conversions.
-       var effect func(f *Frame);
+       var effect func(*Thread);
        if isUnpack {
                // This leaks a slot, but is definitely safe.
                temp := b.DefineSlot(a.rmt);
@@ -341,20 +341,20 @@ func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
                if a.isMapUnpack {
                        rf := a.rs[0].evalMapValue;
                        vt := a.rmt.Elems[0];
-                       effect = func(f *Frame) {
-                               m, k := rf(f);
+                       effect = func(t *Thread) {
+                               m, k := rf(t);
                                v := m.Elem(k);
                                found := boolV(true);
                                if v == nil {
                                        found = boolV(false);
                                        v = vt.Zero();
                                }
-                               f.Vars[tempIdx] = multiV([]Value {v, &found});
+                               t.f.Vars[tempIdx] = multiV([]Value {v, &found});
                        };
                } else {
                        rf := a.rs[0].asMulti();
-                       effect = func(f *Frame) {
-                               f.Vars[tempIdx] = multiV(rf(f));
+                       effect = func(t *Thread) {
+                               t.f.Vars[tempIdx] = multiV(rf(t));
                        };
                }
                orig := a.rs[0];
@@ -365,7 +365,7 @@ func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
                        }
                        a.rs[i] = orig.newExpr(t, orig.desc);
                        index := i;
-                       a.rs[i].genValue(func(f *Frame) Value { return f.Vars[tempIdx].(multiV)[index] });
+                       a.rs[i].genValue(func(t *Thread) Value { return t.f.Vars[tempIdx].(multiV)[index] });
                }
        }
        // Now len(a.rs) == len(a.rmt) and we've reduced any unpacking
@@ -400,8 +400,8 @@ func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
                                                rf := a.rs[i].asPtr();
                                                a.rs[i] = a.rs[i].newExpr(lt, a.rs[i].desc);
                                                len := at.Len;
-                                               a.rs[i].eval = func(f *Frame) Slice {
-                                                       return Slice{rf(f).(ArrayValue), len, len};
+                                               a.rs[i].eval = func(t *Thread) Slice {
+                                                       return Slice{rf(t).(ArrayValue), len, len};
                                                };
                                                rt = a.rs[i].t;
                                        }
@@ -428,17 +428,17 @@ func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
                return genAssign(lt, a.rs[0]);
        }
        // Case 2 or 3
-       as := make([]func(lv Value, f *Frame), len(a.rs));
+       as := make([]func(lv Value, t *Thread), len(a.rs));
        for i, r := range a.rs {
                as[i] = genAssign(lmt.Elems[i], r);
        }
-       return func(lv Value, f *Frame) {
+       return func(lv Value, t *Thread) {
                if effect != nil {
-                       effect(f);
+                       effect(t);
                }
                lmv := lv.(multiV);
                for i, a := range as {
-                       a(lmv[i], f);
+                       a(lmv[i], t);
                }
        };
 }
@@ -446,7 +446,7 @@ func (a *assignCompiler) compile(b *block, lt Type) (func(lv Value, f *Frame)) {
 // compileAssign compiles an assignment operation without the full
 // generality of an assignCompiler.  See assignCompiler for a
 // description of the arguments.
-func (a *compiler) compileAssign(pos token.Position, b *block, lt Type, rs []*expr, errOp, errPosName string) (func(lv Value, f *Frame)) {
+func (a *compiler) compileAssign(pos token.Position, b *block, lt Type, rs []*expr, errOp, errPosName string) (func(Value, *Thread)) {
        ac, ok := a.checkAssign(pos, rs, errOp, errPosName);
        if !ok {
                return nil;
@@ -758,7 +758,7 @@ func (a *exprInfo) compileString(s string) *expr {
 
        // TODO(austin) Use unnamed string type.
        expr := a.newExpr(StringType, "string literal");
-       expr.eval = func(*Frame) string { return s };
+       expr.eval = func(*Thread) string { return s };
        return expr;
 }
 
@@ -779,7 +779,7 @@ func (a *exprInfo) compileStringList(list []*expr) *expr {
        return a.compileString(strings.Join(ss, ""));
 }
 
-func (a *exprInfo) compileFuncLit(decl *FuncDecl, fn func(f *Frame) Func) *expr {
+func (a *exprInfo) compileFuncLit(decl *FuncDecl, fn func(*Thread) Func) *expr {
        expr := a.newExpr(decl.Type, "function literal");
        expr.eval = fn;
        return expr;
@@ -880,8 +880,8 @@ func (a *exprInfo) compileSelectorExpr(v *expr, name string) *expr {
                                        }
                                        expr := a.newExpr(ft, "selector expression");
                                        pf := parent.asStruct();
-                                       evalAddr := func(f *Frame) Value {
-                                               return pf(f).Field(index);
+                                       evalAddr := func(t *Thread) Value {
+                                               return pf(t).Field(index);
                                        };
                                        expr.genValue(evalAddr);
                                        return sub(expr);
@@ -964,10 +964,10 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
                lf := l.asArray();
                rf := r.asInt();
                bound := lt.Len;
-               expr.genValue(func(f *Frame) Value {
-                       l, r := lf(f), rf(f);
+               expr.genValue(func(t *Thread) Value {
+                       l, r := lf(t), rf(t);
                        if r < 0 || r >= bound {
-                               Abort(IndexOutOfBounds{r, bound});
+                               Abort(IndexError{r, bound});
                        }
                        return l.Elem(r);
                });
@@ -975,13 +975,13 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
        case *SliceType:
                lf := l.asSlice();
                rf := r.asInt();
-               expr.genValue(func(f *Frame) Value {
-                       l, r := lf(f), rf(f);
+               expr.genValue(func(t *Thread) Value {
+                       l, r := lf(t), rf(t);
                        if l.Base == nil {
-                               Abort(NilPointer{});
+                               Abort(NilPointerError{});
                        }
                        if r < 0 || r >= l.Len {
-                               Abort(IndexOutOfBounds{r, l.Len});
+                               Abort(IndexError{r, l.Len});
                        }
                        return l.Base.Elem(r);
                });
@@ -991,10 +991,10 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
                rf := r.asInt();
                // TODO(austin) This pulls over the whole string in a
                // remote setting, instead of just the one character.
-               expr.eval = func(f *Frame) uint64 {
-                       l, r := lf(f), rf(f);
+               expr.eval = func(t *Thread) uint64 {
+                       l, r := lf(t), rf(t);
                        if r < 0 || r >= int64(len(l)) {
-                               Abort(IndexOutOfBounds{r, int64(len(l))});
+                               Abort(IndexError{r, int64(len(l))});
                        }
                        return uint64(l[r]);
                }
@@ -1002,24 +1002,24 @@ func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
        case *MapType:
                lf := l.asMap();
                rf := r.asInterface();
-               expr.genValue(func(f *Frame) Value {
-                       m := lf(f);
-                       k := rf(f);
+               expr.genValue(func(t *Thread) Value {
+                       m := lf(t);
+                       k := rf(t);
                        if m == nil {
-                               Abort(NilPointer{});
+                               Abort(NilPointerError{});
                        }
                        e := m.Elem(k);
                        if e == nil {
-                               Abort(KeyNotFound{k});
+                               Abort(KeyError{k});
                        }
                        return e;
                });
                // genValue makes things addressable, but map values
                // aren't addressable.
                expr.evalAddr = nil;
-               expr.evalMapValue = func(f *Frame) (Map, interface{}) {
+               expr.evalMapValue = func(t *Thread) (Map, interface{}) {
                        // TODO(austin) Key check?  nil check?
-                       return lf(f), rf(f);
+                       return lf(t), rf(t);
                };
 
        default:
@@ -1080,14 +1080,17 @@ func (a *exprInfo) compileCallExpr(b *block, l *expr, as []*expr) *expr {
 
        // Compile
        lf := l.asFunc();
-       call := func(f *Frame) []Value {
-               fun := lf(f);
+       call := func(t *Thread) []Value {
+               fun := lf(t);
                fr := fun.NewFrame();
                for i, t := range vts {
                        fr.Vars[i] = t.Zero();
                }
-               assign(multiV(fr.Vars[0:nin]), f);
-               fun.Call(fr);
+               assign(multiV(fr.Vars[0:nin]), t);
+               oldf := t.f;
+               t.f = fr;
+               fun.Call(t);
+               t.f = oldf;
                return fr.Vars[nin:nin+nout];
        };
        expr.genFuncCall(call);
@@ -1119,14 +1122,14 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                        // TODO(austin) It would be nice if this could
                        // be a constant int.
                        v := t.Len;
-                       expr.eval = func(f *Frame) int64 {
+                       expr.eval = func(t *Thread) int64 {
                                return v;
                        };
 
                case *SliceType:
                        vf := arg.asSlice();
-                       expr.eval = func(f *Frame) int64 {
-                               return vf(f).Cap;
+                       expr.eval = func(t *Thread) int64 {
+                               return vf(t).Cap;
                        };
 
                //case *ChanType:
@@ -1146,30 +1149,30 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                switch t := arg.t.lit().(type) {
                case *stringType:
                        vf := arg.asString();
-                       expr.eval = func(f *Frame) int64 {
-                               return int64(len(vf(f)));
+                       expr.eval = func(t *Thread) int64 {
+                               return int64(len(vf(t)));
                        };
 
                case *ArrayType:
                        // TODO(austin) It would be nice if this could
                        // be a constant int.
                        v := t.Len;
-                       expr.eval = func(f *Frame) int64 {
+                       expr.eval = func(t *Thread) int64 {
                                return v;
                        };
 
                case *SliceType:
                        vf := arg.asSlice();
-                       expr.eval = func(f *Frame) int64 {
-                               return vf(f).Len;
+                       expr.eval = func(t *Thread) int64 {
+                               return vf(t).Len;
                        };
 
                case *MapType:
                        vf := arg.asMap();
-                       expr.eval = func(f *Frame) int64 {
+                       expr.eval = func(t *Thread) int64 {
                                // XXX(Spec) What's the len of an
                                // uninitialized map?
-                               m := vf(f);
+                               m := vf(t);
                                if m == nil {
                                        return 0;
                                }
@@ -1192,7 +1195,7 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                // arguments?  Do they have to be ints?  6g
                // accepts any integral type.
                var lenexpr, capexpr *expr;
-               var lenf, capf func(f *Frame) int64;
+               var lenf, capf func(*Thread) int64;
                if len(as) > 1 {
                        lenexpr = as[1].convertToInt(-1, "length", "make function");
                        if lenexpr == nil {
@@ -1220,18 +1223,18 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                        }
                        et := t.Elem;
                        expr := a.newExpr(t, "function call");
-                       expr.eval = func(f *Frame) Slice {
-                               l := lenf(f);
+                       expr.eval = func(t *Thread) Slice {
+                               l := lenf(t);
                                // XXX(Spec) What if len or cap is
                                // negative?  The runtime panics.
                                if l < 0 {
-                                       Abort(NegativeLength{l});
+                                       Abort(NegativeLengthError{l});
                                }
                                c := l;
                                if capf != nil {
-                                       c = capf(f);
+                                       c = capf(t);
                                        if c < 0 {
-                                               Abort(NegativeCapacity{c});
+                                               Abort(NegativeCapacityError{c});
                                        }
                                        // XXX(Spec) What happens if
                                        // len > cap?  The runtime
@@ -1257,11 +1260,11 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                                return nil;
                        }
                        expr := a.newExpr(t, "function call");
-                       expr.eval = func(f *Frame) Map {
+                       expr.eval = func(t *Thread) Map {
                                if lenf == nil {
                                        return make(evalMap);
                                }
-                               l := lenf(f);
+                               l := lenf(t);
                                return make(evalMap, l);
                        };
                        return expr;
@@ -1287,10 +1290,10 @@ func (a *exprInfo) compileStarExpr(v *expr) *expr {
        case *PtrType:
                expr := a.newExpr(vt.Elem, "indirect expression");
                vf := v.asPtr();
-               expr.genValue(func(f *Frame) Value {
-                       v := vf(f);
+               expr.genValue(func(t *Thread) Value {
+                       v := vf(t);
                        if v == nil {
-                               Abort(NilPointer{});
+                               Abort(NilPointerError{});
                        }
                        return v;
                });
@@ -1376,7 +1379,7 @@ func (a *exprInfo) compileUnaryExpr(op token.Token, v *expr) *expr {
 
        case token.AND:
                vf := v.evalAddr;
-               expr.eval = func(f *Frame) Value { return vf(f) };
+               expr.eval = func(t *Thread) Value { return vf(t) };
 
        default:
                log.Crashf("Compilation of unary op %v not implemented", op);
@@ -1781,7 +1784,7 @@ func (a *compiler) compileExpr(b *block, constant bool, expr ast.Expr) *expr {
 // temporary variable, the caller should create a temporary block for
 // the compilation of this expression and the evaluation of the
 // results.
-func (a *expr) extractEffect(b *block, errOp string) (func(f *Frame), *expr) {
+func (a *expr) extractEffect(b *block, errOp string) (func(*Thread), *expr) {
        // Create "&a" if a is addressable
        rhs := a;
        if a.evalAddr != nil {
@@ -1818,10 +1821,10 @@ func (a *expr) extractEffect(b *block, errOp string) (func(f *Frame), *expr) {
                log.Crashf("compileAssign type check failed");
        }
 
-       effect := func(f *Frame) {
+       effect := func(t *Thread) {
                tempVal := tempType.Zero();
-               f.Vars[tempIdx] = tempVal;
-               assign(tempVal, f);
+               t.f.Vars[tempIdx] = tempVal;
+               assign(tempVal, t);
        };
 
        // Generate "temp" or "*temp"
@@ -1850,6 +1853,8 @@ func (expr *Expr) Type() Type {
 }
 
 func (expr *Expr) Eval(f *Frame) (Value, os.Error) {
+       t := new(Thread);
+       t.f = f;
        switch _ := expr.e.t.(type) {
        case *idealIntType:
                return &idealIntV{expr.e.asIdealInt()()}, nil;
@@ -1858,7 +1863,7 @@ func (expr *Expr) Eval(f *Frame) (Value, os.Error) {
        }
        v := expr.e.t.Zero();
        eval := genAssign(expr.e.t, expr.e);
-       err := Try(func() {eval(v, f)});
+       err := Try(func() {eval(v, t)});
        return v, err;
 }
 
index 1bbe87242c1568e9ec0f442a8cad04c36267c8a7..dce004f40fbab450dedcf7cbbb02d82cf5641c94 100644 (file)
@@ -1,6 +1,6 @@
 
 // This file is machine generated by gen.go.
-// 6g gen.go && 6l gen.6 && 6.out >expr1.go
+// 6g gen.go && 6l gen.6 && ./6.out >expr1.go
 
 package eval
 
@@ -13,77 +13,77 @@ import (
  * "As" functions.  These retrieve evaluator functions from an
  * expr, panicking if the requested evaluator has the wrong type.
  */
-func (a *expr) asBool() (func(*Frame) bool) {
-       return a.eval.(func(*Frame)(bool))
+func (a *expr) asBool() (func(*Thread) bool) {
+       return a.eval.(func(*Thread)(bool))
 }
-func (a *expr) asUint() (func(*Frame) uint64) {
-       return a.eval.(func(*Frame)(uint64))
+func (a *expr) asUint() (func(*Thread) uint64) {
+       return a.eval.(func(*Thread)(uint64))
 }
-func (a *expr) asInt() (func(*Frame) int64) {
-       return a.eval.(func(*Frame)(int64))
+func (a *expr) asInt() (func(*Thread) int64) {
+       return a.eval.(func(*Thread)(int64))
 }
 func (a *expr) asIdealInt() (func() *bignum.Integer) {
        return a.eval.(func()(*bignum.Integer))
 }
-func (a *expr) asFloat() (func(*Frame) float64) {
-       return a.eval.(func(*Frame)(float64))
+func (a *expr) asFloat() (func(*Thread) float64) {
+       return a.eval.(func(*Thread)(float64))
 }
 func (a *expr) asIdealFloat() (func() *bignum.Rational) {
        return a.eval.(func()(*bignum.Rational))
 }
-func (a *expr) asString() (func(*Frame) string) {
-       return a.eval.(func(*Frame)(string))
+func (a *expr) asString() (func(*Thread) string) {
+       return a.eval.(func(*Thread)(string))
 }
-func (a *expr) asArray() (func(*Frame) ArrayValue) {
-       return a.eval.(func(*Frame)(ArrayValue))
+func (a *expr) asArray() (func(*Thread) ArrayValue) {
+       return a.eval.(func(*Thread)(ArrayValue))
 }
-func (a *expr) asStruct() (func(*Frame) StructValue) {
-       return a.eval.(func(*Frame)(StructValue))
+func (a *expr) asStruct() (func(*Thread) StructValue) {
+       return a.eval.(func(*Thread)(StructValue))
 }
-func (a *expr) asPtr() (func(*Frame) Value) {
-       return a.eval.(func(*Frame)(Value))
+func (a *expr) asPtr() (func(*Thread) Value) {
+       return a.eval.(func(*Thread)(Value))
 }
-func (a *expr) asFunc() (func(*Frame) Func) {
-       return a.eval.(func(*Frame)(Func))
+func (a *expr) asFunc() (func(*Thread) Func) {
+       return a.eval.(func(*Thread)(Func))
 }
-func (a *expr) asSlice() (func(*Frame) Slice) {
-       return a.eval.(func(*Frame)(Slice))
+func (a *expr) asSlice() (func(*Thread) Slice) {
+       return a.eval.(func(*Thread)(Slice))
 }
-func (a *expr) asMap() (func(*Frame) Map) {
-       return a.eval.(func(*Frame)(Map))
+func (a *expr) asMap() (func(*Thread) Map) {
+       return a.eval.(func(*Thread)(Map))
 }
-func (a *expr) asMulti() (func(*Frame) []Value) {
-       return a.eval.(func(*Frame)[]Value)
+func (a *expr) asMulti() (func(*Thread) []Value) {
+       return a.eval.(func(*Thread)[]Value)
 }
 
-func (a *expr) asInterface() (func(*Frame) interface{}) {
+func (a *expr) asInterface() (func(*Thread) interface{}) {
        switch sf := a.eval.(type) {
-       case func(*Frame)bool:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)uint64:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)int64:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)*bignum.Integer:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)float64:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)*bignum.Rational:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)string:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)ArrayValue:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)StructValue:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)Value:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)Func:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)Slice:
-               return func(f *Frame) interface{} { return sf(f) }
-       case func(*Frame)Map:
-               return func(f *Frame) interface{} { return sf(f) }
+       case func(*Thread)bool:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)uint64:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)int64:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)*bignum.Integer:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)float64:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)*bignum.Rational:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)string:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)ArrayValue:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)StructValue:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)Value:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)Func:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)Slice:
+               return func(t *Thread) interface{} { return sf(t) }
+       case func(*Thread)Map:
+               return func(t *Thread) interface{} { return sf(t) }
        default:
                log.Crashf("unexpected expression node type %T at %v", a.eval, a.pos);
        }
@@ -98,135 +98,135 @@ func (a *expr) genConstant(v Value) {
        switch _ := a.t.lit().(type) {
        case *boolType:
                val := v.(BoolValue).Get();
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *uintType:
                val := v.(UintValue).Get();
-               a.eval = func(f *Frame) uint64 { return val }
+               a.eval = func(t *Thread) uint64 { return val }
        case *intType:
                val := v.(IntValue).Get();
-               a.eval = func(f *Frame) int64 { return val }
+               a.eval = func(t *Thread) int64 { return val }
        case *idealIntType:
                val := v.(IdealIntValue).Get();
                a.eval = func() *bignum.Integer { return val }
        case *floatType:
                val := v.(FloatValue).Get();
-               a.eval = func(f *Frame) float64 { return val }
+               a.eval = func(t *Thread) float64 { return val }
        case *idealFloatType:
                val := v.(IdealFloatValue).Get();
                a.eval = func() *bignum.Rational { return val }
        case *stringType:
                val := v.(StringValue).Get();
-               a.eval = func(f *Frame) string { return val }
+               a.eval = func(t *Thread) string { return val }
        case *ArrayType:
                val := v.(ArrayValue).Get();
-               a.eval = func(f *Frame) ArrayValue { return val }
+               a.eval = func(t *Thread) ArrayValue { return val }
        case *StructType:
                val := v.(StructValue).Get();
-               a.eval = func(f *Frame) StructValue { return val }
+               a.eval = func(t *Thread) StructValue { return val }
        case *PtrType:
                val := v.(PtrValue).Get();
-               a.eval = func(f *Frame) Value { return val }
+               a.eval = func(t *Thread) Value { return val }
        case *FuncType:
                val := v.(FuncValue).Get();
-               a.eval = func(f *Frame) Func { return val }
+               a.eval = func(t *Thread) Func { return val }
        case *SliceType:
                val := v.(SliceValue).Get();
-               a.eval = func(f *Frame) Slice { return val }
+               a.eval = func(t *Thread) Slice { return val }
        case *MapType:
                val := v.(MapValue).Get();
-               a.eval = func(f *Frame) Map { return val }
+               a.eval = func(t *Thread) Map { return val }
        default:
                log.Crashf("unexpected constant type %v at %v", a.t, a.pos);
        }
 }
 
 func (a *expr) genIdentOp(level, index int) {
-       a.evalAddr = func(f *Frame) Value { return f.Get(level, index) };
+       a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) };
        switch _ := a.t.lit().(type) {
        case *boolType:
-               a.eval = func(f *Frame) bool { return f.Get(level, index).(BoolValue).Get() }
+               a.eval = func(t *Thread) bool { return t.f.Get(level, index).(BoolValue).Get() }
        case *uintType:
-               a.eval = func(f *Frame) uint64 { return f.Get(level, index).(UintValue).Get() }
+               a.eval = func(t *Thread) uint64 { return t.f.Get(level, index).(UintValue).Get() }
        case *intType:
-               a.eval = func(f *Frame) int64 { return f.Get(level, index).(IntValue).Get() }
+               a.eval = func(t *Thread) int64 { return t.f.Get(level, index).(IntValue).Get() }
        case *floatType:
-               a.eval = func(f *Frame) float64 { return f.Get(level, index).(FloatValue).Get() }
+               a.eval = func(t *Thread) float64 { return t.f.Get(level, index).(FloatValue).Get() }
        case *stringType:
-               a.eval = func(f *Frame) string { return f.Get(level, index).(StringValue).Get() }
+               a.eval = func(t *Thread) string { return t.f.Get(level, index).(StringValue).Get() }
        case *ArrayType:
-               a.eval = func(f *Frame) ArrayValue { return f.Get(level, index).(ArrayValue).Get() }
+               a.eval = func(t *Thread) ArrayValue { return t.f.Get(level, index).(ArrayValue).Get() }
        case *StructType:
-               a.eval = func(f *Frame) StructValue { return f.Get(level, index).(StructValue).Get() }
+               a.eval = func(t *Thread) StructValue { return t.f.Get(level, index).(StructValue).Get() }
        case *PtrType:
-               a.eval = func(f *Frame) Value { return f.Get(level, index).(PtrValue).Get() }
+               a.eval = func(t *Thread) Value { return t.f.Get(level, index).(PtrValue).Get() }
        case *FuncType:
-               a.eval = func(f *Frame) Func { return f.Get(level, index).(FuncValue).Get() }
+               a.eval = func(t *Thread) Func { return t.f.Get(level, index).(FuncValue).Get() }
        case *SliceType:
-               a.eval = func(f *Frame) Slice { return f.Get(level, index).(SliceValue).Get() }
+               a.eval = func(t *Thread) Slice { return t.f.Get(level, index).(SliceValue).Get() }
        case *MapType:
-               a.eval = func(f *Frame) Map { return f.Get(level, index).(MapValue).Get() }
+               a.eval = func(t *Thread) Map { return t.f.Get(level, index).(MapValue).Get() }
        default:
                log.Crashf("unexpected identifier type %v at %v", a.t, a.pos);
        }
 }
 
-func (a *expr) genFuncCall(call func(f *Frame) []Value) {
-       a.exec = func(f *Frame) { call(f)};
+func (a *expr) genFuncCall(call func(t *Thread) []Value) {
+       a.exec = func(t *Thread) { call(t)};
        switch _ := a.t.lit().(type) {
        case *boolType:
-               a.eval = func(f *Frame) bool { return call(f)[0].(BoolValue).Get() }
+               a.eval = func(t *Thread) bool { return call(t)[0].(BoolValue).Get() }
        case *uintType:
-               a.eval = func(f *Frame) uint64 { return call(f)[0].(UintValue).Get() }
+               a.eval = func(t *Thread) uint64 { return call(t)[0].(UintValue).Get() }
        case *intType:
-               a.eval = func(f *Frame) int64 { return call(f)[0].(IntValue).Get() }
+               a.eval = func(t *Thread) int64 { return call(t)[0].(IntValue).Get() }
        case *floatType:
-               a.eval = func(f *Frame) float64 { return call(f)[0].(FloatValue).Get() }
+               a.eval = func(t *Thread) float64 { return call(t)[0].(FloatValue).Get() }
        case *stringType:
-               a.eval = func(f *Frame) string { return call(f)[0].(StringValue).Get() }
+               a.eval = func(t *Thread) string { return call(t)[0].(StringValue).Get() }
        case *ArrayType:
-               a.eval = func(f *Frame) ArrayValue { return call(f)[0].(ArrayValue).Get() }
+               a.eval = func(t *Thread) ArrayValue { return call(t)[0].(ArrayValue).Get() }
        case *StructType:
-               a.eval = func(f *Frame) StructValue { return call(f)[0].(StructValue).Get() }
+               a.eval = func(t *Thread) StructValue { return call(t)[0].(StructValue).Get() }
        case *PtrType:
-               a.eval = func(f *Frame) Value { return call(f)[0].(PtrValue).Get() }
+               a.eval = func(t *Thread) Value { return call(t)[0].(PtrValue).Get() }
        case *FuncType:
-               a.eval = func(f *Frame) Func { return call(f)[0].(FuncValue).Get() }
+               a.eval = func(t *Thread) Func { return call(t)[0].(FuncValue).Get() }
        case *SliceType:
-               a.eval = func(f *Frame) Slice { return call(f)[0].(SliceValue).Get() }
+               a.eval = func(t *Thread) Slice { return call(t)[0].(SliceValue).Get() }
        case *MapType:
-               a.eval = func(f *Frame) Map { return call(f)[0].(MapValue).Get() }
+               a.eval = func(t *Thread) Map { return call(t)[0].(MapValue).Get() }
        case *MultiType:
-               a.eval = func(f *Frame) []Value { return call(f) }
+               a.eval = func(t *Thread) []Value { return call(t) }
        default:
                log.Crashf("unexpected result type %v at %v", a.t, a.pos);
        }
 }
 
-func (a *expr) genValue(vf func(*Frame) Value) {
+func (a *expr) genValue(vf func(*Thread) Value) {
        a.evalAddr = vf;
        switch _ := a.t.lit().(type) {
        case *boolType:
-               a.eval = func(f *Frame) bool { return vf(f).(BoolValue).Get() }
+               a.eval = func(t *Thread) bool { return vf(t).(BoolValue).Get() }
        case *uintType:
-               a.eval = func(f *Frame) uint64 { return vf(f).(UintValue).Get() }
+               a.eval = func(t *Thread) uint64 { return vf(t).(UintValue).Get() }
        case *intType:
-               a.eval = func(f *Frame) int64 { return vf(f).(IntValue).Get() }
+               a.eval = func(t *Thread) int64 { return vf(t).(IntValue).Get() }
        case *floatType:
-               a.eval = func(f *Frame) float64 { return vf(f).(FloatValue).Get() }
+               a.eval = func(t *Thread) float64 { return vf(t).(FloatValue).Get() }
        case *stringType:
-               a.eval = func(f *Frame) string { return vf(f).(StringValue).Get() }
+               a.eval = func(t *Thread) string { return vf(t).(StringValue).Get() }
        case *ArrayType:
-               a.eval = func(f *Frame) ArrayValue { return vf(f).(ArrayValue).Get() }
+               a.eval = func(t *Thread) ArrayValue { return vf(t).(ArrayValue).Get() }
        case *StructType:
-               a.eval = func(f *Frame) StructValue { return vf(f).(StructValue).Get() }
+               a.eval = func(t *Thread) StructValue { return vf(t).(StructValue).Get() }
        case *PtrType:
-               a.eval = func(f *Frame) Value { return vf(f).(PtrValue).Get() }
+               a.eval = func(t *Thread) Value { return vf(t).(PtrValue).Get() }
        case *FuncType:
-               a.eval = func(f *Frame) Func { return vf(f).(FuncValue).Get() }
+               a.eval = func(t *Thread) Func { return vf(t).(FuncValue).Get() }
        case *SliceType:
-               a.eval = func(f *Frame) Slice { return vf(f).(SliceValue).Get() }
+               a.eval = func(t *Thread) Slice { return vf(t).(SliceValue).Get() }
        case *MapType:
-               a.eval = func(f *Frame) Map { return vf(f).(MapValue).Get() }
+               a.eval = func(t *Thread) Map { return vf(t).(MapValue).Get() }
        default:
                log.Crashf("unexpected result type %v at %v", a.t, a.pos);
        }
@@ -236,17 +236,17 @@ func (a *expr) genUnaryOpNeg(v *expr) {
        switch _ := a.t.lit().(type) {
        case *uintType:
                vf := v.asUint();
-               a.eval = func(f *Frame) uint64 { v := vf(f); return -v }
+               a.eval = func(t *Thread) uint64 { v := vf(t); return -v }
        case *intType:
                vf := v.asInt();
-               a.eval = func(f *Frame) int64 { v := vf(f); return -v }
+               a.eval = func(t *Thread) int64 { v := vf(t); return -v }
        case *idealIntType:
                v := v.asIdealInt()();
                val := v.Neg();
                a.eval = func() *bignum.Integer { return val }
        case *floatType:
                vf := v.asFloat();
-               a.eval = func(f *Frame) float64 { v := vf(f); return -v }
+               a.eval = func(t *Thread) float64 { v := vf(t); return -v }
        case *idealFloatType:
                v := v.asIdealFloat()();
                val := v.Neg();
@@ -260,7 +260,7 @@ func (a *expr) genUnaryOpNot(v *expr) {
        switch _ := a.t.lit().(type) {
        case *boolType:
                vf := v.asBool();
-               a.eval = func(f *Frame) bool { v := vf(f); return !v }
+               a.eval = func(t *Thread) bool { v := vf(t); return !v }
        default:
                log.Crashf("unexpected type %v at %v", a.t, a.pos);
        }
@@ -270,10 +270,10 @@ func (a *expr) genUnaryOpXor(v *expr) {
        switch _ := a.t.lit().(type) {
        case *uintType:
                vf := v.asUint();
-               a.eval = func(f *Frame) uint64 { v := vf(f); return ^v }
+               a.eval = func(t *Thread) uint64 { v := vf(t); return ^v }
        case *intType:
                vf := v.asInt();
-               a.eval = func(f *Frame) int64 { v := vf(f); return ^v }
+               a.eval = func(t *Thread) int64 { v := vf(t); return ^v }
        case *idealIntType:
                v := v.asIdealInt()();
                val := v.Neg().Sub(bignum.Int(1));
@@ -288,11 +288,11 @@ func (a *expr) genBinOpAdd(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l + r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l + r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l + r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l + r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -301,7 +301,7 @@ func (a *expr) genBinOpAdd(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) float64 { l, r := lf(f), rf(f); return l + r }
+               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); return l + r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -310,7 +310,7 @@ func (a *expr) genBinOpAdd(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) string { l, r := lf(f), rf(f); return l + r }
+               a.eval = func(t *Thread) string { l, r := lf(t), rf(t); return l + r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -321,11 +321,11 @@ func (a *expr) genBinOpSub(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l - r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l - r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l - r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l - r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -334,7 +334,7 @@ func (a *expr) genBinOpSub(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) float64 { l, r := lf(f), rf(f); return l - r }
+               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); return l - r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -350,11 +350,11 @@ func (a *expr) genBinOpMul(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l * r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l * r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l * r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l * r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -363,7 +363,7 @@ func (a *expr) genBinOpMul(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) float64 { l, r := lf(f), rf(f); return l * r }
+               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); return l * r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -379,11 +379,11 @@ func (a *expr) genBinOpQuo(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) } return l / r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l / r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) } return l / r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l / r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -392,7 +392,7 @@ func (a *expr) genBinOpQuo(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) float64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) } return l / r }
+               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l / r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -408,11 +408,11 @@ func (a *expr) genBinOpRem(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) } return l % r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l % r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) } return l % r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { Abort(DivByZeroError{}) } return l % r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -428,11 +428,11 @@ func (a *expr) genBinOpAnd(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l & r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l & r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l & r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l & r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -448,11 +448,11 @@ func (a *expr) genBinOpOr(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l | r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l | r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l | r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l | r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -468,11 +468,11 @@ func (a *expr) genBinOpXor(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l ^ r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l ^ r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l ^ r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l ^ r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -488,11 +488,11 @@ func (a *expr) genBinOpAndNot(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l &^ r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l &^ r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l &^ r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l &^ r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -508,11 +508,11 @@ func (a *expr) genBinOpShl(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l << r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l << r }
        case *intType:
                lf := l.asInt();
                rf := r.asUint();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l << r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l << r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -523,11 +523,11 @@ func (a *expr) genBinOpShr(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) uint64 { l, r := lf(f), rf(f); return l >> r }
+               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l >> r }
        case *intType:
                lf := l.asInt();
                rf := r.asUint();
-               a.eval = func(f *Frame) int64 { l, r := lf(f), rf(f); return l >> r }
+               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l >> r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -538,29 +538,29 @@ func (a *expr) genBinOpLss(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l < r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l < r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l < r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l < r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
                val := l.Cmp(r) < 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l < r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l < r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
                val := l.Cmp(r) < 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l < r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l < r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -571,29 +571,29 @@ func (a *expr) genBinOpGtr(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l > r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l > r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l > r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l > r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
                val := l.Cmp(r) > 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l > r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l > r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
                val := l.Cmp(r) > 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l > r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l > r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -604,29 +604,29 @@ func (a *expr) genBinOpLeq(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l <= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l <= r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l <= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l <= r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
                val := l.Cmp(r) <= 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l <= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l <= r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
                val := l.Cmp(r) <= 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l <= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l <= r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -637,29 +637,29 @@ func (a *expr) genBinOpGeq(l, r *expr) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l >= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l >= r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l >= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l >= r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
                val := l.Cmp(r) >= 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l >= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l >= r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
                val := l.Cmp(r) >= 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l >= r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l >= r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -670,45 +670,45 @@ func (a *expr) genBinOpEql(l, r *expr) {
        case *boolType:
                lf := l.asBool();
                rf := r.asBool();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
                val := l.Cmp(r) == 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
                val := l.Cmp(r) == 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *PtrType:
                lf := l.asPtr();
                rf := r.asPtr();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *FuncType:
                lf := l.asFunc();
                rf := r.asFunc();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        case *MapType:
                lf := l.asMap();
                rf := r.asMap();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l == r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l == r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
@@ -719,85 +719,85 @@ func (a *expr) genBinOpNeq(l, r *expr) {
        case *boolType:
                lf := l.asBool();
                rf := r.asBool();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
                val := l.Cmp(r) != 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
                val := l.Cmp(r) != 0;
-               a.eval = func(f *Frame) bool { return val }
+               a.eval = func(t *Thread) bool { return val }
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *PtrType:
                lf := l.asPtr();
                rf := r.asPtr();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *FuncType:
                lf := l.asFunc();
                rf := r.asFunc();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        case *MapType:
                lf := l.asMap();
                rf := r.asMap();
-               a.eval = func(f *Frame) bool { l, r := lf(f), rf(f); return l != r }
+               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); return l != r }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
 }
 
-func genAssign(lt Type, r *expr) (func(lv Value, f *Frame)) {
+func genAssign(lt Type, r *expr) (func(lv Value, t *Thread)) {
        switch _ := lt.lit().(type) {
        case *boolType:
                rf := r.asBool();
-               return func(lv Value, f *Frame) { lv.(BoolValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(BoolValue).Set(rf(t)) }
        case *uintType:
                rf := r.asUint();
-               return func(lv Value, f *Frame) { lv.(UintValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(UintValue).Set(rf(t)) }
        case *intType:
                rf := r.asInt();
-               return func(lv Value, f *Frame) { lv.(IntValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(IntValue).Set(rf(t)) }
        case *floatType:
                rf := r.asFloat();
-               return func(lv Value, f *Frame) { lv.(FloatValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(FloatValue).Set(rf(t)) }
        case *stringType:
                rf := r.asString();
-               return func(lv Value, f *Frame) { lv.(StringValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(StringValue).Set(rf(t)) }
        case *ArrayType:
                rf := r.asArray();
-               return func(lv Value, f *Frame) { lv.Assign(rf(f)) }
+               return func(lv Value, t *Thread) { lv.Assign(rf(t)) }
        case *StructType:
                rf := r.asStruct();
-               return func(lv Value, f *Frame) { lv.Assign(rf(f)) }
+               return func(lv Value, t *Thread) { lv.Assign(rf(t)) }
        case *PtrType:
                rf := r.asPtr();
-               return func(lv Value, f *Frame) { lv.(PtrValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(PtrValue).Set(rf(t)) }
        case *FuncType:
                rf := r.asFunc();
-               return func(lv Value, f *Frame) { lv.(FuncValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(FuncValue).Set(rf(t)) }
        case *SliceType:
                rf := r.asSlice();
-               return func(lv Value, f *Frame) { lv.(SliceValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(SliceValue).Set(rf(t)) }
        case *MapType:
                rf := r.asMap();
-               return func(lv Value, f *Frame) { lv.(MapValue).Set(rf(f)) }
+               return func(lv Value, t *Thread) { lv.(MapValue).Set(rf(t)) }
        default:
                log.Crashf("unexpected left operand type %v at %v", lt, r.pos);
        }
index 2281b644d4cb04a08b972d81cb9056de61748490..d13fbbed4054d9deb16586bc264a08a4ebc10074 100644 (file)
@@ -8,18 +8,17 @@ package eval
  * Virtual machine
  */
 
-type vm struct {
+type Thread struct {
        pc uint;
        // The execution frame of this function.  This remains the
        // same throughout a function invocation.
        f *Frame;
 }
 
-type code []func(*vm)
-
-func (i code) exec(fr *Frame) {
-       v := vm{0, fr};
+type code []func(*Thread)
 
+func (i code) exec(t *Thread) {
+       v := Thread{0, t.f};    // TODO: reuse t
        l := uint(len(i));
        for v.pc < l {
                pc := v.pc;
@@ -40,7 +39,7 @@ func newCodeBuf() *codeBuf {
        return &codeBuf{make(code, 0, 16)};
 }
 
-func (b *codeBuf) push(instr func(*vm)) {
+func (b *codeBuf) push(instr func(*Thread)) {
        n := len(b.instrs);
        if n >= cap(b.instrs) {
                a := make(code, n, n*2);
@@ -80,6 +79,6 @@ func (f *evalFunc) NewFrame() *Frame {
        return f.outer.child(f.frameSize);
 }
 
-func (f *evalFunc) Call(fr *Frame) {
-       f.code.exec(fr);
+func (f *evalFunc) Call(t *Thread) {
+       f.code.exec(t);
 }
index c9b5ab6e3b54458f100241d6010732d572b91191..a9d088db8c395a0c84011b5250f462348733737d 100644 (file)
@@ -91,12 +91,12 @@ var binOps = []Op{
        Op{ Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(r)", Types: numbers },
        Op{ Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(r)", Types: numbers },
        Op{ Name: "Quo",
-               Body: "if r == 0 { Abort(DivByZero{}) } return l / r",
+               Body: "if r == 0 { Abort(DivByZeroError{}) } return l / r",
                ConstExpr: "l.Quo(r)",
                Types: numbers,
        },
        Op{ Name: "Rem",
-               Body: "if r == 0 { Abort(DivByZero{}) } return l % r",
+               Body: "if r == 0 { Abort(DivByZeroError{}) } return l % r",
                ConstExpr: "l.Rem(r)",
                Types: integers,
        },
@@ -151,23 +151,23 @@ func (a *expr) «As»() (func() «Native») {
        return a.eval.(func()(«Native»))
 }
 «.or»
-func (a *expr) «As»() (func(*Frame) «Native») {
-       return a.eval.(func(*Frame)(«Native»))
+func (a *expr) «As»() (func(*Thread) «Native») {
+       return a.eval.(func(*Thread)(«Native»))
 }
 «.end»
 «.end»
-func (a *expr) asMulti() (func(*Frame) []Value) {
-       return a.eval.(func(*Frame)[]Value)
+func (a *expr) asMulti() (func(*Thread) []Value) {
+       return a.eval.(func(*Thread)[]Value)
 }
 
-func (a *expr) asInterface() (func(*Frame) interface{}) {
+func (a *expr) asInterface() (func(*Thread) interface{}) {
        switch sf := a.eval.(type) {
 «.repeated section Types»
-       case func(*Frame)«Native»:
+       case func(*Thread)«Native»:
 «.section IsIdeal»
-               return func(f *Frame) interface{} { return sf(f) }
+               return func(t *Thread) interface{} { return sf(t) }
 «.or»
-               return func(f *Frame) interface{} { return sf(f) }
+               return func(t *Thread) interface{} { return sf(t) }
 «.end»
 «.end»
        default:
@@ -188,7 +188,7 @@ func (a *expr) genConstant(v Value) {
 «.section IsIdeal»
                a.eval = func() «Native» { return val }
 «.or»
-               a.eval = func(f *Frame) «Native» { return val }
+               a.eval = func(t *Thread) «Native» { return val }
 «.end»
 «.end»
        default:
@@ -197,13 +197,13 @@ func (a *expr) genConstant(v Value) {
 }
 
 func (a *expr) genIdentOp(level, index int) {
-       a.evalAddr = func(f *Frame) Value { return f.Get(level, index) };
+       a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) };
        switch _ := a.t.lit().(type) {
 «.repeated section Types»
 «.section IsIdeal»
 «.or»
        case «Repr»:
-               a.eval = func(f *Frame) «Native» { return f.Get(level, index).(«Value»).Get() }
+               a.eval = func(t *Thread) «Native» { return t.f.Get(level, index).(«Value»).Get() }
 «.end»
 «.end»
        default:
@@ -211,31 +211,31 @@ func (a *expr) genIdentOp(level, index int) {
        }
 }
 
-func (a *expr) genFuncCall(call func(f *Frame) []Value) {
-       a.exec = func(f *Frame) { call(f)};
+func (a *expr) genFuncCall(call func(t *Thread) []Value) {
+       a.exec = func(t *Thread) { call(t)};
        switch _ := a.t.lit().(type) {
 «.repeated section Types»
 «.section IsIdeal»
 «.or»
        case «Repr»:
-               a.eval = func(f *Frame) «Native» { return call(f)[0].(«Value»).Get() }
+               a.eval = func(t *Thread) «Native» { return call(t)[0].(«Value»).Get() }
 «.end»
 «.end»
        case *MultiType:
-               a.eval = func(f *Frame) []Value { return call(f) }
+               a.eval = func(t *Thread) []Value { return call(t) }
        default:
                log.Crashf("unexpected result type %v at %v", a.t, a.pos);
        }
 }
 
-func (a *expr) genValue(vf func(*Frame) Value) {
+func (a *expr) genValue(vf func(*Thread) Value) {
        a.evalAddr = vf;
        switch _ := a.t.lit().(type) {
 «.repeated section Types»
 «.section IsIdeal»
 «.or»
        case «Repr»:
-               a.eval = func(f *Frame) «Native» { return vf(f).(«Value»).Get() }
+               a.eval = func(t *Thread) «Native» { return vf(t).(«Value»).Get() }
 «.end»
 «.end»
        default:
@@ -254,7 +254,7 @@ func (a *expr) genUnaryOp«Name»(v *expr) {
                a.eval = func() «Native» { return val }
 «.or»
                vf := v.«As»();
-               a.eval = func(f *Frame) «Native» { v := vf(f); return «Expr» }
+               a.eval = func(t *Thread) «Native» { v := vf(t); return «Expr» }
 «.end»
 «.end»
        default:
@@ -273,14 +273,14 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
                r := r.«As»()();
                val := «ConstExpr»;
 «.section ReturnType»
-               a.eval = func(f *Frame) «ReturnType» { return val }
+               a.eval = func(t *Thread) «ReturnType» { return val }
 «.or»
                a.eval = func() «Native» { return val }
 «.end»
 «.or»
                lf := l.«As»();
                rf := r.«.section AsRightName»«@»«.or»«As»«.end»();
-               a.eval = func(f *Frame) «.section ReturnType»«@»«.or»«Native»«.end» { l, r := lf(f), rf(f); «.section Body»«Body»«.or»return «Expr»«.end» }
+               a.eval = func(t *Thread) «.section ReturnType»«@»«.or»«Native»«.end» { l, r := lf(t), rf(t); «.section Body»«Body»«.or»return «Expr»«.end» }
 «.end»
 «.end»
        default:
@@ -289,14 +289,14 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
 }
 
 «.end»
-func genAssign(lt Type, r *expr) (func(lv Value, f *Frame)) {
+func genAssign(lt Type, r *expr) (func(lv Value, t *Thread)) {
        switch _ := lt.lit().(type) {
 «.repeated section Types»
 «.section IsIdeal»
 «.or»
        case «Repr»:
                rf := r.«As»();
-               return func(lv Value, f *Frame) { «.section HasAssign»lv.Assign(rf(f))«.or»lv.(«Value»).Set(rf(f))«.end» }
+               return func(lv Value, t *Thread) { «.section HasAssign»lv.Assign(rf(t))«.or»lv.(«Value»).Set(rf(t))«.end» }
 «.end»
 «.end»
        default:
index 9002b980f53840b96bcee68943d0f40f06df0885..50a776e35e4547b7abc58337a028dea821ab0e8e 100644 (file)
@@ -230,7 +230,7 @@ func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
 
        // Initialize the variable
        index := v.Index;
-       a.push(func(v *vm) {
+       a.push(func(v *Thread) {
                v.f.Vars[index] = t.Zero();
        });
        return v;
@@ -416,10 +416,7 @@ func (a *stmtCompiler) compileExprStmt(s *ast.ExprStmt) {
                return;
        }
 
-       exec := e.exec;
-       a.push(func(v *vm) {
-               exec(v.f);
-       });
+       a.push(e.exec);
 }
 
 func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
@@ -471,9 +468,9 @@ func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
        }
 
        lf := l.evalAddr;
-       a.push(func(v *vm) {
-               effect(v.f);
-               assign(lf(v.f), v.f);
+       a.push(func(v *Thread) {
+               effect(v);
+               assign(lf(v), v);
        });
 }
 
@@ -605,8 +602,8 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
                        ls[i].evalMapValue = sub.evalMapValue;
                        mvf := sub.evalMapValue;
                        et := sub.t;
-                       ls[i].evalAddr = func(f *Frame) Value {
-                               m, k := mvf(f);
+                       ls[i].evalAddr = func(t *Thread) Value {
+                               m, k := mvf(t);
                                e := m.Elem(k);
                                if e == nil {
                                        e = et.Zero();
@@ -666,35 +663,35 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
        if n == 1 {
                // Don't need temporaries and can avoid []Value.
                lf := ls[0].evalAddr;
-               a.push(func(v *vm) { assign(lf(v.f), v.f) });
+               a.push(func(t *Thread) { assign(lf(t), t) });
        } else if tok == token.VAR || (tok == token.DEFINE && nDefs == n) {
                // Don't need temporaries
-               lfs := make([]func(*Frame) Value, n);
+               lfs := make([]func(*Thread) Value, n);
                for i, l := range ls {
                        lfs[i] = l.evalAddr;
                }
-               a.push(func(v *vm) {
+               a.push(func(t *Thread) {
                        dest := make([]Value, n);
                        for i, lf := range lfs {
-                               dest[i] = lf(v.f);
+                               dest[i] = lf(t);
                        }
-                       assign(multiV(dest), v.f);
+                       assign(multiV(dest), t);
                });
        } else {
                // Need temporaries
                lmt := lt.(*MultiType);
-               lfs := make([]func(*Frame) Value, n);
+               lfs := make([]func(*Thread) Value, n);
                for i, l := range ls {
                        lfs[i] = l.evalAddr;
                }
-               a.push(func(v *vm) {
+               a.push(func(t *Thread) {
                        temp := lmt.Zero().(multiV);
-                       assign(temp, v.f);
+                       assign(temp, t);
                        // Copy to destination
                        for i := 0; i < n; i ++ {
                                // TODO(austin) Need to evaluate LHS
                                // before RHS
-                               lfs[i](v.f).Assign(temp[i]);
+                               lfs[i](t).Assign(temp[i]);
                        }
                });
        }
@@ -749,9 +746,9 @@ func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) {
        }
 
        lf := l.evalAddr;
-       a.push(func(v *vm) {
-               effect(v.f);
-               assign(lf(v.f), v.f);
+       a.push(func(t *Thread) {
+               effect(t);
+               assign(lf(t), t);
        });
 }
 
@@ -774,7 +771,7 @@ func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
        if len(s.Results) == 0 && (len(a.fnType.Out) == 0 || a.outVarsNamed) {
                // Simple case.  Simply exit from the function.
                a.flow.putTerm();
-               a.push(func(v *vm) { v.pc = returnPC });
+               a.push(func(v *Thread) { v.pc = returnPC });
                return;
        }
 
@@ -810,9 +807,9 @@ func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
        start := len(a.fnType.In);
        nout := len(a.fnType.Out);
        a.flow.putTerm();
-       a.push(func(v *vm) {
-               assign(multiV(v.f.Vars[start:start+nout]), v.f);
-               v.pc = returnPC;
+       a.push(func(t *Thread) {
+               assign(multiV(t.f.Vars[start:start+nout]), t);
+               t.pc = returnPC;
        });
 }
 
@@ -880,7 +877,7 @@ func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
        }
 
        a.flow.put1(false, pc);
-       a.push(func(v *vm) { v.pc = *pc });
+       a.push(func(v *Thread) { v.pc = *pc });
 }
 
 func (a *stmtCompiler) compileBlockStmt(s *ast.BlockStmt) {
@@ -923,9 +920,9 @@ func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) {
                default:
                        eval := e.asBool();
                        a.flow.put1(true, &elsePC);
-                       a.push(func(v *vm) {
-                               if !eval(v.f) {
-                                       v.pc = elsePC;
+                       a.push(func(t *Thread) {
+                               if !eval(t) {
+                                       t.pc = elsePC;
                                }
                        });
                }
@@ -940,7 +937,7 @@ func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) {
        if s.Else != nil {
                // Skip over else if we executed the body
                a.flow.put1(false, &endPC);
-               a.push(func(v *vm) {
+               a.push(func(v *Thread) {
                        v.pc = endPC;
                });
                elsePC = a.nextPC();
@@ -967,9 +964,9 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
        if s.Tag != nil {
                e := condbc.compileExpr(condbc.block, false, s.Tag);
                if e != nil {
-                       var effect func(f *Frame);
+                       var effect func(*Thread);
                        effect, cond = e.extractEffect(condbc.block, "switch");
-                       a.push(func(v *vm) { effect(v.f) });
+                       a.push(effect);
                }
        }
 
@@ -993,7 +990,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
        }
 
        // Compile case expressions
-       cases := make([]func(f *Frame) bool, ncases);
+       cases := make([]func(*Thread) bool, ncases);
        i := 0;
        for _, c := range s.Body.List {
                clause, ok := c.(*ast.CaseClause);
@@ -1026,14 +1023,14 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
        endPC := badPC;
 
        a.flow.put(false, false, casePCs);
-       a.push(func(v *vm) {
+       a.push(func(t *Thread) {
                for i, c := range cases {
-                       if c(v.f) {
-                               v.pc = *casePCs[i];
+                       if c(t) {
+                               t.pc = *casePCs[i];
                                return;
                        }
                }
-               v.pc = *casePCs[ncases];
+               t.pc = *casePCs[ncases];
        });
        condbc.exit();
 
@@ -1083,7 +1080,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
                // Jump out of switch, unless there was a fallthrough
                if !fall {
                        a.flow.put1(false, &endPC);
-                       a.push(func(v *vm) { v.pc = endPC });
+                       a.push(func(v *Thread) { v.pc = endPC });
                }
        }
 
@@ -1112,7 +1109,7 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
        // Jump to condition check.  We generate slightly less code by
        // placing the condition check after the body.
        a.flow.put1(false, &checkPC);
-       a.push(func(v *vm) { v.pc = checkPC });
+       a.push(func(v *Thread) { v.pc = checkPC });
 
        // Compile body
        bodyPC = a.nextPC();
@@ -1141,7 +1138,7 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
        if s.Cond == nil {
                // If the condition is absent, it is equivalent to true.
                a.flow.put1(false, &bodyPC);
-               a.push(func(v *vm) { v.pc = bodyPC });
+               a.push(func(v *Thread) { v.pc = bodyPC });
        } else {
                e := bc.compileExpr(bc.block, false, s.Cond);
                switch {
@@ -1152,9 +1149,9 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
                default:
                        eval := e.asBool();
                        a.flow.put1(true, &bodyPC);
-                       a.push(func(v *vm) {
-                               if eval(v.f) {
-                                       v.pc = bodyPC;
+                       a.push(func(t *Thread) {
+                               if eval(t) {
+                                       t.pc = bodyPC;
                                }
                        });
                }
@@ -1195,7 +1192,7 @@ func (a *blockCompiler) exit() {
  * Function compiler
  */
 
-func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (func (f *Frame) Func) {
+func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (func (*Thread) Func) {
        // Create body scope
        //
        // The scope of a parameter or result is the body of the
@@ -1250,7 +1247,7 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f
 
        code := fc.get();
        maxVars := bodyScope.maxVars;
-       return func(f *Frame) Func { return &evalFunc{f, maxVars, code} };
+       return func(t *Thread) Func { return &evalFunc{t.f, maxVars, code} };
 }
 
 // Checks that labels were resolved and that all jumps obey scoping
@@ -1282,7 +1279,9 @@ type Stmt struct {
 }
 
 func (s *Stmt) Exec(f *Frame) os.Error {
-       return Try(func() {s.code.exec(f)});
+       t := new(Thread);
+       t.f = f;
+       return Try(func() {s.code.exec(t)});
 }
 
 func CompileStmts(scope *Scope, stmts []ast.Stmt) (*Stmt, os.Error) {
index b40d1aac929f3589be23385a4d8051974053d8c5..abb2ab0d5e06714a10511d259d1963043a22dbb9 100644 (file)
@@ -87,7 +87,7 @@ type PtrValue interface {
 
 type Func interface {
        NewFrame() *Frame;
-       Call(*Frame);
+       Call(*Thread);
 }
 
 type FuncValue interface {