Commit 747cde81 authored by Russ Cox's avatar Russ Cox

s/vm/Thread/

change eval functions from taking *Frame to *Thread

R=austin
DELTA=500  (7 added, 4 deleted, 489 changed)
OCL=34256
CL=34260
parent 72a11c57
......@@ -39,49 +39,49 @@ func Try(f func()) os.Error {
return res;
}
type DivByZero struct {}
type DivByZeroError struct {}
func (DivByZero) String() string {
func (DivByZeroError) String() string {
return "divide by zero";
}
type NilPointer struct {}
type NilPointerError struct {}
func (NilPointer) String() string {
func (NilPointerError) String() string {
return "nil pointer dereference";
}
type IndexOutOfBounds struct {
type IndexError struct {
Idx, Len int64;
}
func (e IndexOutOfBounds) String() string {
func (e IndexError) String() string {
if e.Idx < 0 {
return fmt.Sprintf("negative index: %d", e.Idx);
}
return fmt.Sprintf("index %d exceeds length %d", e.Idx, e.Len);
}
type KeyNotFound struct {
type KeyError struct {
Key interface {};
}
func (e KeyNotFound) String() string {
func (e KeyError) String() string {
return fmt.Sprintf("key '%v' not found in map", e.Key);
}
type NegativeLength struct {
type NegativeLengthError struct {
Len int64;
}
func (e NegativeLength) String() string {
func (e NegativeLengthError) String() string {
return fmt.Sprintf("negative length: %d", e.Len);
}
type NegativeCapacity struct {
type NegativeCapacityError struct {
Len int64;
}
func (e NegativeCapacity) String() string {
func (e NegativeCapacityError) String() string {
return fmt.Sprintf("negative capacity: %d", e.Len);
}
......@@ -146,8 +146,8 @@ func (f *nativeFunc) NewFrame() *Frame {
return &Frame{nil, vars};
}
func (f *nativeFunc) Call(fr *Frame) {
f.fn(fr.Vars[0:f.in], fr.Vars[f.in:f.in+f.out]);
func (f *nativeFunc) Call(t *Thread) {
f.fn(t.f.Vars[0:f.in], t.f.Vars[f.in:f.in+f.out]);
}
// FuncFromNative creates an interpreter function from a native
......
......@@ -277,12 +277,12 @@ func (*testFunc) NewFrame() *Frame {
return &Frame{nil, &[2]Value {}};
}
func (*testFunc) Call(fr *Frame) {
n := fr.Vars[0].(IntValue).Get();
func (*testFunc) Call(t *Thread) {
n := t.f.Vars[0].(IntValue).Get();
res := n + 1;
fr.Vars[1].(IntValue).Set(res);
t.f.Vars[1].(IntValue).Set(res);
}
type oneTwoFunc struct {};
......@@ -291,9 +291,9 @@ func (*oneTwoFunc) NewFrame() *Frame {
return &Frame{nil, &[2]Value {}};
}
func (*oneTwoFunc) Call(fr *Frame) {
fr.Vars[0].(IntValue).Set(1);
fr.Vars[1].(IntValue).Set(2);
func (*oneTwoFunc) Call(t *Thread) {
t.f.Vars[0].(IntValue).Set(1);
t.f.Vars[1].(IntValue).Set(2);
}
type voidFunc struct {};
......@@ -302,7 +302,7 @@ func (*voidFunc) NewFrame() *Frame {
return &Frame{nil, []Value {}};
}
func (*voidFunc) Call(fr *Frame) {
func (*voidFunc) Call(t *Thread) {
}
func newTestScope() *Scope {
......
This diff is collapsed.
This diff is collapsed.
......@@ -8,18 +8,17 @@ package eval
* Virtual machine
*/
type vm struct {
type Thread struct {
pc uint;
// The execution frame of this function. This remains the
// same throughout a function invocation.
f *Frame;
}
type code []func(*vm)
func (i code) exec(fr *Frame) {
v := vm{0, fr};
type code []func(*Thread)
func (i code) exec(t *Thread) {
v := Thread{0, t.f}; // TODO: reuse t
l := uint(len(i));
for v.pc < l {
pc := v.pc;
......@@ -40,7 +39,7 @@ func newCodeBuf() *codeBuf {
return &codeBuf{make(code, 0, 16)};
}
func (b *codeBuf) push(instr func(*vm)) {
func (b *codeBuf) push(instr func(*Thread)) {
n := len(b.instrs);
if n >= cap(b.instrs) {
a := make(code, n, n*2);
......@@ -80,6 +79,6 @@ func (f *evalFunc) NewFrame() *Frame {
return f.outer.child(f.frameSize);
}
func (f *evalFunc) Call(fr *Frame) {
f.code.exec(fr);
func (f *evalFunc) Call(t *Thread) {
f.code.exec(t);
}
......@@ -91,12 +91,12 @@ var binOps = []Op{
Op{ Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(r)", Types: numbers },
Op{ Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(r)", Types: numbers },
Op{ Name: "Quo",
Body: "if r == 0 { Abort(DivByZero{}) } return l / r",
Body: "if r == 0 { Abort(DivByZeroError{}) } return l / r",
ConstExpr: "l.Quo(r)",
Types: numbers,
},
Op{ Name: "Rem",
Body: "if r == 0 { Abort(DivByZero{}) } return l % r",
Body: "if r == 0 { Abort(DivByZeroError{}) } return l % r",
ConstExpr: "l.Rem(r)",
Types: integers,
},
......@@ -151,23 +151,23 @@ func (a *expr) «As»() (func() «Native») {
return a.eval.(func()(«Native»))
}
«.or»
func (a *expr) «As»() (func(*Frame) «Native») {
return a.eval.(func(*Frame)(«Native»))
func (a *expr) «As»() (func(*Thread) «Native») {
return a.eval.(func(*Thread)(«Native»))
}
«.end»
«.end»
func (a *expr) asMulti() (func(*Frame) []Value) {
return a.eval.(func(*Frame)[]Value)
func (a *expr) asMulti() (func(*Thread) []Value) {
return a.eval.(func(*Thread)[]Value)
}
func (a *expr) asInterface() (func(*Frame) interface{}) {
func (a *expr) asInterface() (func(*Thread) interface{}) {
switch sf := a.eval.(type) {
«.repeated section Types»
case func(*Frame)«Native»:
case func(*Thread)«Native»:
«.section IsIdeal»
return func(f *Frame) interface{} { return sf(f) }
return func(t *Thread) interface{} { return sf(t) }
«.or»
return func(f *Frame) interface{} { return sf(f) }
return func(t *Thread) interface{} { return sf(t) }
«.end»
«.end»
default:
......@@ -188,7 +188,7 @@ func (a *expr) genConstant(v Value) {
«.section IsIdeal»
a.eval = func() «Native» { return val }
«.or»
a.eval = func(f *Frame) «Native» { return val }
a.eval = func(t *Thread) «Native» { return val }
«.end»
«.end»
default:
......@@ -197,13 +197,13 @@ func (a *expr) genConstant(v Value) {
}
func (a *expr) genIdentOp(level, index int) {
a.evalAddr = func(f *Frame) Value { return f.Get(level, index) };
a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) };
switch _ := a.t.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
«.or»
case «Repr»:
a.eval = func(f *Frame) «Native» { return f.Get(level, index).(«Value»).Get() }
a.eval = func(t *Thread) «Native» { return t.f.Get(level, index).(«Value»).Get() }
«.end»
«.end»
default:
......@@ -211,31 +211,31 @@ func (a *expr) genIdentOp(level, index int) {
}
}
func (a *expr) genFuncCall(call func(f *Frame) []Value) {
a.exec = func(f *Frame) { call(f)};
func (a *expr) genFuncCall(call func(t *Thread) []Value) {
a.exec = func(t *Thread) { call(t)};
switch _ := a.t.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
«.or»
case «Repr»:
a.eval = func(f *Frame) «Native» { return call(f)[0].(«Value»).Get() }
a.eval = func(t *Thread) «Native» { return call(t)[0].(«Value»).Get() }
«.end»
«.end»
case *MultiType:
a.eval = func(f *Frame) []Value { return call(f) }
a.eval = func(t *Thread) []Value { return call(t) }
default:
log.Crashf("unexpected result type %v at %v", a.t, a.pos);
}
}
func (a *expr) genValue(vf func(*Frame) Value) {
func (a *expr) genValue(vf func(*Thread) Value) {
a.evalAddr = vf;
switch _ := a.t.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
«.or»
case «Repr»:
a.eval = func(f *Frame) «Native» { return vf(f).(«Value»).Get() }
a.eval = func(t *Thread) «Native» { return vf(t).(«Value»).Get() }
«.end»
«.end»
default:
......@@ -254,7 +254,7 @@ func (a *expr) genUnaryOp«Name»(v *expr) {
a.eval = func() «Native» { return val }
«.or»
vf := v.«As»();
a.eval = func(f *Frame) «Native» { v := vf(f); return «Expr» }
a.eval = func(t *Thread) «Native» { v := vf(t); return «Expr» }
«.end»
«.end»
default:
......@@ -273,14 +273,14 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
r := r.«As»()();
val := «ConstExpr»;
«.section ReturnType»
a.eval = func(f *Frame) «ReturnType» { return val }
a.eval = func(t *Thread) «ReturnType» { return val }
«.or»
a.eval = func() «Native» { return val }
«.end»
«.or»
lf := l.«As»();
rf := r.«.section AsRightName»«@»«.or»«As»«.end»();
a.eval = func(f *Frame) «.section ReturnType»«@»«.or»«Native»«.end» { l, r := lf(f), rf(f); «.section Body»«Body»«.or»return «Expr»«.end» }
a.eval = func(t *Thread) «.section ReturnType»«@»«.or»«Native»«.end» { l, r := lf(t), rf(t); «.section Body»«Body»«.or»return «Expr»«.end» }
«.end»
«.end»
default:
......@@ -289,14 +289,14 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
}
«.end»
func genAssign(lt Type, r *expr) (func(lv Value, f *Frame)) {
func genAssign(lt Type, r *expr) (func(lv Value, t *Thread)) {
switch _ := lt.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
«.or»
case «Repr»:
rf := r.«As»();
return func(lv Value, f *Frame) { «.section HasAssign»lv.Assign(rf(f))«.or»lv.(«Value»).Set(rf(f))«.end» }
return func(lv Value, t *Thread) { «.section HasAssign»lv.Assign(rf(t))«.or»lv.(«Value»).Set(rf(t))«.end» }
«.end»
«.end»
default:
......
......@@ -230,7 +230,7 @@ func (a *stmtCompiler) defineVar(ident *ast.Ident, t Type) *Variable {
// Initialize the variable
index := v.Index;
a.push(func(v *vm) {
a.push(func(v *Thread) {
v.f.Vars[index] = t.Zero();
});
return v;
......@@ -416,10 +416,7 @@ func (a *stmtCompiler) compileExprStmt(s *ast.ExprStmt) {
return;
}
exec := e.exec;
a.push(func(v *vm) {
exec(v.f);
});
a.push(e.exec);
}
func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
......@@ -471,9 +468,9 @@ func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
}
lf := l.evalAddr;
a.push(func(v *vm) {
effect(v.f);
assign(lf(v.f), v.f);
a.push(func(v *Thread) {
effect(v);
assign(lf(v), v);
});
}
......@@ -605,8 +602,8 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
ls[i].evalMapValue = sub.evalMapValue;
mvf := sub.evalMapValue;
et := sub.t;
ls[i].evalAddr = func(f *Frame) Value {
m, k := mvf(f);
ls[i].evalAddr = func(t *Thread) Value {
m, k := mvf(t);
e := m.Elem(k);
if e == nil {
e = et.Zero();
......@@ -666,35 +663,35 @@ func (a *stmtCompiler) doAssign(lhs []ast.Expr, rhs []ast.Expr, tok token.Token,
if n == 1 {
// Don't need temporaries and can avoid []Value.
lf := ls[0].evalAddr;
a.push(func(v *vm) { assign(lf(v.f), v.f) });
a.push(func(t *Thread) { assign(lf(t), t) });
} else if tok == token.VAR || (tok == token.DEFINE && nDefs == n) {
// Don't need temporaries
lfs := make([]func(*Frame) Value, n);
lfs := make([]func(*Thread) Value, n);
for i, l := range ls {
lfs[i] = l.evalAddr;
}
a.push(func(v *vm) {
a.push(func(t *Thread) {
dest := make([]Value, n);
for i, lf := range lfs {
dest[i] = lf(v.f);
dest[i] = lf(t);
}
assign(multiV(dest), v.f);
assign(multiV(dest), t);
});
} else {
// Need temporaries
lmt := lt.(*MultiType);
lfs := make([]func(*Frame) Value, n);
lfs := make([]func(*Thread) Value, n);
for i, l := range ls {
lfs[i] = l.evalAddr;
}
a.push(func(v *vm) {
a.push(func(t *Thread) {
temp := lmt.Zero().(multiV);
assign(temp, v.f);
assign(temp, t);
// Copy to destination
for i := 0; i < n; i ++ {
// TODO(austin) Need to evaluate LHS
// before RHS
lfs[i](v.f).Assign(temp[i]);
lfs[i](t).Assign(temp[i]);
}
});
}
......@@ -749,9 +746,9 @@ func (a *stmtCompiler) doAssignOp(s *ast.AssignStmt) {
}
lf := l.evalAddr;
a.push(func(v *vm) {
effect(v.f);
assign(lf(v.f), v.f);
a.push(func(t *Thread) {
effect(t);
assign(lf(t), t);
});
}
......@@ -774,7 +771,7 @@ func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
if len(s.Results) == 0 && (len(a.fnType.Out) == 0 || a.outVarsNamed) {
// Simple case. Simply exit from the function.
a.flow.putTerm();
a.push(func(v *vm) { v.pc = returnPC });
a.push(func(v *Thread) { v.pc = returnPC });
return;
}
......@@ -810,9 +807,9 @@ func (a *stmtCompiler) compileReturnStmt(s *ast.ReturnStmt) {
start := len(a.fnType.In);
nout := len(a.fnType.Out);
a.flow.putTerm();
a.push(func(v *vm) {
assign(multiV(v.f.Vars[start:start+nout]), v.f);
v.pc = returnPC;
a.push(func(t *Thread) {
assign(multiV(t.f.Vars[start:start+nout]), t);
t.pc = returnPC;
});
}
......@@ -880,7 +877,7 @@ func (a *stmtCompiler) compileBranchStmt(s *ast.BranchStmt) {
}
a.flow.put1(false, pc);
a.push(func(v *vm) { v.pc = *pc });
a.push(func(v *Thread) { v.pc = *pc });
}
func (a *stmtCompiler) compileBlockStmt(s *ast.BlockStmt) {
......@@ -923,9 +920,9 @@ func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) {
default:
eval := e.asBool();
a.flow.put1(true, &elsePC);
a.push(func(v *vm) {
if !eval(v.f) {
v.pc = elsePC;
a.push(func(t *Thread) {
if !eval(t) {
t.pc = elsePC;
}
});
}
......@@ -940,7 +937,7 @@ func (a *stmtCompiler) compileIfStmt(s *ast.IfStmt) {
if s.Else != nil {
// Skip over else if we executed the body
a.flow.put1(false, &endPC);
a.push(func(v *vm) {
a.push(func(v *Thread) {
v.pc = endPC;
});
elsePC = a.nextPC();
......@@ -967,9 +964,9 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
if s.Tag != nil {
e := condbc.compileExpr(condbc.block, false, s.Tag);
if e != nil {
var effect func(f *Frame);
var effect func(*Thread);
effect, cond = e.extractEffect(condbc.block, "switch");
a.push(func(v *vm) { effect(v.f) });
a.push(effect);
}
}
......@@ -993,7 +990,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
}
// Compile case expressions
cases := make([]func(f *Frame) bool, ncases);
cases := make([]func(*Thread) bool, ncases);
i := 0;
for _, c := range s.Body.List {
clause, ok := c.(*ast.CaseClause);
......@@ -1026,14 +1023,14 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
endPC := badPC;
a.flow.put(false, false, casePCs);
a.push(func(v *vm) {
a.push(func(t *Thread) {
for i, c := range cases {
if c(v.f) {
v.pc = *casePCs[i];
if c(t) {
t.pc = *casePCs[i];
return;
}
}
v.pc = *casePCs[ncases];
t.pc = *casePCs[ncases];
});
condbc.exit();
......@@ -1083,7 +1080,7 @@ func (a *stmtCompiler) compileSwitchStmt(s *ast.SwitchStmt) {
// Jump out of switch, unless there was a fallthrough
if !fall {
a.flow.put1(false, &endPC);
a.push(func(v *vm) { v.pc = endPC });
a.push(func(v *Thread) { v.pc = endPC });
}
}
......@@ -1112,7 +1109,7 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
// Jump to condition check. We generate slightly less code by
// placing the condition check after the body.
a.flow.put1(false, &checkPC);
a.push(func(v *vm) { v.pc = checkPC });
a.push(func(v *Thread) { v.pc = checkPC });
// Compile body
bodyPC = a.nextPC();
......@@ -1141,7 +1138,7 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
if s.Cond == nil {
// If the condition is absent, it is equivalent to true.
a.flow.put1(false, &bodyPC);
a.push(func(v *vm) { v.pc = bodyPC });
a.push(func(v *Thread) { v.pc = bodyPC });
} else {
e := bc.compileExpr(bc.block, false, s.Cond);
switch {
......@@ -1152,9 +1149,9 @@ func (a *stmtCompiler) compileForStmt(s *ast.ForStmt) {
default:
eval := e.asBool();
a.flow.put1(true, &bodyPC);
a.push(func(v *vm) {
if eval(v.f) {
v.pc = bodyPC;
a.push(func(t *Thread) {
if eval(t) {
t.pc = bodyPC;
}
});
}
......@@ -1195,7 +1192,7 @@ func (a *blockCompiler) exit() {
* Function compiler
*/
func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (func (f *Frame) Func) {
func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (func (*Thread) Func) {
// Create body scope
//
// The scope of a parameter or result is the body of the
......@@ -1250,7 +1247,7 @@ func (a *compiler) compileFunc(b *block, decl *FuncDecl, body *ast.BlockStmt) (f
code := fc.get();
maxVars := bodyScope.maxVars;
return func(f *Frame) Func { return &evalFunc{f, maxVars, code} };
return func(t *Thread) Func { return &evalFunc{t.f, maxVars, code} };
}
// Checks that labels were resolved and that all jumps obey scoping
......@@ -1282,7 +1279,9 @@ type Stmt struct {
}
func (s *Stmt) Exec(f *Frame) os.Error {
return Try(func() {s.code.exec(f)});
t := new(Thread);
t.f = f;
return Try(func() {s.code.exec(t)});
}
func CompileStmts(scope *Scope, stmts []ast.Stmt) (*Stmt, os.Error) {
......
......@@ -87,7 +87,7 @@ type PtrValue interface {
type Func interface {
NewFrame() *Frame;
Call(*Frame);
Call(*Thread);
}
type FuncValue interface {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment