mirror of https://github.com/golang/go.git
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
This commit is contained in:
parent
c9406f930d
commit
b97292791b
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
// 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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue