// 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 // A block represents a definition block in which a name may not be // defined more than once. type block struct { // The block enclosing this one, including blocks in other // scopes. outer *block; // The nested block currently being compiled, or nil. inner *block; // The Scope containing this block. scope *Scope; // The Variables, Constants, and Types defined in this block. defs map[string] Def; // The index of the first variable defined in this block. // This must be greater than the index of any variable defined // in any parent of this block within the same Scope at the // time this block is entered. offset int; // The number of Variables defined in this block. numVars int; } // A Scope is the compile-time analogue of a Frame, which captures // some subtree of blocks. type Scope struct { // The root block of this scope. *block; // The maximum number of variables required at any point in // this Scope. This determines the number of slots needed in // Frame's created from this Scope at run-time. maxVars int; } func (b *block) enterChild() *block func (b *block) exit() func (b *block) ChildScope() *Scope func (b *block) DefineVar(name string, t Type) *Variable func (b *block) DefineSlot(t Type) *Variable func (b *block) DefineConst(name string, t Type, v Value) *Constant func (b *block) DefineType(name string, t Type) Type func (b *block) Lookup(name string) (level int, def Def) // The universal scope func newUniverse() *Scope { sc := &Scope{nil, 0}; sc.block = &block{ scope: sc, defs: make(map[string] Def) }; return sc; } var universe *Scope = newUniverse(); /* * Frames */ type Frame struct { Outer *Frame; Vars []Value; } func (f *Frame) Get(level int, index int) Value func (f *Frame) child(numVars int) *Frame func (s *Scope) NewFrame(outer *Frame) *Frame /* * Functions */ type Func interface { NewFrame() *Frame; Call(*Frame); }