}
// Useful type predicates
+ // TODO(austin) The spec is wrong here. The types must be
+ // identical, not compatible.
compat := func() bool {
return l.t.compatible(r.t);
};
a.genBinOpXor(l, r);
case token.AND_NOT:
- if l.t.isIdeal() || r.t.isIdeal() {
- log.Crashf("&^ for ideals not implemented");
- }
a.genBinOpAndNot(l, r);
case token.SHL:
*/
type Expr struct {
- f func(f *Frame) Value;
+ t Type;
+ f func(f *Frame, out 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) {
if ec == nil {
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) {
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:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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:
- 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);
panic();
lf := l.asInt();
rf := r.asInt();
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:
log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos);
}
)
func NewRootScope() *Scope {
- return &Scope{nil, make(map[string] Def), 0};
+ return &Scope{defs: make(map[string] Def)};
}
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 {
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 {
return nil;
}
- c := &Constant{v.Type(), v};
+ c := &Constant{t, v};
s.defs[name] = c;
return c;
}
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 {
for f.Scope != s {
f = f.Outer;
return "bool";
}
-func (t *boolType) value(v bool) BoolValue
+func (t *boolType) Zero() Value
type uintType struct {
commonType;
return t.name;
}
-func (t *uintType) value(v uint64) UintValue
+func (t *uintType) Zero() Value
func (t *uintType) minVal() *bignum.Rational {
return bignum.Rat(0, 1);
return t.name;
}
-func (t *intType) value(v int64) IntValue
+func (t *intType) Zero() Value
func (t *intType) minVal() *bignum.Rational {
return bignum.MakeRat(bignum.Int(-1).Shl(t.Bits - 1), bignum.Nat(1));
return "ideal integer";
}
-func (t *idealIntType) value(v *bignum.Integer) IdealIntValue
+func (t *idealIntType) Zero() Value
type floatType struct {
commonType;
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 maxFloat64Val = bignum.MakeRat(bignum.Int(0x1fffffffffffff).Shl(1023-52), bignum.Nat(1));
return "ideal float";
}
-func (t *idealFloatType) value(v *bignum.Rational) IdealFloatValue
+func (t *idealFloatType) Zero() Value
type stringType struct {
commonType;
return "string";
}
-func (t *stringType) value(v string) StringValue
+func (t *stringType) Zero() Value
type ArrayType struct {
commonType;
return "[]" + t.Elem.String();
}
-func (t *ArrayType) value(v []Value) ArrayValue
+func (t *ArrayType) Zero() Value
/*
func (t *ArrayType) literal() Type {
return "*" + t.Elem.String();
}
-func (t *PtrType) value(v Value) PtrValue
+func (t *PtrType) Zero() Value
/*
type FuncType struct {
type boolV bool
-func (*boolV) Type() Type {
- return BoolType;
-}
-
func (v *boolV) String() string {
return fmt.Sprint(*v);
}
+func (v *boolV) Assign(o Value) {
+ *v = boolV(o.(BoolValue).Get());
+}
+
func (v *boolV) Get() bool {
return bool(*v);
}
*v = boolV(x);
}
-func (t *boolType) value(v bool) BoolValue {
- res := boolV(v);
+func (t *boolType) Zero() Value {
+ res := boolV(false);
return &res;
}
type uint8V uint8
-func (*uint8V) Type() Type {
- return Uint8Type;
-}
-
func (v *uint8V) String() string {
return fmt.Sprint(*v);
}
+func (v *uint8V) Assign(o Value) {
+ *v = uint8V(o.(UintValue).Get());
+}
+
func (v *uint8V) Get() uint64 {
return uint64(*v);
}
type uint16V uint16
-func (*uint16V) Type() Type {
- return Uint16Type;
-}
-
func (v *uint16V) String() string {
return fmt.Sprint(*v);
}
+func (v *uint16V) Assign(o Value) {
+ *v = uint16V(o.(UintValue).Get());
+}
+
func (v *uint16V) Get() uint64 {
return uint64(*v);
}
type uint32V uint32
-func (*uint32V) Type() Type {
- return Uint32Type;
-}
-
func (v *uint32V) String() string {
return fmt.Sprint(*v);
}
+func (v *uint32V) Assign(o Value) {
+ *v = uint32V(o.(UintValue).Get());
+}
+
func (v *uint32V) Get() uint64 {
return uint64(*v);
}
type uint64V uint64
-func (*uint64V) Type() Type {
- return Uint64Type;
-}
-
func (v *uint64V) String() string {
return fmt.Sprint(*v);
}
+func (v *uint64V) Assign(o Value) {
+ *v = uint64V(o.(UintValue).Get());
+}
+
func (v *uint64V) Get() uint64 {
return uint64(*v);
}
type uintV uint
-func (*uintV) Type() Type {
- return UintType;
-}
-
func (v *uintV) String() string {
return fmt.Sprint(*v);
}
+func (v *uintV) Assign(o Value) {
+ *v = uintV(o.(UintValue).Get());
+}
+
func (v *uintV) Get() uint64 {
return uint64(*v);
}
type uintptrV uintptr
-func (*uintptrV) Type() Type {
- return UintptrType;
-}
-
func (v *uintptrV) String() string {
return fmt.Sprint(*v);
}
+func (v *uintptrV) Assign(o Value) {
+ *v = uintptrV(o.(UintValue).Get());
+}
+
func (v *uintptrV) Get() uint64 {
return uint64(*v);
}
*v = uintptrV(x);
}
-func (t *uintType) value(v uint64) UintValue {
- // TODO(austin) The 'value' methods are only used for
- // testing right now. Get rid of them.
- // TODO(austin) Deal with named types
+func (t *uintType) Zero() Value {
+ // TODO(austin) t may be a named type instead of one of the
+ // base types.
switch Type(t) {
case Uint8Type:
- res := uint8V(v);
+ res := uint8V(0);
return &res;
case Uint16Type:
- res := uint16V(v);
+ res := uint16V(0);
return &res;
case Uint32Type:
- res := uint32V(v);
+ res := uint32V(0);
return &res;
case Uint64Type:
- res := uint64V(v);
+ res := uint64V(0);
return &res;
case UintType:
- res := uintV(v);
+ res := uintV(0);
return &res;
case UintptrType:
- res := uintptrV(v);
+ res := uintptrV(0);
return &res;
}
panic("unknown uint type ", t.String());
type int8V int8
-func (*int8V) Type() Type {
- return Int8Type;
-}
-
func (v *int8V) String() string {
return fmt.Sprint(*v);
}
+func (v *int8V) Assign(o Value) {
+ *v = int8V(o.(IntValue).Get());
+}
+
func (v *int8V) Get() int64 {
return int64(*v);
}
type int16V int16
-func (*int16V) Type() Type {
- return Int16Type;
-}
-
func (v *int16V) String() string {
return fmt.Sprint(*v);
}
+func (v *int16V) Assign(o Value) {
+ *v = int16V(o.(IntValue).Get());
+}
+
func (v *int16V) Get() int64 {
return int64(*v);
}
type int32V int32
-func (*int32V) Type() Type {
- return Int32Type;
-}
-
func (v *int32V) String() string {
return fmt.Sprint(*v);
}
+func (v *int32V) Assign(o Value) {
+ *v = int32V(o.(IntValue).Get());
+}
+
func (v *int32V) Get() int64 {
return int64(*v);
}
type int64V int64
-func (*int64V) Type() Type {
- return Int64Type;
-}
-
func (v *int64V) String() string {
return fmt.Sprint(*v);
}
+func (v *int64V) Assign(o Value) {
+ *v = int64V(o.(IntValue).Get());
+}
+
func (v *int64V) Get() int64 {
return int64(*v);
}
type intV int
-func (*intV) Type() Type {
- return IntType;
-}
-
func (v *intV) String() string {
return fmt.Sprint(*v);
}
+func (v *intV) Assign(o Value) {
+ *v = intV(o.(IntValue).Get());
+}
+
func (v *intV) Get() int64 {
return int64(*v);
}
*v = intV(x);
}
-func (t *intType) value(v int64) IntValue {
+func (t *intType) Zero() Value {
switch Type(t) {
case Int8Type:
- res := int8V(v);
+ res := int8V(0);
return &res;
case Int16Type:
- res := int16V(v);
+ res := int16V(0);
return &res;
case Int32Type:
- res := int32V(v);
+ res := int32V(0);
return &res;
case Int64Type:
- res := int64V(v);
+ res := int64V(0);
return &res;
case IntType:
- res := intV(v);
+ res := intV(0);
return &res;
}
panic("unknown int type ", t.String());
V *bignum.Integer;
}
-func (*idealIntV) Type() Type {
- return IdealIntType;
-}
-
func (v *idealIntV) String() string {
return v.V.String();
}
+func (v *idealIntV) Assign(o Value) {
+ v.V = o.(IdealIntValue).Get();
+}
+
func (v *idealIntV) Get() *bignum.Integer {
return v.V;
}
-func (t *idealIntType) value(v *bignum.Integer) IdealIntValue {
- return &idealIntV{v};
+func (t *idealIntType) Zero() Value {
+ return &idealIntV{bignum.Int(0)};
}
/*
type float32V float32
-func (*float32V) Type() Type {
- return Float32Type;
-}
-
func (v *float32V) String() string {
return fmt.Sprint(*v);
}
+func (v *float32V) Assign(o Value) {
+ *v = float32V(o.(FloatValue).Get());
+}
+
func (v *float32V) Get() float64 {
return float64(*v);
}
type float64V float64
-func (*float64V) Type() Type {
- return Float64Type;
-}
-
func (v *float64V) String() string {
return fmt.Sprint(*v);
}
+func (v *float64V) Assign(o Value) {
+ *v = float64V(o.(FloatValue).Get());
+}
+
func (v *float64V) Get() float64 {
return float64(*v);
}
type floatV float
-func (*floatV) Type() Type {
- return FloatType;
-}
-
func (v *floatV) String() string {
return fmt.Sprint(*v);
}
+func (v *floatV) Assign(o Value) {
+ *v = floatV(o.(FloatValue).Get());
+}
+
func (v *floatV) Get() float64 {
return float64(*v);
}
*v = floatV(x);
}
-func (t *floatType) value(v float64) FloatValue {
+func (t *floatType) Zero() Value {
switch Type(t) {
case Float32Type:
- res := float32V(v);
+ res := float32V(0);
return &res;
case Float64Type:
- res := float64V(v);
+ res := float64V(0);
return &res;
case FloatType:
- res := floatV(v);
+ res := floatV(0);
return &res;
}
panic("unknown float type ", t.String());
V *bignum.Rational;
}
-func (*idealFloatV) Type() Type {
- return IdealFloatType;
-}
-
func (v *idealFloatV) String() string {
return ratToString(v.V);
}
+func (v *idealFloatV) Assign(o Value) {
+ v.V = o.(IdealFloatValue).Get();
+}
+
func (v *idealFloatV) Get() *bignum.Rational {
return v.V;
}
-func (t *idealFloatType) value(v *bignum.Rational) IdealFloatValue {
- return &idealFloatV{v};
+func (t *idealFloatType) Zero() Value {
+ return &idealFloatV{bignum.Rat(1, 0)};
}
/*
type stringV string
-func (*stringV) Type() Type {
- return StringType;
-}
-
func (v *stringV) String() string {
return fmt.Sprint(*v);
}
+func (v *stringV) Assign(o Value) {
+ *v = stringV(o.(StringValue).Get());
+}
+
func (v *stringV) Get() string {
return string(*v);
}
*v = stringV(x);
}
-func (t *stringType) value(v string) StringValue {
- res := stringV(v);
+func (t *stringType) Zero() Value {
+ res := stringV("");
return &res;
}
type arrayV []Value
-func (*arrayV) Type() Type {
- panic("Not implemented");
-}
-
func (v *arrayV) String() string {
return fmt.Sprint(*v);
}
+func (v *arrayV) Assign(o Value) {
+ oa := o.(ArrayValue);
+ l := int64(len(*v));
+ for i := int64(0); i < l; i++ {
+ (*v)[i].Assign(oa.Elem(i));
+ }
+}
+
func (v *arrayV) Get() ArrayValue {
return v;
}
return (*v)[i];
}
-func (t *ArrayType) value(v []Value) ArrayValue {
- res := arrayV(v);
+func (t *ArrayType) Zero() Value {
+ res := arrayV(make([]Value, t.Len));
+ // TODO(austin) It's unfortunate that each element is
+ // separately heap allocated. We could add ZeroArray to
+ // everything, though that doesn't help with multidimensional
+ // arrays. Or we could do something unsafe. We'll have this
+ // same problem with structs.
+ for i := int64(0); i < t.Len; i++ {
+ res[i] = t.Elem.Zero();
+ }
return &res;
}
target Value;
}
-func (v *ptrV) Type() Type {
- return NewPtrType(v.target.Type());
-}
-
func (v *ptrV) String() string {
return "&" + v.target.String();
}
+func (v *ptrV) Assign(o Value) {
+ v.target = o.(PtrValue).Get();
+}
+
func (v *ptrV) Get() Value {
return v.target;
}
v.target = x;
}
-func (t *PtrType) value(v Value) PtrValue {
- res := ptrV{v};
+func (t *PtrType) Zero() Value {
+ res := ptrV{nil};
return &res;
}