diff options
Diffstat (limited to 'src/pkg/exp/eval/func.go')
-rw-r--r-- | src/pkg/exp/eval/func.go | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/pkg/exp/eval/func.go b/src/pkg/exp/eval/func.go new file mode 100644 index 000000000..3bf52871d --- /dev/null +++ b/src/pkg/exp/eval/func.go @@ -0,0 +1,89 @@ +// 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); +} |