mirror of
https://github.com/golang/go
synced 2024-11-26 19:41:19 -07:00
8f694f6661
single frame and non-overlapping variables reuse frame slots. As a result, entering and exiting blocks no longer requires code execution, which means jumps across block boundaries should be doable now. Frame slot initialization happens at definition time now, instead of at frame creation time. As an added bonus, Scope's are now exclusively compile-time objects and we no longer need to specially track the function activation frame for access to out vars. R=rsc APPROVED=rsc DELTA=313 (102 added, 90 deleted, 121 changed) OCL=32416 CL=32420
91 lines
1.4 KiB
Go
91 lines
1.4 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 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);
|
|
}
|