Commit 30dcb134 authored by Austin Clements's avatar Austin Clements

Split decls.go up, taking advantage of whole-package

compilation to put the definitions in reasonable places.  No
code changes, just movement.

R=rsc
APPROVED=rsc
DELTA=479  (232 added, 247 deleted, 0 changed)
OCL=34067
CL=34069
parent 345c1bd4
......@@ -9,7 +9,6 @@ GOFILES=\
abort.go\
bridge.go\
compiler.go\
decls.go\
expr.go\
func.go\
scope.go\
......
......@@ -37,6 +37,17 @@ func (a *compiler) numError() int {
return a.numErrors + a.silentErrors;
}
// 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();
// TODO(austin) These can all go in stmt.go now
type label struct {
......
// 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;
}
......@@ -10,6 +10,65 @@ import (
"log";
)
/*
* Blocks and 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;
}
func (b *block) enterChild() *block {
if b.inner != nil && b.inner.scope == b.scope {
log.Crash("Failed to exit child block before entering another child");
......@@ -117,6 +176,15 @@ func (s *Scope) NewFrame(outer *Frame) *Frame {
return fr;
}
/*
* Frames
*/
type Frame struct {
Outer *Frame;
Vars []Value;
}
func (f *Frame) Get(level int, index int) Value {
for ; level > 0; level-- {
f = f.Outer;
......
......@@ -26,6 +26,44 @@ import (
// sense in the comparison operators section. The compatibility and
// assignment compatibility sections should be rolled into one.
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;
}
var universePos = token.Position{"<universe>", 0, 0, 0};
/*
......
......@@ -9,6 +9,121 @@ import (
"fmt";
)
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);
}
/*
* Bool
*/
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment