// 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"; "go/token"; ) /* * Types */ type Type interface { // compat returns whether this type is compatible with another // type. If conv is false, this is normal compatibility, // where two named types are compatible only if they are the // same named type. If conv if true, this is conversion // compatibility, where two named types are conversion // compatible if their definitions are conversion compatible. // // TODO(austin) Deal with recursive types compat(o Type, conv bool) bool; // lit returns this type's literal. If this is a named type, // this is the unnamed underlying type. Otherwise, this is an // identity operation. lit() 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; // Zero returns a new zero value of this type. Zero() Value; // String returns the string representation of this type. String() string; // The position where this type was defined, if any. Pos() token.Position; } 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); } // TODO(austin) IdealIntValue and IdealFloatValue should not exist // because ideals are not l-values. 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; // From returns an ArrayValue backed by the same array that // starts from element i. From(i int64) ArrayValue; } type StructValue interface { Value; // TODO(austin) This is another useless Get() Get() StructValue; Field(i int) Value; } type PtrValue interface { Value; Get() Value; Set(Value); } type Func interface { NewFrame() *Frame; Call(*Frame); } type FuncValue interface { Value; Get() Func; Set(Func); } type Slice struct { Base ArrayValue; Len, Cap int64; } type SliceValue interface { Value; Get() Slice; Set(Slice); } type Map interface { Len() int64; // Retrieve an element from the map, returning nil if it does // not exist. Elem(key interface{}) Value; // Set an entry in the map. If val is nil, delete the entry. SetElem(key interface{}, val Value); // TODO(austin) Perhaps there should be an iterator interface instead. Iter(func(key interface{}, val Value) bool); } type MapValue interface { Value; Get() Map; Set(Map); } /* * Scopes */ // A definition can be a *Variable, *Constant, or Type. type Def interface { Pos() token.Position; } type Variable struct { token.Position; // Index of this variable in the Frame structure Index int; // Static type of this variable Type Type; // Value of this variable. This is only used by Scope.NewFrame; // therefore, it is useful for global scopes but cannot be used // in function scopes. Init Value; } type Constant struct { token.Position; Type Type; Value Value; } // 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; } // 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; }