Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
flow3r firmware
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
dos
flow3r firmware
Commits
c226dca1
Commit
c226dca1
authored
Oct 16, 2013
by
Damien
Browse files
Options
Downloads
Patches
Plain Diff
Support tuples and list comprehension, albeit crude.
parent
152568bc
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
py/runtime.c
+121
-35
121 additions, 35 deletions
py/runtime.c
py/runtime.h
+2
-0
2 additions, 0 deletions
py/runtime.h
py/vm.c
+14
-0
14 additions, 0 deletions
py/vm.c
with
137 additions
and
35 deletions
py/runtime.c
+
121
−
35
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
));
}
...
...
This diff is collapsed.
Click to expand it.
py/runtime.h
+
2
−
0
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
);
...
...
This diff is collapsed.
Click to expand it.
py/vm.c
+
14
−
0
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
));
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
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!
Save comment
Cancel
Please
register
or
sign in
to comment