Commit b9729279 authored by Evan Shaw's avatar Evan Shaw Committed by Robert Griesemer

exp/eval: Converted from bignum to big

Also in this CL:
* Removed util.go, as its functionality is in big
* Removed some semicolons from the code generated by gen.go
* Added a generate target to Makefile
* Removed an outdated TODO from value.go

R=gri
CC=golang-dev
https://golang.org/cl/1780042
parent c9406f93
......@@ -16,7 +16,6 @@ GOFILES=\
stmt.go\
type.go\
typec.go\
util.go\
value.go\
world.go\
......@@ -27,3 +26,12 @@ main.$O: main.go $(pkgdir)/$(TARG).a
eval: main.$O
$(QUOTED_GOBIN)/$(LD) -o $@ $<
gen.$O: gen.go
$(QUOTED_GOBIN)/$(GC) $<
expr1.go: gen.$O
$(QUOTED_GOBIN)/$(LD) -o generate $<;\
./generate > expr1.go;\
gofmt -w expr1.go
......@@ -5,7 +5,7 @@
package eval
import (
"exp/bignum"
"big"
"flag"
"fmt"
"log"
......@@ -166,12 +166,12 @@ func toValue(val interface{}) Value {
case int:
r := intV(val)
return &r
case *bignum.Integer:
case *big.Int:
return &idealIntV{val}
case float:
r := floatV(val)
return &r
case *bignum.Rational:
case *big.Rat:
return &idealFloatV{val}
case string:
r := stringV(val)
......@@ -235,7 +235,7 @@ func newTestWorld() *World {
def := func(name string, t Type, val interface{}) { w.DefineVar(name, t, toValue(val)) }
w.DefineConst("c", IdealIntType, toValue(bignum.Int(1)))
w.DefineConst("c", IdealIntType, toValue(big.NewInt(1)))
def("i", IntType, 1)
def("i2", IntType, 2)
def("u", UintType, uint(1))
......
......@@ -5,7 +5,7 @@
package eval
import (
"exp/bignum"
"big"
"fmt"
"go/ast"
"go/token"
......@@ -15,6 +15,11 @@ import (
"os"
)
var (
idealZero = big.NewInt(0)
idealOne = big.NewInt(1)
)
// An expr is the result of compiling an expression. It stores the
// type of the expression and its evaluator function.
type expr struct {
......@@ -85,7 +90,7 @@ func (a *expr) convertTo(t Type) *expr {
log.Crashf("attempted to convert from %v, expected ideal", a.t)
}
var rat *bignum.Rational
var rat *big.Rat
// XXX(Spec) The spec says "It is erroneous".
//
......@@ -97,12 +102,12 @@ func (a *expr) convertTo(t Type) *expr {
case IdealFloatType:
rat = a.asIdealFloat()()
if t.isInteger() && !rat.IsInt() {
a.diag("constant %v truncated to integer", ratToString(rat))
a.diag("constant %v truncated to integer", rat.FloatString(6))
return nil
}
case IdealIntType:
i := a.asIdealInt()()
rat = bignum.MakeRat(i, bignum.Nat(1))
rat = new(big.Rat).SetInt(i)
default:
log.Crashf("unexpected ideal type %v", a.t)
}
......@@ -110,11 +115,11 @@ func (a *expr) convertTo(t Type) *expr {
// Check bounds
if t, ok := t.lit().(BoundedType); ok {
if rat.Cmp(t.minVal()) < 0 {
a.diag("constant %v underflows %v", ratToString(rat), t)
a.diag("constant %v underflows %v", rat.FloatString(6), t)
return nil
}
if rat.Cmp(t.maxVal()) > 0 {
a.diag("constant %v overflows %v", ratToString(rat), t)
a.diag("constant %v overflows %v", rat.FloatString(6), t)
return nil
}
}
......@@ -123,25 +128,26 @@ func (a *expr) convertTo(t Type) *expr {
res := a.newExpr(t, a.desc)
switch t := t.lit().(type) {
case *uintType:
n, d := rat.Value()
f := n.Quo(bignum.MakeInt(false, d))
v := f.Abs().Value()
n, d := rat.Num(), rat.Denom()
f := new(big.Int).Quo(n, d)
f = f.Abs(f)
v := uint64(f.Int64())
res.eval = func(*Thread) uint64 { return v }
case *intType:
n, d := rat.Value()
f := n.Quo(bignum.MakeInt(false, d))
v := f.Value()
n, d := rat.Num(), rat.Denom()
f := new(big.Int).Quo(n, d)
v := f.Int64()
res.eval = func(*Thread) int64 { return v }
case *idealIntType:
n, d := rat.Value()
f := n.Quo(bignum.MakeInt(false, d))
res.eval = func() *bignum.Integer { return f }
n, d := rat.Num(), rat.Denom()
f := new(big.Int).Quo(n, d)
res.eval = func() *big.Int { return f }
case *floatType:
n, d := rat.Value()
v := float64(n.Value()) / float64(d.Value())
n, d := rat.Num(), rat.Denom()
v := float64(n.Int64()) / float64(d.Int64())
res.eval = func(*Thread) float64 { return v }
case *idealFloatType:
res.eval = func() *bignum.Rational { return rat }
res.eval = func() *big.Rat { return rat }
default:
log.Crashf("cannot convert to type %T", t)
}
......@@ -158,7 +164,7 @@ func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
switch a.t.lit().(type) {
case *idealIntType:
val := a.asIdealInt()()
if negErr != "" && val.IsNeg() {
if negErr != "" && val.Sign() < 0 {
a.diag("negative %s: %s", negErr, val)
return nil
}
......@@ -166,7 +172,7 @@ func (a *expr) convertToInt(max int64, negErr string, errOp string) *expr {
if negErr == "slice" {
bound++
}
if max != -1 && val.Cmp(bignum.Int(bound)) >= 0 {
if max != -1 && val.Cmp(big.NewInt(bound)) >= 0 {
a.diag("index %s exceeds length %d", val, max)
return nil
}
......@@ -735,14 +741,14 @@ func (a *exprInfo) compileGlobalVariable(v *Variable) *expr {
return expr
}
func (a *exprInfo) compileIdealInt(i *bignum.Integer, desc string) *expr {
func (a *exprInfo) compileIdealInt(i *big.Int, desc string) *expr {
expr := a.newExpr(IdealIntType, desc)
expr.eval = func() *bignum.Integer { return i }
expr.eval = func() *big.Int { return i }
return expr
}
func (a *exprInfo) compileIntLit(lit string) *expr {
i, _, _ := bignum.IntFromString(lit, 0)
i, _ := new(big.Int).SetString(lit, 0)
return a.compileIdealInt(i, "integer literal")
}
......@@ -758,16 +764,16 @@ func (a *exprInfo) compileCharLit(lit string) *expr {
a.silentErrors++
return nil
}
return a.compileIdealInt(bignum.Int(int64(v)), "character literal")
return a.compileIdealInt(big.NewInt(int64(v)), "character literal")
}
func (a *exprInfo) compileFloatLit(lit string) *expr {
f, _, n := bignum.RatFromString(lit, 10)
if n != len(lit) {
f, ok := new(big.Rat).SetString(lit)
if !ok {
log.Crashf("malformed float literal %s at %v passed parser", lit, a.pos)
}
expr := a.newExpr(IdealFloatType, "float literal")
expr.eval = func() *bignum.Rational { return f }
expr.eval = func() *big.Rat { return f }
return expr
}
......@@ -1774,8 +1780,8 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
switch op {
case token.QUO, token.REM:
if r.t.isIdeal() {
if (r.t.isInteger() && r.asIdealInt()().IsZero()) ||
(r.t.isFloat() && r.asIdealFloat()().IsZero()) {
if (r.t.isInteger() && r.asIdealInt()().Sign() == 0) ||
(r.t.isFloat() && r.asIdealFloat()().Sign() == 0) {
a.diag("divide by zero")
return nil
}
......@@ -1817,13 +1823,13 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
lv := l.asIdealInt()()
rv := r.asIdealInt()()
const maxShift = 99999
if rv.Cmp(bignum.Int(maxShift)) > 0 {
if rv.Cmp(big.NewInt(maxShift)) > 0 {
a.diag("left shift by %v; exceeds implementation limit of %v", rv, maxShift)
expr.t = nil
return nil
}
val := lv.Shl(uint(rv.Value()))
expr.eval = func() *bignum.Integer { return val }
val := new(big.Int).Lsh(lv, uint(rv.Int64()))
expr.eval = func() *big.Int { return val }
} else {
expr.genBinOpShl(l, r)
}
......@@ -1832,8 +1838,8 @@ func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
if l.t.isIdeal() {
lv := l.asIdealInt()()
rv := r.asIdealInt()()
val := lv.Shr(uint(rv.Value()))
expr.eval = func() *bignum.Integer { return val }
val := new(big.Int).Rsh(lv, uint(rv.Int64()))
expr.eval = func() *big.Int { return val }
} else {
expr.genBinOpShr(l, r)
}
......
......@@ -4,13 +4,13 @@
package eval
import (
"exp/bignum"
"big"
"log"
)
/*
* "As" functions. These retrieve evaluator functions from an
* expr, panicking if the requested evaluator has the wrong type.
* "As" functions. These retrieve evaluator functions from an
* expr, panicking if the requested evaluator has the wrong type.
*/
func (a *expr) asBool() func(*Thread) bool {
return a.eval.(func(*Thread) bool)
......@@ -21,14 +21,14 @@ func (a *expr) asUint() func(*Thread) uint64 {
func (a *expr) asInt() func(*Thread) int64 {
return a.eval.(func(*Thread) int64)
}
func (a *expr) asIdealInt() func() *bignum.Integer {
return a.eval.(func() *bignum.Integer)
func (a *expr) asIdealInt() func() *big.Int {
return a.eval.(func() *big.Int)
}
func (a *expr) asFloat() func(*Thread) float64 {
return a.eval.(func(*Thread) float64)
}
func (a *expr) asIdealFloat() func() *bignum.Rational {
return a.eval.(func() *bignum.Rational)
func (a *expr) asIdealFloat() func() *big.Rat {
return a.eval.(func() *big.Rat)
}
func (a *expr) asString() func(*Thread) string {
return a.eval.(func(*Thread) string)
......@@ -63,11 +63,11 @@ func (a *expr) asInterface() func(*Thread) interface{} {
return func(t *Thread) interface{} { return sf(t) }
case func(t *Thread) int64:
return func(t *Thread) interface{} { return sf(t) }
case func() *bignum.Integer:
case func() *big.Int:
return func(*Thread) interface{} { return sf() }
case func(t *Thread) float64:
return func(t *Thread) interface{} { return sf(t) }
case func() *bignum.Rational:
case func() *big.Rat:
return func(*Thread) interface{} { return sf() }
case func(t *Thread) string:
return func(t *Thread) interface{} { return sf(t) }
......@@ -90,7 +90,7 @@ func (a *expr) asInterface() func(*Thread) interface{} {
}
/*
* Operator generators.
* Operator generators.
*/
func (a *expr) genConstant(v Value) {
......@@ -103,12 +103,12 @@ func (a *expr) genConstant(v Value) {
a.eval = func(t *Thread) int64 { return v.(IntValue).Get(t) }
case *idealIntType:
val := v.(IdealIntValue).Get()
a.eval = func() *bignum.Integer { return val }
a.eval = func() *big.Int { return val }
case *floatType:
a.eval = func(t *Thread) float64 { return v.(FloatValue).Get(t) }
case *idealFloatType:
val := v.(IdealFloatValue).Get()
a.eval = func() *bignum.Rational { return val }
a.eval = func() *big.Rat { return val }
case *stringType:
a.eval = func(t *Thread) string { return v.(StringValue).Get(t) }
case *ArrayType:
......@@ -229,16 +229,16 @@ func (a *expr) genUnaryOpNeg(v *expr) {
vf := v.asInt()
a.eval = func(t *Thread) int64 { v := vf(t); return -v }
case *idealIntType:
v := v.asIdealInt()()
val := v.Neg()
a.eval = func() *bignum.Integer { return val }
val := v.asIdealInt()()
val.Neg(val)
a.eval = func() *big.Int { return val }
case *floatType:
vf := v.asFloat()
a.eval = func(t *Thread) float64 { v := vf(t); return -v }
case *idealFloatType:
v := v.asIdealFloat()()
val := v.Neg()
a.eval = func() *bignum.Rational { return val }
val := v.asIdealFloat()()
val.Neg(val)
a.eval = func() *big.Rat { return val }
default:
log.Crashf("unexpected type %v at %v", a.t, a.pos)
}
......@@ -263,9 +263,9 @@ func (a *expr) genUnaryOpXor(v *expr) {
vf := v.asInt()
a.eval = func(t *Thread) int64 { v := vf(t); return ^v }
case *idealIntType:
v := v.asIdealInt()()
val := v.Neg().Sub(bignum.Int(1))
a.eval = func() *bignum.Integer { return val }
val := v.asIdealInt()()
val.Not(val)
a.eval = func() *big.Int { return val }
default:
log.Crashf("unexpected type %v at %v", a.t, a.pos)
}
......@@ -372,8 +372,8 @@ func (a *expr) genBinOpAdd(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Add(r)
a.eval = func() *bignum.Integer { return val }
val := l.Add(l, r)
a.eval = func() *big.Int { return val }
case *floatType:
lf := l.asFloat()
rf := r.asFloat()
......@@ -405,8 +405,8 @@ func (a *expr) genBinOpAdd(l, r *expr) {
case *idealFloatType:
l := l.asIdealFloat()()
r := r.asIdealFloat()()
val := l.Add(r)
a.eval = func() *bignum.Rational { return val }
val := l.Add(l, r)
a.eval = func() *big.Rat { return val }
case *stringType:
lf := l.asString()
rf := r.asString()
......@@ -508,8 +508,8 @@ func (a *expr) genBinOpSub(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Sub(r)
a.eval = func() *bignum.Integer { return val }
val := l.Sub(l, r)
a.eval = func() *big.Int { return val }
case *floatType:
lf := l.asFloat()
rf := r.asFloat()
......@@ -541,8 +541,8 @@ func (a *expr) genBinOpSub(l, r *expr) {
case *idealFloatType:
l := l.asIdealFloat()()
r := r.asIdealFloat()()
val := l.Sub(r)
a.eval = func() *bignum.Rational { return val }
val := l.Sub(l, r)
a.eval = func() *big.Rat { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -637,8 +637,8 @@ func (a *expr) genBinOpMul(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Mul(r)
a.eval = func() *bignum.Integer { return val }
val := l.Mul(l, r)
a.eval = func() *big.Int { return val }
case *floatType:
lf := l.asFloat()
rf := r.asFloat()
......@@ -670,8 +670,8 @@ func (a *expr) genBinOpMul(l, r *expr) {
case *idealFloatType:
l := l.asIdealFloat()()
r := r.asIdealFloat()()
val := l.Mul(r)
a.eval = func() *bignum.Rational { return val }
val := l.Mul(l, r)
a.eval = func() *big.Rat { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -796,8 +796,8 @@ func (a *expr) genBinOpQuo(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Quo(r)
a.eval = func() *bignum.Integer { return val }
val := l.Quo(l, r)
a.eval = func() *big.Int { return val }
case *floatType:
lf := l.asFloat()
rf := r.asFloat()
......@@ -838,8 +838,8 @@ func (a *expr) genBinOpQuo(l, r *expr) {
case *idealFloatType:
l := l.asIdealFloat()()
r := r.asIdealFloat()()
val := l.Quo(r)
a.eval = func() *bignum.Rational { return val }
val := l.Quo(l, r)
a.eval = func() *big.Rat { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -964,8 +964,8 @@ func (a *expr) genBinOpRem(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Rem(r)
a.eval = func() *bignum.Integer { return val }
val := l.Rem(l, r)
a.eval = func() *big.Int { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -1060,8 +1060,8 @@ func (a *expr) genBinOpAnd(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.And(r)
a.eval = func() *bignum.Integer { return val }
val := l.And(l, r)
a.eval = func() *big.Int { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -1156,8 +1156,8 @@ func (a *expr) genBinOpOr(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Or(r)
a.eval = func() *bignum.Integer { return val }
val := l.Or(l, r)
a.eval = func() *big.Int { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -1252,8 +1252,8 @@ func (a *expr) genBinOpXor(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.Xor(r)
a.eval = func() *bignum.Integer { return val }
val := l.Xor(l, r)
a.eval = func() *big.Int { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......@@ -1348,8 +1348,8 @@ func (a *expr) genBinOpAndNot(l, r *expr) {
case *idealIntType:
l := l.asIdealInt()()
r := r.asIdealInt()()
val := l.AndNot(r)
a.eval = func() *bignum.Integer { return val }
val := l.AndNot(l, r)
a.eval = func() *big.Int { return val }
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
......
......@@ -5,7 +5,7 @@
package eval
import (
"exp/bignum"
"big"
"testing"
)
......@@ -22,7 +22,7 @@ var implLimit = "implementation limit"
var mustBeUnsigned = "must be unsigned"
var divByZero = "divide by zero"
var hugeInteger = bignum.Int(1).Shl(64)
var hugeInteger = new(big.Int).Lsh(idealOne, 64)
var exprTests = []test{
Val("i", 1),
......@@ -30,9 +30,9 @@ var exprTests = []test{
// TODO(austin) Test variable in constant context
//CErr("t", typeAsExpr),
Val("'a'", bignum.Int('a')),
Val("'\\uffff'", bignum.Int('\uffff')),
Val("'\\n'", bignum.Int('\n')),
Val("'a'", big.NewInt('a')),
Val("'\\uffff'", big.NewInt('\uffff')),
Val("'\\n'", big.NewInt('\n')),
CErr("''+x", badCharLit),
// Produces two parse errors
//CErr("'''", ""),
......@@ -40,10 +40,10 @@ var exprTests = []test{
CErr("'\\z'", unknownEscape),
CErr("'ab'", badCharLit),
Val("1.0", bignum.Rat(1, 1)),
Val("1.", bignum.Rat(1, 1)),
Val(".1", bignum.Rat(1, 10)),
Val("1e2", bignum.Rat(100, 1)),
Val("1.0", big.NewRat(1, 1)),
Val("1.", big.NewRat(1, 1)),
Val(".1", big.NewRat(1, 10)),
Val("1e2", big.NewRat(100, 1)),
Val("\"abc\"", "abc"),
Val("\"\"", ""),
......@@ -140,12 +140,12 @@ var exprTests = []test{
CErr("&c", badAddrOf),
Val("*(&ai[0])", 1),
Val("+1", bignum.Int(+1)),
Val("+1.0", bignum.Rat(1, 1)),
Val("01.5", bignum.Rat(15, 10)),
Val("+1", big.NewInt(+1)),
Val("+1.0", big.NewRat(1, 1)),
Val("01.5", big.NewRat(15, 10)),
CErr("+\"x\"", opTypes),
Val("-42", bignum.Int(-42)),
Val("-42", big.NewInt(-42)),
Val("-i", -1),
Val("-f", -1.0),
// 6g bug?
......@@ -154,8 +154,8 @@ var exprTests = []test{
// TODO(austin) Test unary !
Val("^2", bignum.Int(^2)),
Val("^(-2)", bignum.Int(^(-2))),
Val("^2", big.NewInt(^2)),
Val("^(-2)", big.NewInt(^(-2))),
CErr("^2.0", opTypes),
CErr("^2.5", opTypes),
Val("^i", ^1),
......@@ -165,67 +165,66 @@ var exprTests = []test{
Val("1+i", 2),
Val("1+u", uint(2)),
Val("3.0+i", 4),
Val("1+1", bignum.Int(2)),
Val("1+1", big.NewInt(2)),
Val("f+f", 2.0),
Val("1+f", 2.0),
Val("1.0+1", bignum.Rat(2, 1)),
Val("1.0+1", big.NewRat(2, 1)),
Val("\"abc\" + \"def\"", "abcdef"),
CErr("i+u", opTypes),
CErr("-1+u", constantUnderflows),
// TODO(austin) Test named types
Val("2-1", bignum.Int(1)),
Val("2.0-1", bignum.Rat(1, 1)),
Val("2-1", big.NewInt(1)),
Val("2.0-1", big.NewRat(1, 1)),
Val("f-2", -1.0),
// TOOD(austin) bignum can't do negative 0?
//Val("-0.0", XXX),
Val("2*2", bignum.Int(4)),
Val("-0.0", big.NewRat(0, 1)),
Val("2*2", big.NewInt(4)),
Val("2*i", 2),
Val("3/2", bignum.Int(1)),
Val("3/2", big.NewInt(1)),
Val("3/i", 3),
CErr("1/0", divByZero),
CErr("1.0/0", divByZero),
RErr("i/0", divByZero),
Val("3%2", bignum.Int(1)),
Val("3%2", big.NewInt(1)),
Val("i%2", 1),
CErr("3%0", divByZero),
CErr("3.0%0", opTypes),
RErr("i%0", divByZero),
// Examples from "Arithmetic operators"
Val("5/3", bignum.Int(1)),
Val("5/3", big.NewInt(1)),
Val("(i+4)/(i+2)", 1),
Val("5%3", bignum.Int(2)),
Val("5%3", big.NewInt(2)),
Val("(i+4)%(i+2)", 2),
Val("-5/3", bignum.Int(-1)),
Val("-5/3", big.NewInt(-1)),
Val("(i-6)/(i+2)", -1),
Val("-5%3", bignum.Int(-2)),
Val("-5%3", big.NewInt(-2)),
Val("(i-6)%(i+2)", -2),
Val("5/-3", bignum.Int(-1)),
Val("5/-3", big.NewInt(-1)),
Val("(i+4)/(i-4)", -1),
Val("5%-3", bignum.Int(2)),
Val("5%-3", big.NewInt(2)),
Val("(i+4)%(i-4)", 2),
Val("-5/-3", bignum.Int(1)),
Val("-5/-3", big.NewInt(1)),
Val("(i-6)/(i-4)", 1),
Val("-5%-3", bignum.Int(-2)),
Val("-5%-3", big.NewInt(-2)),
Val("(i-6)%(i-4)", -2),
// Examples from "Arithmetic operators"
Val("11/4", bignum.Int(2)),
Val("11/4", big.NewInt(2)),
Val("(i+10)/4", 2),
Val("11%4", bignum.Int(3)),
Val("11%4", big.NewInt(3)),
Val("(i+10)%4", 3),
Val("11>>2", bignum.Int(2)),
Val("11>>2", big.NewInt(2)),
Val("(i+10)>>2", 2),
Val("11&3", bignum.Int(3)),
Val("11&3", big.NewInt(3)),
Val("(i+10)&3", 3),
Val("-11/4", bignum.Int(-2)),
Val("-11/4", big.NewInt(-2)),
Val("(i-12)/4", -2),
Val("-11%4", bignum.Int(-3)),
Val("-11%4", big.NewInt(-3)),
Val("(i-12)%4", -3),
Val("-11>>2", bignum.Int(-3)),
Val("-11>>2", big.NewInt(-3)),
Val("(i-12)>>2", -3),
Val("-11&3", bignum.Int(1)),
Val("-11&3", big.NewInt(1)),
Val("(i-12)&3", 1),
// TODO(austin) Test bit ops
......@@ -234,29 +233,29 @@ var exprTests = []test{
// ideal int, negative ideal int, big ideal int, ideal
// fractional float, ideal non-fractional float, int, uint,
// and float.
Val("2<<2", bignum.Int(2<<2)),
Val("2<<2", big.NewInt(2<<2)),
CErr("2<<(-1)", constantUnderflows),
CErr("2<<0x10000000000000000", constantOverflows),
CErr("2<<2.5", constantTruncated),
Val("2<<2.0", bignum.Int(2<<2.0)),
Val("2<<2.0", big.NewInt(2<<2.0)),
CErr("2<<i", mustBeUnsigned),
Val("2<<u", 2<<1),
CErr("2<<f", opTypes),
Val("-2<<2", bignum.Int(-2<<2)),
Val("-2<<2", big.NewInt(-2<<2)),
CErr("-2<<(-1)", constantUnderflows),
CErr("-2<<0x10000000000000000", constantOverflows),
CErr("-2<<2.5", constantTruncated),
Val("-2<<2.0", bignum.Int(-2<<2.0)),
Val("-2<<2.0", big.NewInt(-2<<2.0)),
CErr("-2<<i", mustBeUnsigned),
Val("-2<<u", -2<<1),
CErr("-2<<f", opTypes),
Val("0x10000000000000000<<2", hugeInteger.Shl(2)),
Val("0x10000000000000000<<2", new(big.Int).Lsh(hugeInteger, 2)),
CErr("0x10000000000000000<<(-1)", constantUnderflows),
CErr("0x10000000000000000<<0x10000000000000000", constantOverflows),
CErr("0x10000000000000000<<2.5", constantTruncated),
Val("0x10000000000000000<<2.0", hugeInteger.Shl(2)),
Val("0x10000000000000000<<2.0", new(big.Int).Lsh(hugeInteger, 2)),
CErr("0x10000000000000000<<i", mustBeUnsigned),
CErr("0x10000000000000000<<u", constantOverflows),
CErr("0x10000000000000000<<f", opTypes),
......
......@@ -45,11 +45,11 @@ var (
intType = &Type{Repr: "*intType", Value: "IntValue", Native: "int64", As: "asInt",
Sizes: []Size{Size{8, "int8"}, Size{16, "int16"}, Size{32, "int32"}, Size{64, "int64"}, Size{0, "int"}},
}
idealIntType = &Type{Repr: "*idealIntType", Value: "IdealIntValue", Native: "*bignum.Integer", As: "asIdealInt", IsIdeal: true}
idealIntType = &Type{Repr: "*idealIntType", Value: "IdealIntValue", Native: "*big.Int", As: "asIdealInt", IsIdeal: true}
floatType = &Type{Repr: "*floatType", Value: "FloatValue", Native: "float64", As: "asFloat",
Sizes: []Size{Size{32, "float32"}, Size{64, "float64"}, Size{0, "float"}},
}
idealFloatType = &Type{Repr: "*idealFloatType", Value: "IdealFloatValue", Native: "*bignum.Rational", As: "asIdealFloat", IsIdeal: true}
idealFloatType = &Type{Repr: "*idealFloatType", Value: "IdealFloatValue", Native: "*big.Rat", As: "asIdealFloat", IsIdeal: true}
stringType = &Type{Repr: "*stringType", Value: "StringValue", Native: "string", As: "asString"}
arrayType = &Type{Repr: "*ArrayType", Value: "ArrayValue", Native: "ArrayValue", As: "asArray", HasAssign: true}
structType = &Type{Repr: "*StructType", Value: "StructValue", Native: "StructValue", As: "asStruct", HasAssign: true}
......@@ -93,33 +93,33 @@ var (
)
var unOps = []Op{
Op{Name: "Neg", Expr: "-v", ConstExpr: "v.Neg()", Types: numbers},
Op{Name: "Neg", Expr: "-v", ConstExpr: "val.Neg(val)", Types: numbers},
Op{Name: "Not", Expr: "!v", Types: bools},
Op{Name: "Xor", Expr: "^v", ConstExpr: "v.Neg().Sub(bignum.Int(1))", Types: integers},
Op{Name: "Xor", Expr: "^v", ConstExpr: "val.Not(val)", Types: integers},
}
var binOps = []Op{
Op{Name: "Add", Expr: "l + r", ConstExpr: "l.Add(r)", Types: addable},
Op{Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(r)", Types: numbers},
Op{Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(r)", Types: numbers},
Op{Name: "Add", Expr: "l + r", ConstExpr: "l.Add(l, r)", Types: addable},
Op{Name: "Sub", Expr: "l - r", ConstExpr: "l.Sub(l, r)", Types: numbers},
Op{Name: "Mul", Expr: "l * r", ConstExpr: "l.Mul(l, r)", Types: numbers},
Op{Name: "Quo",
Body: "if r == 0 { t.Abort(DivByZeroError{}) }; ret = l / r",
ConstExpr: "l.Quo(r)",
ConstExpr: "l.Quo(l, r)",
Types: numbers,
},
Op{Name: "Rem",
Body: "if r == 0 { t.Abort(DivByZeroError{}) }; ret = l % r",
ConstExpr: "l.Rem(r)",
ConstExpr: "l.Rem(l, r)",
Types: integers,
},
Op{Name: "And", Expr: "l & r", ConstExpr: "l.And(r)", Types: integers},
Op{Name: "Or", Expr: "l | r", ConstExpr: "l.Or(r)", Types: integers},
Op{Name: "Xor", Expr: "l ^ r", ConstExpr: "l.Xor(r)", Types: integers},
Op{Name: "AndNot", Expr: "l &^ r", ConstExpr: "l.AndNot(r)", Types: integers},
Op{Name: "Shl", Expr: "l << r", ConstExpr: "l.Shl(uint(r.Value()))",
Op{Name: "And", Expr: "l & r", ConstExpr: "l.And(l, r)", Types: integers},
Op{Name: "Or", Expr: "l | r", ConstExpr: "l.Or(l, r)", Types: integers},
Op{Name: "Xor", Expr: "l ^ r", ConstExpr: "l.Xor(l, r)", Types: integers},
Op{Name: "AndNot", Expr: "l &^ r", ConstExpr: "l.AndNot(l, r)", Types: integers},
Op{Name: "Shl", Expr: "l << r", ConstExpr: "l.Lsh(l, uint(r.Value()))",
AsRightName: "asUint", Types: shiftable,
},
Op{Name: "Shr", Expr: "l >> r", ConstExpr: "l.Shr(uint(r.Value()))",
Op{Name: "Shr", Expr: "l >> r", ConstExpr: "new(big.Int).Rsh(l, uint(r.Value()))",
AsRightName: "asUint", Types: shiftable,
},
Op{Name: "Lss", Expr: "l < r", ConstExpr: "l.Cmp(r) < 0", ReturnType: "bool", Types: addable},
......@@ -149,8 +149,8 @@ const templateStr = `
package eval
import (
"bignum";
"log";
"big"
"log"
)
/*
......@@ -184,9 +184,9 @@ func (a *expr) asInterface() (func(*Thread) interface{}) {
«.end»
«.end»
default:
log.Crashf("unexpected expression node type %T at %v", a.eval, a.pos);
log.Crashf("unexpected expression node type %T at %v", a.eval, a.pos)
}
panic("fail");
panic("fail")
}
/*
......@@ -198,19 +198,19 @@ func (a *expr) genConstant(v Value) {
«.repeated section Types»
case «Repr»:
«.section IsIdeal»
val := v.(«Value»).Get();
val := v.(«Value»).Get()
a.eval = func() «Native» { return val }
«.or»
a.eval = func(t *Thread) «Native» { return v.(«Value»).Get(t) }
«.end»
«.end»
default:
log.Crashf("unexpected constant type %v at %v", a.t, a.pos);
log.Crashf("unexpected constant type %v at %v", a.t, a.pos)
}
}
func (a *expr) genIdentOp(level, index int) {
a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) };
a.evalAddr = func(t *Thread) Value { return t.f.Get(level, index) }
switch a.t.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
......@@ -220,12 +220,12 @@ func (a *expr) genIdentOp(level, index int) {
«.end»
«.end»
default:
log.Crashf("unexpected identifier type %v at %v", a.t, a.pos);
log.Crashf("unexpected identifier type %v at %v", a.t, a.pos)
}
}
func (a *expr) genFuncCall(call func(t *Thread) []Value) {
a.exec = func(t *Thread) { call(t)};
a.exec = func(t *Thread) { call(t)}
switch a.t.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
......@@ -237,12 +237,12 @@ func (a *expr) genFuncCall(call func(t *Thread) []Value) {
case *MultiType:
a.eval = func(t *Thread) []Value { return call(t) }
default:
log.Crashf("unexpected result type %v at %v", a.t, a.pos);
log.Crashf("unexpected result type %v at %v", a.t, a.pos)
}
}
func (a *expr) genValue(vf func(*Thread) Value) {
a.evalAddr = vf;
a.evalAddr = vf
switch a.t.lit().(type) {
«.repeated section Types»
«.section IsIdeal»
......@@ -252,7 +252,7 @@ func (a *expr) genValue(vf func(*Thread) Value) {
«.end»
«.end»
default:
log.Crashf("unexpected result type %v at %v", a.t, a.pos);
log.Crashf("unexpected result type %v at %v", a.t, a.pos)
}
}
......@@ -262,29 +262,29 @@ func (a *expr) genUnaryOp«Name»(v *expr) {
«.repeated section Types»
case «Repr»:
«.section IsIdeal»
v := v.«As»()();
val := «ConstExpr»;
val := v.«As»()()
«ConstExpr»
a.eval = func() «Native» { return val }
«.or»
vf := v.«As»();
vf := v.«As»()
a.eval = func(t *Thread) «Native» { v := vf(t); return «Expr» }
«.end»
«.end»
default:
log.Crashf("unexpected type %v at %v", a.t, a.pos);
log.Crashf("unexpected type %v at %v", a.t, a.pos)
}
}
«.end»
func (a *expr) genBinOpLogAnd(l, r *expr) {
lf := l.asBool();
rf := r.asBool();
lf := l.asBool()
rf := r.asBool()
a.eval = func(t *Thread) bool { return lf(t) && rf(t) }
}
func (a *expr) genBinOpLogOr(l, r *expr) {
lf := l.asBool();
rf := r.asBool();
lf := l.asBool()
rf := r.asBool()
a.eval = func(t *Thread) bool { return lf(t) || rf(t) }
}
......@@ -294,20 +294,20 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
«.repeated section Types»
case «Repr»:
«.section IsIdeal»
l := l.«As»()();
r := r.«As»()();
val := «ConstExpr»;
l := l.«As»()()
r := r.«As»()()
val := «ConstExpr»
«.section ReturnType»
a.eval = func(t *Thread) «ReturnType» { return val }
«.or»
a.eval = func() «Native» { return val }
«.end»
«.or»
lf := l.«As»();
rf := r.«.section AsRightName»«@»«.or»«As»«.end»();
lf := l.«As»()
rf := r.«.section AsRightName»«@»«.or»«As»«.end»()
«.section ReturnType»
a.eval = func(t *Thread) «@» {
l, r := lf(t), rf(t);
l, r := lf(t), rf(t)
return «Expr»
}
«.or»
......@@ -316,22 +316,22 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
«.repeated section @»
case «Bits»:
a.eval = func(t *Thread) «Native» {
l, r := lf(t), rf(t);
var ret «Native»;
l, r := lf(t), rf(t)
var ret «Native»
«.section Body»
«Body»;
«Body»
«.or»
ret = «Expr»;
ret = «Expr»
«.end»
return «Native»(«Sized»(ret))
}
«.end»
default:
log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos);
log.Crashf("unexpected size %d in type %v at %v", t.Bits, t, a.pos)
}
«.or»
a.eval = func(t *Thread) «Native» {
l, r := lf(t), rf(t);
l, r := lf(t), rf(t)
return «Expr»
}
«.end»
......@@ -339,7 +339,7 @@ func (a *expr) genBinOp«Name»(l, r *expr) {
«.end»
«.end»
default:
log.Crashf("unexpected type %v at %v", l.t, a.pos);
log.Crashf("unexpected type %v at %v", l.t, a.pos)
}
}
......@@ -350,14 +350,14 @@ func genAssign(lt Type, r *expr) (func(lv Value, t *Thread)) {
«.section IsIdeal»
«.or»
case «Repr»:
rf := r.«As»();
rf := r.«As»()
return func(lv Value, t *Thread) { «.section HasAssign»lv.Assign(t, rf(t))«.or»lv.(«Value»).Set(t, rf(t))«.end» }
«.end»
«.end»
default:
log.Crashf("unexpected left operand type %v at %v", lt, r.pos);
log.Crashf("unexpected left operand type %v at %v", lt, r.pos)
}
panic("fail");
panic("fail")
}
`
......
......@@ -5,7 +5,7 @@
package eval
import (
"exp/bignum"
"big"
"log"
"go/ast"
"go/token"
......@@ -493,7 +493,7 @@ func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
one := l.newExpr(IdealIntType, "constant")
one.pos = s.Pos()
one.eval = func() *bignum.Integer { return bignum.Int(1) }
one.eval = func() *big.Int { return big.NewInt(1) }
binop := l.compileBinaryExpr(op, l, one)
if binop == nil {
......
......@@ -5,7 +5,7 @@
package eval
import (
"exp/bignum"
"big"
"go/ast"
"go/token"
"log"
......@@ -60,9 +60,9 @@ type Type interface {
type BoundedType interface {
Type
// minVal returns the smallest value of this type.
minVal() *bignum.Rational
minVal() *big.Rat
// maxVal returns the largest value of this type.
maxVal() *bignum.Rational
maxVal() *big.Rat
}
var universePos = token.Position{"<universe>", 0, 0, 0}
......@@ -234,9 +234,9 @@ func (t *uintType) Zero() Value {
panic("unexpected uint bit count")
}
func (t *uintType) minVal() *bignum.Rational { return bignum.Rat(0, 1) }
func (t *uintType) minVal() *big.Rat { return big.NewRat(0, 1) }
func (t *uintType) maxVal() *bignum.Rational {
func (t *uintType) maxVal() *big.Rat {
bits := t.Bits
if bits == 0 {
if t.Ptr {
......@@ -245,7 +245,10 @@ func (t *uintType) maxVal() *bignum.Rational {
bits = uint(8 * unsafe.Sizeof(uint(0)))
}
}
return bignum.MakeRat(bignum.Int(1).Shl(bits).Add(bignum.Int(-1)), bignum.Nat(1))
numer := big.NewInt(1)
numer.Lsh(numer, bits)
numer.Sub(numer, idealOne)
return new(big.Rat).SetInt(numer)
}
/*
......@@ -307,20 +310,25 @@ func (t *intType) Zero() Value {
panic("unexpected int bit count")
}
func (t *intType) minVal() *bignum.Rational {
func (t *intType) minVal() *big.Rat {
bits := t.Bits
if bits == 0 {
bits = uint(8 * unsafe.Sizeof(int(0)))
}
return bignum.MakeRat(bignum.Int(-1).Shl(bits-1), bignum.Nat(1))
numer := big.NewInt(-1)
numer.Lsh(numer, bits-1)
return new(big.Rat).SetInt(numer)
}
func (t *intType) maxVal() *bignum.Rational {
func (t *intType) maxVal() *big.Rat {
bits := t.Bits
if bits == 0 {
bits = uint(8 * unsafe.Sizeof(int(0)))
}
return bignum.MakeRat(bignum.Int(1).Shl(bits-1).Add(bignum.Int(-1)), bignum.Nat(1))
numer := big.NewInt(1)
numer.Lsh(numer, bits-1)
numer.Sub(numer, idealOne)
return new(big.Rat).SetInt(numer)
}
/*
......@@ -346,7 +354,7 @@ func (t *idealIntType) isIdeal() bool { return true }
func (t *idealIntType) String() string { return "ideal integer" }
func (t *idealIntType) Zero() Value { return &idealIntV{bignum.Int(0)} }
func (t *idealIntType) Zero() Value { return &idealIntV{idealZero} }
/*
* Float
......@@ -393,12 +401,12 @@ func (t *floatType) Zero() Value {
panic("unexpected float bit count")
}
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 minFloat32Val = maxFloat32Val.Neg()
var minFloat64Val = maxFloat64Val.Neg()
var maxFloat32Val *big.Rat
var maxFloat64Val *big.Rat
var minFloat32Val *big.Rat
var minFloat64Val *big.Rat
func (t *floatType) minVal() *bignum.Rational {
func (t *floatType) minVal() *big.Rat {
bits := t.Bits
if bits == 0 {
bits = uint(8 * unsafe.Sizeof(float(0)))
......@@ -413,7 +421,7 @@ func (t *floatType) minVal() *bignum.Rational {
panic("unreachable")
}
func (t *floatType) maxVal() *bignum.Rational {
func (t *floatType) maxVal() *big.Rat {
bits := t.Bits
if bits == 0 {
bits = uint(8 * unsafe.Sizeof(float(0)))
......@@ -451,7 +459,7 @@ func (t *idealFloatType) isIdeal() bool { return true }
func (t *idealFloatType) String() string { return "ideal float" }
func (t *idealFloatType) Zero() Value { return &idealFloatV{bignum.Rat(1, 0)} }
func (t *idealFloatType) Zero() Value { return &idealFloatV{big.NewRat(0, 1)} }
/*
* String
......@@ -1221,6 +1229,15 @@ func (t *MultiType) Zero() Value {
*/
func init() {
numer := big.NewInt(0xffffff)
numer.Lsh(numer, 127-23)
maxFloat32Val = new(big.Rat).SetInt(numer)
numer.SetInt64(0x1fffffffffffff)
numer.Lsh(numer, 1023-52)
maxFloat64Val = new(big.Rat).SetInt(numer)
minFloat32Val = new(big.Rat).Neg(maxFloat32Val)
minFloat64Val = new(big.Rat).Neg(maxFloat64Val)
// To avoid portability issues all numeric types are distinct
// except byte, which is an alias for uint8.
......
// 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 (
"exp/bignum"
)
// TODO(austin): Maybe add to bignum in more general form
func ratToString(rat *bignum.Rational) string {
n, dnat := rat.Value()
d := bignum.MakeInt(false, dnat)
w, frac := n.QuoRem(d)
out := w.String()
if frac.IsZero() {
return out
}
r := frac.Abs()
r = r.Mul(bignum.Nat(1e6))
dec, tail := r.DivMod(dnat)
// Round last digit
if tail.Cmp(dnat.Div(bignum.Nat(2))) >= 0 {
dec = dec.Add(bignum.Nat(1))
}
// Strip zeros
ten := bignum.Nat(10)
for !dec.IsZero() {
dec2, r2 := dec.DivMod(ten)
if !r2.IsZero() {
break
}
dec = dec2
}
out += "." + dec.String()
return out
}
......@@ -5,7 +5,7 @@
package eval
import (
"exp/bignum"
"big"
"fmt"
)
......@@ -40,7 +40,7 @@ type IntValue interface {
// because ideals are not l-values.
type IdealIntValue interface {
Value
Get() *bignum.Integer
Get() *big.Int
}
type FloatValue interface {
......@@ -51,7 +51,7 @@ type FloatValue interface {
type IdealFloatValue interface {
Value
Get() *bignum.Rational
Get() *big.Rat
}
type StringValue interface {
......@@ -272,7 +272,7 @@ func (v *intV) Set(t *Thread, x int64) { *v = intV(x) }
*/
type idealIntV struct {
V *bignum.Integer
V *big.Int
}
func (v *idealIntV) String() string { return v.V.String() }
......@@ -281,7 +281,7 @@ func (v *idealIntV) Assign(t *Thread, o Value) {
v.V = o.(IdealIntValue).Get()
}
func (v *idealIntV) Get() *bignum.Integer { return v.V }
func (v *idealIntV) Get() *big.Int { return v.V }
/*
* Float
......@@ -322,16 +322,16 @@ func (v *floatV) Set(t *Thread, x float64) { *v = floatV(x) }
*/
type idealFloatV struct {
V *bignum.Rational
V *big.Rat
}
func (v *idealFloatV) String() string { return ratToString(v.V) }
func (v *idealFloatV) String() string { return v.V.FloatString(6) }
func (v *idealFloatV) Assign(t *Thread, o Value) {
v.V = o.(IdealFloatValue).Get()
}
func (v *idealFloatV) Get() *bignum.Rational { return v.V }
func (v *idealFloatV) Get() *big.Rat { return v.V }
/*
* String
......@@ -586,8 +586,6 @@ func (v multiV) Assign(t *Thread, o Value) {
* Universal constants
*/
// TODO(austin) Nothing complains if I accidentally define init with
// arguments. Is this intentional?
func init() {
s := universe
......
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