From eae16445d5f6ca4bcd693422fc93ccf4fd7e215e Mon Sep 17 00:00:00 2001 From: Damien George Date: Sat, 11 Jan 2014 19:22:29 +0000 Subject: py: Implement staticmethod and classmethod (internally). Still need to make built-ins by these names, and write tests. --- py/runtime.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'py/runtime.c') diff --git a/py/runtime.c b/py/runtime.c index 29571a44b8..409d1d8262 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -774,12 +774,25 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { dest[0] = base; } else { // generic method lookup + // this is a lookup in the object (ie not class or type) const mp_method_t *meth = type->methods; if (meth != NULL) { for (; meth->name != NULL; meth++) { if (strcmp(meth->name, qstr_str(attr)) == 0) { - dest[1] = (mp_obj_t)meth->fun; - dest[0] = base; + // check if the methods are functions, static or class methods + // see http://docs.python.org/3.3/howto/descriptor.html + if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_staticmethod)) { + // return just the function + dest[1] = ((mp_obj_staticmethod_t*)meth->fun)->fun; + } else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) { + // return a bound method, with self being the type of this object + dest[1] = ((mp_obj_classmethod_t*)meth->fun)->fun; + dest[0] = mp_obj_get_type(base); + } else { + // return a bound method, with self being this object + dest[1] = (mp_obj_t)meth->fun; + dest[0] = base; + } break; } } -- cgit v1.2.3 From b81e1fdef742675b1e285df80c39159f0bdbf90b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 11 Jan 2014 16:33:32 +0200 Subject: Add AssertionError. --- py/emitpass1.c | 5 +---- py/runtime.c | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'py/runtime.c') diff --git a/py/emitpass1.c b/py/emitpass1.c index 2f0ecac86d..60fdd0b825 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -45,10 +45,7 @@ static void emit_pass1_load_id(emit_t *emit, qstr qstr) { bool added; id_info_t *id = scope_find_or_add_id(emit->scope, qstr, &added); if (added) { - if (qstr == MP_QSTR_AssertionError) { - // TODO how much of a hack is this? - id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; - } else if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) { + if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) { // special case, super is a global, and also counts as use of __class__ id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT; id_info_t *id2 = scope_find_local_in_parent(emit->scope, emit->qstr___class__); diff --git a/py/runtime.c b/py/runtime.c index 409d1d8262..44eb79518a 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -90,6 +90,7 @@ void rt_init(void) { mp_map_add_qstr(&map_builtins, MP_QSTR_SyntaxError, mp_obj_new_exception(MP_QSTR_SyntaxError)); mp_map_add_qstr(&map_builtins, MP_QSTR_ValueError, mp_obj_new_exception(MP_QSTR_ValueError)); mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError)); + mp_map_add_qstr(&map_builtins, MP_QSTR_AssertionError, mp_obj_new_exception(MP_QSTR_AssertionError)); // built-in objects mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis); -- cgit v1.2.3 From 729e9cce7bd31d3f107a4d6e9498b0fa27119e22 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 11 Jan 2014 21:12:15 +0200 Subject: rt_binary_op(): Don't fall thru in case small_int op result doesn't fit back. Currently it would report "operation not supported" which is confusing. Overall, this is thinko leading to undefined behavior. --- py/runtime.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'py/runtime.c') diff --git a/py/runtime.c b/py/runtime.c index 409d1d8262..b982ee32d0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -553,6 +553,8 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { if (fit_small_int(lhs_val)) { return MP_OBJ_NEW_SMALL_INT(lhs_val); } + // TODO: return long int + assert(0); } else if (MP_OBJ_IS_TYPE(rhs, &float_type)) { return mp_obj_float_binary_op(op, lhs_val, rhs); } else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) { -- cgit v1.2.3 From 757ac81a69cc2143a6b170367b18c75ac60249e4 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 12 Jan 2014 17:06:25 +0200 Subject: Add proper checks for fits-in-small-int. Make it reusable. We likely should make mp_obj_new_int() inline, and rely on its encapsulated check rather than inline checks everywhere explicitly. Also, parser for big small int values is still broken. --- py/obj.h | 2 ++ py/runtime.c | 17 +++++------------ tests/basics/tests/int-small.py | 26 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 tests/basics/tests/int-small.py (limited to 'py/runtime.c') diff --git a/py/obj.h b/py/obj.h index b92f1e2a7e..5a104d703c 100644 --- a/py/obj.h +++ b/py/obj.h @@ -34,6 +34,8 @@ typedef struct _mp_obj_base_t mp_obj_base_t; // - xxxx...xx10: a qstr, bits 2 and above are the value // - xxxx...xx00: a pointer to an mp_obj_base_t +// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range +#define MP_OBJ_FITS_SMALL_INT(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0) #define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0) #define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2) #define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0) diff --git a/py/runtime.c b/py/runtime.c index 8d3e900286..2af86b6abd 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -268,10 +268,6 @@ void rt_assign_inline_asm_code(int unique_code_id, void *fun, uint len, int n_ar #endif } -static bool fit_small_int(mp_small_int_t o) { - return true; -} - int rt_is_true(mp_obj_t arg) { DEBUG_OP_printf("is true %p\n", arg); if (MP_OBJ_IS_SMALL_INT(arg)) { @@ -436,13 +432,10 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) { case RT_UNARY_OP_INVERT: val = ~val; break; default: assert(0); val = 0; } - if (fit_small_int(val)) { + if (MP_OBJ_FITS_SMALL_INT(val)) { return MP_OBJ_NEW_SMALL_INT(val); - } else { - // TODO make a bignum - assert(0); - return mp_const_none; } + return mp_obj_new_int(val); } else { // will be an object (small ints are caught in previous if) mp_obj_base_t *o = arg; if (o->type->unary_op != NULL) { @@ -551,11 +544,11 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { default: assert(0); } - if (fit_small_int(lhs_val)) { + // TODO: We just should make mp_obj_new_int() inline and use that + if (MP_OBJ_FITS_SMALL_INT(lhs_val)) { return MP_OBJ_NEW_SMALL_INT(lhs_val); } - // TODO: return long int - assert(0); + return mp_obj_new_int(lhs_val); } else if (MP_OBJ_IS_TYPE(rhs, &float_type)) { return mp_obj_float_binary_op(op, lhs_val, rhs); } else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) { diff --git a/tests/basics/tests/int-small.py b/tests/basics/tests/int-small.py new file mode 100644 index 0000000000..be338c4a4c --- /dev/null +++ b/tests/basics/tests/int-small.py @@ -0,0 +1,26 @@ +# This test small int range for 32-bit machine + +a = 0x3fffff +print(a) +a *= 0x10 +print(a) +a *= 0x10 +print(a) +a += 0xff +print(a) +# This would overflow +#a += 1 + +a = -0x3fffff +print(a) +a *= 0x10 +print(a) +a *= 0x10 +print(a) +a -= 0xff +print(a) +# This still doesn't overflow +a -= 1 +print(a) +# This would overflow +#a -= 1 -- cgit v1.2.3