mirror of
https://github.com/golang/go
synced 2024-11-26 20:51:23 -07:00
d3888fe8a3
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
184 lines
3.5 KiB
Go
184 lines
3.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 (
|
|
"bignum";
|
|
)
|
|
|
|
/*
|
|
* Types
|
|
*/
|
|
|
|
type Value interface
|
|
|
|
type Type interface {
|
|
// literal returns this type with all names recursively
|
|
// stripped. This should only be used when determining
|
|
// assignment compatibility. To strip a named type for use in
|
|
// a type switch, use .rep().
|
|
literal() Type;
|
|
// rep returns the representative type. If this is a named
|
|
// type, this is the unnamed underlying type. Otherwise, this
|
|
// is an identity operation.
|
|
rep() Type;
|
|
// isBoolean returns true if this is a boolean type.
|
|
isBoolean() bool;
|
|
// isInteger returns true if this is an integer type.
|
|
isInteger() bool;
|
|
// isFloat returns true if this is a floating type.
|
|
isFloat() bool;
|
|
// isIdeal returns true if this is an ideal int or float.
|
|
isIdeal() bool;
|
|
// ZeroVal returns a new zero value of this type.
|
|
Zero() Value;
|
|
// String returns the string representation of this type.
|
|
String() string;
|
|
}
|
|
|
|
type BoundedType interface {
|
|
Type;
|
|
// minVal returns the smallest value of this type.
|
|
minVal() *bignum.Rational;
|
|
// maxVal returns the largest value of this type.
|
|
maxVal() *bignum.Rational;
|
|
}
|
|
|
|
/*
|
|
* Values
|
|
*/
|
|
|
|
type Value interface {
|
|
String() string;
|
|
// Assign copies another value into this one. It should
|
|
// assume that the other value satisfies the same specific
|
|
// value interface (BoolValue, etc.), but must not assume
|
|
// anything about its specific type.
|
|
Assign(o Value);
|
|
}
|
|
|
|
type BoolValue interface {
|
|
Value;
|
|
Get() bool;
|
|
Set(bool);
|
|
}
|
|
|
|
type UintValue interface {
|
|
Value;
|
|
Get() uint64;
|
|
Set(uint64);
|
|
}
|
|
|
|
type IntValue interface {
|
|
Value;
|
|
Get() int64;
|
|
Set(int64);
|
|
}
|
|
|
|
type IdealIntValue interface {
|
|
Value;
|
|
Get() *bignum.Integer;
|
|
}
|
|
|
|
type FloatValue interface {
|
|
Value;
|
|
Get() float64;
|
|
Set(float64);
|
|
}
|
|
|
|
type IdealFloatValue interface {
|
|
Value;
|
|
Get() *bignum.Rational;
|
|
}
|
|
|
|
type StringValue interface {
|
|
Value;
|
|
Get() string;
|
|
Set(string);
|
|
}
|
|
|
|
type ArrayValue interface {
|
|
Value;
|
|
// TODO(austin) Get() is here for uniformity, but is
|
|
// completely useless. If a lot of other types have similarly
|
|
// useless Get methods, just special-case these uses.
|
|
Get() ArrayValue;
|
|
Elem(i int64) Value;
|
|
}
|
|
|
|
type PtrValue interface {
|
|
Value;
|
|
Get() Value;
|
|
Set(Value);
|
|
}
|
|
|
|
type Func interface
|
|
type FuncValue interface {
|
|
Value;
|
|
Get() Func;
|
|
Set(Func);
|
|
}
|
|
|
|
/*
|
|
* Scopes
|
|
*/
|
|
|
|
type Variable struct {
|
|
// Index of this variable in the Frame structure
|
|
Index int;
|
|
// Static type of this variable
|
|
Type Type;
|
|
}
|
|
|
|
type Constant struct {
|
|
Type Type;
|
|
Value Value;
|
|
}
|
|
|
|
// A definition can be a *Variable, *Constant, or Type.
|
|
type Def interface {}
|
|
|
|
type Scope struct {
|
|
outer *Scope;
|
|
defs map[string] Def;
|
|
temps map[int] *Variable;
|
|
numVars int;
|
|
varTypes []Type;
|
|
}
|
|
|
|
func (s *Scope) Fork() *Scope
|
|
func (s *Scope) DefineVar(name string, t Type) *Variable
|
|
func (s *Scope) DefineTemp(t Type) *Variable
|
|
func (s *Scope) DefineConst(name string, t Type, v Value) *Constant
|
|
func (s *Scope) DefineType(name string, t Type) Type
|
|
func (s *Scope) Lookup(name string) (Def, *Scope)
|
|
|
|
// The universal scope
|
|
var universe = &Scope{defs: make(map[string] Def), temps: make(map[int] *Variable)};
|
|
|
|
/*
|
|
* Frames
|
|
*/
|
|
|
|
type Frame struct {
|
|
Outer *Frame;
|
|
Scope *Scope;
|
|
Vars []Value;
|
|
}
|
|
|
|
func (f *Frame) Get(s *Scope, index int) Value
|
|
func (f *Frame) String() string
|
|
|
|
func (s *Scope) NewFrame(outer *Frame) *Frame
|
|
|
|
/*
|
|
* Functions
|
|
*/
|
|
|
|
type Func interface {
|
|
NewFrame() *Frame;
|
|
Call(*Frame);
|
|
}
|