// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package eval import "os" /* * Virtual machine */ type Thread struct { abort chan os.Error pc uint // The execution frame of this function. This remains the // same throughout a function invocation. f *Frame } type code []func(*Thread) func (i code) exec(t *Thread) { opc := t.pc t.pc = 0 l := uint(len(i)) for t.pc < l { pc := t.pc t.pc++ i[pc](t) } t.pc = opc } /* * Code buffer */ type codeBuf struct { instrs code } func newCodeBuf() *codeBuf { return &codeBuf{make(code, 0, 16)} } func (b *codeBuf) push(instr func(*Thread)) { n := len(b.instrs) if n >= cap(b.instrs) { a := make(code, n, n*2) for i := range b.instrs { a[i] = b.instrs[i] } b.instrs = a } b.instrs = b.instrs[0 : n+1] b.instrs[n] = instr } func (b *codeBuf) nextPC() uint { return uint(len(b.instrs)) } func (b *codeBuf) get() code { // Freeze this buffer into an array of exactly the right size a := make(code, len(b.instrs)) for i := range b.instrs { a[i] = b.instrs[i] } return code(a) } /* * User-defined functions */ type evalFunc struct { outer *Frame frameSize int code code } func (f *evalFunc) NewFrame() *Frame { return f.outer.child(f.frameSize) } func (f *evalFunc) Call(t *Thread) { f.code.exec(t) }