// number = int_lit [ "p" int_lit ] . // func (p *gcParser) parseNumber() (x operand) { x.mode = constant // mantissa mant := exact.MakeFromLiteral(p.parseInt(), token.INT) assert(mant != nil) if p.lit == "p" { // exponent (base 2) p.next() exp, err := strconv.ParseInt(p.parseInt(), 10, 0) if err != nil { p.error(err) } if exp < 0 { denom := exact.MakeInt64(1) denom = exact.Shift(denom, token.SHL, uint(-exp)) x.typ = Typ[UntypedFloat] x.val = exact.BinaryOp(mant, token.QUO, denom) return } if exp > 0 { mant = exact.Shift(mant, token.SHL, uint(exp)) } x.typ = Typ[UntypedFloat] x.val = mant return } x.typ = Typ[UntypedInt] x.val = mant return }
// number = int_lit [ "p" int_lit ] . // func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) { // mantissa mant := exact.MakeFromLiteral(p.parseInt(), token.INT) if mant == nil { panic("invalid mantissa") } if p.lit == "p" { // exponent (base 2) p.next() exp, err := strconv.ParseInt(p.parseInt(), 10, 0) if err != nil { p.error(err) } if exp < 0 { denom := exact.MakeInt64(1) denom = exact.Shift(denom, token.SHL, uint(-exp)) typ = types.Typ[types.UntypedFloat] val = exact.BinaryOp(mant, token.QUO, denom) return } if exp > 0 { mant = exact.Shift(mant, token.SHL, uint(exp)) } typ = types.Typ[types.UntypedFloat] val = mant return } typ = types.Typ[types.UntypedInt] val = mant return }
func (p *importer) ufloat() exact.Value { exp := p.int() x := exact.MakeFromBytes(p.bytes()) switch { case exp < 0: d := exact.Shift(exact.MakeInt64(1), token.SHL, uint(-exp)) x = exact.BinaryOp(x, token.QUO, d) case exp > 0: x = exact.Shift(x, token.SHL, uint(exp)) } return x }
func doOp(x exact.Value, op token.Token, y exact.Value) (z exact.Value) { defer panicHandler(&z) if x == nil { return exact.UnaryOp(op, y, -1) } switch op { case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: return exact.MakeBool(exact.Compare(x, op, y)) case token.SHL, token.SHR: s, _ := exact.Int64Val(y) return exact.Shift(x, op, uint(s)) default: return exact.BinaryOp(x, op, y) } }
func evalAction(n ast.Node) exact.Value { switch e := n.(type) { case *ast.BasicLit: return val(e.Value) case *ast.BinaryExpr: x := evalAction(e.X) if x == nil { return nil } y := evalAction(e.Y) if y == nil { return nil } switch e.Op { case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GTR, token.GEQ: return exact.MakeBool(exact.Compare(x, e.Op, y)) case token.SHL, token.SHR: s, _ := exact.Int64Val(y) return exact.Shift(x, e.Op, uint(s)) default: return exact.BinaryOp(x, e.Op, y) } case *ast.UnaryExpr: return exact.UnaryOp(e.Op, evalAction(e.X), -1) case *ast.CallExpr: fmt.Printf("Can't handle call (%s) yet at pos %d\n", e.Fun, e.Pos()) return nil case *ast.Ident: fmt.Printf("Can't handle Ident %s here at pos %d\n", e.Name, e.Pos()) return nil case *ast.ParenExpr: return evalAction(e.X) default: fmt.Println("Can't handle") fmt.Printf("n: %s, e: %s\n", n, e) return nil } }
func (check *Checker) shift(x, y *operand, op token.Token) { untypedx := isUntyped(x.typ) // The lhs must be of integer type or be representable // as an integer; otherwise the shift has no chance. if !isInteger(x.typ) && (!untypedx || !representableConst(x.val, nil, UntypedInt, nil)) { check.invalidOp(x.pos(), "shifted operand %s must be integer", x) x.mode = invalid return } // spec: "The right operand in a shift expression must have unsigned // integer type or be an untyped constant that can be converted to // unsigned integer type." switch { case isInteger(y.typ) && isUnsigned(y.typ): // nothing to do case isUntyped(y.typ): check.convertUntyped(y, Typ[UntypedInt]) if y.mode == invalid { x.mode = invalid return } default: check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y) x.mode = invalid return } if x.mode == constant { if y.mode == constant { // rhs must be within reasonable bounds const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64 s, ok := exact.Uint64Val(y.val) if !ok || s > stupidShift { check.invalidOp(y.pos(), "stupid shift count %s", y) x.mode = invalid return } // The lhs is representable as an integer but may not be an integer // (e.g., 2.0, an untyped float) - this can only happen for untyped // non-integer numeric constants. Correct the type so that the shift // result is of integer type. if !isInteger(x.typ) { x.typ = Typ[UntypedInt] } x.val = exact.Shift(x.val, op, uint(s)) return } // non-constant shift with constant lhs if untypedx { // spec: "If the left operand of a non-constant shift // expression is an untyped constant, the type of the // constant is what it would be if the shift expression // were replaced by its left operand alone.". // // Delay operand checking until we know the final type: // The lhs expression must be in the untyped map, mark // the entry as lhs shift operand. info, found := check.untyped[x.expr] assert(found) info.isLhs = true check.untyped[x.expr] = info // keep x's type x.mode = value return } } // constant rhs must be >= 0 if y.mode == constant && exact.Sign(y.val) < 0 { check.invalidOp(y.pos(), "shift count %s must not be negative", y) } // non-constant shift - lhs must be an integer if !isInteger(x.typ) { check.invalidOp(x.pos(), "shifted operand %s must be integer", x) x.mode = invalid return } x.mode = value }