// 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 ( "container/vector"; "eval"; ) /* * Virtual machine */ type vm 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}; l := uint(len(i)); for v.pc < l { pc := v.pc; v.pc++; i[pc](&v); } } /* * Code buffer */ type codeBuf struct { instrs code; } func newCodeBuf() *codeBuf { return &codeBuf{make(code, 0, 16)}; } func (b *codeBuf) push(instr func(*vm)) { 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(fr *Frame) { f.code.exec(fr); }