Esempio n. 1
0
func (t *intType) maxVal() *bignum.Rational {
	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))
}
Esempio n. 2
0
func (t *uintType) maxVal() *bignum.Rational {
	bits := t.Bits
	if bits == 0 {
		if t.Ptr {
			bits = uint(8 * unsafe.Sizeof(uintptr(0)))
		} else {
			bits = uint(8 * unsafe.Sizeof(uint(0)))
		}
	}
	return bignum.MakeRat(bignum.Int(1).Shl(bits).Add(bignum.Int(-1)), bignum.Nat(1))
}
Esempio n. 3
0
func main() {
	sum := 0
	two_1000 := bignum.Int(2)
	for i := 1; i < 1000; i++ {
		two_1000 = two_1000.Mul(bignum.Int(2))
	}
	for _, v := range two_1000.String() {
		c, _ := strconv.Atoi(string(v))
		sum += c
	}
	fmt.Printf("%d\n", sum)
}
Esempio n. 4
0
func main() {
	a := bignum.Int(1)
	b := bignum.Int(1)
	i := 2
	for {
		a, b = b, a.Add(b)
		i += 1
		if len(b.String()) == 1000 {
			break
		}

	}
	fmt.Printf("%d\n", i)
}
Esempio n. 5
0
// convertToInt converts this expression to an integer, if possible,
// or produces an error if not.  This accepts ideal ints, uints, and
// ints.  If max is not -1, produces an error if possible if the value
// exceeds max.  If negErr is not "", produces an error if possible if
// the value is negative.
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() {
			a.diag("negative %s: %s", negErr, val)
			return nil
		}
		bound := max
		if negErr == "slice" {
			bound++
		}
		if max != -1 && val.Cmp(bignum.Int(bound)) >= 0 {
			a.diag("index %s exceeds length %d", val, max)
			return nil
		}
		return a.convertTo(IntType)

	case *uintType:
		// Convert to int
		na := a.newExpr(IntType, a.desc)
		af := a.asUint()
		na.eval = func(t *Thread) int64 { return int64(af(t)) }
		return na

	case *intType:
		// Good as is
		return a
	}

	a.diag("illegal operand type for %s\n\t%v", errOp, a.t)
	return nil
}
Esempio n. 6
0
func (a *stmtCompiler) compileIncDecStmt(s *ast.IncDecStmt) {
	// Create temporary block for extractEffect
	bc := a.enterChild()
	defer bc.exit()

	l := a.compileExpr(bc.block, false, s.X)
	if l == nil {
		return
	}

	if l.evalAddr == nil {
		l.diag("cannot assign to %s", l.desc)
		return
	}
	if !(l.t.isInteger() || l.t.isFloat()) {
		l.diagOpType(s.Tok, l.t)
		return
	}

	var op token.Token
	var desc string
	switch s.Tok {
	case token.INC:
		op = token.ADD
		desc = "increment statement"
	case token.DEC:
		op = token.SUB
		desc = "decrement statement"
	default:
		log.Crashf("Unexpected IncDec token %v", s.Tok)
	}

	effect, l := l.extractEffect(bc.block, desc)

	one := l.newExpr(IdealIntType, "constant")
	one.pos = s.Pos()
	one.eval = func() *bignum.Integer { return bignum.Int(1) }

	binop := l.compileBinaryExpr(op, l, one)
	if binop == nil {
		return
	}

	assign := a.compileAssign(s.Pos(), bc.block, l.t, []*expr{binop}, "", "")
	if assign == nil {
		log.Crashf("compileAssign type check failed")
	}

	lf := l.evalAddr
	a.push(func(v *Thread) {
		effect(v)
		assign(lf(v), v)
	})
}
Esempio n. 7
0
func (a *exprInfo) compileCharLit(lit string) *expr {
	if lit[0] != '\'' {
		// Caught by parser
		a.silentErrors++
		return nil
	}
	v, _, tail, err := strconv.UnquoteChar(lit[1:], '\'')
	if err != nil || tail != "'" {
		// Caught by parser
		a.silentErrors++
		return nil
	}
	return a.compileIdealInt(bignum.Int(int64(v)), "character literal")
}
Esempio n. 8
0
func (a *expr) genUnaryOpXor(v *expr) {
	switch a.t.lit().(type) {
	case *uintType:
		vf := v.asUint()
		a.eval = func(t *Thread) uint64 { v := vf(t); return ^v }
	case *intType:
		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 }
	default:
		log.Crashf("unexpected type %v at %v", a.t, a.pos)
	}
}
Esempio n. 9
0
func Mul(a, b string) string {
	ra, rb, f := twop(a, b)
	ar := bignum.Rat(ra, int64(f))
	br := bignum.Rat(rb, int64(f))
	i, n := ar.Mul(br).Value()
	nv := n.Value()
	d := uint64(1)
	for d%nv != 0 {
		d *= 10
	}
	i = i.Mul1(int64(d / nv))
	if uint64(f) < d {
		i = i.Div(bignum.Int(int64(d / uint64(f))))
		d = uint64(f)
	}
	return String(i.Value(), int(d))
}
Esempio n. 10
0
func newTestWorld() *World {
	w := NewWorld()

	def := func(name string, t Type, val interface{}) { w.DefineVar(name, t, toValue(val)) }

	w.DefineConst("c", IdealIntType, toValue(bignum.Int(1)))
	def("i", IntType, 1)
	def("i2", IntType, 2)
	def("u", UintType, uint(1))
	def("f", FloatType, 1.0)
	def("s", StringType, "abc")
	def("t", NewStructType([]StructField{StructField{"a", IntType, false}}), vstruct{1})
	def("ai", NewArrayType(2, IntType), varray{1, 2})
	def("aai", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{1, 2}, varray{3, 4}})
	def("aai2", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{5, 6}, varray{7, 8}})
	def("fn", NewFuncType([]Type{IntType}, false, []Type{IntType}), &testFunc{})
	def("oneTwo", NewFuncType([]Type{}, false, []Type{IntType, IntType}), &oneTwoFunc{})
	def("void", NewFuncType([]Type{}, false, []Type{}), &voidFunc{})
	def("sli", NewSliceType(IntType), vslice{varray{1, 2, 3}, 2, 3})

	return w
}
Esempio n. 11
0
func (t *idealIntType) Zero() Value { return &idealIntV{bignum.Int(0)} }
Esempio n. 12
0
func (t *floatType) Zero() Value {
	switch t.Bits {
	case 32:
		res := float32V(0)
		return &res
	case 64:
		res := float64V(0)
		return &res
	case 0:
		res := floatV(0)
		return &res
	}
	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()

func (t *floatType) minVal() *bignum.Rational {
	bits := t.Bits
	if bits == 0 {
		bits = uint(8 * unsafe.Sizeof(float(0)))
	}
	switch bits {
	case 32:
		return minFloat32Val
	case 64:
		return minFloat64Val
	}
Esempio n. 13
0
func (a *exprInfo) compileBinaryExpr(op token.Token, l, r *expr) *expr {
	// Save the original types of l.t and r.t for error messages.
	origlt := l.t
	origrt := r.t

	// XXX(Spec) What is the exact definition of a "named type"?

	// XXX(Spec) Arithmetic operators: "Integer types" apparently
	// means all types compatible with basic integer types, though
	// this is never explained.  Likewise for float types, etc.
	// This relates to the missing explanation of named types.

	// XXX(Spec) Operators: "If both operands are ideal numbers,
	// the conversion is to ideal floats if one of the operands is
	// an ideal float (relevant for / and %)."  How is that
	// relevant only for / and %?  If I add an ideal int and an
	// ideal float, I get an ideal float.

	if op != token.SHL && op != token.SHR {
		// Except in shift expressions, if one operand has
		// numeric type and the other operand is an ideal
		// number, the ideal number is converted to match the
		// type of the other operand.
		if (l.t.isInteger() || l.t.isFloat()) && !l.t.isIdeal() && r.t.isIdeal() {
			r = r.convertTo(l.t)
		} else if (r.t.isInteger() || r.t.isFloat()) && !r.t.isIdeal() && l.t.isIdeal() {
			l = l.convertTo(r.t)
		}
		if l == nil || r == nil {
			return nil
		}

		// Except in shift expressions, if both operands are
		// ideal numbers and one is an ideal float, the other
		// is converted to ideal float.
		if l.t.isIdeal() && r.t.isIdeal() {
			if l.t.isInteger() && r.t.isFloat() {
				l = l.convertTo(r.t)
			} else if l.t.isFloat() && r.t.isInteger() {
				r = r.convertTo(l.t)
			}
			if l == nil || r == nil {
				return nil
			}
		}
	}

	// Useful type predicates
	// TODO(austin) CL 33668 mandates identical types except for comparisons.
	compat := func() bool { return l.t.compat(r.t, false) }
	integers := func() bool { return l.t.isInteger() && r.t.isInteger() }
	floats := func() bool { return l.t.isFloat() && r.t.isFloat() }
	strings := func() bool {
		// TODO(austin) Deal with named types
		return l.t == StringType && r.t == StringType
	}
	booleans := func() bool { return l.t.isBoolean() && r.t.isBoolean() }

	// Type check
	var t Type
	switch op {
	case token.ADD:
		if !compat() || (!integers() && !floats() && !strings()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = l.t

	case token.SUB, token.MUL, token.QUO:
		if !compat() || (!integers() && !floats()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = l.t

	case token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
		if !compat() || !integers() {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = l.t

	case token.SHL, token.SHR:
		// XXX(Spec) Is it okay for the right operand to be an
		// ideal float with no fractional part?  "The right
		// 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 and 6g agrees.

		if !l.t.isInteger() || !(r.t.isInteger() || r.t.isIdeal()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}

		// The right 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.
		if r.t.isIdeal() {
			r2 := r.convertTo(UintType)
			if r2 == nil {
				return nil
			}

			// If the left operand is not ideal, convert
			// the right to not ideal.
			if !l.t.isIdeal() {
				r = r2
			}

			// 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")
				}
			}
		} else if _, ok := r.t.lit().(*uintType); !ok {
			a.diag("right operand of shift must be unsigned")
			return nil
		}

		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 nil
			}
		}

		// At this point, we should have one of three cases:
		// 1) uint SHIFT uint
		// 2) int SHIFT uint
		// 3) ideal int SHIFT ideal int

		t = l.t

	case token.LOR, token.LAND:
		if !booleans() {
			return nil
		}
		// XXX(Spec) There's no mention of *which* boolean
		// type the logical operators return.  From poking at
		// 6g, it appears to be the named boolean type, NOT
		// the type of the left operand, and NOT an unnamed
		// boolean type.

		t = BoolType

	case token.ARROW:
		// The operands in channel sends differ in type: one
		// is always a channel and the other is a variable or
		// value of the channel's element type.
		log.Crash("Binary op <- not implemented")
		t = BoolType

	case token.LSS, token.GTR, token.LEQ, token.GEQ:
		// XXX(Spec) It's really unclear what types which
		// comparison operators apply to.  I feel like the
		// text is trying to paint a Venn diagram for me,
		// which it's really pretty simple: <, <=, >, >= apply
		// only to numeric types and strings.  == and != apply
		// to everything except arrays and structs, and there
		// are some restrictions on when it applies to slices.

		if !compat() || (!integers() && !floats() && !strings()) {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = BoolType

	case token.EQL, token.NEQ:
		// XXX(Spec) The rules for type checking comparison
		// operators are spread across three places that all
		// partially overlap with each other: the Comparison
		// Compatibility section, the Operators section, and
		// the Comparison Operators section.  The Operators
		// section should just say that operators require
		// identical types (as it does currently) except that
		// there a few special cases for comparison, which are
		// described in section X.  Currently it includes just
		// one of the four special cases.  The Comparison
		// Compatibility section and the Comparison Operators
		// section should either be merged, or at least the
		// Comparison Compatibility section should be
		// exclusively about type checking and the Comparison
		// Operators section should be exclusively about
		// semantics.

		// XXX(Spec) Comparison operators: "All comparison
		// operators apply to basic types except bools."  This
		// is very difficult to parse.  It's explained much
		// better in the Comparison Compatibility section.

		// XXX(Spec) Comparison compatibility: "Function
		// values are equal if they refer to the same
		// function." is rather vague.  It should probably be
		// similar to the way the rule for map values is
		// written: Function values are equal if they were
		// created by the same execution of a function literal
		// or refer to the same function declaration.  This is
		// *almost* but not quite waht 6g implements.  If a
		// function literals does not capture any variables,
		// then multiple executions of it will result in the
		// same closure.  Russ says he'll change that.

		// TODO(austin) Deal with remaining special cases

		if !compat() {
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		// Arrays and structs may not be compared to anything.
		switch l.t.(type) {
		case *ArrayType, *StructType:
			a.diagOpTypes(op, origlt, origrt)
			return nil
		}
		t = BoolType

	default:
		log.Crashf("unknown binary operator %v", op)
	}

	desc, ok := binOpDescs[op]
	if !ok {
		desc = op.String() + " expression"
		binOpDescs[op] = desc
	}

	// Check for ideal divide by zero
	switch op {
	case token.QUO, token.REM:
		if r.t.isIdeal() {
			if (r.t.isInteger() && r.asIdealInt()().IsZero()) ||
				(r.t.isFloat() && r.asIdealFloat()().IsZero()) {
				a.diag("divide by zero")
				return nil
			}
		}
	}

	// Compile
	expr := a.newExpr(t, desc)
	switch op {
	case token.ADD:
		expr.genBinOpAdd(l, r)

	case token.SUB:
		expr.genBinOpSub(l, r)

	case token.MUL:
		expr.genBinOpMul(l, r)

	case token.QUO:
		expr.genBinOpQuo(l, r)

	case token.REM:
		expr.genBinOpRem(l, r)

	case token.AND:
		expr.genBinOpAnd(l, r)

	case token.OR:
		expr.genBinOpOr(l, r)

	case token.XOR:
		expr.genBinOpXor(l, r)

	case token.AND_NOT:
		expr.genBinOpAndNot(l, r)

	case token.SHL:
		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)
				expr.t = nil
				return nil
			}
			val := lv.Shl(uint(rv.Value()))
			expr.eval = func() *bignum.Integer { return val }
		} else {
			expr.genBinOpShl(l, r)
		}

	case token.SHR:
		if l.t.isIdeal() {
			lv := l.asIdealInt()()
			rv := r.asIdealInt()()
			val := lv.Shr(uint(rv.Value()))
			expr.eval = func() *bignum.Integer { return val }
		} else {
			expr.genBinOpShr(l, r)
		}

	case token.LSS:
		expr.genBinOpLss(l, r)

	case token.GTR:
		expr.genBinOpGtr(l, r)

	case token.LEQ:
		expr.genBinOpLeq(l, r)

	case token.GEQ:
		expr.genBinOpGeq(l, r)

	case token.EQL:
		expr.genBinOpEql(l, r)

	case token.NEQ:
		expr.genBinOpNeq(l, r)

	case token.LAND:
		expr.genBinOpLogAnd(l, r)

	case token.LOR:
		expr.genBinOpLogOr(l, r)

	default:
		log.Crashf("Compilation of binary op %v not implemented", op)
	}

	return expr
}
Esempio n. 14
0
)

var undefined = "undefined"
var typeAsExpr = "type .* used as expression"
var badCharLit = "character literal"
var illegalEscape = "illegal char escape"
var opTypes = "illegal (operand|argument) type|cannot index into"
var badAddrOf = "cannot take the address"
var constantTruncated = "constant [^ ]* truncated"
var constantUnderflows = "constant [^ ]* underflows"
var constantOverflows = "constant [^ ]* overflows"
var implLimit = "implementation limit"
var mustBeUnsigned = "must be unsigned"
var divByZero = "divide by zero"

var hugeInteger = bignum.Int(1).Shl(64)

var exprTests = []test{
	Val("i", 1),
	CErr("zzz", undefined),
	// 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')),
	CErr("''+x", badCharLit),
	// Produces two parse errors
	//CErr("'''", ""),
	CErr("'\n'", badCharLit),
	CErr("'\\z'", illegalEscape),
Esempio n. 15
0
package main

import (
	"bignum"
	"flag"
	"fmt"
)

var n = flag.Int("n", 27, "number of digits")
var silent = flag.Bool("s", false, "don't print result")

var (
	tmp1  *bignum.Integer
	tmp2  *bignum.Integer
	numer = bignum.Int(1)
	accum = bignum.Int(0)
	denom = bignum.Int(1)
)

func extract_digit() int64 {
	if numer.Cmp(accum) > 0 {
		return -1
	}

	// Compute (numer * 3 + accum) / denom
	tmp1 = numer.Shl(1)
	bignum.Iadd(tmp1, tmp1, numer)
	bignum.Iadd(tmp1, tmp1, accum)
	tmp1, tmp2 := tmp1.QuoRem(denom)
Esempio n. 16
0
package main

import (
	"bignum";
	"flag";
	"fmt";
)

var n = flag.Int("n", 27, "number of digits");
var silent = flag.Bool("s", false, "don't print result");

var (
	tmp1 *bignum.Integer;
	tmp2 *bignum.Integer;
	numer = bignum.Int(1);
	accum = bignum.Int(0);
	denom = bignum.Int(1);
)

func extract_digit() int64 {
	if numer.Cmp(accum) > 0 {
		return -1;
	}

	// Compute (numer * 3 + accum) / denom
	tmp1 = numer.Shl(1);
	bignum.Iadd(tmp1, tmp1, numer);
	bignum.Iadd(tmp1, tmp1, accum);
	tmp1, tmp2 := tmp1.QuoRem(denom);