diff --git a/builtin/builtin.go b/builtin/builtin.go index 8ffda37d..bb4158c4 100644 --- a/builtin/builtin.go +++ b/builtin/builtin.go @@ -6,6 +6,8 @@ package builtin import ( + "fmt" + "math/big" "unicode/utf8" "github.com/go-python/gpython/compile" @@ -25,7 +27,7 @@ func init() { py.MustNewMethod("all", builtin_all, 0, all_doc), py.MustNewMethod("any", builtin_any, 0, any_doc), py.MustNewMethod("ascii", builtin_ascii, 0, ascii_doc), - // py.MustNewMethod("bin", builtin_bin, 0, bin_doc), + py.MustNewMethod("bin", builtin_bin, 0, bin_doc), // py.MustNewMethod("callable", builtin_callable, 0, callable_doc), py.MustNewMethod("chr", builtin_chr, 0, chr_doc), py.MustNewMethod("compile", builtin_compile, 0, compile_doc), @@ -309,7 +311,12 @@ func builtin_any(self, seq py.Object) (py.Object, error) { return py.False, nil } -const ascii_doc = ` +const ascii_doc = `Return an ASCII-only representation of an object. + +As repr(), return a string containing a printable representation of an +object, but escape the non-ASCII characters in the string returned by +repr() using \\x, \\u or \\U escapes. This generates a string similar +to that returned by repr() in Python 2. ` func builtin_ascii(self, o py.Object) (py.Object, error) { @@ -322,6 +329,29 @@ func builtin_ascii(self, o py.Object) (py.Object, error) { return py.String(out), err } +const bin_doc = `Return the binary representation of an integer. + +>>> bin(2796202) +'0b1010101010101010101010' +` + +func builtin_bin(self, o py.Object) (py.Object, error) { + bigint, ok := py.ConvertToBigInt(o) + if !ok { + return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", o.Type().Name) + } + + value := (*big.Int)(bigint) + var out string + if value.Sign() < 0 { + value = new(big.Int).Abs(value) + out = fmt.Sprintf("-0b%b", value) + } else { + out = fmt.Sprintf("0b%b", value) + } + return py.String(out), nil +} + const round_doc = `round(number[, ndigits]) -> number Round a number to a given precision in decimal digits (default 0 digits). diff --git a/builtin/tests/builtin.py b/builtin/tests/builtin.py index 0b547f3f..88cc38c2 100644 --- a/builtin/tests/builtin.py +++ b/builtin/tests/builtin.py @@ -25,6 +25,19 @@ assert ascii(chr(0x10001)) == "'\\U00010001'" assert ascii('안녕 gpython') == "'\\uc548\\ub155 gpython'" +doc="bin" +assert bin(False) == '0b0' +assert bin(True) == '0b1' +assert bin(0) == '0b0' +assert bin(1) == '0b1' +assert bin(-1) == '-0b1' +assert bin(10) == '0b1010' +assert bin(-10) == '-0b1010' +assert bin(2**32) == '0b100000000000000000000000000000000' +assert bin(2**32-1) == '0b11111111111111111111111111111111' +assert bin(-(2**32)) == '-0b100000000000000000000000000000000' +assert bin(-(2**32-1)) == '-0b11111111111111111111111111111111' + doc="chr" assert chr(65) == "A" assert chr(163) == "£" diff --git a/py/bigint.go b/py/bigint.go index b5e3ef36..0b72804c 100644 --- a/py/bigint.go +++ b/py/bigint.go @@ -66,7 +66,7 @@ func BigIntCheck(obj Object) (*BigInt, error) { // Convert an Object to an BigInt // // Retrurns ok as to whether the conversion worked or not -func convertToBigInt(other Object) (*BigInt, bool) { +func ConvertToBigInt(other Object) (*BigInt, bool) { switch b := other.(type) { case Int: return (*BigInt)(big.NewInt(int64(b))), true @@ -173,7 +173,7 @@ func (a *BigInt) M__invert__() (Object, error) { } func (a *BigInt) M__add__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).Add((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil } return NotImplemented, nil @@ -188,14 +188,14 @@ func (a *BigInt) M__iadd__(other Object) (Object, error) { } func (a *BigInt) M__sub__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).Sub((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil } return NotImplemented, nil } func (a *BigInt) M__rsub__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).Sub((*big.Int)(b), (*big.Int)(a))).MaybeInt(), nil } return NotImplemented, nil @@ -206,7 +206,7 @@ func (a *BigInt) M__isub__(other Object) (Object, error) { } func (a *BigInt) M__mul__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).Mul((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil } return NotImplemented, nil @@ -306,14 +306,14 @@ func (a *BigInt) divMod(b *BigInt) (Object, Object, error) { } func (a *BigInt) M__divmod__(other Object) (Object, Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return a.divMod(b) } return NotImplemented, NotImplemented, nil } func (a *BigInt) M__rdivmod__(other Object) (Object, Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return b.divMod(a) } return NotImplemented, NotImplemented, nil @@ -343,18 +343,18 @@ func (a *BigInt) M__pow__(other, modulus Object) (Object, error) { var m *BigInt if modulus != None { var ok bool - if m, ok = convertToBigInt(modulus); !ok { + if m, ok = ConvertToBigInt(modulus); !ok { return NotImplemented, nil } } - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return a.pow(b, m) } return NotImplemented, nil } func (a *BigInt) M__rpow__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return b.pow(a, nil) } return NotImplemented, nil @@ -365,7 +365,7 @@ func (a *BigInt) M__ipow__(other, modulus Object) (Object, error) { } func (a *BigInt) M__lshift__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { bb, err := b.GoInt() if err != nil { return nil, err @@ -379,7 +379,7 @@ func (a *BigInt) M__lshift__(other Object) (Object, error) { } func (a *BigInt) M__rlshift__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { aa, err := a.GoInt() if err != nil { return nil, err @@ -397,7 +397,7 @@ func (a *BigInt) M__ilshift__(other Object) (Object, error) { } func (a *BigInt) M__rshift__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { bb, err := b.GoInt() if err != nil { return nil, err @@ -411,7 +411,7 @@ func (a *BigInt) M__rshift__(other Object) (Object, error) { } func (a *BigInt) M__rrshift__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { aa, err := a.GoInt() if err != nil { return nil, err @@ -429,7 +429,7 @@ func (a *BigInt) M__irshift__(other Object) (Object, error) { } func (a *BigInt) M__and__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).And((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil } return NotImplemented, nil @@ -444,7 +444,7 @@ func (a *BigInt) M__iand__(other Object) (Object, error) { } func (a *BigInt) M__xor__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).Xor((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil } return NotImplemented, nil @@ -459,7 +459,7 @@ func (a *BigInt) M__ixor__(other Object) (Object, error) { } func (a *BigInt) M__or__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return (*BigInt)(new(big.Int).Or((*big.Int)(a), (*big.Int)(b))).MaybeInt(), nil } return NotImplemented, nil @@ -498,7 +498,7 @@ func (a *BigInt) M__complex__() (Object, error) { } func (a *BigInt) M__round__(digits Object) (Object, error) { - if b, ok := convertToBigInt(digits); ok { + if b, ok := ConvertToBigInt(digits); ok { if (*big.Int)(b).Sign() >= 0 { return a, nil } @@ -528,42 +528,42 @@ func (a *BigInt) M__round__(digits Object) (Object, error) { // Rich comparison func (a *BigInt) M__lt__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) < 0), nil } return NotImplemented, nil } func (a *BigInt) M__le__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) <= 0), nil } return NotImplemented, nil } func (a *BigInt) M__eq__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) == 0), nil } return NotImplemented, nil } func (a *BigInt) M__ne__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) != 0), nil } return NotImplemented, nil } func (a *BigInt) M__gt__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) > 0), nil } return NotImplemented, nil } func (a *BigInt) M__ge__(other Object) (Object, error) { - if b, ok := convertToBigInt(other); ok { + if b, ok := ConvertToBigInt(other); ok { return NewBool((*big.Int)(a).Cmp((*big.Int)(b)) >= 0), nil } return NotImplemented, nil diff --git a/version.go b/version.go index 857ae35d..4a74e91b 100644 --- a/version.go +++ b/version.go @@ -8,4 +8,4 @@ var ( version = "dev" commit = "none" date = "unknown" -) \ No newline at end of file +)