2009-07-27 14:01:23 -06:00
|
|
|
// 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;
|
2009-07-29 12:57:46 -06:00
|
|
|
// The execution frame of this function. This remains the
|
|
|
|
// same throughout a function invocation.
|
2009-07-27 14:01:23 -06:00
|
|
|
f *Frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
type code []func(*vm)
|
|
|
|
|
|
|
|
func (i code) exec(fr *Frame) {
|
2009-07-29 12:57:46 -06:00
|
|
|
v := vm{0, fr};
|
2009-07-27 14:01:23 -06:00
|
|
|
|
|
|
|
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)};
|
|
|
|
}
|
|
|
|
|
2009-07-27 16:21:32 -06:00
|
|
|
func (b *codeBuf) push(instr func(*vm)) {
|
2009-07-27 14:01:23 -06:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2009-07-28 15:37:06 -06:00
|
|
|
func (b *codeBuf) nextPC() uint {
|
|
|
|
return uint(len(b.instrs));
|
|
|
|
}
|
|
|
|
|
2009-07-27 16:21:32 -06:00
|
|
|
func (b *codeBuf) get() code {
|
2009-07-27 14:01:23 -06:00
|
|
|
// 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 {
|
2009-07-29 12:57:46 -06:00
|
|
|
outer *Frame;
|
|
|
|
frameSize int;
|
2009-07-27 14:01:23 -06:00
|
|
|
code code;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *evalFunc) NewFrame() *Frame {
|
2009-07-29 12:57:46 -06:00
|
|
|
return f.outer.child(f.frameSize);
|
2009-07-27 14:01:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *evalFunc) Call(fr *Frame) {
|
|
|
|
f.code.exec(fr);
|
|
|
|
}
|