mirror of
https://github.com/golang/go.git
synced 2025-05-14 11:54:38 +00:00
function calling. Implement a type compiler and named types. Implement a universal scope containing built-in named types, and some built-in constants. Implement a simple virtual machine for executing statements and single-valued return. Fix many places that incorrectly dealt with named types. In particular, the Type.Zero methods now use the type's bit count to determine the appropriate value representation. As a result, a bit count of 0 now means architecture-dependent and bounded types use unsafe.Sizeof to determine the correct bounds. Previously, the bounds on a 32-bit machine would have been wrong. Eliminated Type.compatible, since the implementation is equivalent for all types. Added Type.rep that shallowly strips named types. Replaced almost all uses of Type.literal with Type.rep. Fix implementation of assign-op's so it only evaluates the left side once. As part of this, there is now a generic way to separate out the effect and value of an expression. R=rsc APPROVED=rsc DELTA=1530 (1244 added, 68 deleted, 218 changed) OCL=32184 CL=32230
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 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) 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);
|
|
}
|