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
c226dca1
Commit
c226dca1
authored
Oct 16, 2013
by
Damien
Browse files
Support tuples and list comprehension, albeit crude.
parent
152568bc
Changes
3
Hide whitespace changes
Inline
Side-by-side
py/runtime.c
View file @
c226dca1
// in principle, rt_xxx functions are called only by vm/native/viper and make assumptions about args
// py_xxx functions are safer and can be called by anyone
#include
<stdint.h>
#include
<stdlib.h>
#include
<stdio.h>
...
...
@@ -48,7 +51,10 @@ typedef enum {
O_FUN_BC
,
O_FUN_ASM
,
O_BOUND_METH
,
O_TUPLE
,
O_LIST
,
O_TUPLE_IT
,
O_LIST_IT
,
O_SET
,
O_MAP
,
O_CLASS
,
...
...
@@ -121,11 +127,15 @@ struct _py_obj_base_t {
py_obj_t
meth
;
py_obj_t
self
;
}
u_bound_meth
;
struct
{
// for O_LIST
struct
{
// for
O_TUPLE,
O_LIST
int
alloc
;
int
len
;
py_obj_t
*
items
;
}
u_list
;
}
u_tuple_list
;
struct
{
// for O_TUPLE_IT, O_LIST_IT
py_obj_base_t
*
obj
;
int
cur
;
}
u_tuple_list_it
;
struct
{
// for O_SET
int
alloc
;
int
used
;
...
...
@@ -330,14 +340,30 @@ py_obj_t py_obj_new_range_iterator(int cur, int stop, int step) {
return
o
;
}
py_obj_t
list_append
(
py_obj_t
self_in
,
py_obj_t
arg
)
{
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
rt_list_append
(
py_obj_t
self_in
,
py_obj_t
arg
)
{
assert
(
IS_O
(
self_in
,
O_LIST
));
py_obj_base_t
*
self
=
self_in
;
if
(
self
->
u_list
.
len
>=
self
->
u_list
.
alloc
)
{
self
->
u_list
.
alloc
*=
2
;
self
->
u_list
.
items
=
m_renew
(
py_obj_t
,
self
->
u_list
.
items
,
self
->
u_list
.
alloc
);
if
(
self
->
u_
tuple_
list
.
len
>=
self
->
u_
tuple_
list
.
alloc
)
{
self
->
u_
tuple_
list
.
alloc
*=
2
;
self
->
u_
tuple_
list
.
items
=
m_renew
(
py_obj_t
,
self
->
u_
tuple_
list
.
items
,
self
->
u_
tuple_
list
.
alloc
);
}
self
->
u_list
.
items
[
self
->
u_list
.
len
++
]
=
arg
;
self
->
u_
tuple_
list
.
items
[
self
->
u_
tuple_
list
.
len
++
]
=
arg
;
return
arg
;
}
...
...
@@ -346,6 +372,7 @@ static qstr q_print;
static
qstr
q_len
;
static
qstr
q___build_class__
;
static
qstr
q_AttributeError
;
static
qstr
q_IndexError
;
static
qstr
q_NameError
;
static
qstr
q_TypeError
;
...
...
@@ -392,9 +419,9 @@ py_obj_t py_builtin_print(py_obj_t o) {
py_obj_t
py_builtin_len
(
py_obj_t
o_in
)
{
py_small_int_t
len
=
0
;
if
(
IS_O
(
o_in
,
O_LIST
))
{
if
(
IS_O
(
o_in
,
O_TUPLE
)
||
IS_O
(
o_in
,
O_LIST
))
{
py_obj_base_t
*
o
=
o_in
;
len
=
o
->
u_list
.
len
;
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
;
...
...
@@ -437,6 +464,7 @@ void rt_init() {
q_len
=
qstr_from_str_static
(
"len"
);
q___build_class__
=
qstr_from_str_static
(
"__build_class__"
);
q_AttributeError
=
qstr_from_str_static
(
"AttributeError"
);
q_IndexError
=
qstr_from_str_static
(
"IndexError"
);
q_NameError
=
qstr_from_str_static
(
"NameError"
);
q_TypeError
=
qstr_from_str_static
(
"TypeError"
);
...
...
@@ -458,7 +486,7 @@ void rt_init() {
next_unique_code_id
=
1
;
unique_codes
=
NULL
;
fun_list_append
=
rt_make_function_2
(
list_append
);
fun_list_append
=
rt_make_function_2
(
rt_
list_append
);
#ifdef WRITE_NATIVE
fp_native
=
fopen
(
"out-native"
,
"wb"
);
...
...
@@ -597,8 +625,14 @@ const char *py_obj_get_type_str(py_obj_t o_in) {
case
O_FUN_N
:
case
O_FUN_BC
:
return
"function"
;
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
:
...
...
@@ -639,13 +673,26 @@ void py_obj_print(py_obj_t o_in) {
printf
(
"%s: "
,
qstr_str
(
o
->
u_exc2
.
id
));
printf
(
o
->
u_exc2
.
fmt
,
o
->
u_exc2
.
s1
,
o
->
u_exc2
.
s2
);
break
;
case
O_TUPLE
:
printf
(
"("
);
for
(
int
i
=
0
;
i
<
o
->
u_tuple_list
.
len
;
i
++
)
{
if
(
i
>
0
)
{
printf
(
", "
);
}
py_obj_print
(
o
->
u_tuple_list
.
items
[
i
]);
}
if
(
o
->
u_tuple_list
.
len
==
1
)
{
printf
(
","
);
}
printf
(
")"
);
break
;
case
O_LIST
:
printf
(
"["
);
for
(
int
i
=
0
;
i
<
o
->
u_list
.
len
;
i
++
)
{
for
(
int
i
=
0
;
i
<
o
->
u_
tuple_
list
.
len
;
i
++
)
{
if
(
i
>
0
)
{
printf
(
", "
);
}
py_obj_print
(
o
->
u_list
.
items
[
i
]);
py_obj_print
(
o
->
u_
tuple_
list
.
items
[
i
]);
}
printf
(
"]"
);
break
;
...
...
@@ -711,7 +758,11 @@ int rt_is_true(py_obj_t arg) {
}
int
rt_get_int
(
py_obj_t
arg
)
{
if
(
IS_SMALL_INT
(
arg
))
{
if
(
arg
==
py_const_false
)
{
return
0
;
}
else
if
(
arg
==
py_const_true
)
{
return
1
;
}
else
if
(
IS_SMALL_INT
(
arg
))
{
return
FROM_SMALL_INT
(
arg
);
}
else
{
assert
(
0
);
...
...
@@ -778,11 +829,30 @@ py_obj_t rt_unary_op(int op, py_obj_t arg) {
return
py_const_none
;
}
uint
get_index
(
py_obj_base_t
*
base
,
py_obj_t
index
)
{
// assumes base is O_TUPLE or O_LIST
// TODO False and True are considered 0 and 1 for indexing purposes
int
len
=
base
->
u_tuple_list
.
len
;
if
(
IS_SMALL_INT
(
index
))
{
int
i
=
FROM_SMALL_INT
(
index
);
if
(
i
<
0
)
{
i
+=
len
;
}
if
(
i
<
0
||
i
>=
len
)
{
nlr_jump
(
py_obj_new_exception_2
(
q_IndexError
,
"%s index out of range"
,
py_obj_get_type_str
(
base
),
NULL
));
}
return
i
;
}
else
{
nlr_jump
(
py_obj_new_exception_2
(
q_TypeError
,
"%s indices must be integers, not %s"
,
py_obj_get_type_str
(
base
),
py_obj_get_type_str
(
index
)));
}
}
py_obj_t
rt_binary_op
(
int
op
,
py_obj_t
lhs
,
py_obj_t
rhs
)
{
DEBUG_OP_printf
(
"binary %d %p %p
\n
"
,
op
,
lhs
,
rhs
);
if
(
op
==
RT_BINARY_OP_SUBSCR
)
{
if
(
IS_O
(
lhs
,
O_LIST
)
&&
IS_SMALL_INT
(
rhs
))
{
return
((
py_obj_base_t
*
)
lhs
)
->
u_list
.
items
[
FROM_SMALL_INT
(
rhs
)];
if
((
IS_O
(
lhs
,
O_TUPLE
)
||
IS_O
(
lhs
,
O_LIST
)))
{
uint
index
=
get_index
(
lhs
,
rhs
);
return
((
py_obj_base_t
*
)
lhs
)
->
u_tuple_list
.
items
[
index
];
}
else
{
assert
(
0
);
}
...
...
@@ -945,9 +1015,10 @@ machine_uint_t rt_convert_obj_for_inline_asm(py_obj_t obj) {
return
(
machine_int_t
)
o
->
u_flt
;
#endif
case
O_TUPLE
:
case
O_LIST
:
// pointer to start of list (could pass length, but then could use len(x) for that)
return
(
machine_uint_t
)
o
->
u_list
.
items
;
// pointer to start of
tuple/
list (could pass length, but then could use len(x) for that)
return
(
machine_uint_t
)
o
->
u_
tuple_
list
.
items
;
default:
// just pass along a pointer to the object
...
...
@@ -1073,18 +1144,28 @@ py_obj_t rt_call_method_n(int n_args, const py_obj_t *args) {
return
rt_call_function_n
(
args
[
n_args
+
1
],
n_args
+
((
args
[
n_args
]
==
NULL
)
?
0
:
1
),
args
);
}
// items are in reverse order
py_obj_t
rt_build_tuple
(
int
n_args
,
py_obj_t
*
items
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_TUPLE
;
o
->
u_tuple_list
.
alloc
=
n_args
<
4
?
4
:
n_args
;
o
->
u_tuple_list
.
len
=
n_args
;
o
->
u_tuple_list
.
items
=
m_new
(
py_obj_t
,
o
->
u_tuple_list
.
alloc
);
for
(
int
i
=
0
;
i
<
n_args
;
i
++
)
{
o
->
u_tuple_list
.
items
[
i
]
=
items
[
n_args
-
i
-
1
];
}
return
o
;
}
// items are in reverse order
py_obj_t
rt_build_list
(
int
n_args
,
py_obj_t
*
items
)
{
py_obj_base_t
*
o
=
m_new
(
py_obj_base_t
,
1
);
o
->
kind
=
O_LIST
;
o
->
u_list
.
alloc
=
n_args
;
if
(
o
->
u_list
.
alloc
<
4
)
{
o
->
u_list
.
alloc
=
4
;
}
o
->
u_list
.
len
=
n_args
;
o
->
u_list
.
items
=
m_new
(
py_obj_t
,
o
->
u_list
.
alloc
);
o
->
u_tuple_list
.
alloc
=
n_args
<
4
?
4
:
n_args
;
o
->
u_tuple_list
.
len
=
n_args
;
o
->
u_tuple_list
.
items
=
m_new
(
py_obj_t
,
o
->
u_tuple_list
.
alloc
);
for
(
int
i
=
0
;
i
<
n_args
;
i
++
)
{
o
->
u_list
.
items
[
i
]
=
items
[
n_args
-
i
-
1
];
o
->
u_
tuple_
list
.
items
[
i
]
=
items
[
n_args
-
i
-
1
];
}
return
o
;
}
...
...
@@ -1260,18 +1341,10 @@ void rt_store_attr(py_obj_t base, qstr attr, py_obj_t val) {
}
void
rt_store_subscr
(
py_obj_t
base
,
py_obj_t
index
,
py_obj_t
value
)
{
if
(
IS_O
(
base
,
O_LIST
)
&&
IS_SMALL_INT
(
index
)
)
{
if
(
IS_O
(
base
,
O_LIST
))
{
// list store
py_obj_base_t
*
o
=
base
;
int
idx
=
FROM_SMALL_INT
(
index
);
if
(
idx
<
0
)
{
idx
+=
o
->
u_list
.
len
;
}
if
(
0
<=
idx
&&
idx
<
o
->
u_list
.
len
)
{
o
->
u_list
.
items
[
idx
]
=
value
;
}
else
{
assert
(
0
);
}
uint
i
=
get_index
(
base
,
index
);
((
py_obj_base_t
*
)
base
)
->
u_tuple_list
.
items
[
i
]
=
value
;
}
else
if
(
IS_O
(
base
,
O_MAP
))
{
// map store
py_map_lookup
(
base
,
index
,
true
)
->
value
=
value
;
...
...
@@ -1284,6 +1357,10 @@ py_obj_t rt_getiter(py_obj_t o_in) {
if
(
IS_O
(
o_in
,
O_RANGE
))
{
py_obj_base_t
*
o
=
o_in
;
return
py_obj_new_range_iterator
(
o
->
u_range
.
start
,
o
->
u_range
.
stop
,
o
->
u_range
.
step
);
}
else
if
(
IS_O
(
o_in
,
O_TUPLE
))
{
return
py_obj_new_tuple_iterator
(
o_in
,
0
);
}
else
if
(
IS_O
(
o_in
,
O_LIST
))
{
return
py_obj_new_list_iterator
(
o_in
,
0
);
}
else
{
nlr_jump
(
py_obj_new_exception_2
(
q_TypeError
,
"'%s' object is not iterable"
,
py_obj_get_type_str
(
o_in
),
NULL
));
}
...
...
@@ -1299,6 +1376,15 @@ py_obj_t rt_iternext(py_obj_t o_in) {
}
else
{
return
py_const_stop_iteration
;
}
}
else
if
(
IS_O
(
o_in
,
O_TUPLE_IT
)
||
IS_O
(
o_in
,
O_LIST_IT
))
{
py_obj_base_t
*
o
=
o_in
;
if
(
o
->
u_tuple_list_it
.
cur
<
o
->
u_tuple_list_it
.
obj
->
u_tuple_list
.
len
)
{
py_obj_t
o_out
=
o
->
u_tuple_list_it
.
obj
->
u_tuple_list
.
items
[
o
->
u_tuple_list_it
.
cur
];
o
->
u_tuple_list_it
.
cur
+=
1
;
return
o_out
;
}
else
{
return
py_const_stop_iteration
;
}
}
else
{
nlr_jump
(
py_obj_new_exception_2
(
q_TypeError
,
"? '%s' object is not iterable"
,
py_obj_get_type_str
(
o_in
),
NULL
));
}
...
...
py/runtime.h
View file @
c226dca1
...
...
@@ -116,7 +116,9 @@ py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args);
py_obj_t
rt_call_method_1
(
py_obj_t
fun
,
py_obj_t
self
);
py_obj_t
rt_call_method_2
(
py_obj_t
fun
,
py_obj_t
self
,
py_obj_t
arg
);
py_obj_t
rt_call_method_n
(
int
n_args
,
const
py_obj_t
*
args
);
py_obj_t
rt_build_tuple
(
int
n_args
,
py_obj_t
*
items
);
py_obj_t
rt_build_list
(
int
n_args
,
py_obj_t
*
items
);
py_obj_t
rt_list_append
(
py_obj_t
list
,
py_obj_t
arg
);
py_obj_t
rt_build_map
(
int
n_args
);
py_obj_t
rt_store_map
(
py_obj_t
map
,
py_obj_t
key
,
py_obj_t
value
);
py_obj_t
rt_build_set
(
int
n_args
,
py_obj_t
*
items
);
...
...
py/vm.c
View file @
c226dca1
...
...
@@ -268,6 +268,13 @@ py_obj_t py_execute_byte_code(const byte *code, uint len, const py_obj_t *args,
*
sp
=
rt_compare_op
(
unum
,
obj1
,
obj2
);
break
;
case
PYBC_BUILD_TUPLE
:
DECODE_UINT
;
obj1
=
rt_build_tuple
(
unum
,
sp
);
sp
+=
unum
-
1
;
*
sp
=
obj1
;
break
;
case
PYBC_BUILD_LIST
:
DECODE_UINT
;
obj1
=
rt_build_list
(
unum
,
sp
);
...
...
@@ -275,6 +282,13 @@ py_obj_t py_execute_byte_code(const byte *code, uint len, const py_obj_t *args,
*
sp
=
obj1
;
break
;
case
PYBC_LIST_APPEND
:
DECODE_UINT
;
// I think it's guaranteed by the compiler that sp[unum] is a list
rt_list_append
(
sp
[
unum
],
sp
[
0
]);
sp
++
;
break
;
case
PYBC_BUILD_MAP
:
DECODE_UINT
;
PUSH
(
rt_build_map
(
unum
));
...
...
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