Skip to content

Commit 93edaf3

Browse files
sbinetncw
authored andcommitted
builtin,vm: add implementation for builtin hex function
1 parent b0a0efb commit 93edaf3

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

builtin/builtin.go

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func init() {
4141
py.MustNewMethod("globals", py.InternalMethodGlobals, 0, globals_doc),
4242
py.MustNewMethod("hasattr", builtin_hasattr, 0, hasattr_doc),
4343
// py.MustNewMethod("hash", builtin_hash, 0, hash_doc),
44-
// py.MustNewMethod("hex", builtin_hex, 0, hex_doc),
44+
py.MustNewMethod("hex", builtin_hex, 0, hex_doc),
4545
// py.MustNewMethod("id", builtin_id, 0, id_doc),
4646
// py.MustNewMethod("input", builtin_input, 0, input_doc),
4747
py.MustNewMethod("isinstance", builtin_isinstance, 0, isinstance_doc),
@@ -826,6 +826,52 @@ object.
826826
The globals and locals are dictionaries, defaulting to the current
827827
globals and locals. If only globals is given, locals defaults to it.`
828828

829+
const hex_doc = `hex(number) -> string
830+
831+
Return the hexadecimal representation of an integer.
832+
833+
>>> hex(12648430)
834+
'0xc0ffee'
835+
`
836+
837+
func builtin_hex(self, v py.Object) (py.Object, error) {
838+
var (
839+
i int64
840+
err error
841+
)
842+
switch v := v.(type) {
843+
case *py.BigInt:
844+
// test bigint first to make sure we correctly handle the case
845+
// where int64 isn't large enough.
846+
vv := (*big.Int)(v)
847+
format := "%#x"
848+
if vv.Cmp(big.NewInt(0)) == -1 {
849+
format = "%+#x"
850+
}
851+
str := fmt.Sprintf(format, vv)
852+
return py.String(str), nil
853+
case py.IGoInt64:
854+
i, err = v.GoInt64()
855+
case py.IGoInt:
856+
var vv int
857+
vv, err = v.GoInt()
858+
i = int64(vv)
859+
default:
860+
return nil, py.ExceptionNewf(py.TypeError, "'%s' object cannot be interpreted as an integer", v.Type().Name)
861+
}
862+
863+
if err != nil {
864+
return nil, err
865+
}
866+
867+
format := "%#x"
868+
if i < 0 {
869+
format = "%+#x"
870+
}
871+
str := fmt.Sprintf(format, i)
872+
return py.String(str), nil
873+
}
874+
829875
const isinstance_doc = `isinstance(obj, class_or_tuple) -> bool
830876
831877
Return whether an object is an instance of a class or of a subclass thereof.

vm/tests/builtin.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@
6666
else:
6767
assert False, "SyntaxError not raised"
6868

69+
doc="hex"
70+
assert True, hex( 0)=="0x0"
71+
assert True, hex( 1)=="0x1"
72+
assert True, hex(42)=="0x2a"
73+
assert True, hex( -0)=="0x0"
74+
assert True, hex( -1)=="-0x1"
75+
assert True, hex(-42)=="-0x2a"
76+
assert True, hex( 1<<64) == "0x10000000000000000"
77+
assert True, hex(-1<<64) == "-0x10000000000000000"
78+
assert True, hex( 1<<128) == "0x100000000000000000000000000000000"
79+
assert True, hex(-1<<128) == "-0x100000000000000000000000000000000"
80+
assertRaises(TypeError, hex, 10.0) ## TypeError: 'float' object cannot be interpreted as an integer
81+
assertRaises(TypeError, hex, float(0)) ## TypeError: 'float' object cannot be interpreted as an integer
82+
6983
doc="isinstance"
7084
class A:
7185
pass

0 commit comments

Comments
 (0)