Commit 90ffb7b8 authored by Austin Clements's avatar Austin Clements

Cleanup of Type/Value interface. Add Type.ZeroVal, replace

all type-specific value functions, and use ZeroVal to create
new frames.  Remove Value.Type; it was unused and difficult
for values with composite types.  Add Value.Assign methods.

R=rsc
APPROVED=rsc
DELTA=282  (135 added, 90 deleted, 57 changed)
OCL=31894
CL=31930
parent 39808db1
...@@ -12,6 +12,8 @@ import ( ...@@ -12,6 +12,8 @@ import (
* Types * Types
*/ */
type Value interface
type Type interface { type Type interface {
// literal returns this type with all names recursively // literal returns this type with all names recursively
// stripped. // stripped.
...@@ -28,6 +30,8 @@ type Type interface { ...@@ -28,6 +30,8 @@ type Type interface {
isFloat() bool; isFloat() bool;
// isIdeal returns true if this is an ideal int or float. // isIdeal returns true if this is an ideal int or float.
isIdeal() bool; isIdeal() bool;
// ZeroVal returns a new zero value of this type.
Zero() Value;
// String returns the string representation of this type. // String returns the string representation of this type.
String() string; String() string;
} }
...@@ -45,9 +49,12 @@ type BoundedType interface { ...@@ -45,9 +49,12 @@ type BoundedType interface {
*/ */
type Value interface { type Value interface {
// TODO(austin) Is Type even necessary?
Type() Type;
String() string; 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 { type BoolValue interface {
...@@ -117,7 +124,6 @@ type Variable struct { ...@@ -117,7 +124,6 @@ type Variable struct {
} }
type Constant struct { type Constant struct {
// TODO(austin) Need Type?
Type Type; Type Type;
Value Value; Value Value;
} }
...@@ -129,12 +135,13 @@ type Scope struct { ...@@ -129,12 +135,13 @@ type Scope struct {
outer *Scope; outer *Scope;
defs map[string] Def; defs map[string] Def;
numVars int; numVars int;
varTypes []Type;
} }
func NewRootScope() *Scope func NewRootScope() *Scope
func (s *Scope) Fork() *Scope func (s *Scope) Fork() *Scope
func (s *Scope) DefineVar(name string, t Type) *Variable func (s *Scope) DefineVar(name string, t Type) *Variable
func (s *Scope) DefineConst(name string, v Value) *Constant func (s *Scope) DefineConst(name string, t Type, v Value) *Constant
func (s *Scope) DefineType(name string, t Type) bool func (s *Scope) DefineType(name string, t Type) bool
func (s *Scope) Lookup(name string) (Def, *Scope) func (s *Scope) Lookup(name string) (Def, *Scope)
...@@ -149,3 +156,5 @@ type Frame struct { ...@@ -149,3 +156,5 @@ type Frame struct {
} }
func (f *Frame) Get(s *Scope, index int) Value func (f *Frame) Get(s *Scope, index int) Value
func (s *Scope) NewFrame(outer *Frame) *Frame
...@@ -632,6 +632,8 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { ...@@ -632,6 +632,8 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
} }
// Useful type predicates // Useful type predicates
// TODO(austin) The spec is wrong here. The types must be
// identical, not compatible.
compat := func() bool { compat := func() bool {
return l.t.compatible(r.t); return l.t.compatible(r.t);
}; };
...@@ -829,9 +831,6 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { ...@@ -829,9 +831,6 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
a.genBinOpXor(l, r); a.genBinOpXor(l, r);
case token.AND_NOT: case token.AND_NOT:
if l.t.isIdeal() || r.t.isIdeal() {
log.Crashf("&^ for ideals not implemented");
}
a.genBinOpAndNot(l, r); a.genBinOpAndNot(l, r);
case token.SHL: case token.SHL:
...@@ -911,11 +910,14 @@ func compileExpr(expr ast.Expr, scope *Scope, errors scanner.ErrorHandler) *expr ...@@ -911,11 +910,14 @@ func compileExpr(expr ast.Expr, scope *Scope, errors scanner.ErrorHandler) *expr
*/ */
type Expr struct { type Expr struct {
f func(f *Frame) Value; t Type;
f func(f *Frame, out Value);
} }
func (expr *Expr) Eval(f *Frame) Value { func (expr *Expr) Eval(f *Frame) Value {
return expr.f(f); v := expr.t.Zero();
expr.f(f, v);
return v;
} }
func CompileExpr(expr ast.Expr, scope *Scope) (*Expr, os.Error) { func CompileExpr(expr ast.Expr, scope *Scope) (*Expr, os.Error) {
...@@ -925,26 +927,23 @@ func CompileExpr(expr ast.Expr, scope *Scope) (*Expr, os.Error) { ...@@ -925,26 +927,23 @@ func CompileExpr(expr ast.Expr, scope *Scope) (*Expr, os.Error) {
if ec == nil { if ec == nil {
return nil, errors.GetError(scanner.Sorted); return nil, errors.GetError(scanner.Sorted);
} }
// TODO(austin) This still uses Value as a generic container
// and is the only user of the 'value' methods on each type.
// Need to figure out a better way to do this.
switch t := ec.t.(type) { switch t := ec.t.(type) {
case *boolType: case *boolType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalBool(f)) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(BoolValue).Set(ec.evalBool(f)) }}, nil;
case *uintType: case *uintType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalUint(f)) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(UintValue).Set(ec.evalUint(f)) }}, nil;
case *intType: case *intType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalInt(f)) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(IntValue).Set(ec.evalInt(f)) }}, nil;
case *idealIntType: case *idealIntType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalIdealInt()) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(*idealIntV).V = ec.evalIdealInt() }}, nil;
case *floatType: case *floatType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalFloat(f)) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(FloatValue).Set(ec.evalFloat(f)) }}, nil;
case *idealFloatType: case *idealFloatType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalIdealFloat()) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(*idealFloatV).V = ec.evalIdealFloat() }}, nil;
case *stringType: case *stringType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalString(f)) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(StringValue).Set(ec.evalString(f)) }}, nil;
case *PtrType: case *PtrType:
return &Expr{func(f *Frame) Value { return t.value(ec.evalPtr(f)) }}, nil; return &Expr{t, func(f *Frame, out Value) { out.(PtrValue).Set(ec.evalPtr(f)) }}, nil;
} }
log.Crashf("unexpected type %v", ec.t); log.Crashf("unexpected type %v", ec.t);
panic(); panic();
...@@ -1282,6 +1281,11 @@ func (a *exprCompiler) genBinOpAndNot(l *exprCompiler, r *exprCompiler) { ...@@ -1282,6 +1281,11 @@ func (a *exprCompiler) genBinOpAndNot(l *exprCompiler, r *exprCompiler) {
lf := l.asInt(); lf := l.asInt();
rf := r.asInt(); rf := r.asInt();
a.evalInt = func(f *Frame) int64 { return lf(f) &^ rf(f) }; a.evalInt = func(f *Frame) int64 { return lf(f) &^ rf(f) };
case *idealIntType:
lf := l.asIdealInt();
rf := r.asIdealInt();
val := lf().AndNot(rf());
a.evalIdealInt = func() *bignum.Integer { return val };
default: default:
log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos);
} }
......
...@@ -9,11 +9,11 @@ import ( ...@@ -9,11 +9,11 @@ import (
) )
func NewRootScope() *Scope { func NewRootScope() *Scope {
return &Scope{nil, make(map[string] Def), 0}; return &Scope{defs: make(map[string] Def)};
} }
func (s *Scope) Fork() *Scope { func (s *Scope) Fork() *Scope {
return &Scope{s, make(map[string] Def), 0}; return &Scope{outer: s, defs: make(map[string] Def)};
} }
func (s *Scope) DefineVar(name string, t Type) *Variable { func (s *Scope) DefineVar(name string, t Type) *Variable {
...@@ -26,11 +26,11 @@ func (s *Scope) DefineVar(name string, t Type) *Variable { ...@@ -26,11 +26,11 @@ func (s *Scope) DefineVar(name string, t Type) *Variable {
return v; return v;
} }
func (s *Scope) DefineConst(name string, v Value) *Constant { func (s *Scope) DefineConst(name string, t Type, v Value) *Constant {
if _, ok := s.defs[name]; ok { if _, ok := s.defs[name]; ok {
return nil; return nil;
} }
c := &Constant{v.Type(), v}; c := &Constant{t, v};
s.defs[name] = c; s.defs[name] = c;
return c; return c;
} }
...@@ -53,6 +53,27 @@ func (s *Scope) Lookup(name string) (Def, *Scope) { ...@@ -53,6 +53,27 @@ func (s *Scope) Lookup(name string) (Def, *Scope) {
return nil, nil; return nil, nil;
} }
func (s *Scope) NewFrame(outer *Frame) *Frame {
if s.varTypes == nil {
// First creation of a frame from this scope. Compute
// and memoize the types of all variables.
ts := make([]Type, s.numVars);
for _, d := range s.defs {
if v, ok := d.(*Variable); ok {
ts[v.Index] = v.Type;
}
}
s.varTypes = ts;
}
// Create frame
vars := make([]Value, s.numVars);
for i, t := range s.varTypes {
vars[i] = t.Zero();
}
return &Frame{outer, s, vars};
}
func (f *Frame) Get(s *Scope, index int) Value { func (f *Frame) Get(s *Scope, index int) Value {
for f.Scope != s { for f.Scope != s {
f = f.Outer; f = f.Outer;
......
...@@ -68,7 +68,7 @@ func (boolType) String() string { ...@@ -68,7 +68,7 @@ func (boolType) String() string {
return "bool"; return "bool";
} }
func (t *boolType) value(v bool) BoolValue func (t *boolType) Zero() Value
type uintType struct { type uintType struct {
commonType; commonType;
...@@ -110,7 +110,7 @@ func (t *uintType) String() string { ...@@ -110,7 +110,7 @@ func (t *uintType) String() string {
return t.name; return t.name;
} }
func (t *uintType) value(v uint64) UintValue func (t *uintType) Zero() Value
func (t *uintType) minVal() *bignum.Rational { func (t *uintType) minVal() *bignum.Rational {
return bignum.Rat(0, 1); return bignum.Rat(0, 1);
...@@ -158,7 +158,7 @@ func (t *intType) String() string { ...@@ -158,7 +158,7 @@ func (t *intType) String() string {
return t.name; return t.name;
} }
func (t *intType) value(v int64) IntValue func (t *intType) Zero() Value
func (t *intType) minVal() *bignum.Rational { func (t *intType) minVal() *bignum.Rational {
return bignum.MakeRat(bignum.Int(-1).Shl(t.Bits - 1), bignum.Nat(1)); return bignum.MakeRat(bignum.Int(-1).Shl(t.Bits - 1), bignum.Nat(1));
...@@ -194,7 +194,7 @@ func (t *idealIntType) String() string { ...@@ -194,7 +194,7 @@ func (t *idealIntType) String() string {
return "ideal integer"; return "ideal integer";
} }
func (t *idealIntType) value(v *bignum.Integer) IdealIntValue func (t *idealIntType) Zero() Value
type floatType struct { type floatType struct {
commonType; commonType;
...@@ -223,7 +223,7 @@ func (t *floatType) String() string { ...@@ -223,7 +223,7 @@ func (t *floatType) String() string {
return "float"; return "float";
} }
func (t *floatType) value(v float64) FloatValue func (t *floatType) Zero() Value
var maxFloat32Val = bignum.MakeRat(bignum.Int(0xffffff).Shl(127-23), bignum.Nat(1)); var maxFloat32Val = bignum.MakeRat(bignum.Int(0xffffff).Shl(127-23), bignum.Nat(1));
var maxFloat64Val = bignum.MakeRat(bignum.Int(0x1fffffffffffff).Shl(1023-52), bignum.Nat(1)); var maxFloat64Val = bignum.MakeRat(bignum.Int(0x1fffffffffffff).Shl(1023-52), bignum.Nat(1));
...@@ -278,7 +278,7 @@ func (t *idealFloatType) String() string { ...@@ -278,7 +278,7 @@ func (t *idealFloatType) String() string {
return "ideal float"; return "ideal float";
} }
func (t *idealFloatType) value(v *bignum.Rational) IdealFloatValue func (t *idealFloatType) Zero() Value
type stringType struct { type stringType struct {
commonType; commonType;
...@@ -298,7 +298,7 @@ func (t *stringType) String() string { ...@@ -298,7 +298,7 @@ func (t *stringType) String() string {
return "string"; return "string";
} }
func (t *stringType) value(v string) StringValue func (t *stringType) Zero() Value
type ArrayType struct { type ArrayType struct {
commonType; commonType;
...@@ -338,7 +338,7 @@ func (t *ArrayType) String() string { ...@@ -338,7 +338,7 @@ func (t *ArrayType) String() string {
return "[]" + t.Elem.String(); return "[]" + t.Elem.String();
} }
func (t *ArrayType) value(v []Value) ArrayValue func (t *ArrayType) Zero() Value
/* /*
func (t *ArrayType) literal() Type { func (t *ArrayType) literal() Type {
...@@ -383,7 +383,7 @@ func (t *PtrType) String() string { ...@@ -383,7 +383,7 @@ func (t *PtrType) String() string {
return "*" + t.Elem.String(); return "*" + t.Elem.String();
} }
func (t *PtrType) value(v Value) PtrValue func (t *PtrType) Zero() Value
/* /*
type FuncType struct { type FuncType struct {
......
This diff is collapsed.
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