Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
ec3e14e2
Commit
ec3e14e2
authored
Jan 12, 2014
by
Damien George
Browse files
Merge pull request #160 from pfalcon/elaborate-int
Elaborate small-int/long-int
parents
45eb6eaa
48b3572f
Changes
7
Hide whitespace changes
Inline
Side-by-side
py/gc.c
View file @
ec3e14e2
...
...
@@ -8,15 +8,8 @@
#if MICROPY_ENABLE_GC
// a machine word is big enough to hold a pointer
/*
#define BYTES_PER_WORD (8)
typedef unsigned long machine_uint_t;
*/
typedef
unsigned
char
byte
;
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
#define WORDS_PER_BLOCK (4)
#define BYTES_PER_BLOCK (WORDS_PER_BLOCK * BYTES_PER_WORD)
#define STACK_SIZE (64) // tunable; minimum is 1
...
...
py/mpconfig.h
View file @
ec3e14e2
...
...
@@ -62,6 +62,18 @@
#define MICROPY_ENABLE_LEXER_UNIX (0)
#endif
// Long int implementation
#define MICROPY_LONGINT_IMPL_NONE (0)
#define MICROPY_LONGINT_IMPL_LONGLONG (1)
#ifndef MICROPY_LONGINT_IMPL
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#endif
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
typedef
long
long
mp_longint_impl_t
;
#endif
// Whether to support float and complex types
#ifndef MICROPY_ENABLE_FLOAT
#define MICROPY_ENABLE_FLOAT (0)
...
...
@@ -76,6 +88,11 @@
/*****************************************************************************/
/* Miscellaneous settings */
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
// machine_int_t value with most significant bit set
#define WORD_MSBIT_HIGH (1 << (BYTES_PER_WORD * 8 - 1))
// printf format spec to use for machine_int_t and friends
#ifndef INT_FMT
#ifdef __LP64__
...
...
py/obj.h
View file @
ec3e14e2
...
...
@@ -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)
...
...
@@ -196,6 +198,8 @@ mp_obj_t mp_obj_new_none(void);
mp_obj_t
mp_obj_new_bool
(
bool
value
);
mp_obj_t
mp_obj_new_cell
(
mp_obj_t
obj
);
mp_obj_t
mp_obj_new_int
(
machine_int_t
value
);
mp_obj_t
mp_obj_new_int_from_uint
(
machine_uint_t
value
);
mp_obj_t
mp_obj_new_int_from_long_str
(
const
char
*
s
);
mp_obj_t
mp_obj_new_str
(
qstr
qstr
);
#if MICROPY_ENABLE_FLOAT
mp_obj_t
mp_obj_new_float
(
mp_float_t
val
);
...
...
py/objint.c
View file @
ec3e14e2
...
...
@@ -11,8 +11,16 @@
typedef
struct
_mp_obj_int_t
{
mp_obj_base_t
base
;
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
mp_longint_impl_t
val
;
#endif
}
mp_obj_int_t
;
void
int_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
);
mp_obj_t
int_binary_op
(
int
op
,
mp_obj_t
lhs_in
,
mp_obj_t
rhs_in
);
// This dispatcher function is expected to be independent of the implementation
// of long int
static
mp_obj_t
int_make_new
(
mp_obj_t
type_in
,
int
n_args
,
const
mp_obj_t
*
args
)
{
switch
(
n_args
)
{
case
0
:
...
...
@@ -20,7 +28,7 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
case
1
:
// TODO allow string as arg and parse it
return
MP_OBJ_NEW_SMALL_INT
(
mp_obj_get_int
(
args
[
0
]));
return
mp_obj_new_int
(
mp_obj_get_int
(
args
[
0
]));
//case 2:
// TODO, parse with given base
...
...
@@ -33,9 +41,41 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
const
mp_obj_type_t
int_type
=
{
{
&
mp_const_type
},
"int"
,
.
print
=
int_print
,
.
make_new
=
int_make_new
,
.
binary_op
=
int_binary_op
,
};
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
// This is called only for non-SMALL_INT
void
int_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
)
{
}
// This is called only for non-SMALL_INT
mp_obj_t
int_binary_op
(
int
op
,
mp_obj_t
lhs_in
,
mp_obj_t
rhs_in
)
{
assert
(
0
);
}
// This is called only with strings whose value doesn't fit in SMALL_INT
mp_obj_t
mp_obj_new_int_from_long_str
(
const
char
*
s
)
{
assert
(
0
);
}
mp_obj_t
mp_obj_new_int_from_uint
(
machine_uint_t
value
)
{
// SMALL_INT accepts only signed numbers, of one bit less size
// then word size, which totals 2 bits less for unsigned numbers.
if
((
value
&
(
WORD_MSBIT_HIGH
|
(
WORD_MSBIT_HIGH
>>
1
)))
==
0
)
{
return
MP_OBJ_NEW_SMALL_INT
(
value
);
}
// TODO: Raise exception
assert
(
0
);
}
mp_obj_t
mp_obj_new_int
(
machine_int_t
value
)
{
return
MP_OBJ_NEW_SMALL_INT
(
value
);
if
(
MP_OBJ_FITS_SMALL_INT
(
value
))
{
return
MP_OBJ_NEW_SMALL_INT
(
value
);
}
// TODO: Raise exception
assert
(
0
);
}
#endif
py/parse.c
View file @
ec3e14e2
...
...
@@ -196,7 +196,7 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
}
else
if
(
tok
->
kind
==
MP_TOKEN_NUMBER
)
{
bool
dec
=
false
;
bool
small_int
=
true
;
in
t
int_val
=
0
;
machine_int_
t
int_val
=
0
;
int
len
=
tok
->
len
;
const
char
*
str
=
tok
->
str
;
int
base
=
10
;
...
...
@@ -216,7 +216,9 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
i
=
2
;
}
}
bool
overflow
=
false
;
for
(;
i
<
len
;
i
++
)
{
machine_int_t
old_val
=
int_val
;
if
(
unichar_isdigit
(
str
[
i
])
&&
str
[
i
]
-
'0'
<
base
)
{
int_val
=
base
*
int_val
+
str
[
i
]
-
'0'
;
}
else
if
(
base
==
16
&&
'a'
<=
str
[
i
]
&&
str
[
i
]
<=
'f'
)
{
...
...
@@ -230,10 +232,17 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
small_int
=
false
;
break
;
}
if
(
int_val
<
old_val
)
{
// If new value became less than previous, it's overflow
overflow
=
true
;
}
else
if
((
old_val
^
int_val
)
&
WORD_MSBIT_HIGH
)
{
// If signed number changed sign - it's overflow
overflow
=
true
;
}
}
if
(
dec
)
{
pn
=
mp_parse_node_new_leaf
(
MP_PARSE_NODE_DECIMAL
,
qstr_from_strn_copy
(
str
,
len
));
}
else
if
(
small_int
&&
MP_FIT_SMALL_INT
(
int_val
))
{
}
else
if
(
small_int
&&
!
overflow
&&
MP_FIT_SMALL_INT
(
int_val
))
{
pn
=
mp_parse_node_new_leaf
(
MP_PARSE_NODE_SMALL_INT
,
int_val
);
}
else
{
pn
=
mp_parse_node_new_leaf
(
MP_PARSE_NODE_INTEGER
,
qstr_from_strn_copy
(
str
,
len
));
...
...
py/runtime.c
View file @
ec3e14e2
...
...
@@ -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
))
{
...
...
tests/basics/tests/int-small.py
0 → 100644
View file @
ec3e14e2
# 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
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment