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
660365e1
Commit
660365e1
authored
Dec 17, 2013
by
Damien
Browse files
py: split runtime into map, obj, builtin.
parent
a1b26931
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
py/builtin.c
0 → 100644
View file @
660365e1
#include
<stdint.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<stdarg.h>
#include
<string.h>
#include
<assert.h>
#include
"nlr.h"
#include
"misc.h"
#include
"mpyconfig.h"
#include
"runtime.h"
#include
"bc.h"
#include
"map.h"
#include
"obj.h"
#include
"objprivate.h"
#include
"builtin.h"
py_obj_t
py_builtin___repl_print__
(
py_obj_t
o
)
{
if
(
o
!=
py_const_none
)
{
py_obj_print
(
o
);
printf
(
"
\n
"
);
}
return
py_const_none
;
}
py_obj_t
py_builtin_print
(
int
n_args
,
const
py_obj_t
*
args
)
{
for
(
int
i
=
0
;
i
<
n_args
;
i
++
)
{
if
(
i
>
0
)
{
printf
(
" "
);
}
if
(
IS_O
(
args
[
i
],
O_STR
))
{
// special case, print string raw
printf
(
"%s"
,
qstr_str
(((
py_obj_base_t
*
)
args
[
i
])
->
u_str
));
}
else
{
// print the object Python style
py_obj_print
(
args
[
i
]);
}
}
printf
(
"
\n
"
);
return
py_const_none
;
}
py_obj_t
py_builtin_len
(
py_obj_t
o_in
)
{
py_small_int_t
len
=
0
;
if
(
IS_O
(
o_in
,
O_STR
))
{
py_obj_base_t
*
o
=
o_in
;
len
=
strlen
(
qstr_str
(
o
->
u_str
));
}
else
if
(
IS_O
(
o_in
,
O_TUPLE
)
||
IS_O
(
o_in
,
O_LIST
))
{
py_obj_base_t
*
o
=
o_in
;
len
=
o
->
u_tuple_list
.
len
;
}
else
if
(
IS_O
(
o_in
,
O_MAP
))
{
py_obj_base_t
*
o
=
o_in
;
len
=
o
->
u_map
.
used
;
}
else
{
assert
(
0
);
}
return
TO_SMALL_INT
(
len
);
}
py_obj_t
py_builtin_abs
(
py_obj_t
o_in
)
{
if
(
IS_SMALL_INT
(
o_in
))
{
py_small_int_t
val
=
FROM_SMALL_INT
(
o_in
);
if
(
val
<
0
)
{
val
=
-
val
;
}
return
TO_SMALL_INT
(
val
);
#if MICROPY_ENABLE_FLOAT
}
else
if
(
IS_O
(
o_in
,
O_FLOAT
))
{
py_obj_base_t
*
o
=
o_in
;
// TODO check for NaN etc
if
(
o
->
u_float
<
0
)
{
return
py_obj_new_float
(
-
o
->
u_float
);
}
else
{
return
o_in
;
}
}
else
if
(
IS_O
(
o_in
,
O_COMPLEX
))
{
py_obj_base_t
*
o
=
o_in
;
return
py_obj_new_float
(
machine_sqrt
(
o
->
u_complex
.
real
*
o
->
u_complex
.
real
+
o
->
u_complex
.
imag
*
o
->
u_complex
.
imag
));
#endif
}
else
{
assert
(
0
);
return
py_const_none
;
}
}
py_obj_t
py_builtin___build_class__
(
py_obj_t
o_class_fun
,
py_obj_t
o_class_name
)
{
// we differ from CPython: we set the new __locals__ object here
py_map_t
*
old_locals
=
rt_get_map_locals
();
py_map_t
*
class_locals
=
py_map_new
(
MAP_QSTR
,
0
);
rt_set_map_locals
(
class_locals
);
// call the class code
rt_call_function_1
(
o_class_fun
,
(
py_obj_t
)
0xdeadbeef
);
// restore old __locals__ object
rt_set_map_locals
(
old_locals
);
// create and return the new class
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_CLASS
;
o
->
u_class
.
locals
=
class_locals
;
return
o
;
}
py_obj_t
py_builtin_range
(
int
n_args
,
const
py_obj_t
*
args
)
{
switch
(
n_args
)
{
case
1
:
return
py_obj_new_range
(
0
,
py_obj_get_int
(
args
[
0
]),
1
);
case
2
:
return
py_obj_new_range
(
py_obj_get_int
(
args
[
0
]),
py_obj_get_int
(
args
[
1
]),
1
);
case
3
:
return
py_obj_new_range
(
py_obj_get_int
(
args
[
0
]),
py_obj_get_int
(
args
[
1
]),
py_obj_get_int
(
args
[
2
]));
default:
nlr_jump
(
py_obj_new_exception_2
(
rt_q_TypeError
,
"range expected at most 3 arguments, got %d"
,
(
void
*
)(
machine_int_t
)
n_args
,
NULL
));
}
}
py/builtin.h
0 → 100644
View file @
660365e1
py_obj_t
py_builtin___repl_print__
(
py_obj_t
o
);
py_obj_t
py_builtin_print
(
int
n_args
,
const
py_obj_t
*
args
);
py_obj_t
py_builtin_len
(
py_obj_t
o_in
);
py_obj_t
py_builtin_abs
(
py_obj_t
o_in
);
py_obj_t
py_builtin___build_class__
(
py_obj_t
o_class_fun
,
py_obj_t
o_class_name
);
py_obj_t
py_builtin_range
(
int
n_args
,
const
py_obj_t
*
args
);
py/map.c
0 → 100644
View file @
660365e1
#include
<stdint.h>
#include
<stdlib.h>
#include
<assert.h>
#include
"misc.h"
#include
"mpyconfig.h"
#include
"runtime.h"
#include
"map.h"
#include
"obj.h"
#include
"objprivate.h"
// approximatelly doubling primes; made with Mathematica command: Table[Prime[Floor[(1.7)^n]], {n, 3, 24}]
static
int
doubling_primes
[]
=
{
7
,
19
,
43
,
89
,
179
,
347
,
647
,
1229
,
2297
,
4243
,
7829
,
14347
,
26017
,
47149
,
84947
,
152443
,
273253
,
488399
,
869927
,
1547173
,
2745121
,
4861607
};
int
get_doubling_prime_greater_or_equal_to
(
int
x
)
{
for
(
int
i
=
0
;
i
<
sizeof
(
doubling_primes
)
/
sizeof
(
int
);
i
++
)
{
if
(
doubling_primes
[
i
]
>=
x
)
{
return
doubling_primes
[
i
];
}
}
// ran out of primes in the table!
// return something sensible, at least make it odd
return
x
|
1
;
}
void
py_map_init
(
py_map_t
*
map
,
py_map_kind_t
kind
,
int
n
)
{
map
->
kind
=
kind
;
map
->
used
=
0
;
map
->
alloc
=
get_doubling_prime_greater_or_equal_to
(
n
+
1
);
map
->
table
=
m_new0
(
py_map_elem_t
,
map
->
alloc
);
}
py_map_t
*
py_map_new
(
py_map_kind_t
kind
,
int
n
)
{
py_map_t
*
map
=
m_new
(
py_map_t
,
1
);
py_map_init
(
map
,
kind
,
n
);
return
map
;
}
py_map_elem_t
*
py_map_lookup_helper
(
py_map_t
*
map
,
py_obj_t
index
,
bool
add_if_not_found
)
{
bool
is_map_py_obj
=
(
map
->
kind
==
MAP_PY_OBJ
);
machine_uint_t
hash
;
if
(
is_map_py_obj
)
{
hash
=
py_obj_hash
(
index
);
}
else
{
hash
=
(
machine_uint_t
)
index
;
}
uint
pos
=
hash
%
map
->
alloc
;
for
(;;)
{
py_map_elem_t
*
elem
=
&
map
->
table
[
pos
];
if
(
elem
->
key
==
NULL
)
{
// not in table
if
(
add_if_not_found
)
{
if
(
map
->
used
+
1
>=
map
->
alloc
)
{
// not enough room in table, rehash it
int
old_alloc
=
map
->
alloc
;
py_map_elem_t
*
old_table
=
map
->
table
;
map
->
alloc
=
get_doubling_prime_greater_or_equal_to
(
map
->
alloc
+
1
);
map
->
used
=
0
;
map
->
table
=
m_new0
(
py_map_elem_t
,
map
->
alloc
);
for
(
int
i
=
0
;
i
<
old_alloc
;
i
++
)
{
if
(
old_table
[
i
].
key
!=
NULL
)
{
py_map_lookup_helper
(
map
,
old_table
[
i
].
key
,
true
)
->
value
=
old_table
[
i
].
value
;
}
}
m_free
(
old_table
);
// restart the search for the new element
pos
=
hash
%
map
->
alloc
;
}
else
{
map
->
used
+=
1
;
elem
->
key
=
index
;
return
elem
;
}
}
else
{
return
NULL
;
}
}
else
if
(
elem
->
key
==
index
||
(
is_map_py_obj
&&
py_obj_equal
(
elem
->
key
,
index
)))
{
// found it
/* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
if (add_if_not_found) {
elem->key = index;
}
*/
return
elem
;
}
else
{
// not yet found, keep searching in this table
pos
=
(
pos
+
1
)
%
map
->
alloc
;
}
}
}
py_map_elem_t
*
py_qstr_map_lookup
(
py_map_t
*
map
,
qstr
index
,
bool
add_if_not_found
)
{
py_obj_t
o
=
(
py_obj_t
)(
machine_uint_t
)
index
;
return
py_map_lookup_helper
(
map
,
o
,
add_if_not_found
);
}
py_map_elem_t
*
py_map_lookup
(
py_obj_t
o
,
py_obj_t
index
,
bool
add_if_not_found
)
{
assert
(
IS_O
(
o
,
O_MAP
));
return
py_map_lookup_helper
(
&
((
py_obj_base_t
*
)
o
)
->
u_map
,
index
,
add_if_not_found
);
}
py_obj_t
py_set_lookup
(
py_obj_t
o_in
,
py_obj_t
index
,
bool
add_if_not_found
)
{
assert
(
IS_O
(
o_in
,
O_SET
));
py_obj_base_t
*
o
=
o_in
;
int
hash
=
py_obj_hash
(
index
);
int
pos
=
hash
%
o
->
u_set
.
alloc
;
for
(;;)
{
py_obj_t
elem
=
o
->
u_set
.
table
[
pos
];
if
(
elem
==
NULL
)
{
// not in table
if
(
add_if_not_found
)
{
if
(
o
->
u_set
.
used
+
1
>=
o
->
u_set
.
alloc
)
{
// not enough room in table, rehash it
int
old_alloc
=
o
->
u_set
.
alloc
;
py_obj_t
*
old_table
=
o
->
u_set
.
table
;
o
->
u_set
.
alloc
=
get_doubling_prime_greater_or_equal_to
(
o
->
u_set
.
alloc
+
1
);
o
->
u_set
.
used
=
0
;
o
->
u_set
.
table
=
m_new
(
py_obj_t
,
o
->
u_set
.
alloc
);
for
(
int
i
=
0
;
i
<
old_alloc
;
i
++
)
{
if
(
old_table
[
i
]
!=
NULL
)
{
py_set_lookup
(
o
,
old_table
[
i
],
true
);
}
}
m_free
(
old_table
);
// restart the search for the new element
pos
=
hash
%
o
->
u_set
.
alloc
;
}
else
{
o
->
u_set
.
used
+=
1
;
o
->
u_set
.
table
[
pos
]
=
index
;
return
index
;
}
}
else
{
return
NULL
;
}
}
else
if
(
py_obj_equal
(
elem
,
index
))
{
// found it
return
elem
;
}
else
{
// not yet found, keep searching in this table
pos
=
(
pos
+
1
)
%
o
->
u_set
.
alloc
;
}
}
}
py/map.h
0 → 100644
View file @
660365e1
typedef
enum
{
MAP_QSTR
,
MAP_PY_OBJ
,
}
py_map_kind_t
;
typedef
struct
_py_map_elem_t
{
py_obj_t
key
;
py_obj_t
value
;
}
py_map_elem_t
;
typedef
struct
_py_map_t
{
struct
{
py_map_kind_t
kind
:
1
;
machine_uint_t
used
:
(
8
*
BYTES_PER_WORD
-
1
);
};
machine_uint_t
alloc
;
py_map_elem_t
*
table
;
}
py_map_t
;
// these are defined in runtime.c
py_map_t
*
rt_get_map_locals
(
void
);
void
rt_set_map_locals
(
py_map_t
*
m
);
int
get_doubling_prime_greater_or_equal_to
(
int
x
);
void
py_map_init
(
py_map_t
*
map
,
py_map_kind_t
kind
,
int
n
);
py_map_t
*
py_map_new
(
py_map_kind_t
kind
,
int
n
);
py_map_elem_t
*
py_map_lookup_helper
(
py_map_t
*
map
,
py_obj_t
index
,
bool
add_if_not_found
);
py_map_elem_t
*
py_qstr_map_lookup
(
py_map_t
*
map
,
qstr
index
,
bool
add_if_not_found
);
py_map_elem_t
*
py_map_lookup
(
py_obj_t
o
,
py_obj_t
index
,
bool
add_if_not_found
);
py_obj_t
py_set_lookup
(
py_obj_t
o_in
,
py_obj_t
index
,
bool
add_if_not_found
);
py/obj.c
0 → 100644
View file @
660365e1
#include
<stdint.h>
#include
<stdlib.h>
#include
<stdio.h>
#include
<stdarg.h>
#include
<assert.h>
#include
"nlr.h"
#include
"misc.h"
#include
"mpyconfig.h"
#include
"runtime.h"
#include
"map.h"
#include
"obj.h"
#include
"objprivate.h"
py_obj_t
py_obj_new_int
(
machine_int_t
value
)
{
return
TO_SMALL_INT
(
value
);
}
py_obj_t
py_obj_new_const
(
const
char
*
id
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_CONST
;
o
->
id
=
id
;
return
(
py_obj_t
)
o
;
}
py_obj_t
py_obj_new_str
(
qstr
qstr
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_STR
;
o
->
u_str
=
qstr
;
return
(
py_obj_t
)
o
;
}
#if MICROPY_ENABLE_FLOAT
py_obj_t
py_obj_new_float
(
py_float_t
val
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_FLOAT
;
o
->
u_float
=
val
;
return
(
py_obj_t
)
o
;
}
py_obj_t
py_obj_new_complex
(
py_float_t
real
,
py_float_t
imag
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_COMPLEX
;
o
->
u_complex
.
real
=
real
;
o
->
u_complex
.
imag
=
imag
;
return
(
py_obj_t
)
o
;
}
#endif
py_obj_t
py_obj_new_exception_0
(
qstr
id
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_EXCEPTION_0
;
o
->
u_exc0
.
id
=
id
;
return
(
py_obj_t
)
o
;
}
py_obj_t
py_obj_new_exception_2
(
qstr
id
,
const
char
*
fmt
,
const
char
*
s1
,
const
char
*
s2
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_EXCEPTION_N
;
o
->
u_exc_n
.
id
=
id
;
o
->
u_exc_n
.
n_args
=
3
;
o
->
u_exc_n
.
args
=
m_new
(
const
void
*
,
3
);
o
->
u_exc_n
.
args
[
0
]
=
fmt
;
o
->
u_exc_n
.
args
[
1
]
=
s1
;
o
->
u_exc_n
.
args
[
2
]
=
s2
;
return
(
py_obj_t
)
o
;
}
// range is a class and instances are immutable sequence objects
py_obj_t
py_obj_new_range
(
int
start
,
int
stop
,
int
step
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_RANGE
;
o
->
u_range
.
start
=
start
;
o
->
u_range
.
stop
=
stop
;
o
->
u_range
.
step
=
step
;
return
o
;
}
py_obj_t
py_obj_new_range_iterator
(
int
cur
,
int
stop
,
int
step
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_RANGE_IT
;
o
->
u_range_it
.
cur
=
cur
;
o
->
u_range_it
.
stop
=
stop
;
o
->
u_range_it
.
step
=
step
;
return
o
;
}
py_obj_t
py_obj_new_tuple_iterator
(
py_obj_base_t
*
tuple
,
int
cur
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_TUPLE_IT
;
o
->
u_tuple_list_it
.
obj
=
tuple
;
o
->
u_tuple_list_it
.
cur
=
cur
;
return
o
;
}
py_obj_t
py_obj_new_list_iterator
(
py_obj_base_t
*
list
,
int
cur
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_LIST_IT
;
o
->
u_tuple_list_it
.
obj
=
list
;
o
->
u_tuple_list_it
.
cur
=
cur
;
return
o
;
}
py_obj_t
py_obj_new_user
(
const
py_user_info_t
*
info
,
machine_uint_t
data1
,
machine_uint_t
data2
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_USER
;
// TODO should probably parse the info to turn strings to qstr's, and wrap functions in O_FUN_N objects
// that'll take up some memory. maybe we can lazily do the O_FUN_N: leave it a ptr to a C function, and
// only when the method is looked-up do we change that to the O_FUN_N object.
o
->
u_user
.
info
=
info
;
o
->
u_user
.
data1
=
data1
;
o
->
u_user
.
data2
=
data2
;
return
o
;
}
const
char
*
py_obj_get_type_str
(
py_obj_t
o_in
)
{
if
(
IS_SMALL_INT
(
o_in
))
{
return
"int"
;
}
else
{
py_obj_base_t
*
o
=
o_in
;
switch
(
o
->
kind
)
{
case
O_CONST
:
if
(
o
==
py_const_none
)
{
return
"NoneType"
;
}
else
{
return
"bool"
;
}
case
O_STR
:
return
"str"
;
#if MICROPY_ENABLE_FLOAT
case
O_FLOAT
:
return
"float"
;
#endif
case
O_FUN_0
:
case
O_FUN_1
:
case
O_FUN_2
:
case
O_FUN_N
:
case
O_FUN_VAR
:
case
O_FUN_BC
:
return
"function"
;
case
O_GEN_INSTANCE
:
return
"generator"
;
case
O_TUPLE
:
return
"tuple"
;
case
O_LIST
:
return
"list"
;
case
O_TUPLE_IT
:
return
"tuple_iterator"
;
case
O_LIST_IT
:
return
"list_iterator"
;
case
O_SET
:
return
"set"
;
case
O_MAP
:
return
"dict"
;
case
O_OBJ
:
{
py_map_elem_t
*
qn
=
py_qstr_map_lookup
(
o
->
u_obj
.
class
->
u_class
.
locals
,
qstr_from_str_static
(
"__qualname__"
),
false
);
assert
(
qn
!=
NULL
);
assert
(
IS_O
(
qn
->
value
,
O_STR
));
return
qstr_str
(((
py_obj_base_t
*
)
qn
->
value
)
->
u_str
);
}
case
O_USER
:
return
o
->
u_user
.
info
->
type_name
;
default:
assert
(
0
);
return
"UnknownType"
;
}
}
}
void
printf_wrapper
(
void
*
env
,
const
char
*
fmt
,
...)
{
va_list
args
;
va_start
(
args
,
fmt
);
vprintf
(
fmt
,
args
);
va_end
(
args
);
}
void
py_obj_print_helper
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
py_obj_t
o_in
)
{
if
(
IS_SMALL_INT
(
o_in
))
{
print
(
env
,
"%d"
,
(
int
)
FROM_SMALL_INT
(
o_in
));
}
else
{
py_obj_base_t
*
o
=
o_in
;
switch
(
o
->
kind
)
{
case
O_CONST
:
print
(
env
,
"%s"
,
o
->
id
);
break
;
case
O_STR
:
// TODO need to escape chars etc
print
(
env
,
"'%s'"
,
qstr_str
(
o
->
u_str
));
break
;
#if MICROPY_ENABLE_FLOAT
case
O_FLOAT
:
print
(
env
,
"%.8g"
,
o
->
u_float
);
break
;
case
O_COMPLEX
:
if
(
o
->
u_complex
.
real
==
0
)
{
print
(
env
,
"%.8gj"
,
o
->
u_complex
.
imag
);
}
else
{
print
(
env
,
"(%.8g+%.8gj)"
,
o
->
u_complex
.
real
,
o
->
u_complex
.
imag
);
}
break
;
#endif
case
O_EXCEPTION_0
:
print
(
env
,
"%s"
,
qstr_str
(
o
->
u_exc0
.
id
));
break
;
case
O_EXCEPTION_N
:
print
(
env
,
"%s: "
,
qstr_str
(
o
->
u_exc_n
.
id
));
print
(
env
,
o
->
u_exc_n
.
args
[
0
],
o
->
u_exc_n
.
args
[
1
],
o
->
u_exc_n
.
args
[
2
]);
break
;
case
O_GEN_INSTANCE
:
print
(
env
,
"<generator object 'fun-name' at %p>"
,
o
);
break
;
case
O_TUPLE
:
print
(
env
,
"("
);
for
(
int
i
=
0
;
i
<
o
->
u_tuple_list
.
len
;
i
++
)
{
if
(
i
>
0
)
{
print
(
env
,
", "
);
}
py_obj_print_helper
(
print
,
env
,
o
->
u_tuple_list
.
items
[
i
]);
}
if
(
o
->
u_tuple_list
.
len
==
1
)
{
print
(
env
,
","
);
}
print
(
env
,
")"
);
break
;
case
O_LIST
:
print
(
env
,
"["
);
for
(
int
i
=
0
;
i
<
o
->
u_tuple_list
.
len
;
i
++
)
{
if
(
i
>
0
)
{
print
(
env
,
", "
);
}
py_obj_print_helper
(
print
,
env
,
o
->
u_tuple_list
.
items
[
i
]);
}
print
(
env
,
"]"
);
break
;
case
O_SET
:
{
bool
first
=
true
;
print
(
env
,
"{"
);
for
(
int
i
=
0
;
i
<
o
->
u_set
.
alloc
;
i
++
)
{
if
(
o
->
u_set
.
table
[
i
]
!=
NULL
)
{
if
(
!
first
)
{
print
(
env
,
", "
);
}
first
=
false
;
py_obj_print_helper
(
print
,
env
,
o
->
u_set
.
table
[
i
]);
}
}
print
(
env
,
"}"
);
break
;
}
case
O_MAP
:
{
bool
first
=
true
;
print
(
env
,
"{"
);
for
(
int
i
=
0
;
i
<
o
->
u_map
.
alloc
;
i
++
)
{
if
(
o
->
u_map
.
table
[
i
].
key
!=
NULL
)
{
if
(
!
first
)
{
print
(
env
,
", "
);
}
first
=
false
;
py_obj_print_helper
(
print
,
env
,
o
->
u_map
.
table
[
i
].
key
);
print
(
env
,
": "
);
py_obj_print_helper
(
print
,
env
,
o
->
u_map
.
table
[
i
].
value
);
}
}
print
(
env
,
"}"
);
break
;
}
case
O_USER
:
if
(
o
->
u_user
.
info
->
print
==
NULL
)
{
print
(
env
,
"<unknown user object>"
);
}
else
{
o
->
u_user
.
info
->
print
(
o_in
);
}
break
;
default:
print
(
env
,
"<? %d>"
,
o
->
kind
);
assert
(
0
);
}
}
}
void
py_obj_print
(
py_obj_t
o_in
)
{
py_obj_print_helper
(
printf_wrapper
,
NULL
,
o_in
);
}
bool
py_obj_is_callable
(
py_obj_t
o_in
)
{
if
(
IS_SMALL_INT
(
o_in
))
{
return
false
;
}
else
{
py_obj_base_t
*
o
=
o_in
;
switch
(
o
->
kind
)
{
case
O_FUN_0
:
case
O_FUN_1
:
case
O_FUN_2
:
case
O_FUN_VAR
:
case
O_FUN_N
:
case
O_FUN_BC
:
case
O_FUN_ASM
:
// what about O_CLASS, and an O_OBJ that has a __call__ method?
return
true
;
default:
return
false
;
}
}
}
machine_int_t
py_obj_hash
(
py_obj_t
o_in
)
{
if
(
o_in
==
py_const_false
)
{
return
0
;
// needs to hash to same as the integer 0, since False==0
}
else
if
(
o_in
==
py_const_true
)
{
return
1
;
// needs to hash to same as the integer 1, since True==1
}
else
if
(
IS_SMALL_INT
(
o_in
))
{
return
FROM_SMALL_INT
(
o_in
);
}
else
if
(
IS_O
(
o_in
,
O_CONST
))
{
return
(
machine_int_t
)
o_in
;
}
else
if
(
IS_O
(
o_in
,
O_STR
))
{
return
((
py_obj_base_t
*
)
o_in
)
->
u_str
;
}
else
{