]> Cypherpunks repositories - gostls13.git/commitdiff
move generated code into its own file.
authorRuss Cox <rsc@golang.org>
Tue, 1 Sep 2009 18:51:33 +0000 (11:51 -0700)
committerRuss Cox <rsc@golang.org>
Tue, 1 Sep 2009 18:51:33 +0000 (11:51 -0700)
simplify expr by merging all simple eval functions
into a single eval interface{}.

R=austin
DELTA=1597  (730 added, 780 deleted, 87 changed)
OCL=34182
CL=34198

usr/austin/eval/Makefile
usr/austin/eval/expr.go
usr/austin/eval/expr1.go [new file with mode: 0644]
usr/austin/eval/stmt.go

index 1c550e151af9b1744227fb8175209b8d2825cf55..154838ea379fef4be9f71d06f99637ac472c81cf 100644 (file)
@@ -10,6 +10,7 @@ GOFILES=\
        bridge.go\
        compiler.go\
        expr.go\
+       expr1.go\
        func.go\
        scope.go\
        stmt.go\
index 4b7ead957d4b6861667f84266f19136519cc6d2d..bf30d11a7867c4a0d3f10ea6bdb4f3aa9548334c 100644 (file)
@@ -20,37 +20,28 @@ import (
 type expr struct {
        *exprInfo;
        t Type;
+
        // Evaluate this node as the given type.
-       evalBool func(f *Frame) bool;
-       evalUint func(f *Frame) uint64;
-       evalInt func(f *Frame) int64;
-       // TODO(austin) evalIdealInt and evalIdealFloat shouldn't be
-       // functions at all.
-       evalIdealInt func() *bignum.Integer;
-       evalFloat func(f *Frame) float64;
-       evalIdealFloat func() *bignum.Rational;
-       evalString func(f *Frame) string;
-       evalArray func(f *Frame) ArrayValue;
-       evalStruct func(f *Frame) StructValue;
-       evalPtr func(f *Frame) Value;
-       evalFunc func(f *Frame) Func;
-       evalSlice func(f *Frame) Slice;
-       evalMap func(f *Frame) Map;
-       evalMulti func(f *Frame) []Value;
+       eval interface{};
+
        // Map index expressions permit special forms of assignment,
        // for which we need to know the Map and key.
        evalMapValue func(f *Frame) (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;
+
        // Execute this expression as a statement.  Only expressions
        // that are valid expression statements should set this.
        exec func(f *Frame);
+
        // If this expression is a type, this is its compiled type.
        // This is only permitted in the function position of a call
        // expression.  In this case, t should be nil.
        valType Type;
+
        // A short string describing this expression for error
        // messages.
        desc string;
@@ -82,133 +73,82 @@ func (a *exprInfo) diagOpTypes(op token.Token, lt Type, rt Type) {
 
 /*
  * "As" functions.  These retrieve evaluator functions from an
- * expr, panicking if the requested evaluator is nil.
+ * expr, panicking if the requested evaluator has the wrong type.
  */
-
-func (a *expr) asBool() (func(f *Frame) bool) {
-       if a.evalBool == nil {
-               log.Crashf("tried to get %v node as boolType", a.t);
-       }
-       return a.evalBool;
+func (a *expr) asBool() (func(*Frame) bool) {
+       return a.eval.(func(*Frame)bool);
 }
 
 func (a *expr) asUint() (func(f *Frame) uint64) {
-       if a.evalUint == nil {
-               log.Crashf("tried to get %v node as uintType", a.t);
-       }
-       return a.evalUint;
+       return a.eval.(func(*Frame)uint64);
 }
 
 func (a *expr) asInt() (func(f *Frame) int64) {
-       if a.evalInt == nil {
-               log.Crashf("tried to get %v node as intType", a.t);
-       }
-       return a.evalInt;
+       return a.eval.(func(*Frame)int64);
 }
 
 func (a *expr) asIdealInt() (func() *bignum.Integer) {
-       if a.evalIdealInt == nil {
-               log.Crashf("tried to get %v node as idealIntType", a.t);
-       }
-       return a.evalIdealInt;
+       return a.eval.(func()*bignum.Integer);
 }
 
 func (a *expr) asFloat() (func(f *Frame) float64) {
-       if a.evalFloat == nil {
-               log.Crashf("tried to get %v node as floatType", a.t);
-       }
-       return a.evalFloat;
+       return a.eval.(func(*Frame)float64)
 }
 
 func (a *expr) asIdealFloat() (func() *bignum.Rational) {
-       if a.evalIdealFloat == nil {
-               log.Crashf("tried to get %v node as idealFloatType", a.t);
-       }
-       return a.evalIdealFloat;
+       return a.eval.(func()*bignum.Rational)
 }
 
 func (a *expr) asString() (func(f *Frame) string) {
-       if a.evalString == nil {
-               log.Crashf("tried to get %v node as stringType", a.t);
-       }
-       return a.evalString;
+       return a.eval.(func(*Frame)string)
 }
 
 func (a *expr) asArray() (func(f *Frame) ArrayValue) {
-       if a.evalArray == nil {
-               log.Crashf("tried to get %v node as ArrayType", a.t);
-       }
-       return a.evalArray;
+       return a.eval.(func(*Frame)ArrayValue)
 }
 
 func (a *expr) asStruct() (func(f *Frame) StructValue) {
-       if a.evalStruct == nil {
-               log.Crashf("tried to get %v node as StructType", a.t);
-       }
-       return a.evalStruct;
+       return a.eval.(func(*Frame)StructValue)
 }
 
 func (a *expr) asPtr() (func(f *Frame) Value) {
-       if a.evalPtr == nil {
-               log.Crashf("tried to get %v node as PtrType", a.t);
-       }
-       return a.evalPtr;
+       return a.eval.(func(*Frame)Value)
 }
 
 func (a *expr) asFunc() (func(f *Frame) Func) {
-       if a.evalFunc == nil {
-               log.Crashf("tried to get %v node as FuncType", a.t);
-       }
-       return a.evalFunc;
+       return a.eval.(func(*Frame)Func)
 }
 
 func (a *expr) asSlice() (func(f *Frame) Slice) {
-       if a.evalSlice == nil {
-               log.Crashf("tried to get %v node as SliceType", a.t);
-       }
-       return a.evalSlice;
+       return a.eval.(func(*Frame)Slice)
 }
 
 func (a *expr) asMap() (func(f *Frame) Map) {
-       if a.evalMap == nil {
-               log.Crashf("tried to get %v node as MapType", a.t);
-       }
-       return a.evalMap;
+       return a.eval.(func(*Frame)Map)
 }
 
 func (a *expr) asMulti() (func(f *Frame) []Value) {
-       if a.evalMulti == nil {
-               log.Crashf("tried to get %v node as MultiType", a.t);
-       }
-       return a.evalMulti;
-}
-
-func (a *expr) asInterface() (func(f *Frame) interface {}) {
-       switch _ := a.t.lit().(type) {
-       case *boolType:
-               sf := a.asBool();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *uintType:
-               sf := a.asUint();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *intType:
-               sf := a.asInt();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *floatType:
-               sf := a.asFloat();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *stringType:
-               sf := a.asString();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *PtrType:
-               sf := a.asPtr();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *FuncType:
-               sf := a.asFunc();
-               return func(f *Frame) interface {} { return sf(f) };
-       case *MapType:
-               sf := a.asMap();
-               return func(f *Frame) interface {} { return sf(f) };
+       return a.eval.(func(*Frame)[]Value)
+}
+
+func (a *expr) asInterface() (func(f *Frame) 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)float64:
+               return func(f *Frame) interface{} { return sf(f) };
+       case func(*Frame)string:
+               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)Map:
+               return func(f *Frame) interface{} { return sf(f) };
        default:
                log.Crashf("unexpected expression node type %v at %v", a.t, a.pos);
        }
@@ -270,22 +210,22 @@ func (a *expr) convertTo(t Type) *expr {
                n, d := rat.Value();
                f := n.Quo(bignum.MakeInt(false, d));
                v := f.Abs().Value();
-               res.evalUint = func(*Frame) uint64 { return v };
+               res.eval = func(*Frame) uint64 { return v };
        case *intType:
                n, d := rat.Value();
                f := n.Quo(bignum.MakeInt(false, d));
                v := f.Value();
-               res.evalInt = func(*Frame) int64 { return v };
+               res.eval = func(*Frame) int64 { return v };
        case *idealIntType:
                n, d := rat.Value();
                f := n.Quo(bignum.MakeInt(false, d));
-               res.evalIdealInt = func() *bignum.Integer { return f };
+               res.eval = func() *bignum.Integer { return f };
        case *floatType:
                n, d := rat.Value();
                v := float64(n.Value())/float64(d.Value());
-               res.evalFloat = func(*Frame) float64 { return v };
+               res.eval = func(*Frame) float64 { return v };
        case *idealFloatType:
-               res.evalIdealFloat = func() *bignum.Rational { return rat };
+               res.eval = func() *bignum.Rational { return rat };
        default:
                log.Crashf("cannot convert to type %T", t);
        }
@@ -316,7 +256,7 @@ func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
                // Convert to int
                na := a.newExpr(IntType, a.desc);
                af := a.asUint();
-               na.evalInt = func(f *Frame) int64 {
+               na.eval = func(f *Frame) int64 {
                        return int64(af(f));
                };
                return na;
@@ -544,7 +484,7 @@ 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].evalSlice = func(f *Frame) Slice {
+                                               a.rs[i].eval = func(f *Frame) Slice {
                                                        return Slice{rf(f).(ArrayValue), len, len};
                                                };
                                                rt = a.rs[i].t;
@@ -862,7 +802,7 @@ func (a *exprInfo) compileVariable(level int, v *Variable) *expr {
 
 func (a *exprInfo) compileIdealInt(i *bignum.Integer, desc string) *expr {
        expr := a.newExpr(IdealIntType, desc);
-       expr.evalIdealInt = func() *bignum.Integer { return i };
+       expr.eval = func() *bignum.Integer { return i };
        return expr;
 }
 
@@ -888,7 +828,7 @@ func (a *exprInfo) compileFloatLit(lit string) *expr {
                log.Crashf("malformed float literal %s at %v passed parser", lit, a.pos);
        }
        expr := a.newExpr(IdealFloatType, "float literal");
-       expr.evalIdealFloat = func() *bignum.Rational { return f };
+       expr.eval = func() *bignum.Rational { return f };
        return expr;
 }
 
@@ -898,7 +838,7 @@ func (a *exprInfo) compileString(s string) *expr {
 
        // TODO(austin) Use unnamed string type.
        expr := a.newExpr(StringType, "string literal");
-       expr.evalString = func(*Frame) string { return s };
+       expr.eval = func(*Frame) string { return s };
        return expr;
 }
 
@@ -921,7 +861,7 @@ func (a *exprInfo) compileStringList(list []*expr) *expr {
 
 func (a *exprInfo) compileFuncLit(decl *FuncDecl, fn func(f *Frame) Func) *expr {
        expr := a.newExpr(decl.Type, "function literal");
-       expr.evalFunc = fn;
+       expr.eval = fn;
        return expr;
 }
 
@@ -1131,7 +1071,7 @@ 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.evalUint = func(f *Frame) uint64 {
+               expr.eval = func(f *Frame) uint64 {
                        l, r := lf(f), rf(f);
                        if r < 0 || r >= int64(len(l)) {
                                Abort(IndexOutOfBounds{r, int64(len(l))});
@@ -1259,13 +1199,13 @@ 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.evalInt = func(f *Frame) int64 {
+                       expr.eval = func(f *Frame) int64 {
                                return v;
                        };
 
                case *SliceType:
                        vf := arg.asSlice();
-                       expr.evalInt = func(f *Frame) int64 {
+                       expr.eval = func(f *Frame) int64 {
                                return vf(f).Cap;
                        };
 
@@ -1286,7 +1226,7 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                switch t := arg.t.lit().(type) {
                case *stringType:
                        vf := arg.asString();
-                       expr.evalInt = func(f *Frame) int64 {
+                       expr.eval = func(f *Frame) int64 {
                                return int64(len(vf(f)));
                        };
 
@@ -1294,19 +1234,19 @@ 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.evalInt = func(f *Frame) int64 {
+                       expr.eval = func(f *Frame) int64 {
                                return v;
                        };
 
                case *SliceType:
                        vf := arg.asSlice();
-                       expr.evalInt = func(f *Frame) int64 {
+                       expr.eval = func(f *Frame) int64 {
                                return vf(f).Len;
                        };
 
                case *MapType:
                        vf := arg.asMap();
-                       expr.evalInt = func(f *Frame) int64 {
+                       expr.eval = func(f *Frame) int64 {
                                // XXX(Spec) What's the len of an
                                // uninitialized map?
                                m := vf(f);
@@ -1360,7 +1300,7 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                        }
                        et := t.Elem;
                        expr := a.newExpr(t, "function call");
-                       expr.evalSlice = func(f *Frame) Slice {
+                       expr.eval = func(f *Frame) Slice {
                                l := lenf(f);
                                // XXX(Spec) What if len or cap is
                                // negative?  The runtime panics.
@@ -1397,7 +1337,7 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                                return nil;
                        }
                        expr := a.newExpr(t, "function call");
-                       expr.evalMap = func(f *Frame) Map {
+                       expr.eval = func(f *Frame) Map {
                                if lenf == nil {
                                        return make(evalMap);
                                }
@@ -1516,7 +1456,7 @@ func (a *exprInfo) compileUnaryExpr(op token.Token, v *expr) *expr {
 
        case token.AND:
                vf := v.evalAddr;
-               expr.evalPtr = func(f *Frame) Value { return vf(f) };
+               expr.eval = func(f *Frame) Value { return vf(f) };
 
        default:
                log.Crashf("Compilation of unary op %v not implemented", op);
@@ -1832,7 +1772,7 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
                                return nil;
                        }
                        val := lv.Shl(uint(rv.Value()));
-                       expr.evalIdealInt = func() *bignum.Integer { return val };
+                       expr.eval = func() *bignum.Integer { return val };
                } else {
                        expr.genBinOpShl(l, r);
                }
@@ -1842,7 +1782,7 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
                        lv := l.asIdealInt()();
                        rv := r.asIdealInt()();
                        val := lv.Shr(uint(rv.Value()));
-                       expr.evalIdealInt = func() *bignum.Integer { return val };
+                       expr.eval = func() *bignum.Integer { return val };
                } else {
                        expr.genBinOpShr(l, r);
                }
@@ -1895,9 +1835,9 @@ func (a *compiler) compileArrayLen(b *block, expr ast.Expr) (int64, bool) {
 
        switch _ := lenExpr.t.lit().(type) {
        case *intType:
-               return lenExpr.evalInt(nil), true;
+               return lenExpr.asInt()(nil), true;
        case *uintType:
-               return int64(lenExpr.evalUint(nil)), true;
+               return int64(lenExpr.asUint()(nil)), true;
        }
        log.Crashf("unexpected integer type %T", lenExpr.t);
        return 0, false;
@@ -2000,745 +1940,31 @@ func CompileExpr(scope *Scope, expr ast.Expr) (*Expr, os.Error) {
        if ec == nil {
                return nil, errors.GetError(scanner.Sorted);
        }
-       switch t := ec.t.lit().(type) {
-       case *boolType:
-               return &Expr{t, func(f *Frame, out Value) { out.(BoolValue).Set(ec.evalBool(f)) }}, nil;
-       case *uintType:
-               return &Expr{t, func(f *Frame, out Value) { out.(UintValue).Set(ec.evalUint(f)) }}, nil;
-       case *intType:
-               return &Expr{t, func(f *Frame, out Value) { out.(IntValue).Set(ec.evalInt(f)) }}, nil;
-       case *idealIntType:
-               return &Expr{t, func(f *Frame, out Value) { out.(*idealIntV).V = ec.evalIdealInt() }}, nil;
-       case *floatType:
-               return &Expr{t, func(f *Frame, out Value) { out.(FloatValue).Set(ec.evalFloat(f)) }}, nil;
-       case *idealFloatType:
-               return &Expr{t, func(f *Frame, out Value) { out.(*idealFloatV).V = ec.evalIdealFloat() }}, nil;
-       case *stringType:
-               return &Expr{t, func(f *Frame, out Value) { out.(StringValue).Set(ec.evalString(f)) }}, nil;
-       case *ArrayType:
-               return &Expr{t, func(f *Frame, out Value) { out.(ArrayValue).Assign(ec.evalArray(f)) }}, nil;
-       case *PtrType:
-               return &Expr{t, func(f *Frame, out Value) { out.(PtrValue).Set(ec.evalPtr(f)) }}, nil;
-       case *FuncType:
-               return &Expr{t, func(f *Frame, out Value) { out.(FuncValue).Set(ec.evalFunc(f)) }}, nil;
-       case *SliceType:
-               return &Expr{t, func(f *Frame, out Value) { out.(SliceValue).Set(ec.evalSlice(f)) }}, nil;
+       t := ec.t;
+       switch e := ec.eval.(type) {
+       case func(*Frame)bool:
+               return &Expr{t, func(f *Frame, out Value) { out.(BoolValue).Set(e(f)) }}, nil;
+       case func(*Frame)uint64:
+               return &Expr{t, func(f *Frame, out Value) { out.(UintValue).Set(e(f)) }}, nil;
+       case func(*Frame)int64:
+               return &Expr{t, func(f *Frame, out Value) { out.(IntValue).Set(e(f)) }}, nil;
+       case func()*bignum.Integer:
+               return &Expr{t, func(f *Frame, out Value) { out.(*idealIntV).V = e() }}, nil;
+       case func(*Frame)float64:
+               return &Expr{t, func(f *Frame, out Value) { out.(FloatValue).Set(e(f)) }}, nil;
+       case func()*bignum.Rational:
+               return &Expr{t, func(f *Frame, out Value) { out.(*idealFloatV).V = e() }}, nil;
+       case func(*Frame)string:
+               return &Expr{t, func(f *Frame, out Value) { out.(StringValue).Set(e(f)) }}, nil;
+       case func(*Frame)ArrayValue:
+               return &Expr{t, func(f *Frame, out Value) { out.(ArrayValue).Assign(e(f)) }}, nil;
+       case func(*Frame)Value:
+               return &Expr{t, func(f *Frame, out Value) { out.(PtrValue).Set(e(f)) }}, nil;
+       case func(*Frame)Func:
+               return &Expr{t, func(f *Frame, out Value) { out.(FuncValue).Set(e(f)) }}, nil;
+       case func(*Frame)Slice:
+               return &Expr{t, func(f *Frame, out Value) { out.(SliceValue).Set(e(f)) }}, nil;
        }
        log.Crashf("unexpected type %v", ec.t);
        panic();
 }
-
-/*
- * Operator generators
- * Everything below here is MACHINE GENERATED by gen.py genOps
- */
-
-func (a *expr) genConstant(v Value) {
-       switch _ := a.t.lit().(type) {
-       case *boolType:
-               val := v.(BoolValue).Get();
-               a.evalBool = func(f *Frame) bool { return val };
-       case *uintType:
-               val := v.(UintValue).Get();
-               a.evalUint = func(f *Frame) uint64 { return val };
-       case *intType:
-               val := v.(IntValue).Get();
-               a.evalInt = func(f *Frame) int64 { return val };
-       case *idealIntType:
-               val := v.(IdealIntValue).Get();
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       case *floatType:
-               val := v.(FloatValue).Get();
-               a.evalFloat = func(f *Frame) float64 { return val };
-       case *idealFloatType:
-               val := v.(IdealFloatValue).Get();
-               a.evalIdealFloat = func() *bignum.Rational { return val };
-       case *stringType:
-               val := v.(StringValue).Get();
-               a.evalString = func(f *Frame) string { return val };
-       case *ArrayType:
-               val := v.(ArrayValue).Get();
-               a.evalArray = func(f *Frame) ArrayValue { return val };
-       case *StructType:
-               val := v.(StructValue).Get();
-               a.evalStruct = func(f *Frame) StructValue { return val };
-       case *PtrType:
-               val := v.(PtrValue).Get();
-               a.evalPtr = func(f *Frame) Value { return val };
-       case *FuncType:
-               val := v.(FuncValue).Get();
-               a.evalFunc = func(f *Frame) Func { return val };
-       case *SliceType:
-               val := v.(SliceValue).Get();
-               a.evalSlice = func(f *Frame) Slice { return val };
-       case *MapType:
-               val := v.(MapValue).Get();
-               a.evalMap = func(f *Frame) Map { return val };
-       default:
-               log.Crashf("unexpected constant type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genIdentOp(level int, index int) {
-       a.evalAddr = func(f *Frame) Value { return f.Get(level, index) };
-       switch _ := a.t.lit().(type) {
-       case *boolType:
-               a.evalBool = func(f *Frame) bool { return f.Get(level, index).(BoolValue).Get() };
-       case *uintType:
-               a.evalUint = func(f *Frame) uint64 { return f.Get(level, index).(UintValue).Get() };
-       case *intType:
-               a.evalInt = func(f *Frame) int64 { return f.Get(level, index).(IntValue).Get() };
-       case *floatType:
-               a.evalFloat = func(f *Frame) float64 { return f.Get(level, index).(FloatValue).Get() };
-       case *stringType:
-               a.evalString = func(f *Frame) string { return f.Get(level, index).(StringValue).Get() };
-       case *ArrayType:
-               a.evalArray = func(f *Frame) ArrayValue { return f.Get(level, index).(ArrayValue).Get() };
-       case *StructType:
-               a.evalStruct = func(f *Frame) StructValue { return f.Get(level, index).(StructValue).Get() };
-       case *PtrType:
-               a.evalPtr = func(f *Frame) Value { return f.Get(level, index).(PtrValue).Get() };
-       case *FuncType:
-               a.evalFunc = func(f *Frame) Func { return f.Get(level, index).(FuncValue).Get() };
-       case *SliceType:
-               a.evalSlice = func(f *Frame) Slice { return f.Get(level, index).(SliceValue).Get() };
-       case *MapType:
-               a.evalMap = func(f *Frame) Map { return 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) };
-       switch _ := a.t.lit().(type) {
-       case *boolType:
-               a.evalBool = func(f *Frame) bool { return call(f)[0].(BoolValue).Get() };
-       case *uintType:
-               a.evalUint = func(f *Frame) uint64 { return call(f)[0].(UintValue).Get() };
-       case *intType:
-               a.evalInt = func(f *Frame) int64 { return call(f)[0].(IntValue).Get() };
-       case *floatType:
-               a.evalFloat = func(f *Frame) float64 { return call(f)[0].(FloatValue).Get() };
-       case *stringType:
-               a.evalString = func(f *Frame) string { return call(f)[0].(StringValue).Get() };
-       case *ArrayType:
-               a.evalArray = func(f *Frame) ArrayValue { return call(f)[0].(ArrayValue).Get() };
-       case *StructType:
-               a.evalStruct = func(f *Frame) StructValue { return call(f)[0].(StructValue).Get() };
-       case *PtrType:
-               a.evalPtr = func(f *Frame) Value { return call(f)[0].(PtrValue).Get() };
-       case *FuncType:
-               a.evalFunc = func(f *Frame) Func { return call(f)[0].(FuncValue).Get() };
-       case *SliceType:
-               a.evalSlice = func(f *Frame) Slice { return call(f)[0].(SliceValue).Get() };
-       case *MapType:
-               a.evalMap = func(f *Frame) Map { return call(f)[0].(MapValue).Get() };
-       case *MultiType:
-               a.evalMulti = func(f *Frame) []Value { return call(f) };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genValue(vf func(*Frame) Value) {
-       a.evalAddr = vf;
-       switch _ := a.t.lit().(type) {
-       case *boolType:
-               a.evalBool = func(f *Frame) bool { return vf(f).(BoolValue).Get() };
-       case *uintType:
-               a.evalUint = func(f *Frame) uint64 { return vf(f).(UintValue).Get() };
-       case *intType:
-               a.evalInt = func(f *Frame) int64 { return vf(f).(IntValue).Get() };
-       case *floatType:
-               a.evalFloat = func(f *Frame) float64 { return vf(f).(FloatValue).Get() };
-       case *stringType:
-               a.evalString = func(f *Frame) string { return vf(f).(StringValue).Get() };
-       case *ArrayType:
-               a.evalArray = func(f *Frame) ArrayValue { return vf(f).(ArrayValue).Get() };
-       case *StructType:
-               a.evalStruct = func(f *Frame) StructValue { return vf(f).(StructValue).Get() };
-       case *PtrType:
-               a.evalPtr = func(f *Frame) Value { return vf(f).(PtrValue).Get() };
-       case *FuncType:
-               a.evalFunc = func(f *Frame) Func { return vf(f).(FuncValue).Get() };
-       case *SliceType:
-               a.evalSlice = func(f *Frame) Slice { return vf(f).(SliceValue).Get() };
-       case *MapType:
-               a.evalMap = func(f *Frame) Map { return vf(f).(MapValue).Get() };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genUnaryOpNeg(v *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               vf := v.asUint();
-               a.evalUint = func(f *Frame) uint64 { return -vf(f) };
-       case *intType:
-               vf := v.asInt();
-               a.evalInt = func(f *Frame) int64 { return -vf(f) };
-       case *idealIntType:
-               vf := v.asIdealInt();
-               val := vf().Neg();
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       case *floatType:
-               vf := v.asFloat();
-               a.evalFloat = func(f *Frame) float64 { return -vf(f) };
-       case *idealFloatType:
-               vf := v.asIdealFloat();
-               val := vf().Neg();
-               a.evalIdealFloat = func() *bignum.Rational { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genUnaryOpNot(v *expr) {
-       switch _ := a.t.lit().(type) {
-       case *boolType:
-               vf := v.asBool();
-               a.evalBool = func(f *Frame) bool { return !vf(f) };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genUnaryOpXor(v *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               vf := v.asUint();
-               a.evalUint = func(f *Frame) uint64 { return ^vf(f) };
-       case *intType:
-               vf := v.asInt();
-               a.evalInt = func(f *Frame) int64 { return ^vf(f) };
-       case *idealIntType:
-               vf := v.asIdealInt();
-               val := vf().Neg().Sub(bignum.Int(1));
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpAdd(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) + rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) + rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Add(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalFloat = func(f *Frame) float64 { return lf(f) + rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Add(rf());
-               a.evalIdealFloat = func() *bignum.Rational { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalString = func(f *Frame) string { return lf(f) + rf(f) };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpSub(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) - rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) - rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Sub(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalFloat = func(f *Frame) float64 { return lf(f) - rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Sub(rf());
-               a.evalIdealFloat = func() *bignum.Rational { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpMul(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) * rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) * rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Mul(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalFloat = func(f *Frame) float64 { return lf(f) * rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Mul(rf());
-               a.evalIdealFloat = func() *bignum.Rational { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpQuo(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) }; return l / r };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) }; return l / r };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Quo(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalFloat = func(f *Frame) float64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) }; return l / r };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Quo(rf());
-               a.evalIdealFloat = func() *bignum.Rational { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpRem(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) }; return l % r };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { l, r := lf(f), rf(f); if r == 0 { Abort(DivByZero{}) }; return l % r };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Rem(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpAnd(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) & rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) & rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().And(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpOr(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) | rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) | rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Or(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpXor(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) ^ rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) ^ rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Xor(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpAndNot(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) &^ rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalInt = func(f *Frame) int64 { return lf(f) &^ rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().AndNot(rf());
-               a.evalIdealInt = func() *bignum.Integer { return val };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpShl(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) << rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asUint();
-               a.evalInt = func(f *Frame) int64 { return lf(f) << rf(f) };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpShr(l, r *expr) {
-       switch _ := a.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalUint = func(f *Frame) uint64 { return lf(f) >> rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asUint();
-               a.evalInt = func(f *Frame) int64 { return lf(f) >> rf(f) };
-       default:
-               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpLss(l, r *expr) {
-       switch _ := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalBool = func(f *Frame) bool { return lf(f) < rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalBool = func(f *Frame) bool { return lf(f) < rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Cmp(rf()) < 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalBool = func(f *Frame) bool { return lf(f) < rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Cmp(rf()) < 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalBool = func(f *Frame) bool { return lf(f) < rf(f) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpGtr(l, r *expr) {
-       switch _ := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalBool = func(f *Frame) bool { return lf(f) > rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalBool = func(f *Frame) bool { return lf(f) > rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Cmp(rf()) > 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalBool = func(f *Frame) bool { return lf(f) > rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Cmp(rf()) > 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalBool = func(f *Frame) bool { return lf(f) > rf(f) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpLeq(l, r *expr) {
-       switch _ := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalBool = func(f *Frame) bool { return lf(f) <= rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalBool = func(f *Frame) bool { return lf(f) <= rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Cmp(rf()) <= 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalBool = func(f *Frame) bool { return lf(f) <= rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Cmp(rf()) <= 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalBool = func(f *Frame) bool { return lf(f) <= rf(f) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpGeq(l, r *expr) {
-       switch _ := l.t.lit().(type) {
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalBool = func(f *Frame) bool { return lf(f) >= rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalBool = func(f *Frame) bool { return lf(f) >= rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Cmp(rf()) >= 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalBool = func(f *Frame) bool { return lf(f) >= rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Cmp(rf()) >= 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalBool = func(f *Frame) bool { return lf(f) >= rf(f) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpEql(l, r *expr) {
-       switch _ := l.t.lit().(type) {
-       case *boolType:
-               lf := l.asBool();
-               rf := r.asBool();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Cmp(rf()) == 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Cmp(rf()) == 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *PtrType:
-               lf := l.asPtr();
-               rf := r.asPtr();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *FuncType:
-               lf := l.asFunc();
-               rf := r.asFunc();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       case *MapType:
-               lf := l.asMap();
-               rf := r.asMap();
-               a.evalBool = func(f *Frame) bool { return lf(f) == rf(f) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
-       }
-}
-
-func (a *expr) genBinOpNeq(l, r *expr) {
-       switch _ := l.t.lit().(type) {
-       case *boolType:
-               lf := l.asBool();
-               rf := r.asBool();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *uintType:
-               lf := l.asUint();
-               rf := r.asUint();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *intType:
-               lf := l.asInt();
-               rf := r.asInt();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *idealIntType:
-               lf := l.asIdealInt();
-               rf := r.asIdealInt();
-               val := lf().Cmp(rf()) != 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *floatType:
-               lf := l.asFloat();
-               rf := r.asFloat();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *idealFloatType:
-               lf := l.asIdealFloat();
-               rf := r.asIdealFloat();
-               val := lf().Cmp(rf()) != 0;
-               a.evalBool = func(f *Frame) bool { return val };
-       case *stringType:
-               lf := l.asString();
-               rf := r.asString();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *PtrType:
-               lf := l.asPtr();
-               rf := r.asPtr();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *FuncType:
-               lf := l.asFunc();
-               rf := r.asFunc();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       case *MapType:
-               lf := l.asMap();
-               rf := r.asMap();
-               a.evalBool = func(f *Frame) bool { return lf(f) != rf(f) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
-       }
-}
-
-func genAssign(lt Type, r *expr) (func(lv Value, f *Frame)) {
-       switch _ := lt.lit().(type) {
-       case *boolType:
-               rf := r.asBool();
-               return func(lv Value, f *Frame) { lv.(BoolValue).Set(rf(f)) };
-       case *uintType:
-               rf := r.asUint();
-               return func(lv Value, f *Frame) { lv.(UintValue).Set(rf(f)) };
-       case *intType:
-               rf := r.asInt();
-               return func(lv Value, f *Frame) { lv.(IntValue).Set(rf(f)) };
-       case *floatType:
-               rf := r.asFloat();
-               return func(lv Value, f *Frame) { lv.(FloatValue).Set(rf(f)) };
-       case *stringType:
-               rf := r.asString();
-               return func(lv Value, f *Frame) { lv.(StringValue).Set(rf(f)) };
-       case *ArrayType:
-               rf := r.asArray();
-               return func(lv Value, f *Frame) { lv.Assign(rf(f)) };
-       case *StructType:
-               rf := r.asStruct();
-               return func(lv Value, f *Frame) { lv.Assign(rf(f)) };
-       case *PtrType:
-               rf := r.asPtr();
-               return func(lv Value, f *Frame) { lv.(PtrValue).Set(rf(f)) };
-       case *FuncType:
-               rf := r.asFunc();
-               return func(lv Value, f *Frame) { lv.(FuncValue).Set(rf(f)) };
-       case *SliceType:
-               rf := r.asSlice();
-               return func(lv Value, f *Frame) { lv.(SliceValue).Set(rf(f)) };
-       case *MapType:
-               rf := r.asMap();
-               return func(lv Value, f *Frame) { lv.(MapValue).Set(rf(f)) };
-       default:
-               log.Crashf("unexpected left operand type %v at %v", lt, r.pos);
-       }
-       panic();
-}
diff --git a/usr/austin/eval/expr1.go b/usr/austin/eval/expr1.go
new file mode 100644 (file)
index 0000000..3eac27e
--- /dev/null
@@ -0,0 +1,723 @@
+package eval
+
+// generated code
+
+import (
+       "bignum";
+       "log";
+)
+
+/*
+ * Operator generators
+ * Everything below here is MACHINE GENERATED by gen.py genOps
+ */
+
+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 };
+       case *uintType:
+               val := v.(UintValue).Get();
+               a.eval = func(f *Frame) uint64 { return val };
+       case *intType:
+               val := v.(IntValue).Get();
+               a.eval = func(f *Frame) 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 };
+       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 };
+       case *ArrayType:
+               val := v.(ArrayValue).Get();
+               a.eval = func(f *Frame) ArrayValue { return val };
+       case *StructType:
+               val := v.(StructValue).Get();
+               a.eval = func(f *Frame) StructValue { return val };
+       case *PtrType:
+               val := v.(PtrValue).Get();
+               a.eval = func(f *Frame) Value { return val };
+       case *FuncType:
+               val := v.(FuncValue).Get();
+               a.eval = func(f *Frame) Func { return val };
+       case *SliceType:
+               val := v.(SliceValue).Get();
+               a.eval = func(f *Frame) Slice { return val };
+       case *MapType:
+               val := v.(MapValue).Get();
+               a.eval = func(f *Frame) Map { return val };
+       default:
+               log.Crashf("unexpected constant type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genIdentOp(level int, index int) {
+       a.evalAddr = func(f *Frame) Value { return f.Get(level, index) };
+       switch _ := a.t.lit().(type) {
+       case *boolType:
+               a.eval = func(f *Frame) bool { return f.Get(level, index).(BoolValue).Get() };
+       case *uintType:
+               a.eval = func(f *Frame) uint64 { return f.Get(level, index).(UintValue).Get() };
+       case *intType:
+               a.eval = func(f *Frame) int64 { return f.Get(level, index).(IntValue).Get() };
+       case *floatType:
+               a.eval = func(f *Frame) float64 { return f.Get(level, index).(FloatValue).Get() };
+       case *stringType:
+               a.eval = func(f *Frame) string { return f.Get(level, index).(StringValue).Get() };
+       case *ArrayType:
+               a.eval = func(f *Frame) ArrayValue { return f.Get(level, index).(ArrayValue).Get() };
+       case *StructType:
+               a.eval = func(f *Frame) StructValue { return f.Get(level, index).(StructValue).Get() };
+       case *PtrType:
+               a.eval = func(f *Frame) Value { return f.Get(level, index).(PtrValue).Get() };
+       case *FuncType:
+               a.eval = func(f *Frame) Func { return f.Get(level, index).(FuncValue).Get() };
+       case *SliceType:
+               a.eval = func(f *Frame) Slice { return f.Get(level, index).(SliceValue).Get() };
+       case *MapType:
+               a.eval = func(f *Frame) Map { return 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) };
+       switch _ := a.t.lit().(type) {
+       case *boolType:
+               a.eval = func(f *Frame) bool { return call(f)[0].(BoolValue).Get() };
+       case *uintType:
+               a.eval = func(f *Frame) uint64 { return call(f)[0].(UintValue).Get() };
+       case *intType:
+               a.eval = func(f *Frame) int64 { return call(f)[0].(IntValue).Get() };
+       case *floatType:
+               a.eval = func(f *Frame) float64 { return call(f)[0].(FloatValue).Get() };
+       case *stringType:
+               a.eval = func(f *Frame) string { return call(f)[0].(StringValue).Get() };
+       case *ArrayType:
+               a.eval = func(f *Frame) ArrayValue { return call(f)[0].(ArrayValue).Get() };
+       case *StructType:
+               a.eval = func(f *Frame) StructValue { return call(f)[0].(StructValue).Get() };
+       case *PtrType:
+               a.eval = func(f *Frame) Value { return call(f)[0].(PtrValue).Get() };
+       case *FuncType:
+               a.eval = func(f *Frame) Func { return call(f)[0].(FuncValue).Get() };
+       case *SliceType:
+               a.eval = func(f *Frame) Slice { return call(f)[0].(SliceValue).Get() };
+       case *MapType:
+               a.eval = func(f *Frame) Map { return call(f)[0].(MapValue).Get() };
+       case *MultiType:
+               a.eval = func(f *Frame) []Value { return call(f) };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genValue(vf func(*Frame) Value) {
+       a.evalAddr = vf;
+       switch _ := a.t.lit().(type) {
+       case *boolType:
+               a.eval = func(f *Frame) bool { return vf(f).(BoolValue).Get() };
+       case *uintType:
+               a.eval = func(f *Frame) uint64 { return vf(f).(UintValue).Get() };
+       case *intType:
+               a.eval = func(f *Frame) int64 { return vf(f).(IntValue).Get() };
+       case *floatType:
+               a.eval = func(f *Frame) float64 { return vf(f).(FloatValue).Get() };
+       case *stringType:
+               a.eval = func(f *Frame) string { return vf(f).(StringValue).Get() };
+       case *ArrayType:
+               a.eval = func(f *Frame) ArrayValue { return vf(f).(ArrayValue).Get() };
+       case *StructType:
+               a.eval = func(f *Frame) StructValue { return vf(f).(StructValue).Get() };
+       case *PtrType:
+               a.eval = func(f *Frame) Value { return vf(f).(PtrValue).Get() };
+       case *FuncType:
+               a.eval = func(f *Frame) Func { return vf(f).(FuncValue).Get() };
+       case *SliceType:
+               a.eval = func(f *Frame) Slice { return vf(f).(SliceValue).Get() };
+       case *MapType:
+               a.eval = func(f *Frame) Map { return vf(f).(MapValue).Get() };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genUnaryOpNeg(v *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               vf := v.asUint();
+               a.eval = func(f *Frame) uint64 { return -vf(f) };
+       case *intType:
+               vf := v.asInt();
+               a.eval = func(f *Frame) int64 { return -vf(f) };
+       case *idealIntType:
+               vf := v.asIdealInt();
+               val := vf().Neg();
+               a.eval = func() *bignum.Integer { return val };
+       case *floatType:
+               vf := v.asFloat();
+               a.eval = func(f *Frame) float64 { return -vf(f) };
+       case *idealFloatType:
+               vf := v.asIdealFloat();
+               val := vf().Neg();
+               a.eval = func() *bignum.Rational { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genUnaryOpNot(v *expr) {
+       switch _ := a.t.lit().(type) {
+       case *boolType:
+               vf := v.asBool();
+               a.eval = func(f *Frame) bool { return !vf(f) };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genUnaryOpXor(v *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               vf := v.asUint();
+               a.eval = func(f *Frame) uint64 { return ^vf(f) };
+       case *intType:
+               vf := v.asInt();
+               a.eval = func(f *Frame) int64 { return ^vf(f) };
+       case *idealIntType:
+               vf := v.asIdealInt();
+               val := vf().Neg().Sub(bignum.Int(1));
+               a.eval = func() *bignum.Integer { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpAdd(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) + rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) + rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Add(rf());
+               a.eval = func() *bignum.Integer { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) float64 { return lf(f) + rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Add(rf());
+               a.eval = func() *bignum.Rational { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) string { return lf(f) + rf(f) };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpSub(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) - rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) - rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Sub(rf());
+               a.eval = func() *bignum.Integer { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) float64 { return lf(f) - rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Sub(rf());
+               a.eval = func() *bignum.Rational { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpMul(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) * rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) * rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Mul(rf());
+               a.eval = func() *bignum.Integer { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) float64 { return lf(f) * rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Mul(rf());
+               a.eval = func() *bignum.Rational { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpQuo(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       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 };
+       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 };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Quo(rf());
+               a.eval = func() *bignum.Integer { return val };
+       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 };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Quo(rf());
+               a.eval = func() *bignum.Rational { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpRem(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       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 };
+       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 };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Rem(rf());
+               a.eval = func() *bignum.Integer { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpAnd(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) & rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) & rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().And(rf());
+               a.eval = func() *bignum.Integer { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpOr(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) | rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) | rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Or(rf());
+               a.eval = func() *bignum.Integer { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpXor(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) ^ rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) ^ rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Xor(rf());
+               a.eval = func() *bignum.Integer { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpAndNot(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) &^ rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) int64 { return lf(f) &^ rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().AndNot(rf());
+               a.eval = func() *bignum.Integer { return val };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpShl(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) << rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asUint();
+               a.eval = func(f *Frame) int64 { return lf(f) << rf(f) };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpShr(l, r *expr) {
+       switch _ := a.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) uint64 { return lf(f) >> rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asUint();
+               a.eval = func(f *Frame) int64 { return lf(f) >> rf(f) };
+       default:
+               log.Crashf("unexpected result type %v at %v", a.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpLss(l, r *expr) {
+       switch _ := l.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) bool { return lf(f) < rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) bool { return lf(f) < rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Cmp(rf()) < 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) bool { return lf(f) < rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Cmp(rf()) < 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) bool { return lf(f) < rf(f) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpGtr(l, r *expr) {
+       switch _ := l.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) bool { return lf(f) > rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) bool { return lf(f) > rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Cmp(rf()) > 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) bool { return lf(f) > rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Cmp(rf()) > 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) bool { return lf(f) > rf(f) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpLeq(l, r *expr) {
+       switch _ := l.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) bool { return lf(f) <= rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) bool { return lf(f) <= rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Cmp(rf()) <= 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) bool { return lf(f) <= rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Cmp(rf()) <= 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) bool { return lf(f) <= rf(f) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpGeq(l, r *expr) {
+       switch _ := l.t.lit().(type) {
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) bool { return lf(f) >= rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) bool { return lf(f) >= rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Cmp(rf()) >= 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) bool { return lf(f) >= rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Cmp(rf()) >= 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) bool { return lf(f) >= rf(f) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpEql(l, r *expr) {
+       switch _ := l.t.lit().(type) {
+       case *boolType:
+               lf := l.asBool();
+               rf := r.asBool();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Cmp(rf()) == 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Cmp(rf()) == 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *PtrType:
+               lf := l.asPtr();
+               rf := r.asPtr();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *FuncType:
+               lf := l.asFunc();
+               rf := r.asFunc();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       case *MapType:
+               lf := l.asMap();
+               rf := r.asMap();
+               a.eval = func(f *Frame) bool { return lf(f) == rf(f) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
+       }
+}
+
+func (a *expr) genBinOpNeq(l, r *expr) {
+       switch _ := l.t.lit().(type) {
+       case *boolType:
+               lf := l.asBool();
+               rf := r.asBool();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *uintType:
+               lf := l.asUint();
+               rf := r.asUint();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *intType:
+               lf := l.asInt();
+               rf := r.asInt();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *idealIntType:
+               lf := l.asIdealInt();
+               rf := r.asIdealInt();
+               val := lf().Cmp(rf()) != 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *floatType:
+               lf := l.asFloat();
+               rf := r.asFloat();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *idealFloatType:
+               lf := l.asIdealFloat();
+               rf := r.asIdealFloat();
+               val := lf().Cmp(rf()) != 0;
+               a.eval = func(f *Frame) bool { return val };
+       case *stringType:
+               lf := l.asString();
+               rf := r.asString();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *PtrType:
+               lf := l.asPtr();
+               rf := r.asPtr();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *FuncType:
+               lf := l.asFunc();
+               rf := r.asFunc();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       case *MapType:
+               lf := l.asMap();
+               rf := r.asMap();
+               a.eval = func(f *Frame) bool { return lf(f) != rf(f) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", l.t, a.pos);
+       }
+}
+
+func genAssign(lt Type, r *expr) (func(lv Value, f *Frame)) {
+       switch _ := lt.lit().(type) {
+       case *boolType:
+               rf := r.asBool();
+               return func(lv Value, f *Frame) { lv.(BoolValue).Set(rf(f)) };
+       case *uintType:
+               rf := r.asUint();
+               return func(lv Value, f *Frame) { lv.(UintValue).Set(rf(f)) };
+       case *intType:
+               rf := r.asInt();
+               return func(lv Value, f *Frame) { lv.(IntValue).Set(rf(f)) };
+       case *floatType:
+               rf := r.asFloat();
+               return func(lv Value, f *Frame) { lv.(FloatValue).Set(rf(f)) };
+       case *stringType:
+               rf := r.asString();
+               return func(lv Value, f *Frame) { lv.(StringValue).Set(rf(f)) };
+       case *ArrayType:
+               rf := r.asArray();
+               return func(lv Value, f *Frame) { lv.Assign(rf(f)) };
+       case *StructType:
+               rf := r.asStruct();
+               return func(lv Value, f *Frame) { lv.Assign(rf(f)) };
+       case *PtrType:
+               rf := r.asPtr();
+               return func(lv Value, f *Frame) { lv.(PtrValue).Set(rf(f)) };
+       case *FuncType:
+               rf := r.asFunc();
+               return func(lv Value, f *Frame) { lv.(FuncValue).Set(rf(f)) };
+       case *SliceType:
+               rf := r.asSlice();
+               return func(lv Value, f *Frame) { lv.(SliceValue).Set(rf(f)) };
+       case *MapType:
+               rf := r.asMap();
+               return func(lv Value, f *Frame) { lv.(MapValue).Set(rf(f)) };
+       default:
+               log.Crashf("unexpected left operand type %v at %v", lt, r.pos);
+       }
+       panic();
+}
index b6e471dee0933625d2f53c9f02d68e2ea9bfe603..286c8bce62fc89f6ec4a20cb510d03244a8183ba 100644 (file)
@@ -458,7 +458,7 @@ func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
 
        one := l.newExpr(IdealIntType, "constant");
        one.pos = s.Pos();
-       one.evalIdealInt = func() *bignum.Integer { return bignum.Int(1) };
+       one.eval = func() *bignum.Integer { return bignum.Int(1) };
 
        binop := l.compileBinaryExpr(op, l, one);
        if binop == nil {