From: Austin Clements Date: Fri, 17 Jul 2009 18:50:32 +0000 (-0700) Subject: Finish shift implementation for ideals. X-Git-Tag: weekly.2009-11-06~1111 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2ac1528e55bc5dc04bce02049ab9530f50422a38;p=gostls13.git Finish shift implementation for ideals. R=rsc APPROVED=rsc DELTA=65 (29 added, 17 deleted, 19 changed) OCL=31775 CL=31777 --- diff --git a/usr/austin/eval/expr.go b/usr/austin/eval/expr.go index 8561cb71d5..752f9de6fd 100644 --- a/usr/austin/eval/expr.go +++ b/usr/austin/eval/expr.go @@ -564,7 +564,7 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { // operand in a shift operation must be always be of // unsigned integer type or an ideal number that can // be safely converted into an unsigned integer type - // (§Arithmetic operators)" suggests so. + // (§Arithmetic operators)" suggests so and 6g agrees. if !l.t.isInteger() || !(r.t.isInteger() || r.t.isIdeal()) { a.diagOpTypes(x.Op, origlt, origrt); @@ -580,23 +580,16 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { if r2 == nil { return; } - // If the left operand is ideal, we use the - // original right operand so we can perform - // constant evaluation. Otherwise, we use the - // conversion. + + // If the left operand is not ideal, convert + // the right to not ideal. if !l.t.isIdeal() { r = r2; - // XXX(Spec) What is the meaning of - // "ideal >> non-ideal"? Russ says - // the ideal should be converted to - // an int. 6g says it's illegal. - l = l.convertTo(IntType); - if l == nil { - return; - } - } else if r.t.isFloat() { - // Convert it to an ideal int to - // simplify the cases + } + + // If both are ideal, but the right side isn't + // an ideal int, convert it to simplify things. + if l.t.isIdeal() && !r.t.isInteger() { r = r.convertTo(IdealIntType); if r == nil { log.Crashf("conversion to uintType succeeded, but conversion to idealIntType failed"); @@ -606,6 +599,23 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { a.diag("right operand of shift must be unsigned"); return; } + + if l.t.isIdeal() && !r.t.isIdeal() { + // XXX(Spec) What is the meaning of "ideal >> + // non-ideal"? Russ says the ideal should be + // converted to an int. 6g propagates the + // type down from assignments as a hint. + l = l.convertTo(IntType); + if l == nil { + return; + } + } + + // At this point, we should have one of three cases: + // 1) uint SHIFT uint + // 2) int SHIFT uint + // 3) ideal int SHIFT ideal int + a.t = l.t; case token.LOR, token.LAND: @@ -710,18 +720,30 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) { a.genBinOpAndNot(l, r); case token.SHL: - // TODO(austin) bignum.Integer.Shl takes a uint - if r.t.isIdeal() { - log.Crashf("<< ideal not implemented"); + if l.t.isIdeal() { + lv := l.asIdealInt()(); + rv := r.asIdealInt()(); + const maxShift = 99999; + if rv.Cmp(bignum.Int(maxShift)) > 0 { + a.diag("left shift by %v; exceeds implementation limit of %v", rv, maxShift); + a.t = nil; + return; + } + val := lv.Shl(uint(rv.Value())); + a.evalIdealInt = func() *bignum.Integer { return val }; + } else { + a.genBinOpShl(l, r); } - a.genBinOpShl(l, r); case token.SHR: - // TODO(austin) bignum.Integer.Shr takes a uint - if r.t.isIdeal() { - log.Crashf(">> ideal not implemented"); + if l.t.isIdeal() { + lv := l.asIdealInt()(); + rv := r.asIdealInt()(); + val := lv.Shr(uint(rv.Value())); + a.evalIdealInt = func() *bignum.Integer { return val }; + } else { + a.genBinOpShr(l, r); } - a.genBinOpShr(l, r); default: log.Crashf("Compilation of binary op %v not implemented", x.Op); @@ -1131,11 +1153,6 @@ func (a *exprCompiler) genBinOpShl(l *exprCompiler, r *exprCompiler) { lf := l.asInt(); rf := r.asUint(); a.evalInt = func(f *Frame) int64 { return lf(f) << rf(f) }; - // case *idealIntType: - // lf := l.asIdealInt(); - // rf := r.asIdealInt(); - // val := lf().Shl(rf()); - // a.evalIdealInt = func() *bignum.Integer { return val }; default: log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); } @@ -1151,11 +1168,6 @@ func (a *exprCompiler) genBinOpShr(l *exprCompiler, r *exprCompiler) { lf := l.asInt(); rf := r.asUint(); a.evalInt = func(f *Frame) int64 { return lf(f) >> rf(f) }; - // case *idealIntType: - // lf := l.asIdealInt(); - // rf := r.asIdealInt(); - // val := lf().Shr(rf()); - // a.evalIdealInt = func() *bignum.Integer { return val }; default: log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos); }