From: Austin Clements Date: Tue, 21 Jul 2009 00:41:40 +0000 (-0700) Subject: Implement array types and index expressions. X-Git-Tag: weekly.2009-11-06~1089 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=79fac7ca8677ed634fa5652c9ad451e0f5a2112c;p=gostls13.git Implement array types and index expressions. Some cleanup. Elem() on PtrType is now just Elem and matches with ArrayType. Generators now switch over the result type instead of the operand type. Delete unused diag function. R=rsc APPROVED=rsc DELTA=281 (219 added, 18 deleted, 44 changed) OCL=31876 CL=31891 --- diff --git a/usr/austin/eval/decls.go b/usr/austin/eval/decls.go index 87d700538e..f5b667970c 100644 --- a/usr/austin/eval/decls.go +++ b/usr/austin/eval/decls.go @@ -90,6 +90,15 @@ type StringValue interface { 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; diff --git a/usr/austin/eval/expr.go b/usr/austin/eval/expr.go index 6ab4ad46e4..3368b44fcc 100644 --- a/usr/austin/eval/expr.go +++ b/usr/austin/eval/expr.go @@ -12,7 +12,7 @@ import ( "go/scanner"; "go/token"; "log"; -"os"; + "os"; "strconv"; "strings"; ) @@ -41,6 +41,7 @@ type exprCompiler struct { evalFloat func(f *Frame) float64; evalIdealFloat func() *bignum.Rational; evalString func(f *Frame) string; + evalArray func(f *Frame) ArrayValue; evalPtr func(f *Frame) Value; // Evaluate to the "address of" this value; that is, the // settable Value object. nil for expressions whose address @@ -62,6 +63,7 @@ func newExprCompiler(c *exprContext, pos token.Position) *exprCompiler { // Operator generators // TODO(austin) Remove these forward declarations func (a *exprCompiler) genIdentOp(t Type, s *Scope, index int) +func (a *exprCompiler) genIndexArray(l *exprCompiler, r *exprCompiler) func (a *exprCompiler) genStarOp(v *exprCompiler) func (a *exprCompiler) genUnaryOpNeg(v *exprCompiler) func (a *exprCompiler) genUnaryOpNot(v *exprCompiler) @@ -78,7 +80,13 @@ func (a *exprCompiler) genBinOpAndNot(l *exprCompiler, r *exprCompiler) func (a *exprCompiler) genBinOpShl(l *exprCompiler, r *exprCompiler) func (a *exprCompiler) genBinOpShr(l *exprCompiler, r *exprCompiler) -func (a *exprCompiler) fork(x ast.Expr) *exprCompiler { +func (a *exprCompiler) copy() *exprCompiler { + ec := newExprCompiler(a.exprContext, a.pos); + ec.desc = a.desc; + return ec; +} + +func (a *exprCompiler) copyVisit(x ast.Expr) *exprCompiler { ec := newExprCompiler(a.exprContext, x.Pos()); x.Visit(ec); return ec; @@ -145,6 +153,13 @@ func (a *exprCompiler) asString() (func(f *Frame) string) { return a.evalString; } +func (a *exprCompiler) asArray() (func(f *Frame) ArrayValue) { + if a.evalArray == nil { + log.Crashf("tried to get %v node as ArrayType", a.t); + } + return a.evalArray; +} + func (a *exprCompiler) asPtr() (func(f *Frame) Value) { if a.evalPtr == nil { log.Crashf("tried to get %v node as PtrType", a.t); @@ -152,6 +167,9 @@ func (a *exprCompiler) asPtr() (func(f *Frame) Value) { return a.evalPtr; } +// TODO(austin) Move convertTo somewhere more reasonable +func (a *exprCompiler) convertTo(t Type) *exprCompiler + func (a *exprCompiler) DoBadExpr(x *ast.BadExpr) { // Do nothing. Already reported by parser. } @@ -274,7 +292,103 @@ func (a *exprCompiler) DoSelectorExpr(x *ast.SelectorExpr) { } func (a *exprCompiler) DoIndexExpr(x *ast.IndexExpr) { - log.Crash("Not implemented"); + l, r := a.copyVisit(x.X), a.copyVisit(x.Index); + if l.t == nil || r.t == nil { + return; + } + + // Type check object + if lt, ok := l.t.literal().(*PtrType); ok { + if et, ok := lt.Elem.literal().(*ArrayType); ok { + // Automatic dereference + nl := l.copy(); + nl.t = et; + nl.genStarOp(l); + l = nl; + } + } + + var at Type; + intIndex := false; + var maxIndex int64 = -1; + + switch lt := l.t.literal().(type) { + case *ArrayType: + at = lt.Elem; + intIndex = true; + maxIndex = lt.Len; + + // TODO(austin) Uncomment when there is a SliceType + // case *SliceType: + // a.t = lt.Elem; + // intIndex = true; + + case *stringType: + at = Uint8Type; + intIndex = true; + + // TODO(austin) Uncomment when there is a MapType + // case *MapType: + // log.Crash("Index into map not implemented"); + + default: + a.diag("cannot index into %v", l.t); + return; + } + + // Type check index and convert to int if necessary + if intIndex { + // XXX(Spec) It's unclear if ideal floats with no + // fractional part are allowed here. 6g allows it. I + // believe that's wrong. + switch _ := r.t.literal().(type) { + case *idealIntType: + val := r.asIdealInt()(); + if val.IsNeg() || (maxIndex != -1 && val.Cmp(bignum.Int(maxIndex)) >= 0) { + a.diag("array index out of bounds"); + return; + } + r = r.convertTo(IntType); + if r == nil { + return; + } + + case *uintType: + // Convert to int + nr := r.copy(); + nr.t = IntType; + rf := r.asUint(); + nr.evalInt = func(f *Frame) int64 { + return int64(rf(f)); + }; + r = nr; + + case *intType: + // Good as is + + default: + a.diag("illegal operand type for index\n\t%v", r.t); + return; + } + } + + a.t = at; + + // Compile + switch lt := l.t.literal().(type) { + case *ArrayType: + a.t = lt.Elem; + // TODO(austin) Bounds check + a.genIndexArray(l, r); + lf := l.asArray(); + rf := r.asInt(); + a.evalAddr = func(f *Frame) Value { + return lf(f).Elem(rf(f)); + }; + + default: + log.Crashf("Compilation of index into %T not implemented", l.t.literal()); + } } func (a *exprCompiler) DoTypeAssertExpr(x *ast.TypeAssertExpr) { @@ -286,14 +400,16 @@ func (a *exprCompiler) DoCallExpr(x *ast.CallExpr) { } func (a *exprCompiler) DoStarExpr(x *ast.StarExpr) { - v := a.fork(x.X); + v := a.copyVisit(x.X); if v.t == nil { return; } - switch vt := v.t.(type) { + switch vt := v.t.literal().(type) { case *PtrType: - a.t = vt.Elem(); + // TODO(austin) If this is vt.Elem() I get a + // "call of a non-function: Type" error + a.t = vt.Elem; a.genStarOp(v); vf := v.asPtr(); a.evalAddr = func(f *Frame) Value { return vf(f) }; @@ -307,7 +423,7 @@ func (a *exprCompiler) DoStarExpr(x *ast.StarExpr) { var unaryOpDescs = make(map[token.Token] string) func (a *exprCompiler) DoUnaryExpr(x *ast.UnaryExpr) { - v := a.fork(x.X); + v := a.copyVisit(x.X); if v.t == nil { return; } @@ -431,9 +547,8 @@ func (a *exprCompiler) convertTo(t Type) *exprCompiler { } // Convert rat to type t. - res := newExprCompiler(a.exprContext, a.pos); + res := a.copy(); res.t = t; - res.desc = a.desc; switch t := t.(type) { case *uintType: n, d := rat.Value(); @@ -465,7 +580,7 @@ func (a *exprCompiler) convertTo(t Type) *exprCompiler { var binOpDescs = make(map[token.Token] string) func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { - l, r := a.fork(x.X), a.fork(x.Y); + l, r := a.copyVisit(x.X), a.copyVisit(x.Y); if l.t == nil || r.t == nil { return; } @@ -852,6 +967,8 @@ func (a *exprCompiler) genIdentOp(t Type, s *Scope, index int) { a.evalFloat = func(f *Frame) float64 { return f.Get(s, index).(FloatValue).Get() }; case *stringType: a.evalString = func(f *Frame) string { return f.Get(s, index).(StringValue).Get() }; + case *ArrayType: + a.evalArray = func(f *Frame) ArrayValue { return f.Get(s, index).(ArrayValue).Get() }; case *PtrType: a.evalPtr = func(f *Frame) Value { return f.Get(s, index).(PtrValue).Get() }; default: @@ -859,9 +976,32 @@ func (a *exprCompiler) genIdentOp(t Type, s *Scope, index int) { } } +func (a *exprCompiler) genIndexArray(l *exprCompiler, r *exprCompiler) { + lf := l.asArray(); + rf := r.asInt(); + switch _ := a.t.literal().(type) { + case *boolType: + a.evalBool = func(f *Frame) bool { return lf(f).Elem(rf(f)).(BoolValue).Get() }; + case *uintType: + a.evalUint = func(f *Frame) uint64 { return lf(f).Elem(rf(f)).(UintValue).Get() }; + case *intType: + a.evalInt = func(f *Frame) int64 { return lf(f).Elem(rf(f)).(IntValue).Get() }; + case *floatType: + a.evalFloat = func(f *Frame) float64 { return lf(f).Elem(rf(f)).(FloatValue).Get() }; + case *stringType: + a.evalString = func(f *Frame) string { return lf(f).Elem(rf(f)).(StringValue).Get() }; + case *ArrayType: + a.evalArray = func(f *Frame) ArrayValue { return lf(f).Elem(rf(f)).(ArrayValue).Get() }; + case *PtrType: + a.evalPtr = func(f *Frame) Value { return lf(f).Elem(rf(f)).(PtrValue).Get() }; + default: + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); + } +} + func (a *exprCompiler) genStarOp(v *exprCompiler) { vf := v.asPtr(); - switch _ := v.t.literal().(*PtrType).Elem().literal().(type) { + switch _ := a.t.literal().(type) { case *boolType: a.evalBool = func(f *Frame) bool { return vf(f).(BoolValue).Get() }; case *uintType: @@ -872,15 +1012,17 @@ func (a *exprCompiler) genStarOp(v *exprCompiler) { a.evalFloat = func(f *Frame) float64 { return vf(f).(FloatValue).Get() }; case *stringType: a.evalString = func(f *Frame) string { return vf(f).(StringValue).Get() }; + case *ArrayType: + a.evalArray = func(f *Frame) ArrayValue { return vf(f).(ArrayValue).Get() }; case *PtrType: a.evalPtr = func(f *Frame) Value { return vf(f).(PtrValue).Get() }; default: - log.Crashf("unexpected operand type %v at %v", v.t.literal().(*PtrType).Elem().literal(), a.pos); + log.Crashf("unexpected result type %v at %v", v.t.literal().(*PtrType).Elem.literal(), a.pos); } } func (a *exprCompiler) genUnaryOpNeg(v *exprCompiler) { - switch _ := v.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: vf := v.asUint(); a.evalUint = func(f *Frame) uint64 { return -vf(f) }; @@ -899,22 +1041,22 @@ func (a *exprCompiler) genUnaryOpNeg(v *exprCompiler) { val := vf().Neg(); a.evalIdealFloat = func() *bignum.Rational { return val }; default: - log.Crashf("unexpected operand type %v at %v", v.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", v.t.literal(), a.pos); } } func (a *exprCompiler) genUnaryOpNot(v *exprCompiler) { - switch _ := v.t.literal().(type) { + switch _ := a.t.literal().(type) { case *boolType: vf := v.asBool(); a.evalBool = func(f *Frame) bool { return !vf(f) }; default: - log.Crashf("unexpected operand type %v at %v", v.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", v.t.literal(), a.pos); } } func (a *exprCompiler) genUnaryOpXor(v *exprCompiler) { - switch _ := v.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: vf := v.asUint(); a.evalUint = func(f *Frame) uint64 { return ^vf(f) }; @@ -926,12 +1068,12 @@ func (a *exprCompiler) genUnaryOpXor(v *exprCompiler) { val := vf().Neg().Sub(bignum.Int(1)); a.evalIdealInt = func() *bignum.Integer { return val }; default: - log.Crashf("unexpected operand type %v at %v", v.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", v.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpAdd(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -959,12 +1101,12 @@ func (a *exprCompiler) genBinOpAdd(l *exprCompiler, r *exprCompiler) { rf := r.asString(); a.evalString = func(f *Frame) string { return lf(f) + rf(f) }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpSub(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -988,12 +1130,12 @@ func (a *exprCompiler) genBinOpSub(l *exprCompiler, r *exprCompiler) { val := lf().Sub(rf()); a.evalIdealFloat = func() *bignum.Rational { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpMul(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1017,12 +1159,12 @@ func (a *exprCompiler) genBinOpMul(l *exprCompiler, r *exprCompiler) { val := lf().Mul(rf()); a.evalIdealFloat = func() *bignum.Rational { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpQuo(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1046,12 +1188,12 @@ func (a *exprCompiler) genBinOpQuo(l *exprCompiler, r *exprCompiler) { val := lf().Quo(rf()); a.evalIdealFloat = func() *bignum.Rational { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpRem(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1066,12 +1208,12 @@ func (a *exprCompiler) genBinOpRem(l *exprCompiler, r *exprCompiler) { val := lf().Rem(rf()); a.evalIdealInt = func() *bignum.Integer { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpAnd(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1086,12 +1228,12 @@ func (a *exprCompiler) genBinOpAnd(l *exprCompiler, r *exprCompiler) { val := lf().And(rf()); a.evalIdealInt = func() *bignum.Integer { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpOr(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1106,12 +1248,12 @@ func (a *exprCompiler) genBinOpOr(l *exprCompiler, r *exprCompiler) { val := lf().Or(rf()); a.evalIdealInt = func() *bignum.Integer { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpXor(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1126,12 +1268,12 @@ func (a *exprCompiler) genBinOpXor(l *exprCompiler, r *exprCompiler) { val := lf().Xor(rf()); a.evalIdealInt = func() *bignum.Integer { return val }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpAndNot(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1141,12 +1283,12 @@ func (a *exprCompiler) genBinOpAndNot(l *exprCompiler, r *exprCompiler) { rf := r.asInt(); a.evalInt = func(f *Frame) int64 { return lf(f) &^ rf(f) }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpShl(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1156,12 +1298,12 @@ func (a *exprCompiler) genBinOpShl(l *exprCompiler, r *exprCompiler) { rf := r.asUint(); a.evalInt = func(f *Frame) int64 { return lf(f) << rf(f) }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } func (a *exprCompiler) genBinOpShr(l *exprCompiler, r *exprCompiler) { - switch _ := l.t.literal().(type) { + switch _ := a.t.literal().(type) { case *uintType: lf := l.asUint(); rf := r.asUint(); @@ -1171,6 +1313,6 @@ func (a *exprCompiler) genBinOpShr(l *exprCompiler, r *exprCompiler) { rf := r.asUint(); a.evalInt = func(f *Frame) int64 { return lf(f) >> rf(f) }; default: - log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); + log.Crashf("unexpected result type %v at %v", l.t.literal(), a.pos); } } diff --git a/usr/austin/eval/type.go b/usr/austin/eval/type.go index 5103ce6d5c..1638182cd1 100644 --- a/usr/austin/eval/type.go +++ b/usr/austin/eval/type.go @@ -300,12 +300,47 @@ func (t *stringType) String() string { func (t *stringType) value(v string) StringValue -/* type ArrayType struct { commonType; - elem Type; + Len int64; + Elem Type; + lit Type; +} + +var arrayTypes = make(map[int64] map[Type] *ArrayType); + +func NewArrayType(len int64, elem Type) *ArrayType { + ts, ok := arrayTypes[len]; + if !ok { + ts = make(map[Type] *ArrayType); + arrayTypes[len] = ts; + } + t, ok := ts[elem]; + if !ok { + t = &ArrayType{commonType{}, len, elem, nil}; + ts[elem] = t; + } + return t; } +func (t *ArrayType) literal() Type { + if t.lit == nil { + t.lit = NewArrayType(t.Len, t.Elem.literal()); + } + return t.lit; +} + +func (t *ArrayType) compatible(o Type) bool { + return t.literal() == o.literal(); +} + +func (t *ArrayType) String() string { + return "[]" + t.Elem.String(); +} + +func (t *ArrayType) value(v []Value) ArrayValue + +/* func (t *ArrayType) literal() Type { // TODO(austin) } @@ -318,7 +353,7 @@ type StructType struct { type PtrType struct { commonType; - elem Type; + Elem Type; lit Type; } @@ -333,13 +368,9 @@ func NewPtrType(elem Type) *PtrType { return t; } -func (t *PtrType) Elem() Type { - return t.elem; -} - func (t *PtrType) literal() Type { if t.lit == nil { - t.lit = NewPtrType(t.elem.literal()); + t.lit = NewPtrType(t.Elem.literal()); } return t.lit; } @@ -349,7 +380,7 @@ func (t *PtrType) compatible(o Type) bool { } func (t *PtrType) String() string { - return "*" + t.elem.String(); + return "*" + t.Elem.String(); } func (t *PtrType) value(v Value) PtrValue diff --git a/usr/austin/eval/util.go b/usr/austin/eval/util.go index 0e97d4d240..e08c8ee5a2 100644 --- a/usr/austin/eval/util.go +++ b/usr/austin/eval/util.go @@ -40,11 +40,3 @@ func ratToString(rat *bignum.Rational) string { out += "." + dec.String(); return out; } - -func diag(p token.Position, format string, args ...) { - if p.IsValid() { - fmt.Printf("%s:%d.%d: ", p.Filename, p.Line, p.Column); - } - fmt.Printf(format, args); - fmt.Print("\n"); -} diff --git a/usr/austin/eval/value.go b/usr/austin/eval/value.go index 5849c16d81..7f58b55f68 100644 --- a/usr/austin/eval/value.go +++ b/usr/austin/eval/value.go @@ -441,6 +441,33 @@ func (t *stringType) value(v string) StringValue { return &res; } +/* + * Array + */ + +type arrayV []Value + +func (*arrayV) Type() Type { + panic("Not implemented"); +} + +func (v *arrayV) String() string { + return fmt.Sprint(*v); +} + +func (v *arrayV) Get() ArrayValue { + return v; +} + +func (v *arrayV) Elem(i int64) Value { + return (*v)[i]; +} + +func (t *ArrayType) value(v []Value) ArrayValue { + res := arrayV(v); + return &res; +} + /* * Pointer */