mirror of
https://github.com/golang/go.git
synced 2025-05-14 03:44:40 +00:00
and decrement. blockCompilers now form a tree the mimics the nesting of scopes and provide convenient ways to enter and exit scopes. blockCompilers also track the break and continue PC for the current block. The statement testing interface now works in lists of statements, which simplifies a bunch of things. R=rsc APPROVED=rsc DELTA=401 (335 added, 44 deleted, 22 changed) OCL=32308 CL=32317
95 lines
1.5 KiB
Go
95 lines
1.5 KiB
Go
// 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 current execution frame. If execution is within a
|
|
// block, this may be a child of the original function
|
|
// activation frame.
|
|
f *Frame;
|
|
// The original function activation frame. This is used to
|
|
// access function out args.
|
|
activation *Frame;
|
|
}
|
|
|
|
type code []func(*vm)
|
|
|
|
func (i code) exec(fr *Frame) {
|
|
v := vm{0, fr, 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 {
|
|
sc *Scope;
|
|
fr *Frame;
|
|
code code;
|
|
}
|
|
|
|
func (f *evalFunc) NewFrame() *Frame {
|
|
return f.sc.NewFrame(f.fr);
|
|
}
|
|
|
|
func (f *evalFunc) Call(fr *Frame) {
|
|
f.code.exec(fr);
|
|
}
|