]> Cypherpunks repositories - gostls13.git/commitdiff
interpreter checkpoint.
authorRuss Cox <rsc@golang.org>
Sun, 11 Oct 2009 09:35:53 +0000 (02:35 -0700)
committerRuss Cox <rsc@golang.org>
Sun, 11 Oct 2009 09:35:53 +0000 (02:35 -0700)
  * generate different versions of binary operators
    for each size of int and float, so that proper
    truncating happens after each operation to
    simulate the various sized ops.
  * add slice expressions
  * publish World.CompileStmtList, CompileDeclList, CompileExpr
  * handle type-less expressions in CompileExpr

R=austin
DELTA=1459  (1327 added, 11 deleted, 121 changed)
OCL=34382
CL=35581

usr/austin/eval/abort.go
usr/austin/eval/eval_test.go
usr/austin/eval/expr.go
usr/austin/eval/expr1.go
usr/austin/eval/gen.go
usr/austin/eval/main.go
usr/austin/eval/stmt_test.go
usr/austin/eval/world.go

index 53747f3e1b44fc95105677167d2ff052105cad82..38ad2bf6259e72698fff21d5746125a7f6b3c2a9 100644 (file)
@@ -58,6 +58,14 @@ func (e IndexError) String() string {
        return fmt.Sprintf("index %d exceeds length %d", e.Idx, e.Len);
 }
 
+type SliceError struct {
+       Lo, Hi, Cap int64;
+}
+
+func (e SliceError) String() string {
+       return fmt.Sprintf("slice [%d:%d]; cap %d", e.Lo, e.Hi, e.Cap);
+}
+
 type KeyError struct {
        Key interface {};
 }
index 75c30a7a56454fac0d6ac9a27762ef72557f4385..192a2e782c51dabc13debb96c5c1b4b4254a5c20 100644 (file)
@@ -65,7 +65,7 @@ func (a test) run(t *testing.T, name string) {
                        t.Errorf("%s: Compile %s succeeded; want %s", name, src, j.cerr);
                        break;
                }
-               
+
                val, err := code.Run();
                if err != nil {
                        if j.rterr == "" {
@@ -82,7 +82,7 @@ func (a test) run(t *testing.T, name string) {
                        t.Errorf("%s: Run %s succeeded; want %s", name, src, j.rterr);
                        break;
                }
-       
+
                if !j.noval && !reflect.DeepEqual(val, j.val) {
                        t.Errorf("%s: Run %s = %T(%v) want %T(%v)", name, src, val, val, j.val, j.val);
                }
@@ -122,6 +122,13 @@ func Run(stmts string) test {
        return test([]job{job{code: stmts, noval: true}})
 }
 
+// Two statements without error.
+// TODO(rsc): Should be possible with Run but the parser
+// won't let us do both top-level and non-top-level statements.
+func Run2(stmt1, stmt2 string) test {
+       return test([]job{job{code: stmt1, noval: true}, job{code: stmt2, noval: true}})
+}
+
 // Statement runs and test one expression's value
 func Val1(stmts string, expr1 string, val1 interface{}) test {
        return test([]job{
index e8ca9331469bff410817023e8bcce37de4b679f2..ea4fc082b7c1eb9b9819fe9859bcd8d9ad575eae 100644 (file)
@@ -11,6 +11,7 @@ import (
        "log";
        "strconv";
        "strings";
+       "os";
 )
 
 // An expr is the result of compiling an expression.  It stores the
@@ -160,7 +161,11 @@ func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
                        a.diag("negative %s: %s", negErr, val);
                        return nil;
                }
-               if max != -1 && val.Cmp(bignum.Int(max)) >= 0 {
+               bound := max;
+               if negErr == "slice" {
+                       bound++;
+               }
+               if max != -1 && val.Cmp(bignum.Int(bound)) >= 0 {
                        a.diag("index %s exceeds length %d", val, max);
                        return nil;
                }
@@ -289,7 +294,7 @@ func (a *assignCompiler) allowMapForms(nls int) {
        a.allowMap = true;
 
        // Update unpacking info if this is r, ok = a[x]
-       if nls == 2 && len(a.rs) == 1 && a.rs[0].evalMapValue != nil {
+       if nls == 2 && len(a.rs) == 1 && a.rs[0] != nil && a.rs[0].evalMapValue != nil {
                a.isUnpack = true;
                a.rmt = NewMultiType([]Type {a.rs[0].t, BoolType});
                a.isMapUnpack = true;
@@ -551,7 +556,7 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
                args := make([]*expr, len(x.Args));
                bad := false;
                for i, arg := range x.Args {
-                       if i == 0 && l.t == Type(makeType) {
+                       if i == 0 && l != nil && (l.t == Type(makeType) || l.t == Type(newType)) {
                                argei := &exprInfo{a.compiler, arg.Pos()};
                                args[i] = argei.exprFromType(a.compileType(a.block, arg));
                        } else {
@@ -561,7 +566,7 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
                                bad = true;
                        }
                }
-               if l == nil || bad {
+               if bad || l == nil {
                        return nil;
                }
                if a.constant {
@@ -583,8 +588,13 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
 
        case *ast.IndexExpr:
                if x.End != nil {
-                       a.diagAt(x, "slice expression not implemented");
-                       return nil;
+                       arr := a.compile(x.X, false);
+                       lo := a.compile(x.Index, false);
+                       hi := a.compile(x.End, false);
+                       if arr == nil || lo == nil || hi == nil {
+                               return nil;
+                       }
+                       return ei.compileSliceExpr(arr, lo, hi);
                }
                l, r := a.compile(x.X, false), a.compile(x.Index, false);
                if l == nil || r == nil {
@@ -926,6 +936,86 @@ func (a *exprInfo) compileSelectorExpr(v *expr, name string) *expr {
        return builder(v);
 }
 
+func (a *exprInfo) compileSliceExpr(arr, lo, hi *expr) *expr {
+       // Type check object
+       arr = arr.derefArray();
+
+       var at Type;
+       var maxIndex int64 = -1;
+
+       switch lt := arr.t.lit().(type) {
+       case *ArrayType:
+               at = NewSliceType(lt.Elem);
+               maxIndex = lt.Len;
+
+       case *SliceType:
+               at = lt;
+
+       case *stringType:
+               at = lt;
+
+       default:
+               a.diag("cannot slice %v", arr.t);
+               return nil;
+       }
+
+       // Type check index and convert to int
+       // XXX(Spec) It's unclear if ideal floats with no
+       // fractional part are allowed here.  6g allows it.  I
+       // believe that's wrong.
+       lo = lo.convertToInt(maxIndex, "slice", "slice");
+       hi = hi.convertToInt(maxIndex, "slice", "slice");
+       if lo == nil || hi == nil {
+               return nil;
+       }
+
+       expr := a.newExpr(at, "slice expression");
+
+       // Compile
+       lof := lo.asInt();
+       hif := hi.asInt();
+       switch lt := arr.t.lit().(type) {
+       case *ArrayType:
+               arrf := arr.asArray();
+               bound := lt.Len;
+               expr.eval = func(t *Thread) Slice {
+                       arr, lo, hi := arrf(t), lof(t), hif(t);
+                       if lo > hi || hi > bound || lo < 0 {
+                               t.Abort(SliceError{lo, hi, bound});
+                       }
+                       return Slice{arr.Sub(lo, bound - lo), hi - lo, bound - lo}
+               };
+
+       case *SliceType:
+               arrf := arr.asSlice();
+               expr.eval = func(t *Thread) Slice {
+                       arr, lo, hi := arrf(t), lof(t), hif(t);
+                       if lo > hi || hi > arr.Cap || lo < 0 {
+                               t.Abort(SliceError{lo, hi, arr.Cap});
+                       }
+                       return Slice{arr.Base.Sub(lo, arr.Cap - lo), hi - lo, arr.Cap - lo}
+               };
+
+       case *stringType:
+               arrf := arr.asString();
+               // TODO(austin) This pulls over the whole string in a
+               // remote setting, instead of creating a substring backed
+               // by remote memory.
+               expr.eval = func(t *Thread) string {
+                       arr, lo, hi := arrf(t), lof(t), hif(t);
+                       if lo > hi || hi > int64(len(arr)) || lo < 0 {
+                               t.Abort(SliceError{lo, hi, int64(len(arr))});
+                       }
+                       return arr[lo:hi];
+               }
+
+       default:
+               log.Crashf("unexpected left operand type %T", arr.t.lit());
+       }
+
+       return expr;
+}
+
 func (a *exprInfo) compileIndexExpr(l, r *expr) *expr {
        // Type check object
        l = l.derefArray();
@@ -1297,9 +1387,66 @@ func (a *exprInfo) compileBuiltinCallExpr(b *block, ft *FuncType, as []*expr) *e
                        return nil;
                }
 
-       case closeType, closedType, newType, panicType, paniclnType, printType, printlnType:
+       case closeType, closedType:
                a.diag("built-in function %s not implemented", ft.builtin);
                return nil;
+
+       case newType:
+               if !checkCount(1, 1) {
+                       return nil;
+               }
+
+               t := as[0].valType;
+               expr := a.newExpr(NewPtrType(t), "new");
+               expr.eval = func(*Thread) Value {
+                       return t.Zero();
+               };
+               return expr;
+
+       case panicType, paniclnType, printType, printlnType:
+               evals := make([]func(*Thread)interface{}, len(as));
+               for i, x := range as {
+                       evals[i] = x.asInterface();
+               }
+               spaces := ft == paniclnType || ft == printlnType;
+               newline := ft != printType;
+               printer := func(t *Thread) {
+                       for i, eval := range evals {
+                               if i > 0 && spaces {
+                                       print(" ");
+                               }
+                               v := eval(t);
+                               type stringer interface { String() string }
+                               switch v1 := v.(type) {
+                               case bool:
+                                       print(v1);
+                               case uint64:
+                                       print(v1);
+                               case int64:
+                                       print(v1);
+                               case float64:
+                                       print(v1);
+                               case string:
+                                       print(v1);
+                               case stringer:
+                                       print(v1.String());
+                               default:
+                                       print("???");
+                               }
+                       }
+                       if newline {
+                               print("\n");
+                       }
+               };
+               expr := a.newExpr(EmptyType, "print");
+               expr.exec = printer;
+               if ft == panicType || ft == paniclnType {
+                       expr.exec = func(t *Thread) {
+                               printer(t);
+                               t.Abort(os.NewError("panic"));
+                       }
+               }
+               return expr;
        }
 
        log.Crashf("unexpected built-in function '%s'", ft.builtin);
@@ -1680,13 +1827,9 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
                expr.genBinOpMul(l, r);
 
        case token.QUO:
-               // TODO(austin) Clear higher bits that may have
-               // accumulated in our temporary.
                expr.genBinOpQuo(l, r);
 
        case token.REM:
-               // TODO(austin) Clear higher bits that may have
-               // accumulated in our temporary.
                expr.genBinOpRem(l, r);
 
        case token.AND:
@@ -1745,6 +1888,12 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
        case token.NEQ:
                expr.genBinOpNeq(l, r);
 
+       case token.LAND:
+               expr.genBinOpLogAnd(l, r);
+
+       case token.LOR:
+               expr.genBinOpLogOr(l, r);
+
        default:
                log.Crashf("Compilation of binary op %v not implemented", op);
        }
index d337ea1770e7ad7782573e6522c15017dd042640..7787a2112f6d39cceb2b16d4a11d28a8fc0d70e4 100644 (file)
@@ -1,4 +1,3 @@
-
 // This file is machine generated by gen.go.
 // 6g gen.go && 6l gen.6 && ./6.out >expr1.go
 
@@ -58,31 +57,31 @@ func (a *expr) asMulti() (func(*Thread) []Value) {
 
 func (a *expr) asInterface() (func(*Thread) interface{}) {
        switch sf := a.eval.(type) {
-       case func(*Thread)bool:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)uint64:
+       case func(t *Thread)bool:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)int64:
+       case func(t *Thread)uint64:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)*bignum.Integer:
+       case func(t *Thread)int64:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)float64:
+       case func()*bignum.Integer:
+               return func(*Thread) interface{} { return sf() }
+       case func(t *Thread)float64:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)*bignum.Rational:
+       case func()*bignum.Rational:
+               return func(*Thread) interface{} { return sf() }
+       case func(t *Thread)string:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)string:
+       case func(t *Thread)ArrayValue:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)ArrayValue:
+       case func(t *Thread)StructValue:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)StructValue:
+       case func(t *Thread)Value:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)Value:
+       case func(t *Thread)Func:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)Func:
+       case func(t *Thread)Slice:
                return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)Slice:
-               return func(t *Thread) interface{} { return sf(t) }
-       case func(*Thread)Map:
+       case func(t *Thread)Map:
                return func(t *Thread) interface{} { return sf(t) }
        default:
                log.Crashf("unexpected expression node type %T at %v", a.eval, a.pos);
@@ -272,16 +271,104 @@ func (a *expr) genUnaryOpXor(v *expr) {
        }
 }
 
+func (a *expr) genBinOpLogAnd(l, r *expr) {
+       lf := l.asBool();
+       rf := r.asBool();
+       a.eval = func(t *Thread) bool { return lf(t) && rf(t) }
+}
+
+func (a *expr) genBinOpLogOr(l, r *expr) {
+       lf := l.asBool();
+       rf := r.asBool();
+       a.eval = func(t *Thread) bool { return lf(t) || rf(t) }
+}
+
 func (a *expr) genBinOpAdd(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l + r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l + r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l + r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l + r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l + r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l + r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l + r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l + r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l + r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l + r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l + r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l + r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -290,7 +377,31 @@ func (a *expr) genBinOpAdd(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); return l + r }
+               switch t.Bits {
+               case 32:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l + r;
+                               return float64(float32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l + r;
+                               return float64(float64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l + r;
+                               return float64(float(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -299,22 +410,101 @@ func (a *expr) genBinOpAdd(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) string { l, r := lf(t), rf(t); 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);
        }
 }
 
 func (a *expr) genBinOpSub(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l - r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l - r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l - r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l - r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l - r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l - r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l - r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l - r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l - r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l - r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l - r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l - r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -323,7 +513,31 @@ func (a *expr) genBinOpSub(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); return l - r }
+               switch t.Bits {
+               case 32:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l - r;
+                               return float64(float32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l - r;
+                               return float64(float64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l - r;
+                               return float64(float(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -335,15 +549,91 @@ func (a *expr) genBinOpSub(l, r *expr) {
 }
 
 func (a *expr) genBinOpMul(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l * r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l * r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l * r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l * r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l * r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l * r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l * r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l * r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l * r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l * r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l * r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l * r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -352,7 +642,31 @@ func (a *expr) genBinOpMul(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); return l * r }
+               switch t.Bits {
+               case 32:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l * r;
+                               return float64(float32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l * r;
+                               return float64(float64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               ret = l * r;
+                               return float64(float(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -364,15 +678,91 @@ func (a *expr) genBinOpMul(l, r *expr) {
 }
 
 func (a *expr) genBinOpQuo(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l / r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l / r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -381,7 +771,31 @@ func (a *expr) genBinOpQuo(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) float64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l / r }
+               switch t.Bits {
+               case 32:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return float64(float32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return float64(float64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) float64 {
+                               l, r := lf(t), rf(t);
+                               var ret float64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r;
+                               return float64(float(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealFloatType:
                l := l.asIdealFloat()();
                r := r.asIdealFloat()();
@@ -393,15 +807,91 @@ func (a *expr) genBinOpQuo(l, r *expr) {
 }
 
 func (a *expr) genBinOpRem(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l % r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); if r == 0 { t.Abort(DivByZeroError{}) } return l % r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -413,15 +903,91 @@ func (a *expr) genBinOpRem(l, r *expr) {
 }
 
 func (a *expr) genBinOpAnd(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l & r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l & r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l & r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l & r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l & r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l & r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l & r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l & r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l & r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l & r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l & r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l & r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -433,15 +999,91 @@ func (a *expr) genBinOpAnd(l, r *expr) {
 }
 
 func (a *expr) genBinOpOr(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l | r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l | r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l | r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l | r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l | r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l | r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l | r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l | r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l | r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l | r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l | r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l | r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -453,15 +1095,91 @@ func (a *expr) genBinOpOr(l, r *expr) {
 }
 
 func (a *expr) genBinOpXor(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l ^ r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l ^ r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l ^ r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l ^ r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l ^ r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l ^ r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l ^ r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l ^ r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l ^ r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l ^ r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l ^ r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l ^ r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -473,15 +1191,91 @@ func (a *expr) genBinOpXor(l, r *expr) {
 }
 
 func (a *expr) genBinOpAndNot(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l &^ r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l &^ r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l &^ r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l &^ r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l &^ r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l &^ r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asInt();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l &^ r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l &^ r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l &^ r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l &^ r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l &^ r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l &^ r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *idealIntType:
                l := l.asIdealInt()();
                r := r.asIdealInt()();
@@ -493,45 +1287,203 @@ func (a *expr) genBinOpAndNot(l, r *expr) {
 }
 
 func (a *expr) genBinOpShl(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l << r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l << r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l << r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l << r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l << r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l << r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asUint();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l << r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l << r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l << r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l << r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l << r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l << r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
 }
 
 func (a *expr) genBinOpShr(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) uint64 { l, r := lf(t), rf(t); return l >> r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l >> r;
+                               return uint64(uint8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l >> r;
+                               return uint64(uint16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l >> r;
+                               return uint64(uint32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l >> r;
+                               return uint64(uint64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) uint64 {
+                               l, r := lf(t), rf(t);
+                               var ret uint64;
+                               ret = l >> r;
+                               return uint64(uint(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        case *intType:
                lf := l.asInt();
                rf := r.asUint();
-               a.eval = func(t *Thread) int64 { l, r := lf(t), rf(t); return l >> r }
+               switch t.Bits {
+               case 8:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l >> r;
+                               return int64(int8(ret))
+                       }
+               case 16:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l >> r;
+                               return int64(int16(ret))
+                       }
+               case 32:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l >> r;
+                               return int64(int32(ret))
+                       }
+               case 64:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l >> r;
+                               return int64(int64(ret))
+                       }
+               case 0:
+                       a.eval = func(t *Thread) int64 {
+                               l, r := lf(t), rf(t);
+                               var ret int64;
+                               ret = l >> r;
+                               return int64(int(ret))
+                       }
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
 }
 
 func (a *expr) genBinOpLss(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -540,7 +1492,10 @@ func (a *expr) genBinOpLss(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -549,22 +1504,31 @@ func (a *expr) genBinOpLss(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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 (a *expr) genBinOpGtr(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -573,7 +1537,10 @@ func (a *expr) genBinOpGtr(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -582,22 +1549,31 @@ func (a *expr) genBinOpGtr(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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 (a *expr) genBinOpLeq(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -606,7 +1582,10 @@ func (a *expr) genBinOpLeq(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -615,22 +1594,31 @@ func (a *expr) genBinOpLeq(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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 (a *expr) genBinOpGeq(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *uintType:
                lf := l.asUint();
                rf := r.asUint();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -639,7 +1627,10 @@ func (a *expr) genBinOpGeq(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -648,26 +1639,38 @@ func (a *expr) genBinOpGeq(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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 (a *expr) genBinOpEql(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *boolType:
                lf := l.asBool();
                rf := r.asBool();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -676,7 +1679,10 @@ func (a *expr) genBinOpEql(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -685,38 +1691,59 @@ func (a *expr) genBinOpEql(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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 (a *expr) genBinOpNeq(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
        case *boolType:
                lf := l.asBool();
                rf := r.asBool();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -725,7 +1752,10 @@ func (a *expr) genBinOpNeq(l, r *expr) {
        case *floatType:
                lf := l.asFloat();
                rf := r.asFloat();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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()();
@@ -734,19 +1764,31 @@ func (a *expr) genBinOpNeq(l, r *expr) {
        case *stringType:
                lf := l.asString();
                rf := r.asString();
-               a.eval = func(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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(t *Thread) bool { l, r := lf(t), rf(t); 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);
        }
index 5e7465e3d7a8f1215746dc2ff919a360e463a277..06939e58c716c0fa733b0bf2d9e964c392ae1bbb 100644 (file)
@@ -22,6 +22,11 @@ type Op struct {
        Types []*Type;
 }
 
+type Size struct {
+       Bits int;
+       Sized string;
+}
+
 type Type struct {
        Repr string;
        Value string;
@@ -29,14 +34,21 @@ type Type struct {
        As string;
        IsIdeal bool;
        HasAssign bool;
+       Sizes []Size;
 }
 
 var (
        boolType = &Type{ Repr: "*boolType", Value: "BoolValue", Native: "bool", As: "asBool" };
-       uintType = &Type{ Repr: "*uintType", Value: "UintValue", Native: "uint64", As: "asUint" };
-       intType = &Type{ Repr: "*intType", Value: "IntValue", Native: "int64", As: "asInt" };
+       uintType = &Type{ Repr: "*uintType", Value: "UintValue", Native: "uint64", As: "asUint",
+               Sizes: []Size{ Size{8, "uint8"}, Size{16, "uint16"}, Size{32, "uint32"}, Size{64, "uint64"}, Size{0, "uint"}}
+       };
+       intType = &Type{ Repr: "*intType", Value: "IntValue", Native: "int64", As: "asInt",
+               Sizes: []Size{Size{8, "int8"}, Size{16, "int16"}, Size{32, "int32"}, Size{64, "int64"}, Size{0, "int"}}
+       };
        idealIntType = &Type{ Repr: "*idealIntType", Value: "IdealIntValue", Native: "*bignum.Integer", As: "asIdealInt", IsIdeal: true };
-       floatType = &Type{ Repr: "*floatType", Value: "FloatValue", Native: "float64", As: "asFloat" };
+       floatType = &Type{ Repr: "*floatType", Value: "FloatValue", Native: "float64", As: "asFloat",
+               Sizes: []Size{Size{32, "float32"}, Size{64, "float64"}, Size{0, "float"}}
+       };
        idealFloatType = &Type{ Repr: "*idealFloatType", Value: "IdealFloatValue", Native: "*bignum.Rational", As: "asIdealFloat", IsIdeal: true };
        stringType = &Type{ Repr: "*stringType", Value: "StringValue", Native: "string", As: "asString" };
        arrayType = &Type{ Repr: "*ArrayType", Value: "ArrayValue", Native: "ArrayValue", As: "asArray", HasAssign: true };
@@ -91,12 +103,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 { t.Abort(DivByZeroError{}) } return l / r",
+               Body: "if r == 0 { t.Abort(DivByZeroError{}) } ret =  l / r",
                ConstExpr: "l.Quo(r)",
                Types: numbers,
        },
        Op{ Name: "Rem",
-               Body: "if r == 0 { t.Abort(DivByZeroError{}) } return l % r",
+               Body: "if r == 0 { t.Abort(DivByZeroError{}) } ret = l % r",
                ConstExpr: "l.Rem(r)",
                Types: integers,
        },
@@ -163,10 +175,11 @@ func (a *expr) asMulti() (func(*Thread) []Value) {
 func (a *expr) asInterface() (func(*Thread) interface{}) {
        switch sf := a.eval.(type) {
 «.repeated section Types»
-       case func(*Thread)«Native»:
 «.section IsIdeal»
-               return func(t *Thread) interface{} { return sf(t) }
+       case func()«Native»:
+               return func(*Thread) interface{} { return sf() }
 «.or»
+       case func(t *Thread)«Native»:
                return func(t *Thread) interface{} { return sf(t) }
 «.end»
 «.end»
@@ -263,26 +276,68 @@ func (a *expr) genUnaryOp«Name»(v *expr) {
 }
 
 «.end»
+func (a *expr) genBinOpLogAnd(l, r *expr) {
+       lf := l.asBool();
+       rf := r.asBool();
+       a.eval = func(t *Thread) bool { return lf(t) && rf(t) }
+}
+
+func (a *expr) genBinOpLogOr(l, r *expr) {
+       lf := l.asBool();
+       rf := r.asBool();
+       a.eval = func(t *Thread) bool { return lf(t) || rf(t) }
+}
+
 «.repeated section BinaryOps»
 func (a *expr) genBinOp«Name»(l, r *expr) {
-       switch l.t.lit().(type) {
+       switch t := l.t.lit().(type) {
 «.repeated section Types»
        case «Repr»:
-«.section IsIdeal»
+       «.section IsIdeal»
                l := l.«As»()();
                r := r.«As»()();
                val := «ConstExpr»;
-«.section ReturnType»
+               «.section ReturnType»
                a.eval = func(t *Thread) «ReturnType» { return val }
-«.or»
+               «.or»
                a.eval = func() «Native» { return val }
-«.end»
-«.or»
+               «.end»
+       «.or»
                lf := l.«As»();
                rf := r.«.section AsRightName»«@»«.or»«As»«.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»
+               «.section ReturnType»
+               a.eval = func(t *Thread) «@» {
+                       l, r := lf(t), rf(t);
+                       return «Expr»
+               }
+               «.or»
+               «.section Sizes»
+               switch t.Bits {
+               «.repeated section @»
+               case «Bits»:
+                       a.eval = func(t *Thread) «Native» {
+                               l, r := lf(t), rf(t);
+                               var ret «Native»;
+                               «.section Body»
+                               «Body»;
+                               «.or»
+                               ret = «Expr»;
+                               «.end»
+                               return «Native»(«Sized»(ret))
+                       }
+               «.end»
+               default:
+                       log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
+               }
+               «.or»
+               a.eval = func(t *Thread) «Native» {
+                       l, r := lf(t), rf(t);
+                       return «Expr»
+               }
+               «.end»
+               «.end»
+       «.end»
+       «.end»
        default:
                log.Crashf("unexpected type %v at %v", l.t, a.pos);
        }
index a4401e1dd5a22ef6e659ec685ea6236d89057922..2a6d94845e986a7eabd95e9b4e812a4756be1df2 100644 (file)
@@ -7,11 +7,66 @@ package main
 import (
        "./_obj/eval";
        "bufio";
+       "flag";
+       "go/parser";
+       "go/scanner";
+       "io";
        "os";
 )
 
+var filename = flag.String("f", "", "file to run");
+
 func main() {
+       flag.Parse();
        w := eval.NewWorld();
+       if *filename != "" {
+               data, err := io.ReadFile(*filename);
+               if err != nil {
+                       println(err.String());
+                       os.Exit(1);
+               }
+               file, err := parser.ParseFile(*filename, data, 0);
+               if err != nil {
+                       println(err.String());
+                       os.Exit(1);
+               }
+               code, err := w.CompileDeclList(file.Decls);
+               if err != nil {
+                       if list, ok := err.(scanner.ErrorList); ok {
+                               for _, e := range list {
+                                       println(e.String());
+                               }
+                       } else {
+                               println(err.String());
+                       }
+                       os.Exit(1);
+               }
+               _, err := code.Run();
+               if err != nil {
+                       println(err.String());
+                       os.Exit(1);
+               }
+               code, err = w.Compile("init()");
+               if code != nil {
+                       _, err := code.Run();
+                       if err != nil {
+                               println(err.String());
+                               os.Exit(1);
+                       }
+               }
+               code, err = w.Compile("main()");
+               if err != nil {
+                       println(err.String());
+                       os.Exit(1);
+               }
+               _, err = code.Run();
+               if err != nil {
+                       println(err.String());
+                       os.Exit(1);
+               }
+               os.Exit(0);
+       }
+
        r := bufio.NewReader(os.Stdin);
        for {
                print("; ");
index 77e907088a9cf521aed083b3e99118f45fb1ca9a..e94adfb602c1522819056ee96a3634f9c1e08e0f 100644 (file)
@@ -331,9 +331,11 @@ var stmtTests = []test {
        CErr("x := make(map[int] int); (func(a,b int){})(x[0])", "not enough"),
        CErr("x := make(map[int] int); x[1] = oneTwo()", "too many"),
        RErr("x := make(map[int] int); i = x[1]", "key '1' not found"),
-       
+
        // Functions
        Val2("func fib(n int) int { if n <= 2 { return n } return fib(n-1) + fib(n-2) }", "fib(4)", 5, "fib(10)", 89),
+       Run("func f1(){}"),
+       Run2("func f1(){}", "f1()"),
 }
 
 func TestStmt(t *testing.T) {
index 397da097a89b7302937581f0745ab48082ef1d69..6d547f6e83600dd654e1f0bde4bccbaefe49785b 100644 (file)
@@ -12,9 +12,6 @@ import (
        "os";
 )
 
-// TODO: Make CompileExpr and CompileStmts
-// methods on World.
-
 type World struct {
        scope *Scope;
        frame *Frame;
@@ -41,10 +38,10 @@ type stmtCode struct {
        code code;
 }
 
-func (w *World) compileStmts(stmts []ast.Stmt) (Code, os.Error) {
+func (w *World) CompileStmtList(stmts []ast.Stmt) (Code, os.Error) {
        if len(stmts) == 1 {
                if s, ok := stmts[0].(*ast.ExprStmt); ok {
-                       return w.compileExpr(s.X);
+                       return w.CompileExpr(s.X);
                }
        }
        errors := scanner.NewErrorVector();
@@ -73,12 +70,12 @@ func (w *World) compileStmts(stmts []ast.Stmt) (Code, os.Error) {
        return &stmtCode{w, fc.get()}, nil;
 }
 
-func (w *World) compileDecls(decls []ast.Decl) (Code, os.Error) {      
+func (w *World) CompileDeclList(decls []ast.Decl) (Code, os.Error) {
        stmts := make([]ast.Stmt, len(decls));
        for i, d := range decls {
                stmts[i] = &ast.DeclStmt{d};
        }
-       return w.compileStmts(stmts);
+       return w.CompileStmtList(stmts);
 }
 
 func (s *stmtCode) Type() Type {
@@ -97,7 +94,7 @@ type exprCode struct {
        eval func(Value, *Thread);
 }
 
-func (w *World) compileExpr(e ast.Expr) (Code, os.Error) {
+func (w *World) CompileExpr(e ast.Expr) (Code, os.Error) {
        errors := scanner.NewErrorVector();
        cc := &compiler{errors, 0, 0};
 
@@ -144,13 +141,13 @@ func (e *exprCode) Run() (Value, os.Error) {
 func (w *World) Compile(text string) (Code, os.Error) {
        stmts, err := parser.ParseStmtList("input", text);
        if err == nil {
-               return w.compileStmts(stmts);
+               return w.CompileStmtList(stmts);
        }
 
        // Otherwise try as DeclList.
        decls, err1 := parser.ParseDeclList("input", text);
        if err1 == nil {
-               return w.compileDecls(decls);
+               return w.CompileDeclList(decls);
        }
 
        // Have to pick an error.