Change object representation from 1 big union to individual structs.

A big change.  Micro Python objects are allocated as individual structs
with the first element being a pointer to the type information (which
is itself an object).  This scheme follows CPython.  Much more flexible,
not necessarily slower, uses same heap memory, and can allocate objects
statically.

Also change name prefix, from py_ to mp_ (mp for Micro Python).
This commit is contained in:
Damien 2013-12-21 18:17:45 +00:00
parent e2880aa2fd
commit d99b05282d
74 changed files with 4808 additions and 3668 deletions

View File

@ -4,7 +4,7 @@
#include <string.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "asmthumb.h"
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)

103
py/bc.h
View File

@ -1,101 +1,2 @@
#define PYBC_LOAD_CONST_FALSE (0x10)
#define PYBC_LOAD_CONST_NONE (0x11)
#define PYBC_LOAD_CONST_TRUE (0x12)
#define PYBC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess
#define PYBC_LOAD_CONST_INT (0x14) // qstr
#define PYBC_LOAD_CONST_DEC (0x15) // qstr
#define PYBC_LOAD_CONST_ID (0x16) // qstr
#define PYBC_LOAD_CONST_BYTES (0x17) // qstr
#define PYBC_LOAD_CONST_STRING (0x18) // qstr
#define PYBC_LOAD_FAST_0 (0x20)
#define PYBC_LOAD_FAST_1 (0x21)
#define PYBC_LOAD_FAST_2 (0x22)
#define PYBC_LOAD_FAST_N (0x23) // uint
#define PYBC_LOAD_DEREF (0x24) // uint
#define PYBC_LOAD_CLOSURE (0x25) // uint
#define PYBC_LOAD_NAME (0x26) // qstr
#define PYBC_LOAD_GLOBAL (0x27) // qstr
#define PYBC_LOAD_ATTR (0x28) // qstr
#define PYBC_LOAD_METHOD (0x29) // qstr
#define PYBC_LOAD_BUILD_CLASS (0x2a)
#define PYBC_STORE_FAST_0 (0x30)
#define PYBC_STORE_FAST_1 (0x31)
#define PYBC_STORE_FAST_2 (0x32)
#define PYBC_STORE_FAST_N (0x33) // uint
#define PYBC_STORE_DEREF (0x34) // uint
#define PYBC_STORE_NAME (0x35) // qstr
#define PYBC_STORE_GLOBAL (0x36) // qstr
#define PYBC_STORE_ATTR (0x37) // qstr
#define PYBC_STORE_SUBSCR (0x38)
#define PYBC_DELETE_FAST_N (0x39) // uint
#define PYBC_DELETE_DEREF (0x3a) // uint
#define PYBC_DELETE_NAME (0x3b) // qstr
#define PYBC_DELETE_GLOBAL (0x3c) // qstr
#define PYBC_DELETE_ATTR (0x3d) // qstr
#define PYBC_DELETE_SUBSCR (0x3e)
#define PYBC_DUP_TOP (0x40)
#define PYBC_DUP_TOP_TWO (0x41)
#define PYBC_POP_TOP (0x42)
#define PYBC_ROT_TWO (0x43)
#define PYBC_ROT_THREE (0x44)
#define PYBC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
#define PYBC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
#define PYBC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
#define PYBC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
#define PYBC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
#define PYBC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned
#define PYBC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned
#define PYBC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned
#define PYBC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
#define PYBC_WITH_CLEANUP (0x4e)
#define PYBC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
#define PYBC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
#define PYBC_END_FINALLY (0x51)
#define PYBC_GET_ITER (0x52)
#define PYBC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
#define PYBC_POP_BLOCK (0x54)
#define PYBC_POP_EXCEPT (0x55)
#define PYBC_UNARY_OP (0x60) // byte
#define PYBC_BINARY_OP (0x61) // byte
#define PYBC_COMPARE_OP (0x62) // byte
#define PYBC_BUILD_TUPLE (0x70) // uint
#define PYBC_BUILD_LIST (0x71) // uint
#define PYBC_LIST_APPEND (0x72) // uint
#define PYBC_BUILD_MAP (0x73) // uint
#define PYBC_STORE_MAP (0x74)
#define PYBC_MAP_ADD (0x75) // uint
#define PYBC_BUILD_SET (0x76) // uint
#define PYBC_SET_ADD (0x77) // uint
#define PYBC_BUILD_SLICE (0x78) // uint
#define PYBC_UNPACK_SEQUENCE (0x79) // uint
#define PYBC_UNPACK_EX (0x7a) // uint
#define PYBC_RETURN_VALUE (0x80)
#define PYBC_RAISE_VARARGS (0x81) // uint
#define PYBC_YIELD_VALUE (0x82)
#define PYBC_YIELD_FROM (0x83)
#define PYBC_MAKE_FUNCTION (0x90) // uint
#define PYBC_MAKE_CLOSURE (0x91) // uint
#define PYBC_CALL_FUNCTION (0x92) // uint
#define PYBC_CALL_FUNCTION_VAR (0x93) // uint
#define PYBC_CALL_FUNCTION_KW (0x94) // uint
#define PYBC_CALL_FUNCTION_VAR_KW (0x95) // uint
#define PYBC_CALL_METHOD (0x96) // uint
#define PYBC_CALL_METHOD_VAR (0x97) // uint
#define PYBC_CALL_METHOD_KW (0x98) // uint
#define PYBC_CALL_METHOD_VAR_KW (0x99) // uint
#define PYBC_IMPORT_NAME (0xe0) // qstr
#define PYBC_IMPORT_FROM (0xe1) // qstr
#define PYBC_IMPORT_STAR (0xe2)
py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args, uint n_state);
bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out);
mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state);
bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out);

98
py/bc0.h Normal file
View File

@ -0,0 +1,98 @@
#define MP_BC_LOAD_CONST_FALSE (0x10)
#define MP_BC_LOAD_CONST_NONE (0x11)
#define MP_BC_LOAD_CONST_TRUE (0x12)
#define MP_BC_LOAD_CONST_SMALL_INT (0x13) // 24-bit, in excess
#define MP_BC_LOAD_CONST_INT (0x14) // qstr
#define MP_BC_LOAD_CONST_DEC (0x15) // qstr
#define MP_BC_LOAD_CONST_ID (0x16) // qstr
#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr
#define MP_BC_LOAD_CONST_STRING (0x18) // qstr
#define MP_BC_LOAD_FAST_0 (0x20)
#define MP_BC_LOAD_FAST_1 (0x21)
#define MP_BC_LOAD_FAST_2 (0x22)
#define MP_BC_LOAD_FAST_N (0x23) // uint
#define MP_BC_LOAD_DEREF (0x24) // uint
#define MP_BC_LOAD_CLOSURE (0x25) // uint
#define MP_BC_LOAD_NAME (0x26) // qstr
#define MP_BC_LOAD_GLOBAL (0x27) // qstr
#define MP_BC_LOAD_ATTR (0x28) // qstr
#define MP_BC_LOAD_METHOD (0x29) // qstr
#define MP_BC_LOAD_BUILD_CLASS (0x2a)
#define MP_BC_STORE_FAST_0 (0x30)
#define MP_BC_STORE_FAST_1 (0x31)
#define MP_BC_STORE_FAST_2 (0x32)
#define MP_BC_STORE_FAST_N (0x33) // uint
#define MP_BC_STORE_DEREF (0x34) // uint
#define MP_BC_STORE_NAME (0x35) // qstr
#define MP_BC_STORE_GLOBAL (0x36) // qstr
#define MP_BC_STORE_ATTR (0x37) // qstr
#define MP_BC_STORE_SUBSCR (0x38)
#define MP_BC_DELETE_FAST_N (0x39) // uint
#define MP_BC_DELETE_DEREF (0x3a) // uint
#define MP_BC_DELETE_NAME (0x3b) // qstr
#define MP_BC_DELETE_GLOBAL (0x3c) // qstr
#define MP_BC_DELETE_ATTR (0x3d) // qstr
#define MP_BC_DELETE_SUBSCR (0x3e)
#define MP_BC_DUP_TOP (0x40)
#define MP_BC_DUP_TOP_TWO (0x41)
#define MP_BC_POP_TOP (0x42)
#define MP_BC_ROT_TWO (0x43)
#define MP_BC_ROT_THREE (0x44)
#define MP_BC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
#define MP_BC_SETUP_LOOP (0x4a) // rel byte code offset, 16-bit unsigned
#define MP_BC_BREAK_LOOP (0x4b) // rel byte code offset, 16-bit unsigned
#define MP_BC_CONTINUE_LOOP (0x4c) // rel byte code offset, 16-bit unsigned
#define MP_BC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
#define MP_BC_WITH_CLEANUP (0x4e)
#define MP_BC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
#define MP_BC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
#define MP_BC_END_FINALLY (0x51)
#define MP_BC_GET_ITER (0x52)
#define MP_BC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
#define MP_BC_POP_BLOCK (0x54)
#define MP_BC_POP_EXCEPT (0x55)
#define MP_BC_UNARY_OP (0x60) // byte
#define MP_BC_BINARY_OP (0x61) // byte
#define MP_BC_COMPARE_OP (0x62) // byte
#define MP_BC_BUILD_TUPLE (0x70) // uint
#define MP_BC_BUILD_LIST (0x71) // uint
#define MP_BC_LIST_APPEND (0x72) // uint
#define MP_BC_BUILD_MAP (0x73) // uint
#define MP_BC_STORE_MAP (0x74)
#define MP_BC_MAP_ADD (0x75) // uint
#define MP_BC_BUILD_SET (0x76) // uint
#define MP_BC_SET_ADD (0x77) // uint
#define MP_BC_BUILD_SLICE (0x78) // uint
#define MP_BC_UNPACK_SEQUENCE (0x79) // uint
#define MP_BC_UNPACK_EX (0x7a) // uint
#define MP_BC_RETURN_VALUE (0x80)
#define MP_BC_RAISE_VARARGS (0x81) // uint
#define MP_BC_YIELD_VALUE (0x82)
#define MP_BC_YIELD_FROM (0x83)
#define MP_BC_MAKE_FUNCTION (0x90) // uint
#define MP_BC_MAKE_CLOSURE (0x91) // uint
#define MP_BC_CALL_FUNCTION (0x92) // uint
#define MP_BC_CALL_FUNCTION_VAR (0x93) // uint
#define MP_BC_CALL_FUNCTION_KW (0x94) // uint
#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint
#define MP_BC_CALL_METHOD (0x96) // uint
#define MP_BC_CALL_METHOD_VAR (0x97) // uint
#define MP_BC_CALL_METHOD_KW (0x98) // uint
#define MP_BC_CALL_METHOD_VAR_KW (0x99) // uint
#define MP_BC_IMPORT_NAME (0xe0) // qstr
#define MP_BC_IMPORT_FROM (0xe1) // qstr
#define MP_BC_IMPORT_STAR (0xe2)

View File

@ -7,253 +7,258 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "runtime.h"
#include "bc.h"
#include "map.h"
#include "mpconfig.h"
#include "obj.h"
#include "objprivate.h"
#include "runtime0.h"
#include "runtime.h"
//#include "bc.h"
#include "map.h"
#include "builtin.h"
py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name) {
mp_obj_t mp_builtin___build_class__(mp_obj_t o_class_fun, mp_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);
mp_map_t *old_locals = rt_get_map_locals();
mp_map_t *class_locals = mp_map_new(MP_MAP_QSTR, 0);
rt_set_map_locals(class_locals);
// call the class code
rt_call_function_1(o_class_fun, (py_obj_t)0xdeadbeef);
rt_call_function_1(o_class_fun, (mp_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;
return mp_obj_new_class(class_locals);
}
py_obj_t py_builtin___import__(int n, py_obj_t *args) {
mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) {
printf("import:\n");
for (int i = 0; i < n; i++) {
printf(" ");
py_obj_print(args[i]);
mp_obj_print(args[i]);
printf("\n");
}
return py_const_none;
return mp_const_none;
}
py_obj_t py_builtin___repl_print__(py_obj_t o) {
if (o != py_const_none) {
py_obj_print(o);
mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
if (o != mp_const_none) {
mp_obj_print(o);
printf("\n");
}
return py_const_none;
return mp_const_none;
}
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);
mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
if (val < 0) {
val = -val;
}
return TO_SMALL_INT(val);
return MP_OBJ_NEW_SMALL_INT(val);
#if MICROPY_ENABLE_FLOAT
} else if (IS_O(o_in, O_FLOAT)) {
py_obj_base_t *o = o_in;
} else if (MP_OBJ_IS_TYPE(o_in, &float_type)) {
mp_float_t value = mp_obj_float_get(o_in);
// TODO check for NaN etc
if (o->u_float < 0) {
return py_obj_new_float(-o->u_float);
if (value < 0) {
return mp_obj_new_float(-value);
} 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));
} else if (MP_OBJ_IS_TYPE(o_in, &complex_type)) {
mp_float_t real, imag;
mp_obj_complex_get(o_in, &real, &imag);
return mp_obj_new_float(machine_sqrt(real*real + imag*imag));
#endif
} else {
assert(0);
return py_const_none;
return mp_const_none;
}
}
py_obj_t py_builtin_all(py_obj_t o_in) {
py_obj_t iterable = rt_getiter(o_in);
py_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
mp_obj_t mp_builtin_all(mp_obj_t o_in) {
mp_obj_t iterable = rt_getiter(o_in);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (!rt_is_true(item)) {
return py_const_false;
return mp_const_false;
}
}
return py_const_true;
return mp_const_true;
}
py_obj_t py_builtin_any(py_obj_t o_in) {
py_obj_t iterable = rt_getiter(o_in);
py_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
mp_obj_t mp_builtin_any(mp_obj_t o_in) {
mp_obj_t iterable = rt_getiter(o_in);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (rt_is_true(item)) {
return py_const_true;
return mp_const_true;
}
}
return py_const_false;
return mp_const_false;
}
py_obj_t py_builtin_bool(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0: return py_const_false;
case 1: if (rt_is_true(args[0])) { return py_const_true; } else { return py_const_false; }
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL));
case 0: return mp_const_false;
case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
py_obj_t py_builtin_callable(py_obj_t o_in) {
if (py_obj_is_callable(o_in)) {
return py_const_true;
mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
if (mp_obj_is_callable(o_in)) {
return mp_const_true;
} else {
return py_const_false;
return mp_const_false;
}
}
#if MICROPY_ENABLE_FLOAT
py_obj_t py_builtin_complex(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
return py_obj_new_complex(0, 0);
return mp_obj_new_complex(0, 0);
case 1:
// TODO allow string as first arg
if (IS_O(args[0], O_COMPLEX)) {
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
return args[0];
} else {
return py_obj_new_complex(py_obj_get_float(args[0]), 0);
return mp_obj_new_complex(mp_obj_get_float(args[0]), 0);
}
case 2:
{
py_float_t real, imag;
if (IS_O(args[0], O_COMPLEX)) {
py_obj_get_complex(args[0], &real, &imag);
mp_float_t real, imag;
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
mp_obj_get_complex(args[0], &real, &imag);
} else {
real = py_obj_get_float(args[0]);
real = mp_obj_get_float(args[0]);
imag = 0;
}
if (IS_O(args[1], O_COMPLEX)) {
py_float_t real2, imag2;
py_obj_get_complex(args[1], &real2, &imag2);
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
mp_float_t real2, imag2;
mp_obj_get_complex(args[1], &real2, &imag2);
real -= imag2;
imag += real2;
} else {
imag += py_obj_get_float(args[1]);
imag += mp_obj_get_float(args[1]);
}
return py_obj_new_complex(real, imag);
return mp_obj_new_complex(real, imag);
}
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args, NULL));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "comlpex() takes at most 2 arguments (%d given)", (void*)(machine_int_t)n_args));
}
}
#endif
py_obj_t py_builtin_chr(py_obj_t o_in) {
int ord = py_obj_get_int(o_in);
mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
int ord = mp_obj_get_int(o_in);
if (0 <= ord && ord <= 0x10ffff) {
char *str = m_new(char, 2);
str[0] = ord;
str[1] = '\0';
return py_obj_new_str(qstr_from_str_take(str));
return mp_obj_new_str(qstr_from_str_take(str));
} else {
nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "chr() arg not in range(0x110000)", NULL, NULL));
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "chr() arg not in range(0x110000)"));
}
}
py_obj_t py_builtin_dict(void) {
mp_obj_t mp_builtin_dict(void) {
// TODO create from an iterable!
return rt_build_map(0);
}
py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in) {
if (IS_SMALL_INT(o1_in) && IS_SMALL_INT(o2_in)) {
py_small_int_t i1 = FROM_SMALL_INT(o1_in);
py_small_int_t i2 = FROM_SMALL_INT(o2_in);
py_obj_t revs_args[2];
revs_args[1] = TO_SMALL_INT(i1 / i2);
revs_args[0] = TO_SMALL_INT(i1 % i2);
mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
mp_obj_t revs_args[2];
revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args);
} else {
nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", py_obj_get_type_str(o1_in), py_obj_get_type_str(o2_in)));
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
}
}
py_obj_t py_builtin_hash(py_obj_t o_in) {
static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
// TODO hash will generally overflow small integer; can we safely truncate it?
return py_obj_new_int(py_obj_hash(o_in));
return mp_obj_new_int(mp_obj_hash(o_in));
}
py_obj_t py_builtin_iter(py_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
static mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
return rt_getiter(o_in);
}
py_obj_t py_builtin_next(py_obj_t o_in) {
return rt_gen_instance_next(o_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
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;
mp_obj_t mp_builtin_len(mp_obj_t o_in) {
mp_small_int_t len = 0;
if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
len = strlen(qstr_str(mp_obj_str_get(o_in)));
} else if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
uint seq_len;
mp_obj_t *seq_items;
mp_obj_tuple_get(o_in, &seq_len, &seq_items);
len = seq_len;
} else if (MP_OBJ_IS_TYPE(o_in, &list_type)) {
uint seq_len;
mp_obj_t *seq_items;
mp_obj_list_get(o_in, &seq_len, &seq_items);
len = seq_len;
/* TODO
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
mp_obj_base_t *o = o_in;
len = o->u_map.used;
*/
} else {
nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "object of type '%s' has no len()", py_obj_get_type_str(o_in), NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
}
return TO_SMALL_INT(len);
return MP_OBJ_NEW_SMALL_INT(len);
}
py_obj_t py_builtin_list(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0: return rt_build_list(0, NULL);
case 1:
{
// make list from iterable
py_obj_t iterable = rt_getiter(args[0]);
py_obj_t list = rt_build_list(0, NULL);
py_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t list = rt_build_list(0, NULL);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
rt_list_append(list, item);
}
return list;
}
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args, NULL));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
py_obj_t py_builtin_max(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
if (n_args == 1) {
// given an iterable
py_obj_t iterable = rt_getiter(args[0]);
py_obj_t max_obj = NULL;
py_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
if (max_obj == NULL || py_obj_less(max_obj, item)) {
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t max_obj = NULL;
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (max_obj == NULL || mp_obj_less(max_obj, item)) {
max_obj = item;
}
}
if (max_obj == NULL) {
nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "max() arg is an empty sequence", NULL, NULL));
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "max() arg is an empty sequence"));
}
return max_obj;
} else {
// given many args
py_obj_t max_obj = args[0];
mp_obj_t max_obj = args[0];
for (int i = 1; i < n_args; i++) {
if (py_obj_less(max_obj, args[i])) {
if (mp_obj_less(max_obj, args[i])) {
max_obj = args[i];
}
}
@ -261,26 +266,26 @@ py_obj_t py_builtin_max(int n_args, const py_obj_t *args) {
}
}
py_obj_t py_builtin_min(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
if (n_args == 1) {
// given an iterable
py_obj_t iterable = rt_getiter(args[0]);
py_obj_t min_obj = NULL;
py_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
if (min_obj == NULL || py_obj_less(item, min_obj)) {
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t min_obj = NULL;
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
if (min_obj == NULL || mp_obj_less(item, min_obj)) {
min_obj = item;
}
}
if (min_obj == NULL) {
nlr_jump(py_obj_new_exception_2(rt_q_ValueError, "min() arg is an empty sequence", NULL, NULL));
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "min() arg is an empty sequence"));
}
return min_obj;
} else {
// given many args
py_obj_t min_obj = args[0];
mp_obj_t min_obj = args[0];
for (int i = 1; i < n_args; i++) {
if (py_obj_less(args[i], min_obj)) {
if (mp_obj_less(args[i], min_obj)) {
min_obj = args[i];
}
}
@ -288,59 +293,85 @@ py_obj_t py_builtin_min(int n_args, const py_obj_t *args) {
}
}
py_obj_t py_builtin_ord(py_obj_t o_in) {
const char *str = qstr_str(py_obj_get_qstr(o_in));
static mp_obj_t mp_builtin_next(mp_obj_t o_in) {
return mp_obj_gen_instance_next(o_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next);
mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
const char *str = qstr_str(mp_obj_get_qstr(o_in));
if (strlen(str) == 1) {
return py_obj_new_int(str[0]);
return mp_obj_new_int(str[0]);
} else {
nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str), NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str)));
}
}
py_obj_t py_builtin_pow(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 2: return rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]);
case 3: return rt_binary_op(RT_BINARY_OP_MODULO, rt_binary_op(RT_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise...
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
}
}
py_obj_t py_builtin_print(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args) {
for (int i = 0; i < n_args; i++) {
if (i > 0) {
printf(" ");
}
if (IS_O(args[i], O_STR)) {
if (MP_OBJ_IS_TYPE(args[i], &str_type)) {
// special case, print string raw
printf("%s", qstr_str(((py_obj_base_t*)args[i])->u_str));
printf("%s", qstr_str(mp_obj_str_get(args[i])));
} else {
// print the object Python style
py_obj_print(args[i]);
mp_obj_print(args[i]);
}
}
printf("\n");
return py_const_none;
return mp_const_none;
}
py_obj_t py_builtin_range(int n_args, const py_obj_t *args) {
mp_obj_t mp_builtin_range(int n_args, const mp_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));
case 1: return mp_obj_new_range(0, mp_obj_get_int(args[0]), 1);
case 2: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), 1);
case 3: return mp_obj_new_range(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
}
}
py_obj_t py_builtin_sum(int n_args, const py_obj_t *args) {
py_obj_t value;
static mp_obj_t mp_builtin_set(int n_args, const mp_obj_t *args) {
assert(0 <= n_args && n_args <= 1);
if (n_args == 0) {
// return a new, empty set
return mp_obj_new_set(0, NULL);
} else {
// 1 argument, an iterable from which we make a new set
mp_obj_t set = mp_obj_new_set(0, NULL);
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
mp_obj_set_store(set, item);
}
return set;
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_set_obj, 0, 1, mp_builtin_set);
mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
mp_obj_t value;
switch (n_args) {
case 1: value = py_obj_new_int(0); break;
case 1: value = mp_obj_new_int(0); break;
case 2: value = args[1]; break;
default: nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args, NULL));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args));
}
py_obj_t iterable = rt_getiter(args[0]);
py_obj_t item;
while ((item = rt_iternext(iterable)) != py_const_stop_iteration) {
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;
while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) {
value = rt_binary_op(RT_BINARY_OP_ADD, value, item);
}
return value;

View File

@ -1,24 +1,27 @@
py_obj_t py_builtin___build_class__(py_obj_t o_class_fun, py_obj_t o_class_name);
py_obj_t py_builtin___import__(int n, py_obj_t *args);
py_obj_t py_builtin___repl_print__(py_obj_t o);
py_obj_t py_builtin_abs(py_obj_t o_in);
py_obj_t py_builtin_all(py_obj_t o_in);
py_obj_t py_builtin_any(py_obj_t o_in);
py_obj_t py_builtin_bool(int n_args, const py_obj_t *args);
py_obj_t py_builtin_callable(py_obj_t o_in);
py_obj_t py_builtin_complex(int n_args, const py_obj_t *args);
py_obj_t py_builtin_chr(py_obj_t o_in);
py_obj_t py_builtin_dict(void);
py_obj_t py_builtin_divmod(py_obj_t o1_in, py_obj_t o2_in);
py_obj_t py_builtin_hash(py_obj_t o_in);
py_obj_t py_builtin_iter(py_obj_t o_in);
py_obj_t py_builtin_len(py_obj_t o_in);
py_obj_t py_builtin_list(int n_args, const py_obj_t *args);
py_obj_t py_builtin_max(int n_args, const py_obj_t *args);
py_obj_t py_builtin_min(int n_args, const py_obj_t *args);
py_obj_t py_builtin_next(py_obj_t o_in);
py_obj_t py_builtin_ord(py_obj_t o_in);
py_obj_t py_builtin_pow(int n_args, const py_obj_t *args);
py_obj_t py_builtin_print(int n_args, const py_obj_t *args);
py_obj_t py_builtin_range(int n_args, const py_obj_t *args);
py_obj_t py_builtin_sum(int n_args, const py_obj_t *args);
// TODO convert all these to objects using MP_DECLARE and MP_DEFINE
mp_obj_t mp_builtin___build_class__(mp_obj_t o_class_fun, mp_obj_t o_class_name);
mp_obj_t mp_builtin___import__(int n, mp_obj_t *args);
mp_obj_t mp_builtin___repl_print__(mp_obj_t o);
mp_obj_t mp_builtin_abs(mp_obj_t o_in);
mp_obj_t mp_builtin_all(mp_obj_t o_in);
mp_obj_t mp_builtin_any(mp_obj_t o_in);
mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_callable(mp_obj_t o_in);
mp_obj_t mp_builtin_complex(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_chr(mp_obj_t o_in);
mp_obj_t mp_builtin_dict(void);
mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_iter_obj);
mp_obj_t mp_builtin_len(mp_obj_t o_in);
mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_next_obj);
mp_obj_t mp_builtin_ord(mp_obj_t o_in);
mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_set_obj);
mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args);

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
bool py_compile(py_parse_node_t pn, bool is_repl);
bool mp_compile(mp_parse_node_t pn, bool is_repl);

View File

@ -32,7 +32,7 @@ typedef struct _emit_method_table_t {
void (*import_name)(emit_t *emit, qstr qstr);
void (*import_from)(emit_t *emit, qstr qstr);
void (*import_star)(emit_t *emit);
void (*load_const_tok)(emit_t *emit, py_token_kind_t tok);
void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);
void (*load_const_small_int)(emit_t *emit, int arg);
void (*load_const_int)(emit_t *emit, qstr qstr);
void (*load_const_dec)(emit_t *emit, qstr qstr);
@ -129,9 +129,9 @@ typedef struct _emit_inline_asm_t emit_inline_asm_t;
typedef struct _emit_inline_asm_method_table_t {
void (*start_pass)(emit_inline_asm_t *emit, pass_kind_t pass, scope_t *scope);
void (*end_pass)(emit_inline_asm_t *emit);
int (*count_params)(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params);
int (*count_params)(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params);
void (*label)(emit_inline_asm_t *emit, int label_num, qstr label_id);
void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args);
void (*op)(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args);
} emit_inline_asm_method_table_t;
extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table;

View File

@ -6,14 +6,14 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
#include "compile.h"
#include "scope.h"
#include "runtime.h"
#include "runtime0.h"
#include "emit.h"
#include "bc.h"
#include "bc0.h"
struct _emit_t {
pass_kind_t pass;
@ -214,55 +214,55 @@ static void emit_bc_label_assign(emit_t *emit, int l) {
static void emit_bc_import_name(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, PYBC_IMPORT_NAME, qstr);
emit_write_byte_1_qstr(emit, MP_BC_IMPORT_NAME, qstr);
}
static void emit_bc_import_from(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, PYBC_IMPORT_FROM, qstr);
emit_write_byte_1_qstr(emit, MP_BC_IMPORT_FROM, qstr);
}
static void emit_bc_import_star(emit_t *emit) {
emit_pre(emit, -1);
emit_write_byte_1(emit, PYBC_IMPORT_STAR);
emit_write_byte_1(emit, MP_BC_IMPORT_STAR);
}
static void emit_bc_load_const_tok(emit_t *emit, py_token_kind_t tok) {
static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
emit_pre(emit, 1);
switch (tok) {
case PY_TOKEN_KW_FALSE: emit_write_byte_1(emit, PYBC_LOAD_CONST_FALSE); break;
case PY_TOKEN_KW_NONE: emit_write_byte_1(emit, PYBC_LOAD_CONST_NONE); break;
case PY_TOKEN_KW_TRUE: emit_write_byte_1(emit, PYBC_LOAD_CONST_TRUE); break;
case MP_TOKEN_KW_FALSE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_FALSE); break;
case MP_TOKEN_KW_NONE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_NONE); break;
case MP_TOKEN_KW_TRUE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_TRUE); break;
default: assert(0);
}
}
static void emit_bc_load_const_small_int(emit_t *emit, int arg) {
emit_pre(emit, 1);
emit_write_byte_1_int(emit, PYBC_LOAD_CONST_SMALL_INT, arg);
emit_write_byte_1_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
}
static void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_INT, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
}
static void emit_bc_load_const_dec(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_DEC, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr);
}
static void emit_bc_load_const_id(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_ID, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_ID, qstr);
}
static void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
emit_pre(emit, 1);
if (bytes) {
emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_BYTES, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
} else {
emit_write_byte_1_qstr(emit, PYBC_LOAD_CONST_STRING, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
}
}
@ -275,219 +275,219 @@ static void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
assert(local_num >= 0);
emit_pre(emit, 1);
switch (local_num) {
case 0: emit_write_byte_1(emit, PYBC_LOAD_FAST_0); break;
case 1: emit_write_byte_1(emit, PYBC_LOAD_FAST_1); break;
case 2: emit_write_byte_1(emit, PYBC_LOAD_FAST_2); break;
default: emit_write_byte_1_uint(emit, PYBC_LOAD_FAST_N, local_num); break;
case 0: emit_write_byte_1(emit, MP_BC_LOAD_FAST_0); break;
case 1: emit_write_byte_1(emit, MP_BC_LOAD_FAST_1); break;
case 2: emit_write_byte_1(emit, MP_BC_LOAD_FAST_2); break;
default: emit_write_byte_1_uint(emit, MP_BC_LOAD_FAST_N, local_num); break;
}
}
static void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, PYBC_LOAD_DEREF, local_num);
emit_write_byte_1_uint(emit, MP_BC_LOAD_DEREF, local_num);
}
static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, PYBC_LOAD_CLOSURE, local_num);
emit_write_byte_1_uint(emit, MP_BC_LOAD_CLOSURE, local_num);
}
static void emit_bc_load_name(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, PYBC_LOAD_NAME, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_NAME, qstr);
}
static void emit_bc_load_global(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, PYBC_LOAD_GLOBAL, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
}
static void emit_bc_load_attr(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, PYBC_LOAD_ATTR, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_ATTR, qstr);
}
static void emit_bc_load_method(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, PYBC_LOAD_METHOD, qstr);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_METHOD, qstr);
}
static void emit_bc_load_build_class(emit_t *emit) {
emit_pre(emit, 1);
emit_write_byte_1(emit, PYBC_LOAD_BUILD_CLASS);
emit_write_byte_1(emit, MP_BC_LOAD_BUILD_CLASS);
}
static void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
assert(local_num >= 0);
emit_pre(emit, -1);
switch (local_num) {
case 0: emit_write_byte_1(emit, PYBC_STORE_FAST_0); break;
case 1: emit_write_byte_1(emit, PYBC_STORE_FAST_1); break;
case 2: emit_write_byte_1(emit, PYBC_STORE_FAST_2); break;
default: emit_write_byte_1_uint(emit, PYBC_STORE_FAST_N, local_num); break;
case 0: emit_write_byte_1(emit, MP_BC_STORE_FAST_0); break;
case 1: emit_write_byte_1(emit, MP_BC_STORE_FAST_1); break;
case 2: emit_write_byte_1(emit, MP_BC_STORE_FAST_2); break;
default: emit_write_byte_1_uint(emit, MP_BC_STORE_FAST_N, local_num); break;
}
}
static void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, -1);
emit_write_byte_1_uint(emit, PYBC_STORE_DEREF, local_num);
emit_write_byte_1_uint(emit, MP_BC_STORE_DEREF, local_num);
}
static void emit_bc_store_name(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, PYBC_STORE_NAME, qstr);
emit_write_byte_1_qstr(emit, MP_BC_STORE_NAME, qstr);
}
static void emit_bc_store_global(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, PYBC_STORE_GLOBAL, qstr);
emit_write_byte_1_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
}
static void emit_bc_store_attr(emit_t *emit, qstr qstr) {
emit_pre(emit, -2);
emit_write_byte_1_qstr(emit, PYBC_STORE_ATTR, qstr);
emit_write_byte_1_qstr(emit, MP_BC_STORE_ATTR, qstr);
}
static void emit_bc_store_subscr(emit_t *emit) {
emit_pre(emit, -3);
emit_write_byte_1(emit, PYBC_STORE_SUBSCR);
emit_write_byte_1(emit, MP_BC_STORE_SUBSCR);
}
static void emit_bc_store_locals(emit_t *emit) {
// not needed
emit_pre(emit, -1);
emit_write_byte_1(emit, PYBC_POP_TOP);
emit_write_byte_1(emit, MP_BC_POP_TOP);
}
static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
assert(local_num >= 0);
emit_pre(emit, 0);
emit_write_byte_1_uint(emit, PYBC_DELETE_FAST_N, local_num);
emit_write_byte_1_uint(emit, MP_BC_DELETE_FAST_N, local_num);
}
static void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, PYBC_DELETE_DEREF, local_num);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_DEREF, local_num);
}
static void emit_bc_delete_name(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, PYBC_DELETE_NAME, qstr);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_NAME, qstr);
}
static void emit_bc_delete_global(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, PYBC_DELETE_GLOBAL, qstr);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
}
static void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, PYBC_DELETE_ATTR, qstr);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_ATTR, qstr);
}
static void emit_bc_delete_subscr(emit_t *emit) {
emit_pre(emit, -2);
emit_write_byte_1(emit, PYBC_DELETE_SUBSCR);
emit_write_byte_1(emit, MP_BC_DELETE_SUBSCR);
}
static void emit_bc_dup_top(emit_t *emit) {
emit_pre(emit, 1);
emit_write_byte_1(emit, PYBC_DUP_TOP);
emit_write_byte_1(emit, MP_BC_DUP_TOP);
}
static void emit_bc_dup_top_two(emit_t *emit) {
emit_pre(emit, 2);
emit_write_byte_1(emit, PYBC_DUP_TOP_TWO);
emit_write_byte_1(emit, MP_BC_DUP_TOP_TWO);
}
static void emit_bc_pop_top(emit_t *emit) {
emit_pre(emit, -1);
emit_write_byte_1(emit, PYBC_POP_TOP);
emit_write_byte_1(emit, MP_BC_POP_TOP);
}
static void emit_bc_rot_two(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, PYBC_ROT_TWO);
emit_write_byte_1(emit, MP_BC_ROT_TWO);
}
static void emit_bc_rot_three(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, PYBC_ROT_THREE);
emit_write_byte_1(emit, MP_BC_ROT_THREE);
}
static void emit_bc_jump(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_signed_label(emit, PYBC_JUMP, label);
emit_write_byte_1_signed_label(emit, MP_BC_JUMP, label);
}
static void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, PYBC_POP_JUMP_IF_TRUE, label);
emit_write_byte_1_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
}
static void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, PYBC_POP_JUMP_IF_FALSE, label);
emit_write_byte_1_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
}
static void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, PYBC_JUMP_IF_TRUE_OR_POP, label);
emit_write_byte_1_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
}
static void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, PYBC_JUMP_IF_FALSE_OR_POP, label);
emit_write_byte_1_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
}
static void emit_bc_setup_loop(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_LOOP, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
}
static void emit_bc_break_loop(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_unsigned_label(emit, PYBC_BREAK_LOOP, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_BREAK_LOOP, label);
}
static void emit_bc_continue_loop(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_unsigned_label(emit, PYBC_CONTINUE_LOOP, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_CONTINUE_LOOP, label);
}
static void emit_bc_setup_with(emit_t *emit, int label) {
emit_pre(emit, 7);
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_WITH, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_WITH, label);
}
static void emit_bc_with_cleanup(emit_t *emit) {
emit_pre(emit, -7);
emit_write_byte_1(emit, PYBC_WITH_CLEANUP);
emit_write_byte_1(emit, MP_BC_WITH_CLEANUP);
}
static void emit_bc_setup_except(emit_t *emit, int label) {
emit_pre(emit, 6);
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_EXCEPT, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
}
static void emit_bc_setup_finally(emit_t *emit, int label) {
emit_pre(emit, 6);
emit_write_byte_1_unsigned_label(emit, PYBC_SETUP_FINALLY, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
}
static void emit_bc_end_finally(emit_t *emit) {
emit_pre(emit, -1);
emit_write_byte_1(emit, PYBC_END_FINALLY);
emit_write_byte_1(emit, MP_BC_END_FINALLY);
}
static void emit_bc_get_iter(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, PYBC_GET_ITER);
emit_write_byte_1(emit, MP_BC_GET_ITER);
}
static void emit_bc_for_iter(emit_t *emit, int label) {
emit_pre(emit, 1);
emit_write_byte_1_unsigned_label(emit, PYBC_FOR_ITER, label);
emit_write_byte_1_unsigned_label(emit, MP_BC_FOR_ITER, label);
}
static void emit_bc_for_iter_end(emit_t *emit) {
@ -496,104 +496,104 @@ static void emit_bc_for_iter_end(emit_t *emit) {
static void emit_bc_pop_block(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, PYBC_POP_BLOCK);
emit_write_byte_1(emit, MP_BC_POP_BLOCK);
}
static void emit_bc_pop_except(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, PYBC_POP_EXCEPT);
emit_write_byte_1(emit, MP_BC_POP_EXCEPT);
}
static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
emit_pre(emit, 0);
emit_write_byte_1_byte(emit, PYBC_UNARY_OP, op);
emit_write_byte_1_byte(emit, MP_BC_UNARY_OP, op);
}
static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
emit_pre(emit, -1);
emit_write_byte_1_byte(emit, PYBC_BINARY_OP, op);
emit_write_byte_1_byte(emit, MP_BC_BINARY_OP, op);
}
static void emit_bc_compare_op(emit_t *emit, rt_compare_op_t op) {
emit_pre(emit, -1);
emit_write_byte_1_byte(emit, PYBC_COMPARE_OP, op);
emit_write_byte_1_byte(emit, MP_BC_COMPARE_OP, op);
}
static void emit_bc_build_tuple(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, PYBC_BUILD_TUPLE, n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_TUPLE, n_args);
}
static void emit_bc_build_list(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, PYBC_BUILD_LIST, n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_LIST, n_args);
}
static void emit_bc_list_append(emit_t *emit, int list_stack_index) {
assert(list_stack_index >= 0);
emit_pre(emit, -1);
emit_write_byte_1_uint(emit, PYBC_LIST_APPEND, list_stack_index);
emit_write_byte_1_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
}
static void emit_bc_build_map(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, PYBC_BUILD_MAP, n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_MAP, n_args);
}
static void emit_bc_store_map(emit_t *emit) {
emit_pre(emit, -2);
emit_write_byte_1(emit, PYBC_STORE_MAP);
emit_write_byte_1(emit, MP_BC_STORE_MAP);
}
static void emit_bc_map_add(emit_t *emit, int map_stack_index) {
assert(map_stack_index >= 0);
emit_pre(emit, -2);
emit_write_byte_1_uint(emit, PYBC_MAP_ADD, map_stack_index);
emit_write_byte_1_uint(emit, MP_BC_MAP_ADD, map_stack_index);
}
static void emit_bc_build_set(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, PYBC_BUILD_SET, n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_SET, n_args);
}
static void emit_bc_set_add(emit_t *emit, int set_stack_index) {
assert(set_stack_index >= 0);
emit_pre(emit, -1);
emit_write_byte_1_uint(emit, PYBC_SET_ADD, set_stack_index);
emit_write_byte_1_uint(emit, MP_BC_SET_ADD, set_stack_index);
}
static void emit_bc_build_slice(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, PYBC_BUILD_SLICE, n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_SLICE, n_args);
}
static void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, -1 + n_args);
emit_write_byte_1_uint(emit, PYBC_UNPACK_SEQUENCE, n_args);
emit_write_byte_1_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
}
static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
assert(n_left >=0 && n_right >= 0);
emit_pre(emit, -1 + n_left + n_right + 1);
emit_write_byte_1_uint(emit, PYBC_UNPACK_EX, n_left | (n_right << 8));
emit_write_byte_1_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
}
static void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
assert(n_default_params == 0 && n_dict_params == 0);
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, PYBC_MAKE_FUNCTION, scope->unique_code_id);
emit_write_byte_1_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
}
static void emit_bc_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
assert(n_default_params == 0 && n_dict_params == 0);
emit_pre(emit, 0);
emit_write_byte_1_uint(emit, PYBC_MAKE_CLOSURE, scope->unique_code_id);
emit_write_byte_1_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
}
static void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
@ -608,15 +608,15 @@ static void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword,
int op;
if (have_star_arg) {
if (have_dbl_star_arg) {
op = PYBC_CALL_FUNCTION_VAR_KW;
op = MP_BC_CALL_FUNCTION_VAR_KW;
} else {
op = PYBC_CALL_FUNCTION_VAR;
op = MP_BC_CALL_FUNCTION_VAR;
}
} else {
if (have_dbl_star_arg) {
op = PYBC_CALL_FUNCTION_KW;
op = MP_BC_CALL_FUNCTION_KW;
} else {
op = PYBC_CALL_FUNCTION;
op = MP_BC_CALL_FUNCTION;
}
}
emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
@ -634,15 +634,15 @@ static void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, b
int op;
if (have_star_arg) {
if (have_dbl_star_arg) {
op = PYBC_CALL_METHOD_VAR_KW;
op = MP_BC_CALL_METHOD_VAR_KW;
} else {
op = PYBC_CALL_METHOD_VAR;
op = MP_BC_CALL_METHOD_VAR;
}
} else {
if (have_dbl_star_arg) {
op = PYBC_CALL_METHOD_KW;
op = MP_BC_CALL_METHOD_KW;
} else {
op = PYBC_CALL_METHOD;
op = MP_BC_CALL_METHOD;
}
}
emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
@ -651,13 +651,13 @@ static void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, b
static void emit_bc_return_value(emit_t *emit) {
emit_pre(emit, -1);
emit->last_emit_was_return_value = true;
emit_write_byte_1(emit, PYBC_RETURN_VALUE);
emit_write_byte_1(emit, MP_BC_RETURN_VALUE);
}
static void emit_bc_raise_varargs(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, -n_args);
emit_write_byte_1_uint(emit, PYBC_RAISE_VARARGS, n_args);
emit_write_byte_1_uint(emit, MP_BC_RAISE_VARARGS, n_args);
}
static void emit_bc_yield_value(emit_t *emit) {
@ -665,7 +665,7 @@ static void emit_bc_yield_value(emit_t *emit) {
if (emit->pass == PASS_2) {
emit->scope->flags |= SCOPE_FLAG_GENERATOR;
}
emit_write_byte_1(emit, PYBC_YIELD_VALUE);
emit_write_byte_1(emit, MP_BC_YIELD_VALUE);
}
static void emit_bc_yield_from(emit_t *emit) {
@ -673,7 +673,7 @@ static void emit_bc_yield_from(emit_t *emit) {
if (emit->pass == PASS_2) {
emit->scope->flags |= SCOPE_FLAG_GENERATOR;
}
emit_write_byte_1(emit, PYBC_YIELD_FROM);
emit_write_byte_1(emit, MP_BC_YIELD_FROM);
}
const emit_method_table_t emit_bc_method_table = {

View File

@ -5,11 +5,11 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
#include "runtime.h"
#include "runtime0.h"
#include "emit.h"
#define EMIT(fun, arg...) (emit_method_table->fun(emit, ##arg))

View File

@ -6,12 +6,12 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
#include "compile.h"
#include "scope.h"
#include "runtime.h"
#include "runtime0.h"
#include "emit.h"
#if MICROPY_EMIT_CPYTHON
@ -136,9 +136,9 @@ static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) {
if (emit->pass == PASS_3) {
printf("LOAD_CONST ");
switch (tok) {
case PY_TOKEN_KW_FALSE: printf("False"); break;
case PY_TOKEN_KW_NONE: printf("None"); break;
case PY_TOKEN_KW_TRUE: printf("True"); break;
case MP_TOKEN_KW_FALSE: printf("False"); break;
case MP_TOKEN_KW_NONE: printf("None"); break;
case MP_TOKEN_KW_TRUE: printf("True"); break;
default: printf("?=%d\n", tok); return; assert(0);
}
printf("\n");

View File

@ -6,11 +6,11 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
#include "runtime.h"
#include "runtime0.h"
#include "emit.h"
#include "asmthumb.h"
@ -45,22 +45,22 @@ static void emit_inline_thumb_end_pass(emit_inline_asm_t *emit) {
asm_thumb_end_pass(emit->as);
if (emit->pass == PASS_3) {
py_fun_t f = asm_thumb_get_code(emit->as);
void *f = asm_thumb_get_code(emit->as);
rt_assign_inline_asm_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
}
}
static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, py_parse_node_t *pn_params) {
static int emit_inline_thumb_count_params(emit_inline_asm_t *emit, int n_params, mp_parse_node_t *pn_params) {
if (n_params > 4) {
printf("SyntaxError: can only have up to 4 parameters to inline thumb assembly\n");
return 0;
}
for (int i = 0; i < n_params; i++) {
if (!PY_PARSE_NODE_IS_ID(pn_params[i])) {
if (!MP_PARSE_NODE_IS_ID(pn_params[i])) {
printf("SyntaxError: parameter to inline assembler must be an identifier\n");
return 0;
}
const char *p = qstr_str(PY_PARSE_NODE_LEAF_ARG(pn_params[i]));
const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i]));
if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) {
printf("SyntaxError: parameter %d to inline assembler must be r%d\n", i + 1, i);
return 0;
@ -84,12 +84,12 @@ static bool check_n_arg(qstr op, int n_args, int wanted_n_args) {
}
}
static uint get_arg_rlo(qstr op, py_parse_node_t *pn_args, int wanted_arg_num) {
if (!PY_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
static uint get_arg_rlo(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) {
if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
return 0;
}
qstr reg_qstr = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
const char *reg_str = qstr_str(reg_qstr);
if (!(strlen(reg_str) == 2 && reg_str[0] == 'r' && ('0' <= reg_str[1] && reg_str[1] <= '7'))) {
printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
@ -98,12 +98,12 @@ static uint get_arg_rlo(qstr op, py_parse_node_t *pn_args, int wanted_arg_num) {
return reg_str[1] - '0';
}
static int get_arg_i(qstr op, py_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
if (!PY_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) {
static int get_arg_i(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) {
printf("SyntaxError: '%s' expects an integer in position %d\n", qstr_str(op), wanted_arg_num);
return 0;
}
int i = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
int i = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
if ((i & (~fit_mask)) != 0) {
printf("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n", qstr_str(op), i, fit_mask);
return 0;
@ -111,12 +111,12 @@ static int get_arg_i(qstr op, py_parse_node_t *pn_args, int wanted_arg_num, int
return i;
}
static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_args, int wanted_arg_num) {
if (!PY_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
static int get_arg_label(emit_inline_asm_t *emit, qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) {
if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
printf("SyntaxError: '%s' expects a label in position %d\n", qstr_str(op), wanted_arg_num);
return 0;
}
qstr label_qstr = PY_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
for (int i = 0; i < emit->max_num_labels; i++) {
if (emit->label_lookup[i] == label_qstr) {
return i;
@ -129,7 +129,7 @@ static int get_arg_label(emit_inline_asm_t *emit, qstr op, py_parse_node_t *pn_a
return 0;
}
static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, py_parse_node_t *pn_args) {
static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args) {
// TODO perhaps make two tables:
// one_args =
// "b", LAB, asm_thumb_b_n,

View File

@ -24,12 +24,14 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
#include "runtime.h"
#include "runtime0.h"
#include "emit.h"
#include "obj.h"
#include "runtime.h"
// wrapper around everything in this file
#if N_X64 || N_THUMB
@ -258,10 +260,10 @@ static void emit_native_end_pass(emit_t *emit) {
if (emit->pass == PASS_3) {
#if N_X64
py_fun_t f = asm_x64_get_code(emit->as);
void *f = asm_x64_get_code(emit->as);
rt_assign_native_code(emit->scope->unique_code_id, f, asm_x64_get_code_size(emit->as), emit->scope->num_params);
#elif N_THUMB
py_fun_t f = asm_thumb_get_code(emit->as);
void *f = asm_thumb_get_code(emit->as);
rt_assign_native_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params);
#endif
}
@ -460,9 +462,9 @@ static void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, in
case VTYPE_BOOL:
si->vtype = VTYPE_PYOBJ;
if (si->u_imm == 0) {
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)py_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
} else {
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)py_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
}
break;
case VTYPE_INT:
@ -561,23 +563,23 @@ static void emit_native_import_star(emit_t *emit) {
assert(0);
}
static void emit_native_load_const_tok(emit_t *emit, py_token_kind_t tok) {
static void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
emit_pre(emit);
int vtype;
machine_uint_t val;
if (emit->do_viper_types) {
switch (tok) {
case PY_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
case PY_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break;
case PY_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break;
case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
case MP_TOKEN_KW_FALSE: vtype = VTYPE_BOOL; val = 0; break;
case MP_TOKEN_KW_TRUE: vtype = VTYPE_BOOL; val = 1; break;
default: assert(0); vtype = 0; val = 0; // shouldn't happen
}
} else {
vtype = VTYPE_PYOBJ;
switch (tok) {
case PY_TOKEN_KW_NONE: val = (machine_uint_t)py_const_none; break;
case PY_TOKEN_KW_FALSE: val = (machine_uint_t)py_const_false; break;
case PY_TOKEN_KW_TRUE: val = (machine_uint_t)py_const_true; break;
case MP_TOKEN_KW_NONE: val = (machine_uint_t)mp_const_none; break;
case MP_TOKEN_KW_FALSE: val = (machine_uint_t)mp_const_false; break;
case MP_TOKEN_KW_TRUE: val = (machine_uint_t)mp_const_true; break;
default: assert(0); vtype = 0; val = 0; // shouldn't happen
}
}
@ -956,7 +958,7 @@ static void emit_native_for_iter(emit_t *emit, int label) {
emit_access_stack(emit, 1, &vtype, REG_ARG_1);
assert(vtype == VTYPE_PYOBJ);
emit_call(emit, RT_F_ITERNEXT, rt_iternext);
ASM_MOV_IMM_TO_REG((machine_uint_t)py_const_stop_iteration, REG_TEMP1);
ASM_MOV_IMM_TO_REG((machine_uint_t)mp_const_stop_iteration, REG_TEMP1);
#if N_X64
asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
asm_x64_jcc_label(emit->as, JCC_JE, label);

View File

@ -6,12 +6,12 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
#include "compile.h"
#include "scope.h"
#include "runtime.h"
#include "runtime0.h"
#include "emit.h"
struct _emit_t {

View File

@ -3,7 +3,7 @@
#include <stdint.h>
#include <string.h>
#include "mpyconfig.h"
#include "mpconfig.h"
#include "gc.h"
// a machine word is big enough to hold a pointer

View File

@ -13,11 +13,11 @@
// TODO seems that CPython allows NULL byte in the input stream
// don't know if that's intentional or not, but we don't allow it
struct _py_lexer_t {
struct _mp_lexer_t {
const char *name; // name of source
void *stream_data; // data for stream
py_lexer_stream_next_char_t stream_next_char; // stream callback to get next char
py_lexer_stream_close_t stream_close; // stream callback to free
mp_lexer_stream_next_char_t stream_next_char; // stream callback to get next char
mp_lexer_stream_close_t stream_close; // stream callback to free
unichar chr0, chr1, chr2; // current cached characters from source
@ -32,7 +32,7 @@ struct _py_lexer_t {
uint16_t *indent_level;
vstr_t vstr;
py_token_t tok_cur;
mp_token_t tok_cur;
};
bool str_strn_equal(const char *str, const char *strn, int len) {
@ -47,7 +47,7 @@ bool str_strn_equal(const char *str, const char *strn, int len) {
return i == len && *str == 0;
}
void py_token_show(const py_token_t *tok) {
void mp_token_show(const mp_token_t *tok) {
printf("(%s:%d:%d) kind:%d str:%p len:%d", tok->src_name, tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
if (tok->str != NULL && tok->len > 0) {
const char *i = tok->str;
@ -66,83 +66,83 @@ void py_token_show(const py_token_t *tok) {
printf("\n");
}
void py_token_show_error_prefix(const py_token_t *tok) {
void mp_token_show_error_prefix(const mp_token_t *tok) {
printf("(%s:%d:%d) ", tok->src_name, tok->src_line, tok->src_column);
}
bool py_token_show_error(const py_token_t *tok, const char *msg) {
bool mp_token_show_error(const mp_token_t *tok, const char *msg) {
printf("(%s:%d:%d) %s\n", tok->src_name, tok->src_line, tok->src_column, msg);
return false;
}
#define CUR_CHAR(lex) ((lex)->chr0)
static bool is_end(py_lexer_t *lex) {
return lex->chr0 == PY_LEXER_CHAR_EOF;
static bool is_end(mp_lexer_t *lex) {
return lex->chr0 == MP_LEXER_CHAR_EOF;
}
static bool is_physical_newline(py_lexer_t *lex) {
static bool is_physical_newline(mp_lexer_t *lex) {
return lex->chr0 == '\n' || lex->chr0 == '\r';
}
static bool is_char(py_lexer_t *lex, char c) {
static bool is_char(mp_lexer_t *lex, char c) {
return lex->chr0 == c;
}
static bool is_char_or(py_lexer_t *lex, char c1, char c2) {
static bool is_char_or(mp_lexer_t *lex, char c1, char c2) {
return lex->chr0 == c1 || lex->chr0 == c2;
}
static bool is_char_or3(py_lexer_t *lex, char c1, char c2, char c3) {
static bool is_char_or3(mp_lexer_t *lex, char c1, char c2, char c3) {
return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;
}
/*
static bool is_char_following(py_lexer_t *lex, char c) {
static bool is_char_following(mp_lexer_t *lex, char c) {
return lex->chr1 == c;
}
*/
static bool is_char_following_or(py_lexer_t *lex, char c1, char c2) {
static bool is_char_following_or(mp_lexer_t *lex, char c1, char c2) {
return lex->chr1 == c1 || lex->chr1 == c2;
}
static bool is_char_following_following_or(py_lexer_t *lex, char c1, char c2) {
static bool is_char_following_following_or(mp_lexer_t *lex, char c1, char c2) {
return lex->chr2 == c1 || lex->chr2 == c2;
}
static bool is_char_and(py_lexer_t *lex, char c1, char c2) {
static bool is_char_and(mp_lexer_t *lex, char c1, char c2) {
return lex->chr0 == c1 && lex->chr1 == c2;
}
static bool is_whitespace(py_lexer_t *lex) {
static bool is_whitespace(mp_lexer_t *lex) {
return g_unichar_isspace(lex->chr0);
}
static bool is_letter(py_lexer_t *lex) {
static bool is_letter(mp_lexer_t *lex) {
return g_unichar_isalpha(lex->chr0);
}
static bool is_digit(py_lexer_t *lex) {
static bool is_digit(mp_lexer_t *lex) {
return g_unichar_isdigit(lex->chr0);
}
static bool is_following_digit(py_lexer_t *lex) {
static bool is_following_digit(mp_lexer_t *lex) {
return g_unichar_isdigit(lex->chr1);
}
// TODO UNICODE include unicode characters in definition of identifiers
static bool is_head_of_identifier(py_lexer_t *lex) {
static bool is_head_of_identifier(mp_lexer_t *lex) {
return is_letter(lex) || lex->chr0 == '_';
}
// TODO UNICODE include unicode characters in definition of identifiers
static bool is_tail_of_identifier(py_lexer_t *lex) {
static bool is_tail_of_identifier(mp_lexer_t *lex) {
return is_head_of_identifier(lex) || is_digit(lex);
}
static void next_char(py_lexer_t *lex) {
if (lex->chr0 == PY_LEXER_CHAR_EOF) {
static void next_char(mp_lexer_t *lex) {
if (lex->chr0 == MP_LEXER_CHAR_EOF) {
return;
}
@ -172,16 +172,16 @@ static void next_char(py_lexer_t *lex) {
lex->chr0 = lex->chr1;
lex->chr1 = lex->chr2;
lex->chr2 = lex->stream_next_char(lex->stream_data);
if (lex->chr2 == PY_LEXER_CHAR_EOF) {
if (lex->chr2 == MP_LEXER_CHAR_EOF) {
// EOF
if (lex->chr1 != PY_LEXER_CHAR_EOF && lex->chr1 != '\n' && lex->chr1 != '\r') {
if (lex->chr1 != MP_LEXER_CHAR_EOF && lex->chr1 != '\n' && lex->chr1 != '\r') {
lex->chr2 = '\n'; // insert newline at end of file
}
}
}
}
void indent_push(py_lexer_t *lex, uint indent) {
void indent_push(mp_lexer_t *lex, uint indent) {
if (lex->num_indent_level >= lex->alloc_indent_level) {
lex->alloc_indent_level *= 2;
lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level);
@ -189,11 +189,11 @@ void indent_push(py_lexer_t *lex, uint indent) {
lex->indent_level[lex->num_indent_level++] = indent;
}
uint indent_top(py_lexer_t *lex) {
uint indent_top(mp_lexer_t *lex) {
return lex->indent_level[lex->num_indent_level - 1];
}
void indent_pop(py_lexer_t *lex) {
void indent_pop(mp_lexer_t *lex) {
lex->num_indent_level -= 1;
}
@ -222,24 +222,24 @@ static const char *tok_enc =
// TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries
static const uint8_t tok_enc_kind[] = {
PY_TOKEN_DEL_PAREN_OPEN, PY_TOKEN_DEL_PAREN_CLOSE,
PY_TOKEN_DEL_BRACKET_OPEN, PY_TOKEN_DEL_BRACKET_CLOSE,
PY_TOKEN_DEL_BRACE_OPEN, PY_TOKEN_DEL_BRACE_CLOSE,
PY_TOKEN_DEL_COMMA, PY_TOKEN_DEL_COLON, PY_TOKEN_DEL_SEMICOLON, PY_TOKEN_DEL_AT, PY_TOKEN_OP_TILDE,
MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE,
MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE,
MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE,
MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_COLON, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_DEL_AT, MP_TOKEN_OP_TILDE,
PY_TOKEN_OP_LESS, PY_TOKEN_OP_LESS_EQUAL, PY_TOKEN_OP_DBL_LESS, PY_TOKEN_DEL_DBL_LESS_EQUAL,
PY_TOKEN_OP_MORE, PY_TOKEN_OP_MORE_EQUAL, PY_TOKEN_OP_DBL_MORE, PY_TOKEN_DEL_DBL_MORE_EQUAL,
PY_TOKEN_OP_STAR, PY_TOKEN_DEL_STAR_EQUAL, PY_TOKEN_OP_DBL_STAR, PY_TOKEN_DEL_DBL_STAR_EQUAL,
PY_TOKEN_OP_PLUS, PY_TOKEN_DEL_PLUS_EQUAL,
PY_TOKEN_OP_MINUS, PY_TOKEN_DEL_MINUS_EQUAL, PY_TOKEN_DEL_MINUS_MORE,
PY_TOKEN_OP_AMPERSAND, PY_TOKEN_DEL_AMPERSAND_EQUAL,
PY_TOKEN_OP_PIPE, PY_TOKEN_DEL_PIPE_EQUAL,
PY_TOKEN_OP_SLASH, PY_TOKEN_DEL_SLASH_EQUAL, PY_TOKEN_OP_DBL_SLASH, PY_TOKEN_DEL_DBL_SLASH_EQUAL,
PY_TOKEN_OP_PERCENT, PY_TOKEN_DEL_PERCENT_EQUAL,
PY_TOKEN_OP_CARET, PY_TOKEN_DEL_CARET_EQUAL,
PY_TOKEN_DEL_EQUAL, PY_TOKEN_OP_DBL_EQUAL,
PY_TOKEN_OP_NOT_EQUAL,
PY_TOKEN_DEL_PERIOD, PY_TOKEN_ELLIPSES,
MP_TOKEN_OP_LESS, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_DEL_DBL_LESS_EQUAL,
MP_TOKEN_OP_MORE, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_DEL_DBL_MORE_EQUAL,
MP_TOKEN_OP_STAR, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_OP_DBL_STAR, MP_TOKEN_DEL_DBL_STAR_EQUAL,
MP_TOKEN_OP_PLUS, MP_TOKEN_DEL_PLUS_EQUAL,
MP_TOKEN_OP_MINUS, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_MINUS_MORE,
MP_TOKEN_OP_AMPERSAND, MP_TOKEN_DEL_AMPERSAND_EQUAL,
MP_TOKEN_OP_PIPE, MP_TOKEN_DEL_PIPE_EQUAL,
MP_TOKEN_OP_SLASH, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_DEL_DBL_SLASH_EQUAL,
MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL,
MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
MP_TOKEN_DEL_PERIOD, MP_TOKEN_ELLIPSES,
};
// must have the same order as enum in lexer.h
@ -280,7 +280,7 @@ static const char *tok_kw[] = {
NULL,
};
static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool first_token) {
static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool first_token) {
// skip white space and comments
bool had_physical_newline = false;
while (!is_end(lex)) {
@ -322,18 +322,18 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
// if first token is not on first line, we get a physical newline and
// this check is done as part of normal indent/dedent checking below
// (done to get equivalence with CPython)
tok->kind = PY_TOKEN_INDENT;
tok->kind = MP_TOKEN_INDENT;
} else if (lex->emit_dent < 0) {
tok->kind = PY_TOKEN_DEDENT;
tok->kind = MP_TOKEN_DEDENT;
lex->emit_dent += 1;
} else if (lex->emit_dent > 0) {
tok->kind = PY_TOKEN_INDENT;
tok->kind = MP_TOKEN_INDENT;
lex->emit_dent -= 1;
} else if (had_physical_newline && lex->nested_bracket_level == 0) {
tok->kind = PY_TOKEN_NEWLINE;
tok->kind = MP_TOKEN_NEWLINE;
uint num_spaces = lex->column - 1;
lex->emit_dent = 0;
@ -347,20 +347,20 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
lex->emit_dent -= 1;
}
if (num_spaces != indent_top(lex)) {
tok->kind = PY_TOKEN_DEDENT_MISMATCH;
tok->kind = MP_TOKEN_DEDENT_MISMATCH;
}
}
} else if (is_end(lex)) {
if (indent_top(lex) > 0) {
tok->kind = PY_TOKEN_NEWLINE;
tok->kind = MP_TOKEN_NEWLINE;
lex->emit_dent = 0;
while (indent_top(lex) > 0) {
indent_pop(lex);
lex->emit_dent -= 1;
}
} else {
tok->kind = PY_TOKEN_END;
tok->kind = MP_TOKEN_END;
}
} else if (is_char_or(lex, '\'', '\"')
@ -391,9 +391,9 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
// set token kind
if (is_bytes) {
tok->kind = PY_TOKEN_BYTES;
tok->kind = MP_TOKEN_BYTES;
} else {
tok->kind = PY_TOKEN_STRING;
tok->kind = MP_TOKEN_STRING;
}
// get first quoting character
@ -427,8 +427,8 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
next_char(lex);
unichar c = CUR_CHAR(lex);
switch (c) {
case PY_LEXER_CHAR_EOF: break; // TODO a proper error message?
case '\n': c = PY_LEXER_CHAR_EOF; break; // TODO check this works correctly (we are supposed to ignore it
case MP_LEXER_CHAR_EOF: break; // TODO a proper error message?
case '\n': c = MP_LEXER_CHAR_EOF; break; // TODO check this works correctly (we are supposed to ignore it
case '\\': break;
case '\'': break;
case '"': break;
@ -446,7 +446,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
case 'U': // TODO \Uxxxxxxxx only in strings
default: break; // TODO error message
}
if (c != PY_LEXER_CHAR_EOF) {
if (c != MP_LEXER_CHAR_EOF) {
vstr_add_char(&lex->vstr, c);
}
} else {
@ -458,14 +458,14 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
// check we got the required end quotes
if (n_closing < num_quotes) {
tok->kind = PY_TOKEN_LONELY_STRING_OPEN;
tok->kind = MP_TOKEN_LONELY_STRING_OPEN;
}
// cut off the end quotes from the token text
vstr_cut_tail(&lex->vstr, n_closing);
} else if (is_head_of_identifier(lex)) {
tok->kind = PY_TOKEN_NAME;
tok->kind = MP_TOKEN_NAME;
// get first char
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
@ -478,7 +478,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
}
} else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
tok->kind = PY_TOKEN_NUMBER;
tok->kind = MP_TOKEN_NUMBER;
// get first char
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
@ -520,7 +520,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
if (*t == 0) {
// didn't match any delimiter or operator characters
tok->kind = PY_TOKEN_INVALID;
tok->kind = MP_TOKEN_INVALID;
} else {
// matched a delimiter or operator character
@ -545,7 +545,7 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
next_char(lex);
tok_enc_index = t_index;
} else {
tok->kind = PY_TOKEN_INVALID;
tok->kind = MP_TOKEN_INVALID;
}
break;
}
@ -569,9 +569,9 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
tok->kind = tok_enc_kind[tok_enc_index];
// compute bracket level for implicit line joining
if (tok->kind == PY_TOKEN_DEL_PAREN_OPEN || tok->kind == PY_TOKEN_DEL_BRACKET_OPEN || tok->kind == PY_TOKEN_DEL_BRACE_OPEN) {
if (tok->kind == MP_TOKEN_DEL_PAREN_OPEN || tok->kind == MP_TOKEN_DEL_BRACKET_OPEN || tok->kind == MP_TOKEN_DEL_BRACE_OPEN) {
lex->nested_bracket_level += 1;
} else if (tok->kind == PY_TOKEN_DEL_PAREN_CLOSE || tok->kind == PY_TOKEN_DEL_BRACKET_CLOSE || tok->kind == PY_TOKEN_DEL_BRACE_CLOSE) {
} else if (tok->kind == MP_TOKEN_DEL_PAREN_CLOSE || tok->kind == MP_TOKEN_DEL_BRACKET_CLOSE || tok->kind == MP_TOKEN_DEL_BRACE_CLOSE) {
lex->nested_bracket_level -= 1;
}
}
@ -582,18 +582,18 @@ static void py_lexer_next_token_into(py_lexer_t *lex, py_token_t *tok, bool firs
tok->len = vstr_len(&lex->vstr);
// check for keywords
if (tok->kind == PY_TOKEN_NAME) {
if (tok->kind == MP_TOKEN_NAME) {
for (int i = 0; tok_kw[i] != NULL; i++) {
if (str_strn_equal(tok_kw[i], tok->str, tok->len)) {
tok->kind = PY_TOKEN_KW_FALSE + i;
tok->kind = MP_TOKEN_KW_FALSE + i;
break;
}
}
}
}
py_lexer_t *py_lexer_new(const char *src_name, void *stream_data, py_lexer_stream_next_char_t stream_next_char, py_lexer_stream_close_t stream_close) {
py_lexer_t *lex = m_new(py_lexer_t, 1);
mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close) {
mp_lexer_t *lex = m_new(mp_lexer_t, 1);
lex->name = src_name; // TODO do we need to strdup this?
lex->stream_data = stream_data;
@ -615,25 +615,25 @@ py_lexer_t *py_lexer_new(const char *src_name, void *stream_data, py_lexer_strea
lex->chr2 = stream_next_char(stream_data);
// if input stream is 0, 1 or 2 characters long and doesn't end in a newline, then insert a newline at the end
if (lex->chr0 == PY_LEXER_CHAR_EOF) {
if (lex->chr0 == MP_LEXER_CHAR_EOF) {
lex->chr0 = '\n';
} else if (lex->chr1 == PY_LEXER_CHAR_EOF) {
} else if (lex->chr1 == MP_LEXER_CHAR_EOF) {
if (lex->chr0 != '\n' && lex->chr0 != '\r') {
lex->chr1 = '\n';
}
} else if (lex->chr2 == PY_LEXER_CHAR_EOF) {
} else if (lex->chr2 == MP_LEXER_CHAR_EOF) {
if (lex->chr1 != '\n' && lex->chr1 != '\r') {
lex->chr2 = '\n';
}
}
// preload first token
py_lexer_next_token_into(lex, &lex->tok_cur, true);
mp_lexer_next_token_into(lex, &lex->tok_cur, true);
return lex;
}
void py_lexer_free(py_lexer_t *lex) {
void mp_lexer_free(mp_lexer_t *lex) {
if (lex) {
if (lex->stream_close) {
lex->stream_close(lex->stream_data);
@ -643,45 +643,45 @@ void py_lexer_free(py_lexer_t *lex) {
}
}
void py_lexer_to_next(py_lexer_t *lex) {
py_lexer_next_token_into(lex, &lex->tok_cur, false);
void mp_lexer_to_next(mp_lexer_t *lex) {
mp_lexer_next_token_into(lex, &lex->tok_cur, false);
}
const py_token_t *py_lexer_cur(const py_lexer_t *lex) {
const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex) {
return &lex->tok_cur;
}
bool py_lexer_is_kind(py_lexer_t *lex, py_token_kind_t kind) {
bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind) {
return lex->tok_cur.kind == kind;
}
/*
bool py_lexer_is_str(py_lexer_t *lex, const char *str) {
return py_token_is_str(&lex->tok_cur, str);
bool mp_lexer_is_str(mp_lexer_t *lex, const char *str) {
return mp_token_is_str(&lex->tok_cur, str);
}
bool py_lexer_opt_kind(py_lexer_t *lex, py_token_kind_t kind) {
if (py_lexer_is_kind(lex, kind)) {
py_lexer_to_next(lex);
bool mp_lexer_opt_kind(mp_lexer_t *lex, mp_token_kind_t kind) {
if (mp_lexer_is_kind(lex, kind)) {
mp_lexer_to_next(lex);
return true;
}
return false;
}
bool py_lexer_opt_str(py_lexer_t *lex, const char *str) {
if (py_lexer_is_str(lex, str)) {
py_lexer_to_next(lex);
bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str) {
if (mp_lexer_is_str(lex, str)) {
mp_lexer_to_next(lex);
return true;
}
return false;
}
*/
bool py_lexer_show_error(py_lexer_t *lex, const char *msg) {
return py_token_show_error(&lex->tok_cur, msg);
bool mp_lexer_show_error(mp_lexer_t *lex, const char *msg) {
return mp_token_show_error(&lex->tok_cur, msg);
}
bool py_lexer_show_error_pythonic(py_lexer_t *lex, const char *msg) {
bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg) {
printf(" File \"%s\", line %d column %d\n%s\n", lex->tok_cur.src_name, lex->tok_cur.src_line, lex->tok_cur.src_column, msg);
return false;
}

View File

@ -1,146 +1,140 @@
/* lexer.h -- simple tokeniser for Python implementation
/* lexer.h -- simple tokeniser for Micro Python
*
* Uses (byte) length instead of null termination.
* Tokens are the same - UTF-8 with (byte) length.
*/
#ifndef INCLUDED_LEXER_H
#define INCLUDED_LEXER_H
typedef enum _mp_token_kind_t {
MP_TOKEN_END, // 0
/* uses (byte) length instead of null termination
* tokens are the same - UTF-8 with (byte) length
*/
MP_TOKEN_INVALID,
MP_TOKEN_DEDENT_MISMATCH,
MP_TOKEN_LONELY_STRING_OPEN,
typedef enum _py_token_kind_t {
PY_TOKEN_END, // 0
MP_TOKEN_NEWLINE, // 4
MP_TOKEN_INDENT, // 5
MP_TOKEN_DEDENT, // 6
PY_TOKEN_INVALID,
PY_TOKEN_DEDENT_MISMATCH,
PY_TOKEN_LONELY_STRING_OPEN,
MP_TOKEN_NAME, // 7
MP_TOKEN_NUMBER,
MP_TOKEN_STRING,
MP_TOKEN_BYTES,
PY_TOKEN_NEWLINE, // 4
PY_TOKEN_INDENT, // 5
PY_TOKEN_DEDENT, // 6
MP_TOKEN_ELLIPSES,
PY_TOKEN_NAME, // 7
PY_TOKEN_NUMBER,
PY_TOKEN_STRING,
PY_TOKEN_BYTES,
MP_TOKEN_KW_FALSE, // 12
MP_TOKEN_KW_NONE,
MP_TOKEN_KW_TRUE,
MP_TOKEN_KW_AND,
MP_TOKEN_KW_AS,
MP_TOKEN_KW_ASSERT,
MP_TOKEN_KW_BREAK,
MP_TOKEN_KW_CLASS,
MP_TOKEN_KW_CONTINUE,
MP_TOKEN_KW_DEF, // 21
MP_TOKEN_KW_DEL,
MP_TOKEN_KW_ELIF,
MP_TOKEN_KW_ELSE,
MP_TOKEN_KW_EXCEPT,
MP_TOKEN_KW_FINALLY,
MP_TOKEN_KW_FOR,
MP_TOKEN_KW_FROM,
MP_TOKEN_KW_GLOBAL,
MP_TOKEN_KW_IF,
MP_TOKEN_KW_IMPORT, // 31
MP_TOKEN_KW_IN,
MP_TOKEN_KW_IS,
MP_TOKEN_KW_LAMBDA,
MP_TOKEN_KW_NONLOCAL,
MP_TOKEN_KW_NOT,
MP_TOKEN_KW_OR,
MP_TOKEN_KW_PASS,
MP_TOKEN_KW_RAISE,
MP_TOKEN_KW_RETURN,
MP_TOKEN_KW_TRY, // 41
MP_TOKEN_KW_WHILE,
MP_TOKEN_KW_WITH,
MP_TOKEN_KW_YIELD,
PY_TOKEN_ELLIPSES,
MP_TOKEN_OP_PLUS, // 45
MP_TOKEN_OP_MINUS,
MP_TOKEN_OP_STAR,
MP_TOKEN_OP_DBL_STAR,
MP_TOKEN_OP_SLASH,
MP_TOKEN_OP_DBL_SLASH,
MP_TOKEN_OP_PERCENT,
MP_TOKEN_OP_LESS,
MP_TOKEN_OP_DBL_LESS,
MP_TOKEN_OP_MORE,
MP_TOKEN_OP_DBL_MORE, // 55
MP_TOKEN_OP_AMPERSAND,
MP_TOKEN_OP_PIPE,
MP_TOKEN_OP_CARET,
MP_TOKEN_OP_TILDE,
MP_TOKEN_OP_LESS_EQUAL,
MP_TOKEN_OP_MORE_EQUAL,
MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
PY_TOKEN_KW_FALSE, // 12
PY_TOKEN_KW_NONE,
PY_TOKEN_KW_TRUE,
PY_TOKEN_KW_AND,
PY_TOKEN_KW_AS,
PY_TOKEN_KW_ASSERT,
PY_TOKEN_KW_BREAK,
PY_TOKEN_KW_CLASS,
PY_TOKEN_KW_CONTINUE,
PY_TOKEN_KW_DEF, // 21
PY_TOKEN_KW_DEL,
PY_TOKEN_KW_ELIF,
PY_TOKEN_KW_ELSE,
PY_TOKEN_KW_EXCEPT,
PY_TOKEN_KW_FINALLY,
PY_TOKEN_KW_FOR,
PY_TOKEN_KW_FROM,
PY_TOKEN_KW_GLOBAL,
PY_TOKEN_KW_IF,
PY_TOKEN_KW_IMPORT, // 31
PY_TOKEN_KW_IN,
PY_TOKEN_KW_IS,
PY_TOKEN_KW_LAMBDA,
PY_TOKEN_KW_NONLOCAL,
PY_TOKEN_KW_NOT,
PY_TOKEN_KW_OR,
PY_TOKEN_KW_PASS,
PY_TOKEN_KW_RAISE,
PY_TOKEN_KW_RETURN,
PY_TOKEN_KW_TRY, // 41
PY_TOKEN_KW_WHILE,
PY_TOKEN_KW_WITH,
PY_TOKEN_KW_YIELD,
MP_TOKEN_DEL_PAREN_OPEN, // 64
MP_TOKEN_DEL_PAREN_CLOSE,
MP_TOKEN_DEL_BRACKET_OPEN,
MP_TOKEN_DEL_BRACKET_CLOSE,
MP_TOKEN_DEL_BRACE_OPEN,
MP_TOKEN_DEL_BRACE_CLOSE,
MP_TOKEN_DEL_COMMA,
MP_TOKEN_DEL_COLON,
MP_TOKEN_DEL_PERIOD,
MP_TOKEN_DEL_SEMICOLON,
MP_TOKEN_DEL_AT, // 74
MP_TOKEN_DEL_EQUAL,
MP_TOKEN_DEL_PLUS_EQUAL,
MP_TOKEN_DEL_MINUS_EQUAL,
MP_TOKEN_DEL_STAR_EQUAL,
MP_TOKEN_DEL_SLASH_EQUAL,
MP_TOKEN_DEL_DBL_SLASH_EQUAL,
MP_TOKEN_DEL_PERCENT_EQUAL,
MP_TOKEN_DEL_AMPERSAND_EQUAL,
MP_TOKEN_DEL_PIPE_EQUAL,
MP_TOKEN_DEL_CARET_EQUAL, // 84
MP_TOKEN_DEL_DBL_MORE_EQUAL,
MP_TOKEN_DEL_DBL_LESS_EQUAL,
MP_TOKEN_DEL_DBL_STAR_EQUAL,
MP_TOKEN_DEL_MINUS_MORE,
} mp_token_kind_t;
PY_TOKEN_OP_PLUS, // 45
PY_TOKEN_OP_MINUS,
PY_TOKEN_OP_STAR,
PY_TOKEN_OP_DBL_STAR,
PY_TOKEN_OP_SLASH,
PY_TOKEN_OP_DBL_SLASH,
PY_TOKEN_OP_PERCENT,
PY_TOKEN_OP_LESS,
PY_TOKEN_OP_DBL_LESS,
PY_TOKEN_OP_MORE,
PY_TOKEN_OP_DBL_MORE, // 55
PY_TOKEN_OP_AMPERSAND,
PY_TOKEN_OP_PIPE,
PY_TOKEN_OP_CARET,
PY_TOKEN_OP_TILDE,
PY_TOKEN_OP_LESS_EQUAL,
PY_TOKEN_OP_MORE_EQUAL,
PY_TOKEN_OP_DBL_EQUAL,
PY_TOKEN_OP_NOT_EQUAL,
PY_TOKEN_DEL_PAREN_OPEN, // 64
PY_TOKEN_DEL_PAREN_CLOSE,
PY_TOKEN_DEL_BRACKET_OPEN,
PY_TOKEN_DEL_BRACKET_CLOSE,
PY_TOKEN_DEL_BRACE_OPEN,
PY_TOKEN_DEL_BRACE_CLOSE,
PY_TOKEN_DEL_COMMA,
PY_TOKEN_DEL_COLON,
PY_TOKEN_DEL_PERIOD,
PY_TOKEN_DEL_SEMICOLON,
PY_TOKEN_DEL_AT, // 74
PY_TOKEN_DEL_EQUAL,
PY_TOKEN_DEL_PLUS_EQUAL,
PY_TOKEN_DEL_MINUS_EQUAL,
PY_TOKEN_DEL_STAR_EQUAL,
PY_TOKEN_DEL_SLASH_EQUAL,
PY_TOKEN_DEL_DBL_SLASH_EQUAL,
PY_TOKEN_DEL_PERCENT_EQUAL,
PY_TOKEN_DEL_AMPERSAND_EQUAL,
PY_TOKEN_DEL_PIPE_EQUAL,
PY_TOKEN_DEL_CARET_EQUAL, // 84
PY_TOKEN_DEL_DBL_MORE_EQUAL,
PY_TOKEN_DEL_DBL_LESS_EQUAL,
PY_TOKEN_DEL_DBL_STAR_EQUAL,
PY_TOKEN_DEL_MINUS_MORE,
} py_token_kind_t;
typedef struct _py_token_t {
typedef struct _mp_token_t {
const char *src_name; // name of source
uint src_line; // source line
uint src_column; // source column
py_token_kind_t kind; // kind of token
mp_token_kind_t kind; // kind of token
const char *str; // string of token (valid only while this token is current token)
uint len; // (byte) length of string of token
} py_token_t;
} mp_token_t;
// the next-char function must return the next character in the stream
// it must return PY_LEXER_CHAR_EOF if end of stream
// it can be called again after returning PY_LEXER_CHAR_EOF, and in that case must return PY_LEXER_CHAR_EOF
#define PY_LEXER_CHAR_EOF (-1)
typedef unichar (*py_lexer_stream_next_char_t)(void*);
typedef void (*py_lexer_stream_close_t)(void*);
// it must return MP_LEXER_CHAR_EOF if end of stream
// it can be called again after returning MP_LEXER_CHAR_EOF, and in that case must return MP_LEXER_CHAR_EOF
#define MP_LEXER_CHAR_EOF (-1)
typedef unichar (*mp_lexer_stream_next_char_t)(void*);
typedef void (*mp_lexer_stream_close_t)(void*);
typedef struct _py_lexer_t py_lexer_t;
typedef struct _mp_lexer_t mp_lexer_t;
void py_token_show(const py_token_t *tok);
void py_token_show_error_prefix(const py_token_t *tok);
bool py_token_show_error(const py_token_t *tok, const char *msg);
void mp_token_show(const mp_token_t *tok);
void mp_token_show_error_prefix(const mp_token_t *tok);
bool mp_token_show_error(const mp_token_t *tok, const char *msg);
py_lexer_t *py_lexer_new(const char *src_name, void *stream_data, py_lexer_stream_next_char_t stream_next_char, py_lexer_stream_close_t stream_close);
void py_lexer_free(py_lexer_t *lex);
void py_lexer_to_next(py_lexer_t *lex);
const py_token_t *py_lexer_cur(const py_lexer_t *lex);
bool py_lexer_is_kind(py_lexer_t *lex, py_token_kind_t kind);
mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close);
void mp_lexer_free(mp_lexer_t *lex);
void mp_lexer_to_next(mp_lexer_t *lex);
const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex);
bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind);
/* unused
bool py_lexer_is_str(py_lexer_t *lex, const char *str);
bool py_lexer_opt_kind(py_lexer_t *lex, py_token_kind_t kind);
bool py_lexer_opt_str(py_lexer_t *lex, const char *str);
bool mp_lexer_is_str(mp_lexer_t *lex, const char *str);
bool mp_lexer_opt_kind(mp_lexer_t *lex, mp_token_kind_t kind);
bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str);
*/
bool py_lexer_show_error(py_lexer_t *lex, const char *msg);
bool py_lexer_show_error_pythonic(py_lexer_t *lex, const char *msg);
#endif /* INCLUDED_LEXER_H */
bool mp_lexer_show_error(mp_lexer_t *lex, const char *msg);
bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg);

View File

@ -3,12 +3,10 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "runtime.h"
#include "map.h"
#include "mpconfig.h"
#include "obj.h"
#include "objprivate.h"
#include "runtime0.h"
#include "map.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};
@ -24,43 +22,46 @@ int get_doubling_prime_greater_or_equal_to(int x) {
return x | 1;
}
void py_map_init(py_map_t *map, py_map_kind_t kind, int n) {
/******************************************************************************/
/* map */
void mp_map_init(mp_map_t *map, mp_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);
map->table = m_new0(mp_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);
mp_map_t *mp_map_new(mp_map_kind_t kind, int n) {
mp_map_t *map = m_new(mp_map_t, 1);
mp_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);
mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_not_found) {
bool is_map_mp_obj = (map->kind == MP_MAP_OBJ);
machine_uint_t hash;
if (is_map_py_obj) {
hash = py_obj_hash(index);
if (is_map_mp_obj) {
hash = mp_obj_hash(index);
} else {
hash = (machine_uint_t)index;
}
uint pos = hash % map->alloc;
for (;;) {
py_map_elem_t *elem = &map->table[pos];
mp_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;
mp_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);
map->table = m_new0(mp_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;
mp_map_lookup_helper(map, old_table[i].key, true)->value = old_table[i].value;
}
}
m_free(old_table);
@ -74,7 +75,7 @@ py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_n
} else {
return NULL;
}
} else if (elem->key == index || (is_map_py_obj && py_obj_equal(elem->key, index))) {
} else if (elem->key == index || (is_map_mp_obj && mp_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) {
@ -89,55 +90,57 @@ py_map_elem_t* py_map_lookup_helper(py_map_t *map, py_obj_t index, bool add_if_n
}
}
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);
mp_map_elem_t* mp_qstr_map_lookup(mp_map_t *map, qstr index, bool add_if_not_found) {
mp_obj_t o = (mp_obj_t)(machine_uint_t)index;
return mp_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);
/******************************************************************************/
/* set */
void mp_set_init(mp_set_t *set, int n) {
set->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
set->used = 0;
set->table = m_new0(mp_obj_t, set->alloc);
}
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;
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) {
int hash = mp_obj_hash(index);
int pos = hash % set->alloc;
for (;;) {
py_obj_t elem = o->u_set.table[pos];
if (elem == NULL) {
mp_obj_t elem = set->table[pos];
if (elem == MP_OBJ_NULL) {
// not in table
if (add_if_not_found) {
if (o->u_set.used + 1 >= o->u_set.alloc) {
if (set->used + 1 >= 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);
int old_alloc = set->alloc;
mp_obj_t *old_table = set->table;
set->alloc = get_doubling_prime_greater_or_equal_to(set->alloc + 1);
set->used = 0;
set->table = m_new(mp_obj_t, set->alloc);
for (int i = 0; i < old_alloc; i++) {
if (old_table[i] != NULL) {
py_set_lookup(o, old_table[i], true);
mp_set_lookup(set, old_table[i], true);
}
}
m_free(old_table);
// restart the search for the new element
pos = hash % o->u_set.alloc;
pos = hash % set->alloc;
} else {
o->u_set.used += 1;
o->u_set.table[pos] = index;
set->used += 1;
set->table[pos] = index;
return index;
}
} else {
return NULL;
return MP_OBJ_NULL;
}
} else if (py_obj_equal(elem, index)) {
} else if (mp_obj_equal(elem, index)) {
// found it
return elem;
} else {
// not yet found, keep searching in this table
pos = (pos + 1) % o->u_set.alloc;
pos = (pos + 1) % set->alloc;
}
}
}

View File

@ -1,30 +1,37 @@
typedef enum {
MAP_QSTR,
MAP_PY_OBJ,
} py_map_kind_t;
MP_MAP_QSTR,
MP_MAP_OBJ,
} mp_map_kind_t;
typedef struct _py_map_elem_t {
py_obj_t key;
py_obj_t value;
} py_map_elem_t;
typedef struct _mp_map_elem_t {
mp_obj_t key;
mp_obj_t value;
} mp_map_elem_t;
typedef struct _py_map_t {
typedef struct _mp_map_t {
struct {
py_map_kind_t kind : 1;
mp_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;
mp_map_elem_t *table;
} mp_map_t;
typedef struct _mp_set_t {
machine_uint_t alloc;
machine_uint_t used;
mp_obj_t *table;
} mp_set_t;
// these are defined in runtime.c
py_map_t *rt_get_map_locals(void);
void rt_set_map_locals(py_map_t *m);
mp_map_t *rt_get_map_locals(void);
void rt_set_map_locals(mp_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);
void mp_map_init(mp_map_t *map, mp_map_kind_t kind, int n);
mp_map_t *mp_map_new(mp_map_kind_t kind, int n);
mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_not_found);
mp_map_elem_t* mp_qstr_map_lookup(mp_map_t *map, qstr index, bool add_if_not_found);
void mp_set_init(mp_set_t *set, int n);
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found);

View File

@ -19,6 +19,8 @@ typedef unsigned int uint;
#define m_new(type, num) ((type*)(m_malloc(sizeof(type) * (num))))
#define m_new0(type, num) ((type*)(m_malloc0(sizeof(type) * (num))))
#define m_renew(type, ptr, num) ((type*)(m_realloc((ptr), sizeof(type) * (num))))
#define m_new_obj(type) (m_new(type, 1))
#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type*)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num)))
void m_free(void *ptr);
void *m_malloc(int num_bytes);

446
py/obj.c
View File

@ -6,166 +6,22 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "runtime.h"
#include "map.h"
#include "mpconfig.h"
#include "obj.h"
#include "objprivate.h"
#include "runtime0.h"
#include "runtime.h"
#include "map.h"
py_obj_t py_obj_new_int(machine_int_t value) {
return TO_SMALL_INT(value);
mp_obj_t mp_obj_new_int(machine_int_t value) {
return MP_OBJ_NEW_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)) {
const char *mp_obj_get_type_str(mp_obj_t o_in) {
if (MP_OBJ_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";
}
mp_obj_base_t *o = o_in;
return o->type->name;
}
}
@ -176,148 +32,43 @@ void printf_wrapper(void *env, const char *fmt, ...) {
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));
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
print(env, "%d", (int)MP_OBJ_SMALL_INT_VALUE(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);
mp_obj_base_t *o = o_in;
if (o->type->print != NULL) {
o->type->print(print, env, o_in);
} else {
print(env, "<%s>", o->type->name);
}
}
}
void py_obj_print(py_obj_t o_in) {
py_obj_print_helper(printf_wrapper, NULL, o_in);
void mp_obj_print(mp_obj_t o_in) {
mp_obj_print_helper(printf_wrapper, NULL, o_in);
}
bool py_obj_is_callable(py_obj_t o_in) {
if (IS_SMALL_INT(o_in)) {
bool mp_obj_is_callable(mp_obj_t o_in) {
if (MP_OBJ_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;
}
mp_obj_base_t *o = o_in;
return o->type->call_n != NULL;
}
}
machine_int_t py_obj_hash(py_obj_t o_in) {
if (o_in == py_const_false) {
machine_int_t mp_obj_hash(mp_obj_t o_in) {
if (o_in == mp_const_false) {
return 0; // needs to hash to same as the integer 0, since False==0
} else if (o_in == py_const_true) {
} else if (o_in == mp_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)) {
} else if (MP_OBJ_IS_SMALL_INT(o_in)) {
return MP_OBJ_SMALL_INT_VALUE(o_in);
} else if (MP_OBJ_IS_TYPE(o_in, &none_type)) {
return (machine_int_t)o_in;
} else if (IS_O(o_in, O_STR)) {
return ((py_obj_base_t*)o_in)->u_str;
} else if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
return mp_obj_str_get(o_in);
} else {
assert(0);
return 0;
@ -330,38 +81,38 @@ machine_int_t py_obj_hash(py_obj_t o_in) {
// to a common type. Otherwise, the == and != operators always consider objects of
// different types to be unequal."
// note also that False==0 and True==1 are true expressions
bool py_obj_equal(py_obj_t o1, py_obj_t o2) {
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
if (o1 == o2) {
return true;
} else if (IS_SMALL_INT(o1) || IS_SMALL_INT(o2)) {
if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
} else if (MP_OBJ_IS_SMALL_INT(o1) || MP_OBJ_IS_SMALL_INT(o2)) {
if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) {
return false;
} else {
if (IS_SMALL_INT(o2)) {
py_obj_t temp = o1; o1 = o2; o2 = temp;
if (MP_OBJ_IS_SMALL_INT(o2)) {
mp_obj_t temp = o1; o1 = o2; o2 = temp;
}
// o1 is the SMALL_INT, o2 is not
py_small_int_t val = FROM_SMALL_INT(o1);
if (o2 == py_const_false) {
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o1);
if (o2 == mp_const_false) {
return val == 0;
} else if (o2 == py_const_true) {
} else if (o2 == mp_const_true) {
return val == 1;
} else {
return false;
}
}
} else if (IS_O(o1, O_STR) && IS_O(o2, O_STR)) {
return ((py_obj_base_t*)o1)->u_str == ((py_obj_base_t*)o2)->u_str;
} else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) {
return mp_obj_str_get(o1) == mp_obj_str_get(o2);
} else {
assert(0);
return false;
}
}
bool py_obj_less(py_obj_t o1, py_obj_t o2) {
if (IS_SMALL_INT(o1) && IS_SMALL_INT(o2)) {
py_small_int_t i1 = FROM_SMALL_INT(o1);
py_small_int_t i2 = FROM_SMALL_INT(o2);
bool mp_obj_less(mp_obj_t o1, mp_obj_t o2) {
if (MP_OBJ_IS_SMALL_INT(o1) && MP_OBJ_IS_SMALL_INT(o2)) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1);
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2);
return i1 < i2;
} else {
assert(0);
@ -369,13 +120,13 @@ bool py_obj_less(py_obj_t o1, py_obj_t o2) {
}
}
machine_int_t py_obj_get_int(py_obj_t arg) {
if (arg == py_const_false) {
machine_int_t mp_obj_get_int(mp_obj_t arg) {
if (arg == mp_const_false) {
return 0;
} else if (arg == py_const_true) {
} else if (arg == mp_const_true) {
return 1;
} else if (IS_SMALL_INT(arg)) {
return FROM_SMALL_INT(arg);
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
return MP_OBJ_SMALL_INT_VALUE(arg);
} else {
assert(0);
return 0;
@ -383,37 +134,36 @@ machine_int_t py_obj_get_int(py_obj_t arg) {
}
#if MICROPY_ENABLE_FLOAT
machine_float_t py_obj_get_float(py_obj_t arg) {
if (arg == py_const_false) {
machine_float_t mp_obj_get_float(mp_obj_t arg) {
if (arg == mp_const_false) {
return 0;
} else if (arg == py_const_true) {
} else if (arg == mp_const_true) {
return 1;
} else if (IS_SMALL_INT(arg)) {
return FROM_SMALL_INT(arg);
} else if (IS_O(arg, O_FLOAT)) {
return ((py_obj_base_t*)arg)->u_float;
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
return MP_OBJ_SMALL_INT_VALUE(arg);
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
return mp_obj_float_get(arg);
} else {
assert(0);
return 0;
}
}
void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) {
if (arg == py_const_false) {
void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
if (arg == mp_const_false) {
*real = 0;
*imag = 0;
} else if (arg == py_const_true) {
} else if (arg == mp_const_true) {
*real = 1;
*imag = 0;
} else if (IS_SMALL_INT(arg)) {
*real = FROM_SMALL_INT(arg);
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
*real = MP_OBJ_SMALL_INT_VALUE(arg);
*imag = 0;
} else if (IS_O(arg, O_FLOAT)) {
*real = ((py_obj_base_t*)arg)->u_float;
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
*real = mp_obj_float_get(arg);
*imag = 0;
} else if (IS_O(arg, O_COMPLEX)) {
*real = ((py_obj_base_t*)arg)->u_complex.real;
*imag = ((py_obj_base_t*)arg)->u_complex.imag;
} else if (MP_OBJ_IS_TYPE(arg, &complex_type)) {
mp_obj_complex_get(arg, real, imag);
} else {
assert(0);
*real = 0;
@ -422,49 +172,45 @@ void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag) {
}
#endif
qstr py_obj_get_qstr(py_obj_t arg) {
if (IS_O(arg, O_STR)) {
return ((py_obj_base_t*)arg)->u_str;
qstr mp_obj_get_qstr(mp_obj_t arg) {
if (MP_OBJ_IS_TYPE(arg, &str_type)) {
return mp_obj_str_get(arg);
} else {
assert(0);
return 0;
}
}
py_obj_t *py_obj_get_array_fixed_n(py_obj_t o_in, machine_int_t n) {
if (IS_O(o_in, O_TUPLE) || IS_O(o_in, O_LIST)) {
py_obj_base_t *o = o_in;
if (o->u_tuple_list.len != n) {
nlr_jump(py_obj_new_exception_2(rt_q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)o->u_tuple_list.len));
mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) {
if (MP_OBJ_IS_TYPE(o_in, &tuple_type) || MP_OBJ_IS_TYPE(o_in, &list_type)) {
uint seq_len;
mp_obj_t *seq_items;
if (MP_OBJ_IS_TYPE(o_in, &tuple_type)) {
mp_obj_tuple_get(o_in, &seq_len, &seq_items);
} else {
mp_obj_list_get(o_in, &seq_len, &seq_items);
}
return o->u_tuple_list.items;
if (seq_len != n) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len));
}
return seq_items;
} else {
nlr_jump(py_obj_new_exception_2(rt_q_TypeError, "object '%s' is not a tuple or list", py_obj_get_type_str(o_in), NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in)));
}
}
void py_user_get_data(py_obj_t o, machine_uint_t *data1, machine_uint_t *data2) {
assert(IS_O(o, O_USER));
if (data1 != NULL) {
*data1 = ((py_obj_base_t*)o)->u_user.data1;
}
if (data2 != NULL) {
*data2 = ((py_obj_base_t*)o)->u_user.data2;
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index) {
// TODO False and True are considered 0 and 1 for indexing purposes
if (MP_OBJ_IS_SMALL_INT(index)) {
int i = MP_OBJ_SMALL_INT_VALUE(index);
if (i < 0) {
i += len;
}
if (i < 0 || i >= len) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_IndexError, "%s index out of range", type->name));
}
return i;
} else {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index)));
}
}
void py_user_set_data(py_obj_t o, machine_uint_t data1, machine_uint_t data2) {
assert(IS_O(o, O_USER));
((py_obj_base_t*)o)->u_user.data1 = data1;
((py_obj_base_t*)o)->u_user.data2 = data2;
}
// temporary way of making C modules
// hack: use class to mimic a module
py_obj_t py_module_new(void) {
py_obj_base_t *o = m_new(py_obj_base_t, 1);
o->kind = O_CLASS;
o->u_class.locals = py_map_new(MAP_QSTR, 0);
return o;
}

270
py/obj.h
View File

@ -1,56 +1,238 @@
typedef machine_int_t py_small_int_t; // do we need to expose this in the public API?
// All Micro Python objects are at least this type
// It must be of pointer size
typedef machine_ptr_t mp_obj_t;
typedef machine_const_ptr_t mp_const_obj_t;
// Integers that fit in a pointer have this type
// (do we need to expose this in the public API?)
typedef machine_int_t mp_small_int_t;
// The machine floating-point type used for float and complex numbers
#if MICROPY_ENABLE_FLOAT
typedef machine_float_t py_float_t;
typedef machine_float_t mp_float_t;
#endif
// user defined objects
// Anything that wants to be a Micro Python object must
// have mp_obj_base_t as its first member (except NULL and small ints)
typedef struct _py_user_method_t {
typedef struct _mp_obj_base_t mp_obj_base_t;
typedef struct _mp_obj_type_t mp_obj_type_t;
struct _mp_obj_base_t {
const mp_obj_type_t *type;
};
// The NULL object is used to indicate the absence of an object
// It *cannot* be used when an mp_obj_t is expected, except where explicitly allowed
#define MP_OBJ_NULL ((mp_obj_t)NULL)
// These macros check for small int or object, and access small int values
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 1) == 0)
#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
#define MP_OBJ_IS_TYPE(o, t) (((((mp_small_int_t)(o)) & 1) == 0) && (((mp_obj_base_t*)(o))->type == (t)))
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_small_int_t)(o)) >> 1)
#define MP_OBJ_NEW_SMALL_INT(o) ((mp_obj_t)(((o) << 1) | 1))
// These macros are used to declare and define constant function objects
// You can put "static" in front of the definitions to make them local
#define MP_DECLARE_CONST_FUN_OBJ(obj_name) extern const mp_obj_fun_native_t obj_name
#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, 0, 0, fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, 1, 1, fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, 2, 2, fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, n_args_min, (~((machine_uint_t)0)), fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) const mp_obj_fun_native_t obj_name = {{&fun_native_type}, n_args_min, n_args_max, fun_name}
// Type definitions for methods
typedef mp_obj_t (*mp_fun_0_t)(void);
typedef mp_obj_t (*mp_fun_1_t)(mp_obj_t);
typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t);
typedef mp_obj_t (*mp_fun_t)(void);
typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *);
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o);
typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
typedef struct _mp_method_t {
const char *name;
machine_uint_t kind;
mp_const_obj_t fun;
} mp_method_t;
struct _mp_obj_type_t {
mp_obj_base_t base;
const char *name;
mp_print_fun_t print;
mp_call_n_fun_t call_n;
mp_unary_op_fun_t unary_op; // can return NULL if op not supported
mp_binary_op_fun_t binary_op; // can return NULL if op not supported
mp_fun_1_t getiter;
mp_fun_1_t iternext;
const mp_method_t methods[];
/*
What we might need to add here:
dynamic_type instance
compare_op
load_attr instance class list
load_method instance str gen list user
store_attr instance class
store_subscr list dict
len str tuple list map
abs float complex
hash bool int none str
equal int str
less int
get_array_n tuple list
unpack seq list tuple
__next__ gen-instance
*/
};
// Constant objects, globally accessible
extern const mp_obj_type_t mp_const_type;
extern const mp_obj_t mp_const_none;
extern const mp_obj_t mp_const_false;
extern const mp_obj_t mp_const_true;
extern const mp_obj_t mp_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!)
// Need to declare this here so we are not dependent on map.h
typedef struct _mp_map_t mp_map_t;
// General API for objects
mp_obj_t mp_obj_new_none(void);
mp_obj_t mp_obj_new_bool(bool value);
mp_obj_t mp_obj_new_int(machine_int_t value);
mp_obj_t mp_obj_new_str(qstr qstr);
#if MICROPY_ENABLE_FLOAT
mp_obj_t mp_obj_new_float(mp_float_t val);
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag);
#endif
mp_obj_t mp_obj_new_exception(qstr id);
mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg);
mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1);
mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2);
mp_obj_t mp_obj_new_range(int start, int stop, int step);
mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step);
mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code);
mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun);
mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_cells, uint n_stack, mp_obj_t fun);
mp_obj_t mp_obj_new_gen_instance(mp_obj_t state, const byte *ip, mp_obj_t *sp);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple);
mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(int n_args);
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth);
mp_obj_t mp_obj_new_class(mp_map_t *class_locals);
mp_obj_t mp_obj_new_instance(mp_obj_t clas);
const char *mp_obj_get_type_str(mp_obj_t o_in);
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in);
void mp_obj_print(mp_obj_t o);
bool mp_obj_is_callable(mp_obj_t o_in);
machine_int_t mp_obj_hash(mp_obj_t o_in);
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);
bool mp_obj_less(mp_obj_t o1, mp_obj_t o2);
machine_int_t mp_obj_get_int(mp_obj_t arg);
#if MICROPY_ENABLE_FLOAT
mp_float_t mp_obj_get_float(mp_obj_t self_in);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
qstr mp_obj_get_qstr(mp_obj_t arg);
mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o, machine_int_t n);
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index);
// none
extern const mp_obj_type_t none_type;
// bool
extern const mp_obj_type_t bool_type;
// cell
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);
// str
extern const mp_obj_type_t str_type;
qstr mp_obj_str_get(mp_obj_t self_in);
#if MICROPY_ENABLE_FLOAT
// float
extern const mp_obj_type_t float_type;
mp_float_t mp_obj_float_get(mp_obj_t self_in);
// complex
extern const mp_obj_type_t complex_type;
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
// tuple
extern const mp_obj_type_t tuple_type;
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
// list
extern const mp_obj_type_t list_type;
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
// dict
extern const mp_obj_type_t dict_type;
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);
// set
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
// functions
typedef struct _mp_obj_fun_native_t { // need this so we can define static objects
mp_obj_base_t base;
machine_uint_t n_args_min; // inclusive
machine_uint_t n_args_max; // inclusive
void *fun;
} py_user_method_t;
} mp_obj_fun_native_t;
extern const mp_obj_type_t fun_native_type;
extern const mp_obj_type_t fun_bc_type;
void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code);
typedef struct _py_user_info_t {
const char *type_name;
void (*print)(py_obj_t);
const py_user_method_t methods[];
} py_user_info_t;
// generator
extern const mp_obj_type_t gen_instance_type;
mp_obj_t mp_obj_gen_instance_next(mp_obj_t self_in);
MP_DECLARE_CONST_FUN_OBJ(mp_obj_gen_instance_next_obj);
py_obj_t py_obj_new_int(machine_int_t value);
py_obj_t py_obj_new_const(const char *id);
py_obj_t py_obj_new_str(qstr qstr);
#if MICROPY_ENABLE_FLOAT
py_obj_t py_obj_new_float(py_float_t val);
py_obj_t py_obj_new_complex(py_float_t real, py_float_t imag);
#endif
py_obj_t py_obj_new_exception_0(qstr id);
py_obj_t py_obj_new_exception_2(qstr id, const char *fmt, const char *s1, const char *s2);
py_obj_t py_obj_new_range(int start, int stop, int step);
py_obj_t py_obj_new_range_iterator(int cur, int stop, int step);
py_obj_t py_obj_new_user(const py_user_info_t *info, machine_uint_t data1, machine_uint_t data2);
// class
extern const mp_obj_type_t class_type;
extern const mp_obj_t gen_instance_next_obj;
mp_map_t *mp_obj_class_get_locals(mp_obj_t self_in);
const char *py_obj_get_type_str(py_obj_t o_in);
void py_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, py_obj_t o_in);
void py_obj_print(py_obj_t o);
bool py_obj_is_callable(py_obj_t o_in);
machine_int_t py_obj_hash(py_obj_t o_in);
bool py_obj_equal(py_obj_t o1, py_obj_t o2);
bool py_obj_less(py_obj_t o1, py_obj_t o2);
machine_int_t py_obj_get_int(py_obj_t arg);
#if MICROPY_ENABLE_FLOAT
machine_float_t py_obj_get_float(py_obj_t arg);
void py_obj_get_complex(py_obj_t arg, py_float_t *real, py_float_t *imag);
#endif
qstr py_obj_get_qstr(py_obj_t arg);
py_obj_t *py_obj_get_array_fixed_n(py_obj_t o, machine_int_t n);
void py_user_get_data(py_obj_t o, machine_uint_t *data1, machine_uint_t *data2);
void py_user_set_data(py_obj_t o, machine_uint_t data1, machine_uint_t data2);
// instance
extern const mp_obj_type_t instance_type;
mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr);
void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value);
// temporary way of making C modules
py_obj_t py_module_new(void);
mp_obj_t mp_module_new(void);

39
py/objbool.c Normal file
View File

@ -0,0 +1,39 @@
#include <stdlib.h>
#include <stdint.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
typedef struct _mp_obj_bool_t {
mp_obj_base_t base;
bool value;
} mp_obj_bool_t;
void bool_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_bool_t *self = self_in;
if (self->value) {
print(env, "True");
} else {
print(env, "False");
}
}
const mp_obj_type_t bool_type = {
{ &mp_const_type },
"bool",
bool_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
static const mp_obj_bool_t false_obj = {{&bool_type}, false};
static const mp_obj_bool_t true_obj = {{&bool_type}, true};
const mp_obj_t mp_const_false = (mp_obj_t)&false_obj;
const mp_obj_t mp_const_true = (mp_obj_t)&true_obj;

54
py/objboundmeth.c Normal file
View File

@ -0,0 +1,54 @@
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
typedef struct _mp_obj_bound_meth_t {
mp_obj_base_t base;
mp_obj_t meth;
mp_obj_t self;
} mp_obj_bound_meth_t;
// args are in reverse order in the array
mp_obj_t bound_meth_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_bound_meth_t *self = self_in;
if (n_args == 0) {
return rt_call_function_n(self->meth, 1, &self->self);
} else if (n_args == 1) {
mp_obj_t args2[2];
args2[1] = self->self;
args2[0] = args[0];
return rt_call_function_n(self->meth, 2, args2);
} else {
// TODO not implemented
assert(0);
return mp_const_none;
//return rt_call_function_2(self->meth, n_args + 1, self->self + args);
}
}
const mp_obj_type_t bound_meth_type = {
{ &mp_const_type },
"bound_method",
NULL, // print
bound_meth_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth) {
mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t);
o->base.type = &bound_meth_type;
o->meth = meth;
o->self = self;
return o;
}

43
py/objcell.c Normal file
View File

@ -0,0 +1,43 @@
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
typedef struct _mp_obj_cell_t {
mp_obj_base_t base;
mp_obj_t obj;
} mp_obj_cell_t;
mp_obj_t mp_obj_cell_get(mp_obj_t self_in) {
mp_obj_cell_t *self = self_in;
return self->obj;
}
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) {
mp_obj_cell_t *self = self_in;
self->obj = obj;
}
const mp_obj_type_t cell_type = {
{ &mp_const_type },
"cell",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_cell(mp_obj_t obj) {
mp_obj_cell_t *o = m_new_obj(mp_obj_cell_t);
o->base.type = &cell_type;
o->obj = obj;
return o;
}

85
py/objclass.c Normal file
View File

@ -0,0 +1,85 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
typedef struct _mp_obj_class_t {
mp_obj_base_t base;
mp_map_t *locals;
} mp_obj_class_t;
// args are in reverse order in the array
mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
// instantiate an instance of a class
mp_obj_class_t *self = self_in;
// make instance
mp_obj_t o = mp_obj_new_instance(self_in);
// look for __init__ function
mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, qstr_from_str_static("__init__"), false);
if (init_fn != NULL) {
// call __init__ function
mp_obj_t init_ret;
if (n_args == 0) {
init_ret = rt_call_function_n(init_fn->value, 1, (mp_obj_t*)&o);
} else {
mp_obj_t *args2 = m_new(mp_obj_t, n_args + 1);
memcpy(args2, args, n_args * sizeof(mp_obj_t));
args2[n_args] = o;
init_ret = rt_call_function_n(init_fn->value, n_args + 1, args2);
m_free(args2);
}
if (init_ret != mp_const_none) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
}
} else {
// TODO
if (n_args != 0) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args));
}
}
return o;
}
mp_map_t *mp_obj_class_get_locals(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &class_type));
mp_obj_class_t *self = self_in;
return self->locals;
}
const mp_obj_type_t class_type = {
{ &mp_const_type },
"class",
NULL, // print
class_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_class(mp_map_t *class_locals) {
mp_obj_class_t *o = m_new_obj(mp_obj_class_t);
o->base.type = &class_type;
o->locals = class_locals;
return o;
}
// temporary way of making C modules
// hack: use class to mimic a module
mp_obj_t mp_module_new(void) {
return mp_obj_new_class(mp_map_new(MP_MAP_QSTR, 0));
}

35
py/objclosure.c Normal file
View File

@ -0,0 +1,35 @@
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
typedef struct _mp_obj_closure_t {
mp_obj_base_t base;
mp_obj_t fun;
mp_obj_t vars;
} mp_obj_closure_t;
const mp_obj_type_t closure_type = {
{ &mp_const_type },
"closure",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple) {
mp_obj_closure_t *o = m_new_obj(mp_obj_closure_t);
o->base.type = &closure_type;
o->fun = fun;
o->vars = closure_tuple;
return o;
}

105
py/objcomplex.c Normal file
View File

@ -0,0 +1,105 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
#include "map.h"
#if MICROPY_ENABLE_FLOAT
typedef struct _mp_obj_complex_t {
mp_obj_base_t base;
mp_float_t real;
mp_float_t imag;
} mp_obj_complex_t;
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag);
void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_complex_t *o = o_in;
if (o->real == 0) {
print(env, "%.8gj", o->imag);
} else {
print(env, "(%.8g+%.8gj)", o->real, o->imag);
}
}
mp_obj_t complex_unary_op(int op, mp_obj_t o_in) {
mp_obj_complex_t *o = o_in;
switch (op) {
case RT_UNARY_OP_NOT: if (o->real != 0 || o->imag != 0) { return mp_const_true;} else { return mp_const_false; }
case RT_UNARY_OP_POSITIVE: return o_in;
case RT_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag);
default: return MP_OBJ_NULL; // op not supported
}
}
mp_obj_t complex_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_float_t lhs_real, lhs_imag, rhs_real, rhs_imag;
mp_obj_complex_get(lhs_in, &lhs_real, &lhs_imag);
mp_obj_complex_get(rhs_in, &rhs_real, &rhs_imag);
switch (op) {
case RT_BINARY_OP_ADD:
case RT_BINARY_OP_INPLACE_ADD:
lhs_real += rhs_real;
lhs_imag += rhs_imag;
break;
case RT_BINARY_OP_SUBTRACT:
case RT_BINARY_OP_INPLACE_SUBTRACT:
lhs_real -= rhs_real;
lhs_imag -= rhs_imag;
break;
case RT_BINARY_OP_MULTIPLY:
case RT_BINARY_OP_INPLACE_MULTIPLY:
{
mp_float_t real = lhs_real * rhs_real - lhs_imag * rhs_imag;
lhs_imag = lhs_real * rhs_imag + lhs_imag * rhs_real;
lhs_real = real;
break;
}
/* TODO floor(?) the value
case RT_BINARY_OP_FLOOR_DIVIDE:
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
*/
/* TODO
case RT_BINARY_OP_TRUE_DIVIDE:
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: val = lhs_val / rhs_val; break;
*/
return NULL; // op not supported
}
return mp_obj_new_complex(lhs_real, lhs_imag);
}
const mp_obj_type_t complex_type = {
{ &mp_const_type },
"complex",
complex_print, // print
NULL, // call_n
complex_unary_op, // unary_op
complex_binary_op, // binary_op
NULL, // getiter
NULL, // iternext
{ { NULL, NULL }, }, // method list
};
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) {
mp_obj_complex_t *o = m_new_obj(mp_obj_complex_t);
o->base.type = &complex_type;
o->real = real;
o->imag = imag;
return o;
}
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {
assert(MP_OBJ_IS_TYPE(self_in, &complex_type));
mp_obj_complex_t *self = self_in;
*real = self->real;
*imag = self->imag;
}
#endif

80
py/objdict.c Normal file
View File

@ -0,0 +1,80 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "map.h"
typedef struct _mp_obj_dict_t {
mp_obj_base_t base;
mp_map_t map;
} mp_obj_dict_t;
void dict_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_dict_t *self = self_in;
bool first = true;
print(env, "{");
for (int i = 0; i < self->map.alloc; i++) {
if (self->map.table[i].key != NULL) {
if (!first) {
print(env, ", ");
}
first = false;
mp_obj_print_helper(print, env, self->map.table[i].key);
print(env, ": ");
mp_obj_print_helper(print, env, self->map.table[i].value);
}
}
print(env, "}");
}
mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = lhs_in;
switch (op) {
case RT_BINARY_OP_SUBSCR:
{
// dict load
mp_map_elem_t *elem = mp_map_lookup_helper(&o->map, rhs_in, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_KeyError, "<value>"));
} else {
return elem->value;
}
}
default:
// op not supported
return NULL;
}
}
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
mp_obj_dict_t *self = self_in;
mp_map_lookup_helper(&self->map, key, true)->value = value;
return self_in;
}
const mp_obj_type_t dict_type = {
{ &mp_const_type },
"dict",
dict_print, // print
NULL, // call_n
NULL, // unary_op
dict_binary_op, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_dict(int n_args) {
mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
o->base.type = &dict_type;
mp_map_init(&o->map, MP_MAP_OBJ, n_args);
return o;
}

86
py/objexcept.c Normal file
View File

@ -0,0 +1,86 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
typedef struct mp_obj_exception_t {
mp_obj_base_t base;
qstr id;
int n_args;
const void *args[];
} mp_obj_exception_t;
void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_exception_t *o = o_in;
switch (o->n_args) {
case 0:
print(env, "%s", qstr_str(o->id));
break;
case 1:
print(env, "%s: %s", qstr_str(o->id), (const char*)o->args[0]);
break;
case 2:
print(env, "%s: ", qstr_str(o->id));
print(env, (const char*)o->args[0], o->args[1]);
break;
default: // here we just assume at least 3 args, but only use first 3
print(env, "%s: ", qstr_str(o->id));
print(env, (const char*)o->args[0], o->args[1], o->args[2]);
break;
}
}
const mp_obj_type_t exception_type = {
{ &mp_const_type },
"exception",
exception_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_exception(qstr id) {
mp_obj_exception_t *o = m_new_obj(mp_obj_exception_t);
o->base.type = &exception_type;
o->id = id;
o->n_args = 0;
return o;
}
mp_obj_t mp_obj_new_exception_msg(qstr id, const char *msg) {
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 1);
o->base.type = &exception_type;
o->id = id;
o->n_args = 1;
o->args[0] = msg;
return o;
}
mp_obj_t mp_obj_new_exception_msg_1_arg(qstr id, const char *fmt, const char *a1) {
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 2);
o->base.type = &exception_type;
o->id = id;
o->n_args = 2;
o->args[0] = fmt;
o->args[1] = a1;
return o;
}
mp_obj_t mp_obj_new_exception_msg_2_args(qstr id, const char *fmt, const char *a1, const char *a2) {
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, void*, 3);
o->base.type = &exception_type;
o->id = id;
o->n_args = 3;
o->args[0] = fmt;
o->args[1] = a1;
o->args[2] = a2;
return o;
}

85
py/objfloat.c Normal file
View File

@ -0,0 +1,85 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
#if MICROPY_ENABLE_FLOAT
typedef struct _mp_obj_float_t {
mp_obj_base_t base;
mp_float_t value;
} mp_obj_float_t;
mp_obj_t mp_obj_new_float(mp_float_t value);
void float_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_float_t *o = o_in;
print(env, "%.8g", o->value);
}
mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
mp_obj_float_t *o = o_in;
switch (op) {
case RT_UNARY_OP_NOT: if (o->value != 0) { return mp_const_true;} else { return mp_const_false; }
case RT_UNARY_OP_POSITIVE: return o_in;
case RT_UNARY_OP_NEGATIVE: return mp_obj_new_float(-o->value);
default: return NULL; // op not supported
}
}
mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (MP_OBJ_IS_TYPE(rhs_in, &complex_type)) {
return complex_type.binary_op(op, lhs_in, rhs_in);
}
mp_float_t lhs_val = mp_obj_get_float(lhs_in);
mp_float_t rhs_val = mp_obj_get_float(rhs_in);
switch (op) {
case RT_BINARY_OP_ADD:
case RT_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
case RT_BINARY_OP_SUBTRACT:
case RT_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
case RT_BINARY_OP_MULTIPLY:
case RT_BINARY_OP_INPLACE_MULTIPLY: lhs_val *= rhs_val; break;
/* TODO floor(?) the value
case RT_BINARY_OP_FLOOR_DIVIDE:
case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: val = lhs_val / rhs_val; break;
*/
case RT_BINARY_OP_TRUE_DIVIDE:
case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: lhs_val /= rhs_val; break;
return NULL; // op not supported
}
return mp_obj_new_float(lhs_val);
}
const mp_obj_type_t float_type = {
{ &mp_const_type },
"float",
float_print,
NULL, // call_n
float_unary_op,
float_binary_op,
NULL, // getiter
NULL, // iternext
{ { NULL, NULL }, }, // method list
};
mp_obj_t mp_obj_new_float(mp_float_t value) {
mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
o->base.type = &float_type;
o->value = value;
return (mp_obj_t)o;
}
mp_float_t mp_obj_float_get(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &float_type));
mp_obj_float_t *self = self_in;
return self->value;
}
#endif

280
py/objfun.c Normal file
View File

@ -0,0 +1,280 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
#include "bc.h"
/******************************************************************************/
/* native functions */
// mp_obj_fun_native_t defined in obj.h
// args are in reverse order in the array
mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_fun_native_t *self = self_in;
if (self->n_args_min == self->n_args_max) {
// function requires a fixed number of arguments
// check number of arguments
if (n_args != self->n_args_min) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args_min, (const char*)(machine_int_t)n_args));
}
// dispatch function call
switch (self->n_args_min) {
case 0:
return ((mp_fun_0_t)self->fun)();
case 1:
return ((mp_fun_1_t)self->fun)(args[0]);
case 2:
return ((mp_fun_2_t)self->fun)(args[1], args[0]);
default:
assert(0);
return mp_const_none;
}
} else {
// function takes a variable number of arguments
if (n_args < self->n_args_min) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "<fun name>() missing %d required positional arguments: <list of names of params>", (const char*)(machine_int_t)(self->n_args_min - n_args)));
} else if (n_args > self->n_args_max) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "<fun name> expected at most %d arguments, got %d", (void*)(machine_int_t)self->n_args_max, (void*)(machine_int_t)n_args));
}
// TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args
mp_obj_t *args_ordered = m_new(mp_obj_t, n_args);
for (int i = 0; i < n_args; i++) {
args_ordered[i] = args[n_args - i - 1];
}
mp_obj_t res = ((mp_fun_var_t)self->fun)(n_args, args_ordered);
m_free(args_ordered);
return res;
}
}
const mp_obj_type_t fun_native_type = {
{ &mp_const_type },
"function",
NULL, // print
fun_native_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{NULL, NULL}, // end-of-list sentinel
},
};
mp_obj_t rt_make_function_0(mp_fun_0_t fun) {
mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t);
o->base.type = &fun_native_type;
o->n_args_min = 0;
o->n_args_max = 0;
o->fun = fun;
return o;
}
mp_obj_t rt_make_function_1(mp_fun_1_t fun) {
mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t);
o->base.type = &fun_native_type;
o->n_args_min = 1;
o->n_args_max = 1;
o->fun = fun;
return o;
}
mp_obj_t rt_make_function_2(mp_fun_2_t fun) {
mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t);
o->base.type = &fun_native_type;
o->n_args_min = 2;
o->n_args_max = 2;
o->fun = fun;
return o;
}
mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t fun) {
mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t);
o->base.type = &fun_native_type;
o->n_args_min = n_args_min;
o->n_args_max = ~((machine_uint_t)0);
o->fun = fun;
return o;
}
// min and max are inclusive
mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun) {
mp_obj_fun_native_t *o = m_new_obj(mp_obj_fun_native_t);
o->base.type = &fun_native_type;
o->n_args_min = n_args_min;
o->n_args_max = n_args_max;
o->fun = fun;
return o;
}
/******************************************************************************/
/* byte code functions */
typedef struct _mp_obj_fun_bc_t {
mp_obj_base_t base;
int n_args;
uint n_state;
const byte *code;
} mp_obj_fun_bc_t;
// args are in reverse order in the array
mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_fun_bc_t *self = self_in;
if (n_args != self->n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
}
return mp_execute_byte_code(self->code, args, n_args, self->n_state);
}
void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte **code) {
assert(MP_OBJ_IS_TYPE(self_in, &fun_bc_type));
mp_obj_fun_bc_t *self = self_in;
*n_args = self->n_args;
*n_state = self->n_state;
*code = self->code;
}
const mp_obj_type_t fun_bc_type = {
{ &mp_const_type },
"function",
NULL, // print
fun_bc_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{NULL, NULL}, // end-of-list sentinel
},
};
mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code) {
mp_obj_fun_bc_t *o = m_new_obj(mp_obj_fun_bc_t);
o->base.type = &fun_bc_type;
o->n_args = n_args;
o->n_state = n_state;
o->code = code;
return o;
}
/******************************************************************************/
/* inline assembler functions */
typedef struct _mp_obj_fun_asm_t {
mp_obj_base_t base;
int n_args;
void *fun;
} mp_obj_fun_asm_t;
typedef machine_uint_t (*inline_asm_fun_0_t)();
typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
// convert a Micro Python object to a sensible value for inline asm
machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
// TODO for byte_array, pass pointer to the array
if (MP_OBJ_IS_SMALL_INT(obj)) {
return MP_OBJ_SMALL_INT_VALUE(obj);
} else if (obj == mp_const_none) {
return 0;
} else if (obj == mp_const_false) {
return 0;
} else if (obj == mp_const_true) {
return 1;
} else if (MP_OBJ_IS_TYPE(obj, &str_type)) {
// pointer to the string (it's probably constant though!)
return (machine_uint_t)qstr_str(mp_obj_str_get(obj));
#if MICROPY_ENABLE_FLOAT
} else if (MP_OBJ_IS_TYPE(obj, &float_type)) {
// convert float to int (could also pass in float registers)
return (machine_int_t)mp_obj_float_get(obj);
#endif
} else if (MP_OBJ_IS_TYPE(obj, &tuple_type)) {
// pointer to start of tuple (could pass length, but then could use len(x) for that)
uint len;
mp_obj_t *items;
mp_obj_tuple_get(obj, &len, &items);
return (machine_uint_t)items;
} else if (MP_OBJ_IS_TYPE(obj, &list_type)) {
// pointer to start of list (could pass length, but then could use len(x) for that)
uint len;
mp_obj_t *items;
mp_obj_list_get(obj, &len, &items);
return (machine_uint_t)items;
} else {
// just pass along a pointer to the object
return (machine_uint_t)obj;
}
}
// convert a return value from inline asm to a sensible Micro Python object
mp_obj_t convert_val_from_inline_asm(machine_uint_t val) {
return MP_OBJ_NEW_SMALL_INT(val);
}
// args are in reverse order in the array
mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_fun_asm_t *self = self_in;
if (n_args != self->n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
}
machine_uint_t ret;
if (n_args == 0) {
ret = ((inline_asm_fun_0_t)self->fun)();
} else if (n_args == 1) {
ret = ((inline_asm_fun_1_t)self->fun)(convert_obj_for_inline_asm(args[0]));
} else if (n_args == 2) {
ret = ((inline_asm_fun_2_t)self->fun)(convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[0]));
} else if (n_args == 3) {
ret = ((inline_asm_fun_3_t)self->fun)(convert_obj_for_inline_asm(args[2]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[0]));
} else {
assert(0);
ret = 0;
}
return convert_val_from_inline_asm(ret);
}
static const mp_obj_type_t fun_asm_type = {
{ &mp_const_type },
"function",
NULL, // print
fun_asm_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{NULL, NULL}, // end-of-list sentinel
},
};
mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun) {
mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t);
o->base.type = &fun_asm_type;
o->n_args = n_args;
o->fun = fun;
return o;
}

130
py/objgenerator.c Normal file
View File

@ -0,0 +1,130 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
#include "bc.h"
/******************************************************************************/
/* generator wrapper */
typedef struct _mp_obj_gen_wrap_t {
mp_obj_base_t base;
int n_state;
mp_obj_t *fun;
} mp_obj_gen_wrap_t;
// args are in reverse order in the array
mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_gen_wrap_t *self = self_in;
mp_obj_t self_fun = self->fun;
assert(MP_OBJ_IS_TYPE(self_fun, &fun_bc_type));
int bc_n_args;
uint bc_n_state;
const byte *bc_code;
mp_obj_fun_bc_get(self_fun, &bc_n_args, &bc_n_state, &bc_code);
if (n_args != bc_n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args));
}
mp_obj_t *state = m_new(mp_obj_t, 1 + self->n_state);
// put function object at first slot in state (to keep u_gen_instance small)
state[0] = self_fun;
// init args
for (int i = 0; i < n_args; i++) {
state[1 + i] = args[n_args - 1 - i];
}
return mp_obj_new_gen_instance(state, bc_code, state + self->n_state);
}
const mp_obj_type_t gen_wrap_type = {
{ &mp_const_type },
"generator",
NULL, // print
gen_wrap_call_n, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_cells, uint n_stack, mp_obj_t fun) {
mp_obj_gen_wrap_t *o = m_new_obj(mp_obj_gen_wrap_t);
o->base.type = &gen_wrap_type;
// we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
o->n_state = ((n_locals + n_cells) < 3 ? 3 : (n_locals + n_cells)) + n_stack;
o->fun = fun;
return o;
}
/******************************************************************************/
/* generator instance */
typedef struct _mp_obj_gen_instance_t {
mp_obj_base_t base;
mp_obj_t *state;
const byte *ip;
mp_obj_t *sp;
} mp_obj_gen_instance_t;
void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "<generator object 'fun-name' at %p>", self_in);
}
mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
return self_in;
}
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
mp_obj_gen_instance_t *self = self_in;
//mp_obj_base_t *fun = self->u_gen_instance.state[0];
//assert(fun->kind == O_FUN_BC);
bool yield = mp_execute_byte_code_2(&self->ip, &self->state[1], &self->sp);
if (yield) {
return *self->sp;
} else {
if (*self->sp == mp_const_none) {
return mp_const_stop_iteration;
} else {
// TODO return StopIteration with value *self->sp
return mp_const_stop_iteration;
}
}
}
const mp_obj_type_t gen_instance_type = {
{ &mp_const_type },
"generator",
gen_instance_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
gen_instance_getiter, // getiter
gen_instance_iternext, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_gen_instance(mp_obj_t state, const byte *ip, mp_obj_t *sp) {
mp_obj_gen_instance_t *o = m_new_obj(mp_obj_gen_instance_t);
o->base.type = &gen_instance_type;
o->state = state;
o->ip = ip;
o->sp = sp;
return o;
}
mp_obj_t mp_obj_gen_instance_next(mp_obj_t self_in) {
mp_obj_t ret = rt_iternext(self_in);
if (ret == mp_const_stop_iteration) {
nlr_jump(mp_obj_new_exception(qstr_from_str_static("StopIteration")));
} else {
return ret;
}
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_gen_instance_next_obj, mp_obj_gen_instance_next);

109
py/objinstance.c Normal file
View File

@ -0,0 +1,109 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
typedef struct _mp_obj_instance_t {
mp_obj_base_t base;
mp_obj_base_t *class; // points to a "class" object
mp_map_t *members;
} mp_obj_instance_t;
/*
type needs to be specified dynamically
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);
}
*/
mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) {
// logic: look in obj members then class locals (TODO check this against CPython)
mp_obj_instance_t *self = self_in;
mp_map_elem_t *elem = mp_qstr_map_lookup(self->members, attr, false);
if (elem != NULL) {
// object member, always treated as a value
return elem->value;
}
elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false);
if (elem != NULL) {
if (mp_obj_is_callable(elem->value)) {
// class member is callable so build a bound method
return mp_obj_new_bound_meth(self_in, elem->value);
} else {
// class member is a value, so just return that value
return elem->value;
}
}
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(self_in), qstr_str(attr)));
}
void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
// logic: look in obj members then class locals (TODO check this against CPython)
mp_obj_instance_t *self = self_in;
mp_map_elem_t *elem = mp_qstr_map_lookup(self->members, attr, false);
if (elem != NULL) {
// object member, always treated as a value
dest[1] = elem->value;
dest[0] = NULL;
return;
}
elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false);
if (elem != NULL) {
if (mp_obj_is_callable(elem->value)) {
// class member is callable so build a bound method
dest[1] = elem->value;
dest[0] = self_in;
return;
} else {
// class member is a value, so just return that value
dest[1] = elem->value;
dest[0] = NULL;
return;
}
}
// no such method, so fall back to load attr
dest[1] = rt_load_attr(self_in, attr);
dest[0] = NULL;
}
void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
// logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
mp_obj_instance_t *self = self_in;
mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false);
if (elem != NULL) {
elem->value = value;
} else {
mp_qstr_map_lookup(self->members, attr, true)->value = value;
}
}
const mp_obj_type_t instance_type = {
{ &mp_const_type },
"instance",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_instance(mp_obj_t class) {
mp_obj_instance_t *o = m_new_obj(mp_obj_instance_t);
o->base.type = &instance_type;
o->class = class;
o->members = mp_map_new(MP_MAP_QSTR, 0);
return o;
}

204
py/objlist.c Normal file
View File

@ -0,0 +1,204 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
typedef struct _mp_obj_list_t {
mp_obj_base_t base;
machine_uint_t alloc;
machine_uint_t len;
mp_obj_t *items;
} mp_obj_list_t;
static mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur);
/******************************************************************************/
/* list */
static void list_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_list_t *o = o_in;
print(env, "[");
for (int i = 0; i < o->len; i++) {
if (i > 0) {
print(env, ", ");
}
mp_obj_print_helper(print, env, o->items[i]);
}
print(env, "]");
}
static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_list_t *o = lhs;
switch (op) {
case RT_BINARY_OP_SUBSCR:
{
// list load
uint index = mp_get_index(o->base.type, o->len, rhs);
return o->items[index];
}
default:
// op not supported
return NULL;
}
}
static mp_obj_t list_getiter(mp_obj_t o_in) {
return mp_obj_new_list_iterator(o_in, 0);
}
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
mp_obj_list_t *self = self_in;
if (self->len >= self->alloc) {
self->alloc *= 2;
self->items = m_renew(mp_obj_t, self->items, self->alloc);
}
self->items[self->len++] = arg;
return mp_const_none; // return None, as per CPython
}
static mp_obj_t list_pop(mp_obj_t self_in, mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
mp_obj_list_t *self = self_in;
uint index = mp_get_index(self->base.type, self->len, arg);
mp_obj_t ret = self->items[index];
self->len -= 1;
memcpy(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
return ret;
}
// TODO make this conform to CPython's definition of sort
static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn) {
while (head < tail) {
mp_obj_t *h = head - 1;
mp_obj_t *t = tail;
mp_obj_t v = rt_call_function_1(key_fn, tail[0]); // get pivot using key_fn
for (;;) {
do ++h; while (rt_compare_op(RT_COMPARE_OP_LESS, rt_call_function_1(key_fn, h[0]), v) == mp_const_true);
do --t; while (h < t && rt_compare_op(RT_COMPARE_OP_LESS, v, rt_call_function_1(key_fn, t[0])) == mp_const_true);
if (h >= t) break;
mp_obj_t x = h[0];
h[0] = t[0];
t[0] = x;
}
mp_obj_t x = h[0];
h[0] = tail[0];
tail[0] = x;
mp_quicksort(head, t, key_fn);
head = h + 1;
}
}
static mp_obj_t list_sort(mp_obj_t self_in, mp_obj_t key_fn) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
mp_obj_list_t *self = self_in;
if (self->len > 1) {
mp_quicksort(self->items, self->items + self->len - 1, key_fn);
}
return mp_const_none; // return None, as per CPython
}
static MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append);
static MP_DEFINE_CONST_FUN_OBJ_2(list_pop_obj, list_pop);
static MP_DEFINE_CONST_FUN_OBJ_2(list_sort_obj, list_sort);
const mp_obj_type_t list_type = {
{ &mp_const_type },
"list",
list_print, // print
NULL, // call_n
NULL, // unary_op
list_binary_op, // binary_op
list_getiter, // getiter
NULL, // iternext
{ // method list
{ "append", &list_append_obj },
{ "pop", &list_pop_obj },
{ "sort", &list_sort_obj },
{ NULL, NULL }, // end-of-list sentinel
},
};
static mp_obj_list_t *list_new(uint n) {
mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
o->base.type = &list_type;
o->alloc = n < 4 ? 4 : n;
o->len = n;
o->items = m_new(mp_obj_t, o->alloc);
return o;
}
mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items) {
mp_obj_list_t *o = list_new(n);
for (int i = 0; i < n; i++) {
o->items[i] = items[i];
}
return o;
}
mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items) {
mp_obj_list_t *o = list_new(n);
for (int i = 0; i < n; i++) {
o->items[i] = items[n - i - 1];
}
return o;
}
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
mp_obj_list_t *self = self_in;
*len = self->len;
*items = self->items;
}
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_list_t *self = self_in;
uint i = mp_get_index(self->base.type, self->len, index);
self->items[i] = value;
}
/******************************************************************************/
/* list iterator */
typedef struct _mp_obj_list_it_t {
mp_obj_base_t base;
mp_obj_list_t *list;
machine_uint_t cur;
} mp_obj_list_it_t;
mp_obj_t list_it_iternext(mp_obj_t self_in) {
mp_obj_list_it_t *self = self_in;
if (self->cur < self->list->len) {
mp_obj_t o_out = self->list->items[self->cur];
self->cur += 1;
return o_out;
} else {
return mp_const_stop_iteration;
}
}
static const mp_obj_type_t list_it_type = {
{ &mp_const_type },
"list_iterator",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
list_it_iternext, // iternext
{ { NULL, NULL }, }, // method list
};
mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur) {
mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t);
o->base.type = &list_it_type;
o->list = list;
o->cur = cur;
return o;
}

35
py/objnone.c Normal file
View File

@ -0,0 +1,35 @@
#include <stdlib.h>
#include <stdint.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
typedef struct _mp_obj_none_t {
mp_obj_base_t base;
} mp_obj_none_t;
void none_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "None");
}
const mp_obj_type_t none_type = {
{ &mp_const_type },
"NoneType",
none_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
static const mp_obj_none_t none_obj = {{&none_type}};
const mp_obj_t mp_const_none = (mp_obj_t)&none_obj;
// the stop-iteration object just needs to be something unique
// it's not the StopIteration exception
static const mp_obj_none_t stop_it_obj = {{&none_type}};
const mp_obj_t mp_const_stop_iteration = (mp_obj_t)&stop_it_obj;

View File

@ -1,140 +0,0 @@
// internal py_obj_t representation
// not for general use, instead access using py_obj_xxx functions
#define IS_O(o, k) (((((py_small_int_t)(o)) & 1) == 0) && (((py_obj_base_t*)(o))->kind == (k)))
#define IS_SMALL_INT(o) (((py_small_int_t)(o)) & 1)
#define FROM_SMALL_INT(o) (((py_small_int_t)(o)) >> 1)
#define TO_SMALL_INT(o) ((py_obj_t)(((o) << 1) | 1))
typedef enum {
O_CONST,
O_STR,
#if MICROPY_ENABLE_FLOAT
O_FLOAT,
O_COMPLEX,
#endif
O_CELL,
O_EXCEPTION_0,
O_EXCEPTION_N,
O_RANGE,
O_RANGE_IT,
O_FUN_0,
O_FUN_1,
O_FUN_2,
O_FUN_N,
O_FUN_VAR,
O_FUN_BC,
O_FUN_ASM,
O_GEN_WRAP,
O_GEN_INSTANCE,
O_BOUND_METH,
O_CLOSURE,
O_TUPLE,
O_LIST,
O_TUPLE_IT,
O_LIST_IT,
O_SET,
O_MAP,
O_CLASS,
O_OBJ,
O_USER,
} py_obj_kind_t;
typedef struct _py_obj_base_t py_obj_base_t;
struct _py_obj_base_t {
py_obj_kind_t kind;
union {
const char *id;
qstr u_str;
#if MICROPY_ENABLE_FLOAT
py_float_t u_float; // for O_FLOAT
struct { // for O_COMPLEX
py_float_t real;
py_float_t imag;
} u_complex;
#endif
py_obj_t u_cell; // for O_CELL
struct { // for O_EXCEPTION_0
qstr id;
} u_exc0;
struct { // for O_EXCEPTION_N
// TODO make generic object or something
qstr id;
int n_args;
const void **args;
} u_exc_n;
struct { // for O_RANGE
// TODO make generic object or something
machine_int_t start;
machine_int_t stop;
machine_int_t step;
} u_range;
struct { // for O_RANGE_IT
// TODO make generic object or something
machine_int_t cur;
machine_int_t stop;
machine_int_t step;
} u_range_it;
struct { // for O_FUN_[012N], O_FUN_VAR
int n_args;
void *fun;
} u_fun;
struct { // for O_FUN_BC
int n_args;
uint n_state;
byte *code;
} u_fun_bc;
struct { // for O_FUN_ASM
int n_args;
void *fun;
} u_fun_asm;
struct { // for O_GEN_WRAP
int n_state;
py_obj_base_t *fun;
} u_gen_wrap;
struct { // for O_GEN_INSTANCE
py_obj_t *state;
const byte *ip;
py_obj_t *sp;
} u_gen_instance;
struct { // for O_BOUND_METH
py_obj_t meth;
py_obj_t self;
} u_bound_meth;
struct { // for O_CLOSURE
py_obj_t fun;
py_obj_t vars;
} u_closure;
struct { // for O_TUPLE, O_LIST
machine_uint_t alloc;
machine_uint_t len;
py_obj_t *items;
} u_tuple_list;
struct { // for O_TUPLE_IT, O_LIST_IT
py_obj_base_t *obj;
machine_uint_t cur;
} u_tuple_list_it;
struct { // for O_SET
machine_uint_t alloc;
machine_uint_t used;
py_obj_t *table;
} u_set;
py_map_t u_map; // for O_MAP
struct { // for O_CLASS
py_map_t *locals;
} u_class;
struct { // for O_OBJ
py_obj_base_t *class; // points to a O_CLASS object
py_map_t *members;
} u_obj;
struct { // for O_USER
const py_user_info_t *info;
machine_uint_t data1;
machine_uint_t data2;
} u_user;
};
};
py_obj_t py_obj_new_tuple_iterator(py_obj_base_t *tuple, int cur);
py_obj_t py_obj_new_list_iterator(py_obj_base_t *list, int cur);

88
py/objrange.c Normal file
View File

@ -0,0 +1,88 @@
#include <stdlib.h>
#include <stdint.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
/******************************************************************************/
/* range */
typedef struct _mp_obj_range_t {
mp_obj_base_t base;
// TODO make these values generic objects or something
machine_int_t start;
machine_int_t stop;
machine_int_t step;
} mp_obj_range_t;
mp_obj_t range_getiter(mp_obj_t o_in) {
mp_obj_range_t *o = o_in;
return mp_obj_new_range_iterator(o->start, o->stop, o->step);
}
static const mp_obj_type_t range_type = {
{ &mp_const_type} ,
"range",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
range_getiter,
NULL, // iternext
{{NULL, NULL},}, // method list
};
// range is a class and instances are immutable sequence objects
mp_obj_t mp_obj_new_range(int start, int stop, int step) {
mp_obj_range_t *o = m_new_obj(mp_obj_range_t);
o->base.type = &range_type;
o->start = start;
o->stop = stop;
o->step = step;
return o;
}
/******************************************************************************/
/* range iterator */
typedef struct _mp_obj_range_it_t {
mp_obj_base_t base;
// TODO make these values generic objects or something
machine_int_t cur;
machine_int_t stop;
machine_int_t step;
} mp_obj_range_it_t;
mp_obj_t range_it_iternext(mp_obj_t o_in) {
mp_obj_range_it_t *o = o_in;
if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) {
mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur);
o->cur += o->step;
return o_out;
} else {
return mp_const_stop_iteration;
}
}
static const mp_obj_type_t range_it_type = {
{ &mp_const_type },
"range_iterator",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
range_it_iternext,
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step) {
mp_obj_range_it_t *o = m_new_obj(mp_obj_range_it_t);
o->base.type = &range_it_type;
o->cur = cur;
o->stop = stop;
o->step = step;
return o;
}

58
py/objset.c Normal file
View File

@ -0,0 +1,58 @@
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "map.h"
typedef struct _mp_obj_set_t {
mp_obj_base_t base;
mp_set_t set;
} mp_obj_set_t;
void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_set_t *self = self_in;
bool first = true;
print(env, "{");
for (int i = 0; i < self->set.alloc; i++) {
if (self->set.table[i] != MP_OBJ_NULL) {
if (!first) {
print(env, ", ");
}
first = false;
mp_obj_print_helper(print, env, self->set.table[i]);
}
}
print(env, "}");
}
static const mp_obj_type_t set_type = {
{ &mp_const_type },
"set",
set_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ { NULL, NULL }, }, // method list
};
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
mp_obj_set_t *o = m_new_obj(mp_obj_set_t);
o->base.type = &set_type;
mp_set_init(&o->set, n_args);
for (int i = 0; i < n_args; i++) {
mp_set_lookup(&o->set, items[i], true);
}
return o;
}
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_set_lookup(&self->set, item, true);
}

151
py/objstr.c Normal file
View File

@ -0,0 +1,151 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
typedef struct _mp_obj_str_t {
mp_obj_base_t base;
qstr qstr;
} mp_obj_str_t;
void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_str_t *self = self_in;
// TODO need to escape chars etc
print(env, "'%s'", qstr_str(self->qstr));
}
mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_str_t *lhs = lhs_in;
const char *lhs_str = qstr_str(lhs->qstr);
switch (op) {
case RT_BINARY_OP_SUBSCR:
// string access
// XXX a massive hack!
return mp_obj_new_int(lhs_str[mp_obj_get_int(rhs_in)]);
case RT_BINARY_OP_ADD:
case RT_BINARY_OP_INPLACE_ADD:
if (MP_OBJ_IS_TYPE(rhs_in, &str_type)) {
// add 2 strings
const char *rhs_str = qstr_str(((mp_obj_str_t*)rhs_in)->qstr);
char *val = m_new(char, strlen(lhs_str) + strlen(rhs_str) + 1);
stpcpy(stpcpy(val, lhs_str), rhs_str);
return mp_obj_new_str(qstr_from_str_take(val));
}
break;
}
return MP_OBJ_NULL; // op not supported
}
mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(self_in, &str_type));
mp_obj_str_t *self = self_in;
int required_len = strlen(qstr_str(self->qstr));
// process arg, count required chars
uint seq_len;
mp_obj_t *seq_items;
if (MP_OBJ_IS_TYPE(arg, &tuple_type)) {
mp_obj_tuple_get(arg, &seq_len, &seq_items);
} else if (MP_OBJ_IS_TYPE(arg, &list_type)) {
mp_obj_list_get(arg, &seq_len, &seq_items);
} else {
goto bad_arg;
}
for (int i = 0; i < seq_len; i++) {
if (!MP_OBJ_IS_TYPE(seq_items[i], &str_type)) {
goto bad_arg;
}
required_len += strlen(qstr_str(mp_obj_str_get(seq_items[i])));
}
// make joined string
char *joined_str = m_new(char, required_len + 1);
joined_str[0] = 0;
for (int i = 0; i < seq_len; i++) {
const char *s2 = qstr_str(mp_obj_str_get(seq_items[i]));
if (i > 0) {
strcat(joined_str, qstr_str(self->qstr));
}
strcat(joined_str, s2);
}
return mp_obj_new_str(qstr_from_str_take(joined_str));
bad_arg:
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "?str.join expecting a list of str's"));
}
void vstr_printf_wrapper(void *env, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vstr_vprintf(env, fmt, args);
va_end(args);
}
mp_obj_t str_format(int n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(args[0], &str_type));
mp_obj_str_t *self = args[0];
const char *str = qstr_str(self->qstr);
int arg_i = 1;
vstr_t *vstr = vstr_new();
for (; *str; str++) {
if (*str == '{') {
str++;
if (*str == '{') {
vstr_add_char(vstr, '{');
} else if (*str == '}') {
if (arg_i >= n_args) {
nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "tuple index out of range"));
}
mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]);
arg_i++;
}
} else {
vstr_add_char(vstr, *str);
}
}
return mp_obj_new_str(qstr_from_str_take(vstr->buf));
}
static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format);
const mp_obj_type_t str_type = {
{ &mp_const_type },
"str",
str_print, // print
NULL, // call_n
NULL, // unary_op
str_binary_op, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{ "join", &str_join_obj },
{ "format", &str_format_obj },
{ NULL, NULL }, // end-of-list sentinel
},
};
mp_obj_t mp_obj_new_str(qstr qstr) {
mp_obj_str_t *o = m_new_obj(mp_obj_str_t);
o->base.type = &str_type;
o->qstr = qstr;
return o;
}
qstr mp_obj_str_get(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &str_type));
mp_obj_str_t *self = self_in;
return self->qstr;
}

133
py/objtuple.c Normal file
View File

@ -0,0 +1,133 @@
#include <stdlib.h>
#include <stdint.h>
//#include <string.h>
#include <assert.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime0.h"
typedef struct _mp_obj_tuple_t {
mp_obj_base_t base;
machine_uint_t len;
mp_obj_t items[];
} mp_obj_tuple_t;
static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur);
/******************************************************************************/
/* tuple */
void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in) {
mp_obj_tuple_t *o = o_in;
print(env, "(");
for (int i = 0; i < o->len; i++) {
if (i > 0) {
print(env, ", ");
}
mp_obj_print_helper(print, env, o->items[i]);
}
if (o->len == 1) {
print(env, ",");
}
print(env, ")");
}
mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_tuple_t *o = lhs;
switch (op) {
case RT_BINARY_OP_SUBSCR:
{
// tuple load
uint index = mp_get_index(o->base.type, o->len, rhs);
return o->items[index];
}
default:
// op not supported
return NULL;
}
}
mp_obj_t tuple_getiter(mp_obj_t o_in) {
return mp_obj_new_tuple_iterator(o_in, 0);
}
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
mp_obj_tuple_t *self = self_in;
*len = self->len;
*items = &self->items[0];
}
const mp_obj_type_t tuple_type = {
{ &mp_const_type },
"tuple",
tuple_print, // print
NULL, // call_n
NULL, // unary_op
tuple_binary_op, // binary_op
tuple_getiter, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};
mp_obj_t mp_obj_new_tuple(uint n, mp_obj_t *items) {
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);
o->base.type = &tuple_type;
o->len = n;
for (int i = 0; i < n; i++) {
o->items[i] = items[i];
}
return o;
}
mp_obj_t mp_obj_new_tuple_reverse(uint n, mp_obj_t *items) {
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n);
o->base.type = &tuple_type;
o->len = n;
for (int i = 0; i < n; i++) {
o->items[i] = items[n - i - 1];
}
return o;
}
/******************************************************************************/
/* tuple iterator */
typedef struct _mp_obj_tuple_it_t {
mp_obj_base_t base;
mp_obj_tuple_t *tuple;
machine_uint_t cur;
} mp_obj_tuple_it_t;
mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
mp_obj_tuple_it_t *self = self_in;
if (self->cur < self->tuple->len) {
mp_obj_t o_out = self->tuple->items[self->cur];
self->cur += 1;
return o_out;
} else {
return mp_const_stop_iteration;
}
}
static const mp_obj_type_t tuple_it_type = {
{ &mp_const_type },
"tuple_iterator",
NULL, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
tuple_it_iternext,
{{NULL, NULL},}, // method list
};
static mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, int cur) {
mp_obj_tuple_it_t *o = m_new_obj(mp_obj_tuple_it_t);
o->base.type = &tuple_it_type;
o->tuple = tuple;
o->cur = cur;
return o;
}

23
py/objtype.c Normal file
View File

@ -0,0 +1,23 @@
#include <stdlib.h>
#include <stdint.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
void type_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "type?");
}
const mp_obj_type_t mp_const_type = {
{ &mp_const_type },
"type?",
type_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{{NULL, NULL},}, // method list
};

View File

@ -7,7 +7,7 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "parse.h"
@ -50,9 +50,9 @@ enum {
#define one_or_more (RULE_ACT_LIST | 2)
#define list (RULE_ACT_LIST | 1)
#define list_with_end (RULE_ACT_LIST | 3)
#define tok(t) (RULE_ARG_TOK | PY_TOKEN_##t)
#define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t)
#define rule(r) (RULE_ARG_RULE | RULE_##r)
#define opt_tok(t) (RULE_ARG_OPT_TOK | PY_TOKEN_##t)
#define opt_tok(t) (RULE_ARG_OPT_TOK | MP_TOKEN_##t)
#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
#ifdef USE_RULE_NAME
#define DEF_RULE(rule, comp, kind, arg...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { arg } };
@ -89,7 +89,7 @@ typedef struct _parser_t {
rule_stack_t *rule_stack;
uint result_stack_top;
py_parse_node_t *result_stack;
mp_parse_node_t *result_stack;
} parser_t;
static void push_rule(parser_t *parser, const rule_t *rule, int arg_i) {
@ -115,47 +115,47 @@ static void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i) {
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
}
py_parse_node_t py_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
return (py_parse_node_t)(kind | (arg << 4));
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
return (mp_parse_node_t)(kind | (arg << 4));
}
int num_parse_nodes_allocated = 0;
py_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) {
py_parse_node_struct_t *pn = m_malloc(sizeof(py_parse_node_struct_t) + num_args * sizeof(py_parse_node_t));
mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) {
mp_parse_node_struct_t *pn = m_malloc(sizeof(mp_parse_node_struct_t) + num_args * sizeof(mp_parse_node_t));
pn->source = 0; // TODO
pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8);
num_parse_nodes_allocated += 1;
return pn;
}
void py_parse_node_show(py_parse_node_t pn, int indent) {
void mp_parse_node_show(mp_parse_node_t pn, int indent) {
for (int i = 0; i < indent; i++) {
printf(" ");
}
if (PY_PARSE_NODE_IS_NULL(pn)) {
if (MP_PARSE_NODE_IS_NULL(pn)) {
printf("NULL\n");
} else if (PY_PARSE_NODE_IS_LEAF(pn)) {
int arg = PY_PARSE_NODE_LEAF_ARG(pn);
switch (PY_PARSE_NODE_LEAF_KIND(pn)) {
case PY_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
case PY_PARSE_NODE_SMALL_INT: printf("int(%d)\n", arg); break;
case PY_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
case PY_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break;
case PY_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
case PY_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
case PY_PARSE_NODE_TOKEN: printf("tok(%d)\n", arg); break;
} else if (MP_PARSE_NODE_IS_LEAF(pn)) {
int arg = MP_PARSE_NODE_LEAF_ARG(pn);
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_SMALL_INT: printf("int(%d)\n", arg); break;
case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_DECIMAL: printf("dec(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_STRING: printf("str(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_BYTES: printf("bytes(%s)\n", qstr_str(arg)); break;
case MP_PARSE_NODE_TOKEN: printf("tok(%d)\n", arg); break;
default: assert(0);
}
} else {
py_parse_node_struct_t *pns2 = (py_parse_node_struct_t*)pn;
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pn;
int n = pns2->kind_num_nodes >> 8;
#ifdef USE_RULE_NAME
printf("%s(%d) (n=%d)\n", rules[PY_PARSE_NODE_STRUCT_KIND(pns2)]->rule_name, PY_PARSE_NODE_STRUCT_KIND(pns2), n);
printf("%s(%d) (n=%d)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns2)]->rule_name, MP_PARSE_NODE_STRUCT_KIND(pns2), n);
#else
printf("rule(%u) (n=%d)\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns2), n);
printf("rule(%u) (n=%d)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns2), n);
#endif
for (int i = 0; i < n; i++) {
py_parse_node_show(pns2->nodes[i], indent + 2);
mp_parse_node_show(pns2->nodes[i], indent + 2);
}
}
}
@ -164,31 +164,31 @@ void py_parse_node_show(py_parse_node_t pn, int indent) {
static void result_stack_show(parser_t *parser) {
printf("result stack, most recent first\n");
for (int i = parser->result_stack_top - 1; i >= 0; i--) {
py_parse_node_show(parser->result_stack[i], 0);
mp_parse_node_show(parser->result_stack[i], 0);
}
}
*/
static py_parse_node_t pop_result(parser_t *parser) {
static mp_parse_node_t pop_result(parser_t *parser) {
assert(parser->result_stack_top > 0);
return parser->result_stack[--parser->result_stack_top];
}
static py_parse_node_t peek_result(parser_t *parser, int pos) {
static mp_parse_node_t peek_result(parser_t *parser, int pos) {
assert(parser->result_stack_top > pos);
return parser->result_stack[parser->result_stack_top - 1 - pos];
}
static void push_result_node(parser_t *parser, py_parse_node_t pn) {
static void push_result_node(parser_t *parser, mp_parse_node_t pn) {
parser->result_stack[parser->result_stack_top++] = pn;
}
static void push_result_token(parser_t *parser, const py_lexer_t *lex) {
const py_token_t *tok = py_lexer_cur(lex);
py_parse_node_t pn;
if (tok->kind == PY_TOKEN_NAME) {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_ID, qstr_from_strn_copy(tok->str, tok->len));
} else if (tok->kind == PY_TOKEN_NUMBER) {
static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
const mp_token_t *tok = mp_lexer_cur(lex);
mp_parse_node_t pn;
if (tok->kind == MP_TOKEN_NAME) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, qstr_from_strn_copy(tok->str, tok->len));
} else if (tok->kind == MP_TOKEN_NUMBER) {
bool dec = false;
bool small_int = true;
int int_val = 0;
@ -227,43 +227,43 @@ static void push_result_token(parser_t *parser, const py_lexer_t *lex) {
}
}
if (dec) {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_DECIMAL, qstr_from_strn_copy(str, len));
} else if (small_int && PY_FIT_SMALL_INT(int_val)) {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_SMALL_INT, int_val);
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)) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val);
} else {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_INTEGER, qstr_from_strn_copy(str, len));
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn_copy(str, len));
}
} else if (tok->kind == PY_TOKEN_STRING) {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_STRING, qstr_from_strn_copy(tok->str, tok->len));
} else if (tok->kind == PY_TOKEN_BYTES) {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_BYTES, qstr_from_strn_copy(tok->str, tok->len));
} else if (tok->kind == MP_TOKEN_STRING) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_STRING, qstr_from_strn_copy(tok->str, tok->len));
} else if (tok->kind == MP_TOKEN_BYTES) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_BYTES, qstr_from_strn_copy(tok->str, tok->len));
} else {
pn = py_parse_node_new_leaf(PY_PARSE_NODE_TOKEN, tok->kind);
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, tok->kind);
}
push_result_node(parser, pn);
}
static void push_result_rule(parser_t *parser, const rule_t *rule, int num_args) {
py_parse_node_struct_t *pn = parse_node_new_struct(rule->rule_id, num_args);
mp_parse_node_struct_t *pn = parse_node_new_struct(rule->rule_id, num_args);
for (int i = num_args; i > 0; i--) {
pn->nodes[i - 1] = pop_result(parser);
}
push_result_node(parser, (py_parse_node_t)pn);
push_result_node(parser, (mp_parse_node_t)pn);
}
py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
parser_t *parser = m_new(parser_t, 1);
parser->rule_stack_alloc = 64;
parser->rule_stack_top = 0;
parser->rule_stack = m_new(rule_stack_t, parser->rule_stack_alloc);
parser->result_stack = m_new(py_parse_node_t, 1000);
parser->result_stack = m_new(mp_parse_node_t, 1000);
parser->result_stack_top = 0;
int top_level_rule;
switch (input_kind) {
case PY_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
//case PY_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
//case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
default: top_level_rule = RULE_file_input;
}
push_rule(parser, rules[top_level_rule], 0);
@ -271,7 +271,7 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
uint n, i;
bool backtrack = false;
const rule_t *rule;
py_token_kind_t tok_kind;
mp_token_kind_t tok_kind;
bool emit_rule;
bool had_trailing_sep;
@ -303,9 +303,9 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
for (; i < n - 1; ++i) {
switch (rule->arg[i] & RULE_ARG_KIND_MASK) {
case RULE_ARG_TOK:
if (py_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) {
if (mp_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) {
push_result_token(parser, lex);
py_lexer_to_next(lex);
mp_lexer_to_next(lex);
goto next_rule;
}
break;
@ -318,9 +318,9 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
}
}
if ((rule->arg[i] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
if (py_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) {
if (mp_lexer_is_kind(lex, rule->arg[i] & RULE_ARG_ARG_MASK)) {
push_result_token(parser, lex);
py_lexer_to_next(lex);
mp_lexer_to_next(lex);
} else {
backtrack = true;
goto next_rule;
@ -337,7 +337,7 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
assert(i > 0);
if ((rule->arg[i - 1] & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE) {
// an optional rule that failed, so continue with next arg
push_result_node(parser, PY_PARSE_NODE_NULL);
push_result_node(parser, MP_PARSE_NODE_NULL);
backtrack = false;
} else {
// a mandatory rule that failed, so propagate backtrack
@ -356,12 +356,12 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
case RULE_ARG_TOK:
// need to match a token
tok_kind = rule->arg[i] & RULE_ARG_ARG_MASK;
if (py_lexer_is_kind(lex, tok_kind)) {
if (mp_lexer_is_kind(lex, tok_kind)) {
// matched token
if (tok_kind == PY_TOKEN_NAME) {
if (tok_kind == MP_TOKEN_NAME) {
push_result_token(parser, lex);
}
py_lexer_to_next(lex);
mp_lexer_to_next(lex);
} else {
// failed to match token
if (i > 0) {
@ -399,10 +399,10 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
for (int x = 0; x < n; ++x) {
if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;
if (tok_kind >= PY_TOKEN_NAME) {
if (tok_kind >= MP_TOKEN_NAME) {
emit_rule = true;
}
if (tok_kind == PY_TOKEN_NAME) {
if (tok_kind == MP_TOKEN_NAME) {
// only tokens which were names are pushed to stack
i += 1;
}
@ -427,13 +427,13 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
// always emit these rules, and add an extra blank node at the end (to be used by the compiler to store data)
if (rule->rule_id == RULE_funcdef || rule->rule_id == RULE_classdef || rule->rule_id == RULE_comp_for || rule->rule_id == RULE_lambdef || rule->rule_id == RULE_lambdef_nocond) {
emit_rule = true;
push_result_node(parser, PY_PARSE_NODE_NULL);
push_result_node(parser, MP_PARSE_NODE_NULL);
i += 1;
}
int num_not_nil = 0;
for (int x = 0; x < i; ++x) {
if (peek_result(parser, x) != PY_PARSE_NODE_NULL) {
if (peek_result(parser, x) != MP_PARSE_NODE_NULL) {
num_not_nil += 1;
}
}
@ -446,10 +446,10 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
//assert(0);
} else if (num_not_nil == 1) {
// single result, leave it on stack
py_parse_node_t pn = PY_PARSE_NODE_NULL;
mp_parse_node_t pn = MP_PARSE_NODE_NULL;
for (int x = 0; x < i; ++x) {
py_parse_node_t pn2 = pop_result(parser);
if (pn2 != PY_PARSE_NODE_NULL) {
mp_parse_node_t pn2 = pop_result(parser);
if (pn2 != MP_PARSE_NODE_NULL) {
pn = pn2;
}
}
@ -498,13 +498,13 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
uint arg = rule->arg[i & 1 & n];
switch (arg & RULE_ARG_KIND_MASK) {
case RULE_ARG_TOK:
if (py_lexer_is_kind(lex, arg & RULE_ARG_ARG_MASK)) {
if (mp_lexer_is_kind(lex, arg & RULE_ARG_ARG_MASK)) {
if (i & 1 & n) {
// separators which are tokens are not pushed to result stack
} else {
push_result_token(parser, lex);
}
py_lexer_to_next(lex);
mp_lexer_to_next(lex);
// got element of list, so continue parsing list
i += 1;
} else {
@ -552,7 +552,7 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
}
// check we are at the end of the token stream
if (!py_lexer_is_kind(lex, PY_TOKEN_END)) {
if (!mp_lexer_is_kind(lex, MP_TOKEN_END)) {
goto syntax_error;
}
@ -564,16 +564,16 @@ py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
return parser->result_stack[0];
syntax_error:
if (py_lexer_is_kind(lex, PY_TOKEN_INDENT)) {
py_lexer_show_error_pythonic(lex, "IndentationError: unexpected indent");
} else if (py_lexer_is_kind(lex, PY_TOKEN_DEDENT_MISMATCH)) {
py_lexer_show_error_pythonic(lex, "IndentationError: unindent does not match any outer indentation level");
if (mp_lexer_is_kind(lex, MP_TOKEN_INDENT)) {
mp_lexer_show_error_pythonic(lex, "IndentationError: unexpected indent");
} else if (mp_lexer_is_kind(lex, MP_TOKEN_DEDENT_MISMATCH)) {
mp_lexer_show_error_pythonic(lex, "IndentationError: unindent does not match any outer indentation level");
} else {
py_lexer_show_error_pythonic(lex, "syntax error:");
mp_lexer_show_error_pythonic(lex, "syntax error:");
#ifdef USE_RULE_NAME
py_lexer_show_error(lex, rule->rule_name);
mp_lexer_show_error(lex, rule->rule_name);
#endif
py_token_show(py_lexer_cur(lex));
mp_token_show(mp_lexer_cur(lex));
}
return PY_PARSE_NODE_NULL;
return MP_PARSE_NODE_NULL;
}

View File

@ -1,6 +1,6 @@
struct _py_lexer_t;
struct _mp_lexer_t;
// a py_parse_node_t is:
// a mp_parse_node_t is:
// - 0000...0000: no node
// - xxxx...0001: an identifier; bits 4 and above are the qstr
// - xxxx...0011: a small integer; bits 4 and above are the signed value, 2's complement
@ -8,58 +8,58 @@ struct _py_lexer_t;
// - xxxx...0111: a decimal; bits 4 and above are the qstr holding the value
// - xxxx...1001: a string; bits 4 and above are the qstr holding the value
// - xxxx...1011: a string with triple quotes; bits 4 and above are the qstr holding the value
// - xxxx...1101: a token; bits 4 and above are py_token_kind_t
// - xxxx...xxx0: pointer to py_parse_node_struct_t
// - xxxx...1101: a token; bits 4 and above are mp_token_kind_t
// - xxxx...xxx0: pointer to mp_parse_node_struct_t
// makes sure the top 5 bits of x are all cleared (positive number) or all set (negavite number)
// these macros can probably go somewhere else because they are used more than just in the parser
#define PY_UINT_HIGH_5_BITS (~((~((machine_uint_t)0)) >> 5))
#define PY_FIT_SMALL_INT(x) (((((machine_uint_t)(x)) & PY_UINT_HIGH_5_BITS) == 0) || ((((machine_uint_t)(x)) & PY_UINT_HIGH_5_BITS) == PY_UINT_HIGH_5_BITS))
#define MP_UINT_HIGH_5_BITS (~((~((machine_uint_t)0)) >> 5))
#define MP_FIT_SMALL_INT(x) (((((machine_uint_t)(x)) & MP_UINT_HIGH_5_BITS) == 0) || ((((machine_uint_t)(x)) & MP_UINT_HIGH_5_BITS) == MP_UINT_HIGH_5_BITS))
#define PY_PARSE_NODE_NULL (0)
#define PY_PARSE_NODE_ID (0x1)
#define PY_PARSE_NODE_SMALL_INT (0x3)
#define PY_PARSE_NODE_INTEGER (0x5)
#define PY_PARSE_NODE_DECIMAL (0x7)
#define PY_PARSE_NODE_STRING (0x9)
#define PY_PARSE_NODE_BYTES (0xb)
#define PY_PARSE_NODE_TOKEN (0xd)
#define MP_PARSE_NODE_NULL (0)
#define MP_PARSE_NODE_ID (0x1)
#define MP_PARSE_NODE_SMALL_INT (0x3)
#define MP_PARSE_NODE_INTEGER (0x5)
#define MP_PARSE_NODE_DECIMAL (0x7)
#define MP_PARSE_NODE_STRING (0x9)
#define MP_PARSE_NODE_BYTES (0xb)
#define MP_PARSE_NODE_TOKEN (0xd)
typedef machine_uint_t py_parse_node_t; // must be pointer size
typedef machine_uint_t mp_parse_node_t; // must be pointer size
typedef struct _py_parse_node_struct_t {
typedef struct _mp_parse_node_struct_t {
uint32_t source; // file identifier, and line number
uint32_t kind_num_nodes; // parse node kind, and number of nodes
py_parse_node_t nodes[]; // nodes
} py_parse_node_struct_t;
mp_parse_node_t nodes[]; // nodes
} mp_parse_node_struct_t;
// macros for py_parse_node_t usage
// macros for mp_parse_node_t usage
// some of these evaluate their argument more than once
#define PY_PARSE_NODE_IS_NULL(pn) ((pn) == PY_PARSE_NODE_NULL)
#define PY_PARSE_NODE_IS_LEAF(pn) ((pn) & 1)
#define PY_PARSE_NODE_IS_STRUCT(pn) ((pn) != PY_PARSE_NODE_NULL && ((pn) & 1) == 0)
#define PY_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != PY_PARSE_NODE_NULL && ((pn) & 1) == 0 && PY_PARSE_NODE_STRUCT_KIND((py_parse_node_struct_t*)(pn)) == (k))
#define MP_PARSE_NODE_IS_NULL(pn) ((pn) == MP_PARSE_NODE_NULL)
#define MP_PARSE_NODE_IS_LEAF(pn) ((pn) & 1)
#define MP_PARSE_NODE_IS_STRUCT(pn) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 1) == 0)
#define MP_PARSE_NODE_IS_STRUCT_KIND(pn, k) ((pn) != MP_PARSE_NODE_NULL && ((pn) & 1) == 0 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)(pn)) == (k))
#define PY_PARSE_NODE_IS_ID(pn) (((pn) & 0xf) == PY_PARSE_NODE_ID)
#define PY_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0xf) == PY_PARSE_NODE_SMALL_INT)
#define PY_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0xf) == PY_PARSE_NODE_TOKEN)
#define PY_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (PY_PARSE_NODE_TOKEN | (k << 4)))
#define MP_PARSE_NODE_IS_ID(pn) (((pn) & 0xf) == MP_PARSE_NODE_ID)
#define MP_PARSE_NODE_IS_SMALL_INT(pn) (((pn) & 0xf) == MP_PARSE_NODE_SMALL_INT)
#define MP_PARSE_NODE_IS_TOKEN(pn) (((pn) & 0xf) == MP_PARSE_NODE_TOKEN)
#define MP_PARSE_NODE_IS_TOKEN_KIND(pn, k) ((pn) == (MP_PARSE_NODE_TOKEN | (k << 4)))
#define PY_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0xf)
#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0xf)
// TODO should probably have int and uint versions of this macro
#define PY_PARSE_NODE_LEAF_ARG(pn) (((machine_int_t)(pn)) >> 4)
#define PY_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
#define PY_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
#define MP_PARSE_NODE_LEAF_ARG(pn) (((machine_int_t)(pn)) >> 4)
#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
py_parse_node_t py_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
void py_parse_node_show(py_parse_node_t pn, int indent);
void mp_parse_node_show(mp_parse_node_t pn, int indent);
typedef enum {
PY_PARSE_SINGLE_INPUT,
PY_PARSE_FILE_INPUT,
PY_PARSE_EVAL_INPUT,
} py_parse_input_kind_t;
MP_PARSE_SINGLE_INPUT,
MP_PARSE_FILE_INPUT,
MP_PARSE_EVAL_INPUT,
} mp_parse_input_kind_t;
py_parse_node_t py_parse(struct _py_lexer_t *lex, py_parse_input_kind_t input_kind);
mp_parse_node_t mp_parse(struct _mp_lexer_t *lex, mp_parse_input_kind_t input_kind);

View File

@ -11,7 +11,7 @@ bool str_startswith_word(const char *str, const char *head) {
return head[i] == '\0' && (str[i] == '\0' || !g_unichar_isalpha(str[i]));
}
bool py_repl_is_compound_stmt(const char *line) {
bool mp_repl_is_compound_stmt(const char *line) {
// compound if line starts with a certain keyword
if (
str_startswith_word(line, "if")

View File

@ -1 +1 @@
bool py_repl_is_compound_stmt(const char *line);
bool mp_repl_is_compound_stmt(const char *line);

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +1,3 @@
typedef enum {
RT_UNARY_OP_NOT,
RT_UNARY_OP_POSITIVE,
RT_UNARY_OP_NEGATIVE,
RT_UNARY_OP_INVERT,
} rt_unary_op_t;
typedef enum {
RT_BINARY_OP_SUBSCR,
RT_BINARY_OP_OR,
RT_BINARY_OP_XOR,
RT_BINARY_OP_AND,
RT_BINARY_OP_LSHIFT,
RT_BINARY_OP_RSHIFT,
RT_BINARY_OP_ADD,
RT_BINARY_OP_SUBTRACT,
RT_BINARY_OP_MULTIPLY,
RT_BINARY_OP_FLOOR_DIVIDE,
RT_BINARY_OP_TRUE_DIVIDE,
RT_BINARY_OP_MODULO,
RT_BINARY_OP_POWER,
RT_BINARY_OP_INPLACE_OR,
RT_BINARY_OP_INPLACE_XOR,
RT_BINARY_OP_INPLACE_AND,
RT_BINARY_OP_INPLACE_LSHIFT,
RT_BINARY_OP_INPLACE_RSHIFT,
RT_BINARY_OP_INPLACE_ADD,
RT_BINARY_OP_INPLACE_SUBTRACT,
RT_BINARY_OP_INPLACE_MULTIPLY,
RT_BINARY_OP_INPLACE_FLOOR_DIVIDE,
RT_BINARY_OP_INPLACE_TRUE_DIVIDE,
RT_BINARY_OP_INPLACE_MODULO,
RT_BINARY_OP_INPLACE_POWER,
} rt_binary_op_t;
typedef enum {
RT_COMPARE_OP_LESS,
RT_COMPARE_OP_MORE,
RT_COMPARE_OP_EQUAL,
RT_COMPARE_OP_LESS_EQUAL,
RT_COMPARE_OP_MORE_EQUAL,
RT_COMPARE_OP_NOT_EQUAL,
RT_COMPARE_OP_IN,
RT_COMPARE_OP_NOT_IN,
RT_COMPARE_OP_IS,
RT_COMPARE_OP_IS_NOT,
RT_COMPARE_OP_EXCEPTION_MATCH,
} rt_compare_op_t;
typedef enum {
RT_F_LOAD_CONST_DEC = 0,
RT_F_LOAD_CONST_STR,
RT_F_LOAD_NAME,
RT_F_LOAD_GLOBAL,
RT_F_LOAD_BUILD_CLASS,
RT_F_LOAD_ATTR,
RT_F_LOAD_METHOD,
RT_F_STORE_NAME,
RT_F_STORE_ATTR,
RT_F_STORE_SUBSCR,
RT_F_IS_TRUE,
RT_F_UNARY_OP,
RT_F_BUILD_TUPLE,
RT_F_BUILD_LIST,
RT_F_LIST_APPEND,
RT_F_BUILD_MAP,
RT_F_STORE_MAP,
RT_F_BUILD_SET,
RT_F_STORE_SET,
RT_F_MAKE_FUNCTION_FROM_ID,
RT_F_CALL_FUNCTION_N,
RT_F_CALL_METHOD_N,
RT_F_BINARY_OP,
RT_F_COMPARE_OP,
RT_F_GETITER,
RT_F_ITERNEXT,
RT_F_NUMBER_OF,
} rt_fun_kind_t;
extern void *const rt_fun_table[RT_F_NUMBER_OF];
typedef machine_ptr_t py_obj_t; // must be of pointer size
typedef py_obj_t (*py_fun_0_t)(void);
typedef py_obj_t (*py_fun_1_t)(py_obj_t);
typedef py_obj_t (*py_fun_2_t)(py_obj_t, py_obj_t);
typedef py_obj_t (*py_fun_t)(void);
typedef py_obj_t (*py_fun_var_t)(int n, const py_obj_t *);
extern qstr rt_q_append;
extern qstr rt_q_pop;
extern qstr rt_q_sort;
@ -101,61 +13,47 @@ extern qstr rt_q_TypeError;
extern qstr rt_q_SyntaxError;
extern qstr rt_q_ValueError;
extern py_obj_t py_const_none;
extern py_obj_t py_const_false;
extern py_obj_t py_const_true;
extern py_obj_t py_const_stop_iteration; // special object indicating end of iteration (not StopIteration exception!)
int rt_is_true(mp_obj_t arg);
void rt_init(void);
void rt_deinit(void);
int rt_get_unique_code_id(bool is_main_module);
void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_cells, int n_stack, bool is_generator);
void rt_assign_native_code(int unique_code_id, py_fun_t f, uint len, int n_args);
void rt_assign_inline_asm_code(int unique_code_id, py_fun_t f, uint len, int n_args);
int rt_is_true(py_obj_t arg);
py_obj_t rt_load_const_dec(qstr qstr);
py_obj_t rt_load_const_str(qstr qstr);
py_obj_t rt_load_name(qstr qstr);
py_obj_t rt_load_global(qstr qstr);
py_obj_t rt_load_build_class(void);
py_obj_t rt_get_cell(py_obj_t cell);
void rt_set_cell(py_obj_t cell, py_obj_t val);
void rt_store_name(qstr qstr, py_obj_t obj);
void rt_store_global(qstr qstr, py_obj_t obj);
py_obj_t rt_unary_op(int op, py_obj_t arg);
py_obj_t rt_binary_op(int op, py_obj_t lhs, py_obj_t rhs);
py_obj_t rt_compare_op(int op, py_obj_t lhs, py_obj_t rhs);
py_obj_t rt_make_function_from_id(int unique_code_id);
py_obj_t rt_make_function_0(py_fun_0_t f);
py_obj_t rt_make_function_1(py_fun_1_t f);
py_obj_t rt_make_function_2(py_fun_2_t f);
py_obj_t rt_make_function(int n_args, py_fun_t code);
py_obj_t rt_make_function_var(int n_fixed_args, py_fun_var_t f);
py_obj_t rt_make_closure_from_id(int unique_code_id, py_obj_t closure_tuple);
py_obj_t rt_call_function_0(py_obj_t fun);
py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg);
py_obj_t rt_call_function_2(py_obj_t fun, py_obj_t arg1, py_obj_t arg2);
py_obj_t rt_call_function_n(py_obj_t fun, int n_args, const py_obj_t *args);
py_obj_t rt_call_function_n_kw(py_obj_t fun, uint n_args, uint n_kw, const py_obj_t *args);
py_obj_t rt_call_method_n(uint n_args, const py_obj_t *args);
py_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, 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_set(int n_args, py_obj_t *items);
py_obj_t rt_store_set(py_obj_t set, py_obj_t item);
void rt_unpack_sequence(py_obj_t seq, uint num, py_obj_t *items);
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_load_attr(py_obj_t base, qstr attr);
void rt_load_method(py_obj_t base, qstr attr, py_obj_t *dest);
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 val);
py_obj_t rt_getiter(py_obj_t o);
py_obj_t rt_iternext(py_obj_t o);
py_obj_t rt_import_name(qstr name, py_obj_t fromlist, py_obj_t level);
py_obj_t rt_import_from(py_obj_t module, qstr name);
py_obj_t rt_gen_instance_next(py_obj_t self_in);
mp_obj_t rt_load_const_dec(qstr qstr);
mp_obj_t rt_load_const_str(qstr qstr);
mp_obj_t rt_load_name(qstr qstr);
mp_obj_t rt_load_global(qstr qstr);
mp_obj_t rt_load_build_class(void);
mp_obj_t rt_get_cell(mp_obj_t cell);
void rt_set_cell(mp_obj_t cell, mp_obj_t val);
void rt_store_name(qstr qstr, mp_obj_t obj);
void rt_store_global(qstr qstr, mp_obj_t obj);
mp_obj_t rt_unary_op(int op, mp_obj_t arg);
mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t rt_make_function_from_id(int unique_code_id);
mp_obj_t rt_make_function_0(mp_fun_0_t f);
mp_obj_t rt_make_function_1(mp_fun_1_t f);
mp_obj_t rt_make_function_2(mp_fun_2_t f);
mp_obj_t rt_make_function_var(int n_args_min, mp_fun_var_t f);
mp_obj_t rt_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive
mp_obj_t rt_make_closure_from_id(int unique_code_id, mp_obj_t closure_tuple);
mp_obj_t rt_call_function_0(mp_obj_t fun);
mp_obj_t rt_call_function_1(mp_obj_t fun, mp_obj_t arg);
mp_obj_t rt_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
mp_obj_t rt_call_function_n(mp_obj_t fun, int n_args, const mp_obj_t *args);
mp_obj_t rt_call_function_n_kw(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
mp_obj_t rt_call_method_n(uint n_args, const mp_obj_t *args);
mp_obj_t rt_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args);
mp_obj_t rt_build_tuple(int n_args, mp_obj_t *items);
mp_obj_t rt_build_list(int n_args, mp_obj_t *items);
mp_obj_t rt_list_append(mp_obj_t list, mp_obj_t arg);
mp_obj_t rt_build_set(int n_args, mp_obj_t *items);
mp_obj_t rt_store_set(mp_obj_t set, mp_obj_t item);
void rt_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
mp_obj_t rt_build_map(int n_args);
mp_obj_t rt_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t rt_load_attr(mp_obj_t base, qstr attr);
void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
mp_obj_t rt_getiter(mp_obj_t o);
mp_obj_t rt_iternext(mp_obj_t o);
mp_obj_t rt_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level);
mp_obj_t rt_import_from(mp_obj_t module, qstr name);

87
py/runtime0.h Normal file
View File

@ -0,0 +1,87 @@
typedef enum {
RT_UNARY_OP_NOT,
RT_UNARY_OP_POSITIVE,
RT_UNARY_OP_NEGATIVE,
RT_UNARY_OP_INVERT,
} rt_unary_op_t;
typedef enum {
RT_BINARY_OP_SUBSCR,
RT_BINARY_OP_OR,
RT_BINARY_OP_XOR,
RT_BINARY_OP_AND,
RT_BINARY_OP_LSHIFT,
RT_BINARY_OP_RSHIFT,
RT_BINARY_OP_ADD,
RT_BINARY_OP_SUBTRACT,
RT_BINARY_OP_MULTIPLY,
RT_BINARY_OP_FLOOR_DIVIDE,
RT_BINARY_OP_TRUE_DIVIDE,
RT_BINARY_OP_MODULO,
RT_BINARY_OP_POWER,
RT_BINARY_OP_INPLACE_OR,
RT_BINARY_OP_INPLACE_XOR,
RT_BINARY_OP_INPLACE_AND,
RT_BINARY_OP_INPLACE_LSHIFT,
RT_BINARY_OP_INPLACE_RSHIFT,
RT_BINARY_OP_INPLACE_ADD,
RT_BINARY_OP_INPLACE_SUBTRACT,
RT_BINARY_OP_INPLACE_MULTIPLY,
RT_BINARY_OP_INPLACE_FLOOR_DIVIDE,
RT_BINARY_OP_INPLACE_TRUE_DIVIDE,
RT_BINARY_OP_INPLACE_MODULO,
RT_BINARY_OP_INPLACE_POWER,
} rt_binary_op_t;
typedef enum {
RT_COMPARE_OP_LESS,
RT_COMPARE_OP_MORE,
RT_COMPARE_OP_EQUAL,
RT_COMPARE_OP_LESS_EQUAL,
RT_COMPARE_OP_MORE_EQUAL,
RT_COMPARE_OP_NOT_EQUAL,
RT_COMPARE_OP_IN,
RT_COMPARE_OP_NOT_IN,
RT_COMPARE_OP_IS,
RT_COMPARE_OP_IS_NOT,
RT_COMPARE_OP_EXCEPTION_MATCH,
} rt_compare_op_t;
typedef enum {
RT_F_LOAD_CONST_DEC = 0,
RT_F_LOAD_CONST_STR,
RT_F_LOAD_NAME,
RT_F_LOAD_GLOBAL,
RT_F_LOAD_BUILD_CLASS,
RT_F_LOAD_ATTR,
RT_F_LOAD_METHOD,
RT_F_STORE_NAME,
RT_F_STORE_ATTR,
RT_F_STORE_SUBSCR,
RT_F_IS_TRUE,
RT_F_UNARY_OP,
RT_F_BUILD_TUPLE,
RT_F_BUILD_LIST,
RT_F_LIST_APPEND,
RT_F_BUILD_MAP,
RT_F_STORE_MAP,
RT_F_BUILD_SET,
RT_F_STORE_SET,
RT_F_MAKE_FUNCTION_FROM_ID,
RT_F_CALL_FUNCTION_N,
RT_F_CALL_METHOD_N,
RT_F_BINARY_OP,
RT_F_COMPARE_OP,
RT_F_GETITER,
RT_F_ITERNEXT,
RT_F_NUMBER_OF,
} rt_fun_kind_t;
extern void *const rt_fun_table[RT_F_NUMBER_OF];
void rt_init(void);
void rt_deinit(void);
int rt_get_unique_code_id(bool is_main_module);
void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_cells, int n_stack, bool is_generator);
void rt_assign_native_code(int unique_code_id, void *f, uint len, int n_args);
void rt_assign_inline_asm_code(int unique_code_id, void *f, uint len, int n_args);

View File

@ -4,11 +4,11 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "parse.h"
#include "scope.h"
scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, uint emit_options) {
scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, uint unique_code_id, uint emit_options) {
scope_t *scope = m_new(scope_t, 1);
scope->kind = kind;
scope->parent = NULL;
@ -20,8 +20,8 @@ scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, u
break;
case SCOPE_FUNCTION:
case SCOPE_CLASS:
assert(PY_PARSE_NODE_IS_STRUCT(pn));
scope->simple_name = PY_PARSE_NODE_LEAF_ARG(((py_parse_node_struct_t*)pn)->nodes[0]);
assert(MP_PARSE_NODE_IS_STRUCT(pn));
scope->simple_name = MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pn)->nodes[0]);
break;
case SCOPE_LAMBDA:
scope->simple_name = qstr_from_str_static("<lambda>");

View File

@ -37,7 +37,7 @@ typedef struct _scope_t {
scope_kind_t kind;
struct _scope_t *parent;
struct _scope_t *next;
py_parse_node_t pn;
mp_parse_node_t pn;
qstr simple_name;
int id_info_alloc;
int id_info_len;
@ -55,7 +55,7 @@ typedef struct _scope_t {
uint emit_options;
} scope_t;
scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, uint emit_options);
scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, uint unique_code_id, uint emit_options);
id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added);
id_info_t *scope_find(scope_t *scope, qstr qstr);
id_info_t *scope_find_global(scope_t *scope, qstr qstr);

View File

@ -5,16 +5,15 @@
#include <assert.h>
#include "misc.h"
#include "mpyconfig.h"
#include "runtime.h"
#include "bc.h"
#include "mpconfig.h"
#include "bc0.h"
#define DECODE_UINT do { unum = *ip++; if (unum > 127) { unum = ((unum & 0x3f) << 8) | (*ip++); } } while (0)
#define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0)
#define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0)
#define DECODE_QSTR do { qstr = *ip++; if (qstr > 127) { qstr = ((qstr & 0x3f) << 8) | (*ip++); } } while (0)
void py_show_byte_code(const byte *ip, int len) {
void mp_show_byte_code(const byte *ip, int len) {
const byte *ip_start = ip;
machine_uint_t unum;
qstr qstr;
@ -22,164 +21,164 @@ void py_show_byte_code(const byte *ip, int len) {
printf("%02u ", (uint)(ip - ip_start));
int op = *ip++;
switch (op) {
case PYBC_LOAD_CONST_FALSE:
case MP_BC_LOAD_CONST_FALSE:
printf("LOAD_CONST_FALSE");
break;
case PYBC_LOAD_CONST_NONE:
case MP_BC_LOAD_CONST_NONE:
printf("LOAD_CONST_NONE");
break;
case PYBC_LOAD_CONST_TRUE:
case MP_BC_LOAD_CONST_TRUE:
printf("LOAD_CONST_TRUE");
break;
case PYBC_LOAD_CONST_SMALL_INT:
case MP_BC_LOAD_CONST_SMALL_INT:
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
ip += 3;
printf("LOAD_CONST_SMALL_INT %d", (int)unum);
break;
/*
case PYBC_LOAD_CONST_DEC:
case MP_BC_LOAD_CONST_DEC:
DECODE_QSTR;
PUSH(rt_load_const_dec(qstr));
break;
*/
case PYBC_LOAD_CONST_ID:
case MP_BC_LOAD_CONST_ID:
DECODE_QSTR;
printf("LOAD_CONST_ID %s", qstr_str(qstr));
break;
case PYBC_LOAD_CONST_STRING:
case MP_BC_LOAD_CONST_STRING:
DECODE_QSTR;
printf("LOAD_CONST_STRING %s", qstr_str(qstr));
break;
case PYBC_LOAD_FAST_0:
case MP_BC_LOAD_FAST_0:
printf("LOAD_FAST_0");
break;
case PYBC_LOAD_FAST_1:
case MP_BC_LOAD_FAST_1:
printf("LOAD_FAST_1");
break;
case PYBC_LOAD_FAST_2:
case MP_BC_LOAD_FAST_2:
printf("LOAD_FAST_2");
break;
case PYBC_LOAD_FAST_N:
case MP_BC_LOAD_FAST_N:
DECODE_UINT;
printf("LOAD_FAST_N %lu", unum);
break;
case PYBC_LOAD_NAME:
case MP_BC_LOAD_NAME:
DECODE_QSTR;
printf("LOAD_NAME %s", qstr_str(qstr));
break;
case PYBC_LOAD_GLOBAL:
case MP_BC_LOAD_GLOBAL:
DECODE_QSTR;
printf("LOAD_GLOBAL %s", qstr_str(qstr));
break;
case PYBC_LOAD_ATTR:
case MP_BC_LOAD_ATTR:
DECODE_QSTR;
printf("LOAD_ATTR %s", qstr_str(qstr));
break;
case PYBC_LOAD_METHOD:
case MP_BC_LOAD_METHOD:
DECODE_QSTR;
printf("LOAD_METHOD %s", qstr_str(qstr));
break;
case PYBC_LOAD_BUILD_CLASS:
case MP_BC_LOAD_BUILD_CLASS:
printf("LOAD_BUILD_CLASS");
break;
case PYBC_STORE_FAST_0:
case MP_BC_STORE_FAST_0:
printf("STORE_FAST_0");
break;
case PYBC_STORE_FAST_1:
case MP_BC_STORE_FAST_1:
printf("STORE_FAST_1");
break;
case PYBC_STORE_FAST_2:
case MP_BC_STORE_FAST_2:
printf("STORE_FAST_2");
break;
case PYBC_STORE_FAST_N:
case MP_BC_STORE_FAST_N:
DECODE_UINT;
printf("STORE_FAST_N %lu", unum);
break;
case PYBC_STORE_NAME:
case MP_BC_STORE_NAME:
DECODE_QSTR;
printf("STORE_NAME %s", qstr_str(qstr));
break;
/*
case PYBC_STORE_GLOBAL:
case MP_BC_STORE_GLOBAL:
DECODE_QSTR;
rt_store_global(qstr, POP());
break;
*/
case PYBC_STORE_ATTR:
case MP_BC_STORE_ATTR:
DECODE_QSTR;
printf("STORE_ATTR %s", qstr_str(qstr));
break;
case PYBC_STORE_SUBSCR:
case MP_BC_STORE_SUBSCR:
printf("STORE_SUBSCR");
break;
/*
case PYBC_DUP_TOP:
case MP_BC_DUP_TOP:
obj1 = *sp;
PUSH(obj1);
break;
*/
case PYBC_DUP_TOP_TWO:
case MP_BC_DUP_TOP_TWO:
printf("DUP_TOP_TWO");
break;
case PYBC_POP_TOP:
case MP_BC_POP_TOP:
printf("POP_TOP");
break;
/*
case PYBC_ROT_TWO:
case MP_BC_ROT_TWO:
obj1 = sp[0];
sp[0] = sp[1];
sp[1] = obj1;
break;
*/
case PYBC_ROT_THREE:
case MP_BC_ROT_THREE:
printf("ROT_THREE");
break;
case PYBC_JUMP:
case MP_BC_JUMP:
DECODE_SLABEL;
printf("JUMP %lu", ip + unum - ip_start);
break;
case PYBC_POP_JUMP_IF_TRUE:
case MP_BC_POP_JUMP_IF_TRUE:
DECODE_SLABEL;
printf("POP_JUMP_IF_TRUE %lu", ip + unum - ip_start);
break;
case PYBC_POP_JUMP_IF_FALSE:
case MP_BC_POP_JUMP_IF_FALSE:
DECODE_SLABEL;
printf("POP_JUMP_IF_FALSE %lu", ip + unum - ip_start);
break;
/*
case PYBC_JUMP_IF_TRUE_OR_POP:
case MP_BC_JUMP_IF_TRUE_OR_POP:
DECODE_SLABEL;
if (rt_is_true(*sp)) {
ip += unum;
@ -188,7 +187,7 @@ void py_show_byte_code(const byte *ip, int len) {
}
break;
case PYBC_JUMP_IF_FALSE_OR_POP:
case MP_BC_JUMP_IF_FALSE_OR_POP:
DECODE_SLABEL;
if (rt_is_true(*sp)) {
sp++;
@ -197,13 +196,13 @@ void py_show_byte_code(const byte *ip, int len) {
}
break;
case PYBC_SETUP_EXCEPT:
case MP_BC_SETUP_EXCEPT:
DECODE_ULABEL; // except labels are always forward
*++exc_sp = (machine_uint_t)ip + unum;
*++exc_sp = (machine_uint_t)sp;
break;
case PYBC_END_FINALLY:
case MP_BC_END_FINALLY:
// not implemented
// if TOS is an exception, reraises the exception (3 values on TOS)
// if TOS is an integer, does something else
@ -213,90 +212,90 @@ void py_show_byte_code(const byte *ip, int len) {
break;
*/
case PYBC_GET_ITER:
case MP_BC_GET_ITER:
printf("GET_ITER");
break;
case PYBC_FOR_ITER:
case MP_BC_FOR_ITER:
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
printf("FOR_ITER %lu", ip + unum - ip_start);
break;
/*
case PYBC_POP_BLOCK:
case MP_BC_POP_BLOCK:
// pops block and restores the stack
assert(0);
break;
case PYBC_POP_EXCEPT:
case MP_BC_POP_EXCEPT:
// TODO need to work out how blocks work etc
// pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
assert(exc_sp >= &exc_stack[0]);
//sp = (py_obj_t*)(*exc_sp--);
//sp = (mp_obj_t*)(*exc_sp--);
//exc_sp--; // discard ip
exc_sp -= 2;
//sp += 3; // pop 3 exception values
break;
case PYBC_UNARY_OP:
case MP_BC_UNARY_OP:
unum = *ip++;
*sp = rt_unary_op(unum, *sp);
break;
*/
case PYBC_BINARY_OP:
case MP_BC_BINARY_OP:
unum = *ip++;
printf("BINARY_OP %lu", unum);
break;
case PYBC_COMPARE_OP:
case MP_BC_COMPARE_OP:
unum = *ip++;
printf("COMPARE_OP %lu", unum);
break;
case PYBC_BUILD_TUPLE:
case MP_BC_BUILD_TUPLE:
DECODE_UINT;
printf("BUILD_TUPLE %lu", unum);
break;
case PYBC_BUILD_LIST:
case MP_BC_BUILD_LIST:
DECODE_UINT;
printf("BUILD_LIST %lu", unum);
break;
/*
case PYBC_LIST_APPEND:
case MP_BC_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:
case MP_BC_BUILD_MAP:
DECODE_UINT;
PUSH(rt_build_map(unum));
break;
case PYBC_STORE_MAP:
case MP_BC_STORE_MAP:
sp += 2;
rt_store_map(sp[0], sp[-2], sp[-1]);
break;
case PYBC_MAP_ADD:
case MP_BC_MAP_ADD:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[unum + 1] is a map
rt_store_map(sp[unum + 1], sp[0], sp[1]);
sp += 2;
break;
case PYBC_BUILD_SET:
case MP_BC_BUILD_SET:
DECODE_UINT;
obj1 = rt_build_set(unum, sp);
sp += unum - 1;
*sp = obj1;
break;
case PYBC_SET_ADD:
case MP_BC_SET_ADD:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[unum] is a set
rt_store_set(sp[unum], sp[0]);
@ -304,32 +303,32 @@ void py_show_byte_code(const byte *ip, int len) {
break;
*/
case PYBC_UNPACK_SEQUENCE:
case MP_BC_UNPACK_SEQUENCE:
DECODE_UINT;
printf("UNPACK_SEQUENCE %lu", unum);
break;
case PYBC_MAKE_FUNCTION:
case MP_BC_MAKE_FUNCTION:
DECODE_UINT;
printf("MAKE_FUNCTION %lu", unum);
break;
case PYBC_CALL_FUNCTION:
case MP_BC_CALL_FUNCTION:
DECODE_UINT;
printf("CALL_FUNCTION n=%lu nkw=%lu", unum & 0xff, (unum >> 8) & 0xff);
break;
case PYBC_CALL_METHOD:
case MP_BC_CALL_METHOD:
DECODE_UINT;
printf("CALL_METHOD n=%lu nkw=%lu", unum & 0xff, (unum >> 8) & 0xff);
break;
case PYBC_RETURN_VALUE:
case MP_BC_RETURN_VALUE:
printf("RETURN_VALUE");
break;
/*
case PYBC_YIELD_VALUE:
case MP_BC_YIELD_VALUE:
nlr_pop();
*ip_in_out = ip;
fastn[0] = fast0;

172
py/vm.c
View File

@ -6,8 +6,10 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "obj.h"
#include "runtime.h"
#include "bc0.h"
#include "bc.h"
// (value) stack grows down (to be compatible with native code when passing pointers to the stack), top element is pointed to
@ -23,12 +25,12 @@
#define SET_TOP(val) *sp = (val)
// args are in reverse order in array
py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_args, uint n_state) {
py_obj_t temp_state[10]; // TODO allocate properly
py_obj_t *state = &temp_state[0];
py_obj_t *sp = &state[10];
mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state) {
mp_obj_t temp_state[10]; // TODO allocate properly
mp_obj_t *state = &temp_state[0];
mp_obj_t *sp = &state[10];
if (n_state > 10) {
state = m_new(py_obj_t, n_state);
state = m_new(mp_obj_t, n_state);
sp = &state[n_state];
}
// init args
@ -37,7 +39,7 @@ py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_arg
state[i] = args[n_args - 1 - i];
}
const byte *ip = code;
if (py_execute_byte_code_2(&ip, &state[0], &sp)) {
if (mp_execute_byte_code_2(&ip, &state[0], &sp)) {
// it shouldn't yield
assert(0);
}
@ -48,15 +50,15 @@ py_obj_t py_execute_byte_code(const byte *code, const py_obj_t *args, uint n_arg
// fastn has items in normal order
// sp points to top of stack which grows down
bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **sp_in_out) {
bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out) {
// careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
const byte *ip = *ip_in_out;
py_obj_t *sp = *sp_in_out;
mp_obj_t *sp = *sp_in_out;
machine_uint_t unum;
qstr qstr;
py_obj_t obj1, obj2;
py_obj_t fast0 = fastn[0], fast1 = fastn[1], fast2 = fastn[2];
mp_obj_t obj1, obj2;
mp_obj_t fast0 = fastn[0], fast1 = fastn[1], fast2 = fastn[2];
nlr_buf_t nlr;
// on the exception stack we store (ip, sp) for each block
@ -70,182 +72,182 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
for (;;) {
int op = *ip++;
switch (op) {
case PYBC_LOAD_CONST_FALSE:
PUSH(py_const_false);
case MP_BC_LOAD_CONST_FALSE:
PUSH(mp_const_false);
break;
case PYBC_LOAD_CONST_NONE:
PUSH(py_const_none);
case MP_BC_LOAD_CONST_NONE:
PUSH(mp_const_none);
break;
case PYBC_LOAD_CONST_TRUE:
PUSH(py_const_true);
case MP_BC_LOAD_CONST_TRUE:
PUSH(mp_const_true);
break;
case PYBC_LOAD_CONST_SMALL_INT:
case MP_BC_LOAD_CONST_SMALL_INT:
unum = (ip[0] | (ip[1] << 8) | (ip[2] << 16)) - 0x800000;
ip += 3;
PUSH((py_obj_t)(unum << 1 | 1));
PUSH((mp_obj_t)(unum << 1 | 1));
break;
case PYBC_LOAD_CONST_DEC:
case MP_BC_LOAD_CONST_DEC:
DECODE_QSTR;
PUSH(rt_load_const_dec(qstr));
break;
case PYBC_LOAD_CONST_ID:
case MP_BC_LOAD_CONST_ID:
DECODE_QSTR;
PUSH(rt_load_const_str(qstr)); // TODO
break;
case PYBC_LOAD_CONST_STRING:
case MP_BC_LOAD_CONST_STRING:
DECODE_QSTR;
PUSH(rt_load_const_str(qstr));
break;
case PYBC_LOAD_FAST_0:
case MP_BC_LOAD_FAST_0:
PUSH(fast0);
break;
case PYBC_LOAD_FAST_1:
case MP_BC_LOAD_FAST_1:
PUSH(fast1);
break;
case PYBC_LOAD_FAST_2:
case MP_BC_LOAD_FAST_2:
PUSH(fast2);
break;
case PYBC_LOAD_FAST_N:
case MP_BC_LOAD_FAST_N:
DECODE_UINT;
PUSH(fastn[unum]);
break;
case PYBC_LOAD_DEREF:
case MP_BC_LOAD_DEREF:
DECODE_UINT;
PUSH(rt_get_cell(fastn[unum]));
break;
case PYBC_LOAD_CLOSURE:
case MP_BC_LOAD_CLOSURE:
DECODE_UINT;
PUSH(fastn[unum]);
break;
case PYBC_LOAD_NAME:
case MP_BC_LOAD_NAME:
DECODE_QSTR;
PUSH(rt_load_name(qstr));
break;
case PYBC_LOAD_GLOBAL:
case MP_BC_LOAD_GLOBAL:
DECODE_QSTR;
PUSH(rt_load_global(qstr));
break;
case PYBC_LOAD_ATTR:
case MP_BC_LOAD_ATTR:
DECODE_QSTR;
SET_TOP(rt_load_attr(TOP(), qstr));
break;
case PYBC_LOAD_METHOD:
case MP_BC_LOAD_METHOD:
DECODE_QSTR;
sp -= 1;
rt_load_method(sp[1], qstr, sp);
break;
case PYBC_LOAD_BUILD_CLASS:
case MP_BC_LOAD_BUILD_CLASS:
PUSH(rt_load_build_class());
break;
case PYBC_STORE_FAST_0:
case MP_BC_STORE_FAST_0:
fast0 = POP();
break;
case PYBC_STORE_FAST_1:
case MP_BC_STORE_FAST_1:
fast1 = POP();
break;
case PYBC_STORE_FAST_2:
case MP_BC_STORE_FAST_2:
fast2 = POP();
break;
case PYBC_STORE_FAST_N:
case MP_BC_STORE_FAST_N:
DECODE_UINT;
fastn[unum] = POP();
break;
case PYBC_STORE_DEREF:
case MP_BC_STORE_DEREF:
DECODE_UINT;
rt_set_cell(fastn[unum], POP());
break;
case PYBC_STORE_NAME:
case MP_BC_STORE_NAME:
DECODE_QSTR;
rt_store_name(qstr, POP());
break;
case PYBC_STORE_GLOBAL:
case MP_BC_STORE_GLOBAL:
DECODE_QSTR;
rt_store_global(qstr, POP());
break;
case PYBC_STORE_ATTR:
case MP_BC_STORE_ATTR:
DECODE_QSTR;
rt_store_attr(sp[0], qstr, sp[1]);
sp += 2;
break;
case PYBC_STORE_SUBSCR:
case MP_BC_STORE_SUBSCR:
rt_store_subscr(sp[1], sp[0], sp[2]);
sp += 3;
break;
case PYBC_DUP_TOP:
case MP_BC_DUP_TOP:
obj1 = TOP();
PUSH(obj1);
break;
case PYBC_DUP_TOP_TWO:
case MP_BC_DUP_TOP_TWO:
sp -= 2;
sp[0] = sp[2];
sp[1] = sp[3];
break;
case PYBC_POP_TOP:
case MP_BC_POP_TOP:
++sp;
break;
case PYBC_ROT_TWO:
case MP_BC_ROT_TWO:
obj1 = sp[0];
sp[0] = sp[1];
sp[1] = obj1;
break;
case PYBC_ROT_THREE:
case MP_BC_ROT_THREE:
obj1 = sp[0];
sp[0] = sp[1];
sp[1] = sp[2];
sp[2] = obj1;
break;
case PYBC_JUMP:
case MP_BC_JUMP:
DECODE_SLABEL;
ip += unum;
break;
case PYBC_POP_JUMP_IF_TRUE:
case MP_BC_POP_JUMP_IF_TRUE:
DECODE_SLABEL;
if (rt_is_true(POP())) {
ip += unum;
}
break;
case PYBC_POP_JUMP_IF_FALSE:
case MP_BC_POP_JUMP_IF_FALSE:
DECODE_SLABEL;
if (!rt_is_true(POP())) {
ip += unum;
}
break;
case PYBC_JUMP_IF_TRUE_OR_POP:
case MP_BC_JUMP_IF_TRUE_OR_POP:
DECODE_SLABEL;
if (rt_is_true(TOP())) {
ip += unum;
@ -254,7 +256,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
}
break;
case PYBC_JUMP_IF_FALSE_OR_POP:
case MP_BC_JUMP_IF_FALSE_OR_POP:
DECODE_SLABEL;
if (rt_is_true(TOP())) {
sp++;
@ -264,19 +266,19 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
break;
/* we are trying to get away without using this opcode
case PYBC_SETUP_LOOP:
case MP_BC_SETUP_LOOP:
DECODE_UINT;
// push_block(PYBC_SETUP_LOOP, ip + unum, sp)
// push_block(MP_BC_SETUP_LOOP, ip + unum, sp)
break;
*/
case PYBC_SETUP_EXCEPT:
case MP_BC_SETUP_EXCEPT:
DECODE_ULABEL; // except labels are always forward
*++exc_sp = (machine_uint_t)ip + unum;
*++exc_sp = (machine_uint_t)sp;
break;
case PYBC_END_FINALLY:
case MP_BC_END_FINALLY:
// not implemented
// if TOS is an exception, reraises the exception (3 values on TOS)
// if TOS is an integer, does something else
@ -285,14 +287,14 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
assert(0);
break;
case PYBC_GET_ITER:
case MP_BC_GET_ITER:
SET_TOP(rt_getiter(TOP()));
break;
case PYBC_FOR_ITER:
case MP_BC_FOR_ITER:
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
obj1 = rt_iternext(TOP());
if (obj1 == py_const_stop_iteration) {
if (obj1 == mp_const_stop_iteration) {
++sp; // pop the exhausted iterator
ip += unum; // jump to after for-block
} else {
@ -300,110 +302,110 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
}
break;
case PYBC_POP_BLOCK:
case MP_BC_POP_BLOCK:
// pops block and restores the stack
assert(0);
break;
case PYBC_POP_EXCEPT:
case MP_BC_POP_EXCEPT:
// TODO need to work out how blocks work etc
// pops block, checks it's an exception block, and restores the stack, saving the 3 exception values to local threadstate
assert(exc_sp >= &exc_stack[0]);
//sp = (py_obj_t*)(*exc_sp--);
//sp = (mp_obj_t*)(*exc_sp--);
//exc_sp--; // discard ip
exc_sp -= 2;
//sp += 3; // pop 3 exception values
break;
case PYBC_UNARY_OP:
case MP_BC_UNARY_OP:
unum = *ip++;
SET_TOP(rt_unary_op(unum, TOP()));
break;
case PYBC_BINARY_OP:
case MP_BC_BINARY_OP:
unum = *ip++;
obj2 = POP();
obj1 = TOP();
SET_TOP(rt_binary_op(unum, obj1, obj2));
break;
case PYBC_COMPARE_OP:
case MP_BC_COMPARE_OP:
unum = *ip++;
obj2 = POP();
obj1 = TOP();
SET_TOP(rt_compare_op(unum, obj1, obj2));
break;
case PYBC_BUILD_TUPLE:
case MP_BC_BUILD_TUPLE:
DECODE_UINT;
obj1 = rt_build_tuple(unum, sp);
sp += unum - 1;
SET_TOP(obj1);
break;
case PYBC_BUILD_LIST:
case MP_BC_BUILD_LIST:
DECODE_UINT;
obj1 = rt_build_list(unum, sp);
sp += unum - 1;
SET_TOP(obj1);
break;
case PYBC_LIST_APPEND:
case MP_BC_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:
case MP_BC_BUILD_MAP:
DECODE_UINT;
PUSH(rt_build_map(unum));
break;
case PYBC_STORE_MAP:
case MP_BC_STORE_MAP:
sp += 2;
rt_store_map(sp[0], sp[-2], sp[-1]);
break;
case PYBC_MAP_ADD:
case MP_BC_MAP_ADD:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[unum + 1] is a map
rt_store_map(sp[unum + 1], sp[0], sp[1]);
sp += 2;
break;
case PYBC_BUILD_SET:
case MP_BC_BUILD_SET:
DECODE_UINT;
obj1 = rt_build_set(unum, sp);
sp += unum - 1;
SET_TOP(obj1);
break;
case PYBC_SET_ADD:
case MP_BC_SET_ADD:
DECODE_UINT;
// I think it's guaranteed by the compiler that sp[unum] is a set
rt_store_set(sp[unum], sp[0]);
sp++;
break;
case PYBC_UNPACK_SEQUENCE:
case MP_BC_UNPACK_SEQUENCE:
DECODE_UINT;
rt_unpack_sequence(sp[0], unum, sp - unum + 1);
sp -= unum - 1;
break;
case PYBC_MAKE_FUNCTION:
case MP_BC_MAKE_FUNCTION:
DECODE_UINT;
PUSH(rt_make_function_from_id(unum));
break;
case PYBC_MAKE_CLOSURE:
case MP_BC_MAKE_CLOSURE:
DECODE_UINT;
obj1 = POP();
PUSH(rt_make_closure_from_id(unum, obj1));
break;
case PYBC_CALL_FUNCTION:
case MP_BC_CALL_FUNCTION:
DECODE_UINT;
assert((unum & 0xff00) == 0); // n_keyword
unum &= 0xff; // n_positional
@ -411,7 +413,7 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
*sp = rt_call_function_n(*sp, unum, sp - unum);
break;
case PYBC_CALL_METHOD:
case MP_BC_CALL_METHOD:
DECODE_UINT;
if ((unum & 0xff00) == 0) {
// no keywords
@ -426,13 +428,13 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
SET_TOP(obj1);
break;
case PYBC_RETURN_VALUE:
case MP_BC_RETURN_VALUE:
nlr_pop();
*sp_in_out = sp;
assert(exc_sp == &exc_stack[-1]);
return false;
case PYBC_YIELD_VALUE:
case MP_BC_YIELD_VALUE:
nlr_pop();
*ip_in_out = ip;
fastn[0] = fast0;
@ -441,13 +443,13 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
*sp_in_out = sp;
return true;
case PYBC_IMPORT_NAME:
case MP_BC_IMPORT_NAME:
DECODE_QSTR;
obj1 = POP();
SET_TOP(rt_import_name(qstr, obj1, TOP()));
break;
case PYBC_IMPORT_FROM:
case MP_BC_IMPORT_FROM:
DECODE_QSTR;
obj1 = rt_import_from(TOP(), qstr);
PUSH(obj1);
@ -466,12 +468,12 @@ bool py_execute_byte_code_2(const byte **ip_in_out, py_obj_t *fastn, py_obj_t **
if (exc_sp >= &exc_stack[0]) {
// catch exception and pass to byte code
sp = (py_obj_t*)(exc_sp[0]);
sp = (mp_obj_t*)(exc_sp[0]);
ip = (const byte*)(exc_sp[-1]);
// push(traceback, exc-val, exc-type)
PUSH(py_const_none);
PUSH(mp_const_none);
PUSH(nlr.ret_val);
PUSH(py_const_none);
PUSH(mp_const_none);
} else {
// re-raise exception
// TODO what to do if this is a generator??

View File

@ -23,6 +23,7 @@ SRC_C = \
lexerstm.c \
led.c \
lcd.c \
servo.c \
flash.c \
storage.c \
mma.c \
@ -57,6 +58,25 @@ PY_O = \
runtime.o \
map.o \
obj.o \
objbool.o \
objboundmeth.o \
objcell.o \
objclass.o \
objclosure.o \
objcomplex.o \
objdict.o \
objexcept.o \
objfloat.o \
objfun.o \
objgenerator.o \
objinstance.o \
objlist.o \
objnone.o \
objrange.o \
objset.o \
objstr.o \
objtuple.o \
objtype.o \
builtin.o \
vm.o \
repl.o \
@ -150,7 +170,7 @@ $(BUILD)/%.o: $(CC3KSRC)/%.c
$(BUILD)/%.o: $(PYSRC)/%.s
$(AS) -o $@ $<
$(BUILD)/%.o: $(PYSRC)/%.c mpyconfig.h
$(BUILD)/%.o: $(PYSRC)/%.c mpconfig.h
$(CC) $(CFLAGS) -c -o $@ $<
$(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h

View File

@ -6,9 +6,10 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "parse.h"
#include "compile.h"
#include "obj.h"
#include "runtime.h"
#include "audio.h"
@ -44,22 +45,22 @@ void audio_drain(void) {
}
// direct access to DAC
py_obj_t pyb_audio_dac(py_obj_t val) {
DAC_SetChannel2Data(DAC_Align_8b_R, py_obj_get_int(val));
return py_const_none;
mp_obj_t pyb_audio_dac(mp_obj_t val) {
DAC_SetChannel2Data(DAC_Align_8b_R, mp_obj_get_int(val));
return mp_const_none;
}
py_obj_t pyb_audio_is_full(void) {
mp_obj_t pyb_audio_is_full(void) {
if (audio_is_full()) {
return py_const_true;
return mp_const_true;
} else {
return py_const_false;
return mp_const_false;
}
}
py_obj_t pyb_audio_fill(py_obj_t val) {
audio_fill(py_obj_get_int(val));
return py_const_none;
mp_obj_t pyb_audio_fill(mp_obj_t val) {
audio_fill(mp_obj_get_int(val));
return mp_const_none;
}
void audio_init(void) {
@ -90,7 +91,7 @@ void audio_init(void) {
// enable interrupt
// Python interface
py_obj_t m = py_module_new();
mp_obj_t m = mp_module_new();
rt_store_attr(m, qstr_from_str_static("dac"), rt_make_function_1(pyb_audio_dac));
rt_store_attr(m, qstr_from_str_static("is_full"), rt_make_function_0(pyb_audio_is_full));
rt_store_attr(m, qstr_from_str_static("fill"), rt_make_function_1(pyb_audio_fill));

View File

@ -3,9 +3,10 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "parse.h"
#include "compile.h"
#include "obj.h"
#include "runtime.h"
#include "systick.h"
@ -88,16 +89,16 @@ static void lcd_data_out(uint8_t i) {
// writes 8 vertical pixels
// pos 0 is upper left, pos 1 is 8 pixels to right of that, pos 128 is 8 pixels below that
py_obj_t lcd_draw_pixel_8(py_obj_t py_pos, py_obj_t py_val) {
int pos = py_obj_get_int(py_pos);
int val = py_obj_get_int(py_val);
mp_obj_t lcd_draw_pixel_8(mp_obj_t mp_pos, mp_obj_t mp_val) {
int pos = mp_obj_get_int(mp_pos);
int val = mp_obj_get_int(mp_val);
int page = pos / 128;
int offset = pos - (page * 128);
lcd_out(LCD_INSTR, 0xb0 | page); // page address set
lcd_out(LCD_INSTR, 0x10 | ((offset >> 4) & 0x0f)); // column address set upper
lcd_out(LCD_INSTR, 0x00 | (offset & 0x0f)); // column address set lower
lcd_out(LCD_DATA, val); // write data
return py_const_none;
return mp_const_none;
}
#define LCD_BUF_W (16)
@ -112,45 +113,45 @@ int lcd_next_line;
byte lcd_pix_buf[LCD_PIX_BUF_SIZE];
byte lcd_pix_buf2[LCD_PIX_BUF_SIZE];
py_obj_t lcd_pix_clear(void) {
mp_obj_t lcd_pix_clear(void) {
memset(lcd_pix_buf, 0, LCD_PIX_BUF_SIZE);
memset(lcd_pix_buf2, 0, LCD_PIX_BUF_SIZE);
return py_const_none;
return mp_const_none;
}
py_obj_t lcd_pix_get(py_obj_t py_x, py_obj_t py_y) {
int x = py_obj_get_int(py_x);
int y = py_obj_get_int(py_y);
mp_obj_t lcd_pix_get(mp_obj_t mp_x, mp_obj_t mp_y) {
int x = mp_obj_get_int(mp_x);
int y = mp_obj_get_int(mp_y);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
if (lcd_pix_buf[byte_pos] & (1 << (y & 7))) {
return py_obj_new_int(1);
return mp_obj_new_int(1);
}
}
return py_obj_new_int(0);
return mp_obj_new_int(0);
}
py_obj_t lcd_pix_set(py_obj_t py_x, py_obj_t py_y) {
int x = py_obj_get_int(py_x);
int y = py_obj_get_int(py_y);
mp_obj_t lcd_pix_set(mp_obj_t mp_x, mp_obj_t mp_y) {
int x = mp_obj_get_int(mp_x);
int y = mp_obj_get_int(mp_y);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
lcd_pix_buf2[byte_pos] |= 1 << (y & 7);
}
return py_const_none;
return mp_const_none;
}
py_obj_t lcd_pix_reset(py_obj_t py_x, py_obj_t py_y) {
int x = py_obj_get_int(py_x);
int y = py_obj_get_int(py_y);
mp_obj_t lcd_pix_reset(mp_obj_t mp_x, mp_obj_t mp_y) {
int x = mp_obj_get_int(mp_x);
int y = mp_obj_get_int(mp_y);
if (0 <= x && x <= 127 && 0 <= y && y <= 31) {
uint byte_pos = x + 128 * ((uint)y >> 3);
lcd_pix_buf2[byte_pos] &= ~(1 << (y & 7));
}
return py_const_none;
return mp_const_none;
}
py_obj_t lcd_pix_show(void) {
mp_obj_t lcd_pix_show(void) {
memcpy(lcd_pix_buf, lcd_pix_buf2, LCD_PIX_BUF_SIZE);
for (uint page = 0; page < 4; page++) {
lcd_out(LCD_INSTR, 0xb0 | page); // page address set
@ -160,12 +161,12 @@ py_obj_t lcd_pix_show(void) {
lcd_out(LCD_DATA, lcd_pix_buf[i + 128 * page]);
}
}
return py_const_none;
return mp_const_none;
}
py_obj_t lcd_print(py_obj_t text) {
lcd_print_str(qstr_str(py_obj_get_qstr(text)));
return py_const_none;
mp_obj_t lcd_print(mp_obj_t text) {
lcd_print_str(qstr_str(mp_obj_get_qstr(text)));
return mp_const_none;
}
void lcd_init(void) {
@ -219,7 +220,7 @@ void lcd_init(void) {
lcd_next_line = 0;
// Python interface
py_obj_t m = py_module_new();
mp_obj_t m = mp_module_new();
rt_store_attr(m, qstr_from_str_static("lcd8"), rt_make_function_2(lcd_draw_pixel_8));
rt_store_attr(m, qstr_from_str_static("clear"), rt_make_function_0(lcd_pix_clear));
rt_store_attr(m, qstr_from_str_static("get"), rt_make_function_2(lcd_pix_get));

View File

@ -1,5 +1,10 @@
#include <stdio.h>
#include <stm32f4xx.h>
#include <stm32f4xx_gpio.h>
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "led.h"
#define PYB_LED_R_PORT (GPIOA)
@ -64,3 +69,60 @@ void led_toggle(pyb_led_t led) {
port->BSRRH = pin;
}
}
/******************************************************************************/
/* Micro Python bindings */
typedef struct _pyb_led_obj_t {
mp_obj_base_t base;
uint led_id;
} pyb_led_obj_t;
void led_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
print(env, "<LED %lu>", self->led_id);
}
mp_obj_t led_obj_on(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
switch (self->led_id) {
case 1: led_state(PYB_LED_G1, 1); break;
case 2: led_state(PYB_LED_G2, 1); break;
}
return mp_const_none;
}
mp_obj_t led_obj_off(mp_obj_t self_in) {
pyb_led_obj_t *self = self_in;
switch (self->led_id) {
case 1: led_state(PYB_LED_G1, 0); break;
case 2: led_state(PYB_LED_G2, 0); break;
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on);
static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off);
static const mp_obj_type_t led_obj_type = {
{ &mp_const_type },
"Led",
led_obj_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{ "on", &led_obj_on_obj },
{ "off", &led_obj_off_obj },
{ NULL, NULL },
}
};
mp_obj_t pyb_Led(mp_obj_t led_id) {
pyb_led_obj_t *o = m_new_obj(pyb_led_obj_t);
o->base.type = &led_obj_type;
o->led_id = mp_obj_get_int(led_id);
return o;
}

View File

@ -8,3 +8,5 @@ typedef enum {
void led_init(void);
void led_state(pyb_led_t led, int state);
void led_toggle(pyb_led_t led);
mp_obj_t pyb_Led(mp_obj_t led_id);

View File

@ -7,37 +7,37 @@
#include "lexer.h"
#include "lexerstm.h"
unichar str_buf_next_char(py_lexer_str_buf_t *sb) {
unichar str_buf_next_char(mp_lexer_str_buf_t *sb) {
if (sb->src_cur < sb->src_end) {
return *sb->src_cur++;
} else {
return PY_LEXER_CHAR_EOF;
return MP_LEXER_CHAR_EOF;
}
}
void str_buf_free(py_lexer_str_buf_t *sb) {
void str_buf_free(mp_lexer_str_buf_t *sb) {
if (sb->free) {
m_free((char*)sb->src_beg);
}
}
py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, py_lexer_str_buf_t *sb) {
mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, mp_lexer_str_buf_t *sb) {
sb->free = free_str;
sb->src_beg = str;
sb->src_cur = str;
sb->src_end = str + len;
return py_lexer_new(src_name, sb, (py_lexer_stream_next_char_t)str_buf_next_char, (py_lexer_stream_close_t)str_buf_free);
return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_char_t)str_buf_next_char, (mp_lexer_stream_close_t)str_buf_free);
}
unichar file_buf_next_char(py_lexer_file_buf_t *fb) {
unichar file_buf_next_char(mp_lexer_file_buf_t *fb) {
if (fb->pos >= fb->len) {
if (fb->len < sizeof(fb->buf)) {
return PY_LEXER_CHAR_EOF;
return MP_LEXER_CHAR_EOF;
} else {
UINT n;
f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n);
if (n == 0) {
return PY_LEXER_CHAR_EOF;
return MP_LEXER_CHAR_EOF;
}
fb->len = n;
fb->pos = 0;
@ -46,11 +46,11 @@ unichar file_buf_next_char(py_lexer_file_buf_t *fb) {
return fb->buf[fb->pos++];
}
void file_buf_close(py_lexer_file_buf_t *fb) {
void file_buf_close(mp_lexer_file_buf_t *fb) {
f_close(&fb->fp);
}
py_lexer_t *py_lexer_new_from_file(const char *filename, py_lexer_file_buf_t *fb) {
mp_lexer_t *mp_lexer_new_from_file(const char *filename, mp_lexer_file_buf_t *fb) {
FRESULT res = f_open(&fb->fp, filename, FA_READ);
if (res != FR_OK) {
return NULL;
@ -59,5 +59,5 @@ py_lexer_t *py_lexer_new_from_file(const char *filename, py_lexer_file_buf_t *fb
f_read(&fb->fp, fb->buf, sizeof(fb->buf), &n);
fb->len = n;
fb->pos = 0;
return py_lexer_new(filename, fb, (py_lexer_stream_next_char_t)file_buf_next_char, (py_lexer_stream_close_t)file_buf_close);
return mp_lexer_new(filename, fb, (mp_lexer_stream_next_char_t)file_buf_next_char, (mp_lexer_stream_close_t)file_buf_close);
}

View File

@ -3,14 +3,14 @@ typedef struct _py_lexer_str_buf_t {
const char *src_beg; // beginning of source
const char *src_cur; // current location in source
const char *src_end; // end (exclusive) of source
} py_lexer_str_buf_t;
} mp_lexer_str_buf_t;
typedef struct _py_lexer_file_buf_t {
FIL fp;
char buf[20];
uint16_t len;
uint16_t pos;
} py_lexer_file_buf_t;
} mp_lexer_file_buf_t;
py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, py_lexer_str_buf_t *sb);
py_lexer_t *py_lexer_new_from_file(const char *filename, py_lexer_file_buf_t *fb);
mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str, mp_lexer_str_buf_t *sb);
mp_lexer_t *mp_lexer_new_from_file(const char *filename, mp_lexer_file_buf_t *fb);

View File

@ -13,16 +13,27 @@
#include "std.h"
#include "misc.h"
#include "mpyconfig.h"
#include "ff.h"
#include "mpconfig.h"
#include "nlr.h"
#include "misc.h"
#include "lexer.h"
#include "lexerstm.h"
#include "parse.h"
#include "compile.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "repl.h"
#include "gc.h"
#include "systick.h"
#include "led.h"
#include "servo.h"
#include "lcd.h"
#include "storage.h"
#include "mma.h"
#include "usart.h"
#include "usb.h"
#include "ff.h"
#include "timer.h"
#include "audio.h"
#include "pybwlan.h"
@ -114,128 +125,43 @@ void __fatal_error(const char *msg) {
}
}
#include "nlr.h"
#include "misc.h"
#include "lexer.h"
#include "lexerstm.h"
#include "mpyconfig.h"
#include "parse.h"
#include "compile.h"
#include "runtime.h"
#include "obj.h"
#include "repl.h"
static qstr pyb_config_source_dir = 0;
static qstr pyb_config_main = 0;
py_obj_t pyb_source_dir(py_obj_t source_dir) {
pyb_config_source_dir = py_obj_get_qstr(source_dir);
return py_const_none;
mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
pyb_config_source_dir = mp_obj_get_qstr(source_dir);
return mp_const_none;
}
py_obj_t pyb_main(py_obj_t main) {
pyb_config_main = py_obj_get_qstr(main);
return py_const_none;
mp_obj_t pyb_main(mp_obj_t main) {
pyb_config_main = mp_obj_get_qstr(main);
return mp_const_none;
}
// sync all file systems
py_obj_t pyb_sync(void) {
mp_obj_t pyb_sync(void) {
storage_flush();
return py_const_none;
return mp_const_none;
}
py_obj_t pyb_delay(py_obj_t count) {
sys_tick_delay_ms(py_obj_get_int(count));
return py_const_none;
mp_obj_t pyb_delay(mp_obj_t count) {
sys_tick_delay_ms(mp_obj_get_int(count));
return mp_const_none;
}
py_obj_t pyb_led(py_obj_t state) {
mp_obj_t pyb_led(mp_obj_t state) {
led_state(PYB_LED_G1, rt_is_true(state));
return state;
}
void led_obj_print(py_obj_t self) {
machine_uint_t led_id;
py_user_get_data(self, &led_id, NULL);
printf("<LED %lu>", led_id);
}
py_obj_t led_obj_on(py_obj_t self) {
machine_uint_t led_id;
py_user_get_data(self, &led_id, NULL);
switch (led_id) {
case 1: led_state(PYB_LED_G1, 1); break;
case 2: led_state(PYB_LED_G2, 1); break;
}
return py_const_none;
}
py_obj_t led_obj_off(py_obj_t self) {
machine_uint_t led_id;
py_user_get_data(self, &led_id, NULL);
switch (led_id) {
case 1: led_state(PYB_LED_G1, 0); break;
case 2: led_state(PYB_LED_G2, 0); break;
}
return py_const_none;
}
const py_user_info_t led_obj_info = {
"Led",
led_obj_print,
{
{"on", 0, led_obj_on},
{"off", 0, led_obj_off},
{NULL, 0, NULL},
}
};
py_obj_t pyb_Led(py_obj_t led_id) {
return py_obj_new_user(&led_obj_info, (machine_uint_t)py_obj_get_int(led_id), 0);
}
py_obj_t pyb_sw(void) {
mp_obj_t pyb_sw(void) {
if (sw_get()) {
return py_const_true;
return mp_const_true;
} else {
return py_const_false;
return mp_const_false;
}
}
void servo_obj_print(py_obj_t self) {
machine_uint_t servo_id;
py_user_get_data(self, &servo_id, NULL);
printf("<Servo %lu>", servo_id);
}
py_obj_t servo_obj_angle(py_obj_t self, py_obj_t angle) {
machine_uint_t servo_id;
py_user_get_data(self, &servo_id, NULL);
machine_int_t v = 152 + 85.0 * py_obj_get_float(angle) / 90.0;
if (v < 65) { v = 65; }
if (v > 210) { v = 210; }
switch (servo_id) {
case 1: TIM2->CCR1 = v; break;
case 2: TIM2->CCR2 = v; break;
case 3: TIM2->CCR3 = v; break;
case 4: TIM2->CCR4 = v; break;
}
return py_const_none;
}
const py_user_info_t servo_obj_info = {
"Servo",
servo_obj_print,
{
{"angle", 1, servo_obj_angle},
{NULL, 0, NULL},
}
};
py_obj_t pyb_Servo(py_obj_t servo_id) {
return py_obj_new_user(&servo_obj_info, (machine_uint_t)py_obj_get_int(servo_id), 0);
}
/*
void g(uint i) {
printf("g:%d\n", i);
@ -306,13 +232,13 @@ static const char *help_text =
;
// get some help about available functions
static py_obj_t pyb_help(void) {
static mp_obj_t pyb_help(void) {
printf("%s", help_text);
return py_const_none;
return mp_const_none;
}
// get lots of info about the board
static py_obj_t pyb_info(void) {
static mp_obj_t pyb_info(void) {
// get and print unique id; 96 bits
{
byte *id = (byte*)0x1fff7a10;
@ -364,14 +290,14 @@ static py_obj_t pyb_info(void) {
printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
}
return py_const_none;
return mp_const_none;
}
// SD card test
static py_obj_t pyb_sd_test(void) {
static mp_obj_t pyb_sd_test(void) {
extern void sdio_init(void);
sdio_init();
return py_const_none;
return mp_const_none;
}
static void SYSCLKConfig_STOP(void) {
@ -398,7 +324,7 @@ static void SYSCLKConfig_STOP(void) {
}
}
static py_obj_t pyb_stop(void) {
static mp_obj_t pyb_stop(void) {
PWR_EnterSTANDBYMode();
//PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this
@ -411,28 +337,28 @@ static py_obj_t pyb_stop(void) {
//PWR_FlashPowerDownCmd(DISABLE);
return py_const_none;
return mp_const_none;
}
static py_obj_t pyb_standby(void) {
static mp_obj_t pyb_standby(void) {
PWR_EnterSTANDBYMode();
return py_const_none;
return mp_const_none;
}
py_obj_t pyb_usart_send(py_obj_t data) {
usart_tx_char(py_obj_get_int(data));
return py_const_none;
mp_obj_t pyb_usart_send(mp_obj_t data) {
usart_tx_char(mp_obj_get_int(data));
return mp_const_none;
}
py_obj_t pyb_usart_receive(void) {
return py_obj_new_int(usart_rx_char());
mp_obj_t pyb_usart_receive(void) {
return mp_obj_new_int(usart_rx_char());
}
py_obj_t pyb_usart_status(void) {
mp_obj_t pyb_usart_status(void) {
if (usart_rx_any()) {
return py_const_true;
return mp_const_true;
} else {
return py_const_false;
return mp_const_false;
}
}
@ -544,7 +470,7 @@ void do_repl(void) {
continue;
}
if (py_repl_is_compound_stmt(vstr_str(&line))) {
if (mp_repl_is_compound_stmt(vstr_str(&line))) {
for (;;) {
vstr_add_char(&line, '\n');
int len = vstr_len(&line);
@ -556,16 +482,16 @@ void do_repl(void) {
}
}
py_lexer_str_buf_t sb;
py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), false, &sb);
py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT);
py_lexer_free(lex);
mp_lexer_str_buf_t sb;
mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), false, &sb);
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
mp_lexer_free(lex);
if (pn != PY_PARSE_NODE_NULL) {
bool comp_ok = py_compile(pn, true);
if (pn != MP_PARSE_NODE_NULL) {
bool comp_ok = mp_compile(pn, true);
if (comp_ok) {
py_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun != py_const_none) {
mp_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun != mp_const_none) {
nlr_buf_t nlr;
uint32_t start = sys_tick_counter;
if (nlr_push(&nlr) == 0) {
@ -578,7 +504,7 @@ void do_repl(void) {
}
} else {
// uncaught exception
py_obj_print((py_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
}
}
@ -590,28 +516,28 @@ void do_repl(void) {
}
bool do_file(const char *filename) {
py_lexer_file_buf_t fb;
py_lexer_t *lex = py_lexer_new_from_file(filename, &fb);
mp_lexer_file_buf_t fb;
mp_lexer_t *lex = mp_lexer_new_from_file(filename, &fb);
if (lex == NULL) {
printf("could not open file '%s' for reading\n", filename);
return false;
}
py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT);
py_lexer_free(lex);
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_lexer_free(lex);
if (pn == PY_PARSE_NODE_NULL) {
if (pn == MP_PARSE_NODE_NULL) {
return false;
}
bool comp_ok = py_compile(pn, false);
bool comp_ok = mp_compile(pn, false);
if (!comp_ok) {
return false;
}
py_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun == py_const_none) {
mp_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun == mp_const_none) {
return false;
}
@ -622,7 +548,7 @@ bool do_file(const char *filename) {
return true;
} else {
// uncaught exception
py_obj_print((py_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
return false;
}
@ -655,115 +581,16 @@ void gc_collect(void) {
}
}
py_obj_t pyb_gc(void) {
mp_obj_t pyb_gc(void) {
gc_collect();
return py_const_none;
}
// PWM
// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively
// they are both 32-bit counters
// 16-bit prescaler
// TIM2_CH3 also on PB10 (used below)
void servo_init(void) {
// TIM2 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// for PB10
/*
// GPIOB Configuration: TIM2_CH3 (PB10)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Connect TIM2 pins to AF1
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
*/
// for PA0, PA1, PA2, PA3
{
// GPIOA Configuration: TIM2_CH0, TIM2_CH1 (PA0, PA1)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Connect TIM2 pins to AF1
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM2);
}
// Compute the prescaler value so TIM2 runs at 100kHz
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 100000) - 1;
// Time base configuration
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 2000; // timer cycles at 50Hz
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// PWM Mode configuration
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 150; // units of 10us
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure); // channel 1
TIM_OC2Init(TIM2, &TIM_OCInitStructure); // channel 2
TIM_OC3Init(TIM2, &TIM_OCInitStructure); // channel 3
TIM_OC4Init(TIM2, &TIM_OCInitStructure); // channel 4
// ?
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 1
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 2
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 3
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 4
// ?
TIM_ARRPreloadConfig(TIM2, ENABLE);
// TIM2 enable counter
TIM_Cmd(TIM2, ENABLE);
}
py_obj_t pyb_servo_set(py_obj_t port, py_obj_t value) {
int p = py_obj_get_int(port);
int v = py_obj_get_int(value);
if (v < 50) { v = 50; }
if (v > 250) { v = 250; }
switch (p) {
case 1: TIM2->CCR1 = v; break;
case 2: TIM2->CCR2 = v; break;
case 3: TIM2->CCR3 = v; break;
case 4: TIM2->CCR4 = v; break;
}
return py_const_none;
}
py_obj_t pyb_pwm_set(py_obj_t period, py_obj_t pulse) {
int pe = py_obj_get_int(period);
int pu = py_obj_get_int(pulse);
TIM2->ARR = pe;
TIM2->CCR3 = pu;
return py_const_none;
return mp_const_none;
}
#define MMA_ADDR (0x4c)
int mma_buf[12];
py_obj_t pyb_mma_read(void) {
mp_obj_t pyb_mma_read(void) {
for (int i = 0; i <= 6; i += 3) {
mma_buf[0 + i] = mma_buf[0 + i + 3];
mma_buf[1 + i] = mma_buf[1 + i + 3];
@ -782,24 +609,24 @@ py_obj_t pyb_mma_read(void) {
}
int jolt_info = mma_read_nack();
py_obj_t data[4];
data[0] = py_obj_new_int(jolt_info);
data[1] = py_obj_new_int(mma_buf[2] + mma_buf[5] + mma_buf[8] + mma_buf[11]);
data[2] = py_obj_new_int(mma_buf[1] + mma_buf[4] + mma_buf[7] + mma_buf[10]);
data[3] = py_obj_new_int(mma_buf[0] + mma_buf[3] + mma_buf[6] + mma_buf[9]);
mp_obj_t data[4];
data[0] = mp_obj_new_int(jolt_info);
data[1] = mp_obj_new_int(mma_buf[2] + mma_buf[5] + mma_buf[8] + mma_buf[11]);
data[2] = mp_obj_new_int(mma_buf[1] + mma_buf[4] + mma_buf[7] + mma_buf[10]);
data[3] = mp_obj_new_int(mma_buf[0] + mma_buf[3] + mma_buf[6] + mma_buf[9]);
return rt_build_tuple(4, data); // items in reverse order in data
}
py_obj_t pyb_hid_send_report(py_obj_t arg) {
py_obj_t *items = py_obj_get_array_fixed_n(arg, 4);
mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
uint8_t data[4];
data[0] = py_obj_get_int(items[0]);
data[1] = py_obj_get_int(items[1]);
data[2] = py_obj_get_int(items[2]);
data[3] = py_obj_get_int(items[3]);
data[0] = mp_obj_get_int(items[0]);
data[1] = mp_obj_get_int(items[1]);
data[2] = mp_obj_get_int(items[2]);
data[3] = mp_obj_get_int(items[3]);
usb_hid_send_report(data);
return py_const_none;
return mp_const_none;
}
static void rtc_init(void) {
@ -855,90 +682,102 @@ static void rtc_init(void) {
//RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
}
py_obj_t pyb_rtc_read(void) {
mp_obj_t pyb_rtc_read(void) {
RTC_TimeTypeDef RTC_TimeStructure;
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
printf("%02d:%02d:%02d\n", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
return py_const_none;
return mp_const_none;
}
void file_obj_print(py_obj_t o) {
FIL *fp;
py_user_get_data(o, (machine_uint_t*)&fp, NULL);
printf("<file %p>", fp);
typedef struct _pyb_file_obj_t {
mp_obj_base_t base;
FIL fp;
} pyb_file_obj_t;
void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
printf("<file %p>", self_in);
}
py_obj_t file_obj_read(py_obj_t self, py_obj_t arg) {
FIL *fp;
py_user_get_data(self, (machine_uint_t*)&fp, NULL);
int n = py_obj_get_int(arg);
mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) {
pyb_file_obj_t *self = self_in;
int n = mp_obj_get_int(arg);
char *buf = m_new(char, n + 1);
UINT n_out;
f_read(fp, buf, n, &n_out);
f_read(&self->fp, buf, n, &n_out);
buf[n_out] = 0;
return py_obj_new_str(qstr_from_str_take(buf));
return mp_obj_new_str(qstr_from_str_take(buf));
}
py_obj_t file_obj_write(py_obj_t self, py_obj_t arg) {
FIL *fp;
py_user_get_data(self, (machine_uint_t*)&fp, NULL);
const char *s = qstr_str(py_obj_get_qstr(arg));
mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) {
pyb_file_obj_t *self = self_in;
const char *s = qstr_str(mp_obj_get_qstr(arg));
UINT n_out;
FRESULT res = f_write(fp, s, strlen(s), &n_out);
FRESULT res = f_write(&self->fp, s, strlen(s), &n_out);
if (res != FR_OK) {
printf("File error: could not write to file; error code %d\n", res);
} else if (n_out != strlen(s)) {
printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, strlen(s));
}
return py_const_none;
return mp_const_none;
}
py_obj_t file_obj_close(py_obj_t self) {
FIL *fp;
py_user_get_data(self, (machine_uint_t*)&fp, NULL);
f_close(fp);
return py_const_none;
mp_obj_t file_obj_close(mp_obj_t self_in) {
pyb_file_obj_t *self = self_in;
f_close(&self->fp);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read);
static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write);
static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close);
// TODO gc hook to close the file if not already closed
const py_user_info_t file_obj_info = {
static const mp_obj_type_t file_obj_type = {
{ &mp_const_type },
"File",
file_obj_print,
{
{"read", 1, file_obj_read},
{"write", 1, file_obj_write},
{"close", 0, file_obj_close},
{NULL, 0, NULL},
file_obj_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{ "read", &file_obj_read_obj },
{ "write", &file_obj_write_obj },
{ "close", &file_obj_close_obj },
{NULL, NULL},
}
};
py_obj_t pyb_io_open(py_obj_t o_filename, py_obj_t o_mode) {
const char *filename = qstr_str(py_obj_get_qstr(o_filename));
const char *mode = qstr_str(py_obj_get_qstr(o_mode));
FIL *fp = m_new(FIL, 1);
mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
const char *filename = qstr_str(mp_obj_get_qstr(o_filename));
const char *mode = qstr_str(mp_obj_get_qstr(o_mode));
pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
self->base.type = &file_obj_type;
if (mode[0] == 'r') {
// open for reading
FRESULT res = f_open(fp, filename, FA_READ);
FRESULT res = f_open(&self->fp, filename, FA_READ);
if (res != FR_OK) {
printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename);
return py_const_none;
return mp_const_none;
}
} else if (mode[0] == 'w') {
// open for writing, truncate the file first
FRESULT res = f_open(fp, filename, FA_WRITE | FA_CREATE_ALWAYS);
FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS);
if (res != FR_OK) {
printf("?FileError: could not create file: '%s'\n", filename);
return py_const_none;
return mp_const_none;
}
} else {
printf("ValueError: invalid mode: '%s'\n", mode);
return py_const_none;
return mp_const_none;
}
return py_obj_new_user(&file_obj_info, (machine_uint_t)fp, 0);
return self;
}
py_obj_t pyb_rng_get(void) {
return py_obj_new_int(RNG_GetRandomNumber() >> 16);
mp_obj_t pyb_rng_get(void) {
return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
}
int main(void) {
@ -1015,7 +854,7 @@ soft_reset:
{
rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help));
py_obj_t m = py_module_new();
mp_obj_t m = mp_module_new();
rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info));
rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_0(pyb_sd_test));
rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_0(pyb_stop));
@ -1312,19 +1151,19 @@ soft_reset:
" pass\n"
"f()\n";
py_lexer_str_buf_t py_lexer_str_buf;
py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", pysrc, strlen(pysrc), false, &py_lexer_str_buf);
mp_lexer_str_buf_t mp_lexer_str_buf;
mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", pysrc, strlen(pysrc), false, &mp_lexer_str_buf);
// nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler
printf("lex; al=%u\n", m_get_total_bytes_allocated());
sys_tick_delay_ms(1000);
py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT);
py_lexer_free(lex);
if (pn != PY_PARSE_NODE_NULL) {
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_lexer_free(lex);
if (pn != MP_PARSE_NODE_NULL) {
printf("pars;al=%u\n", m_get_total_bytes_allocated());
sys_tick_delay_ms(1000);
//parse_node_show(pn, 0);
bool comp_ok = py_compile(pn, false);
bool comp_ok = mp_compile(pn, false);
printf("comp;al=%u\n", m_get_total_bytes_allocated());
sys_tick_delay_ms(1000);
@ -1333,7 +1172,7 @@ soft_reset:
} else {
// execute it!
py_obj_t module_fun = rt_make_function_from_id(1);
mp_obj_t module_fun = rt_make_function_from_id(1);
// flash once
led_state(PYB_LED_G1, 1);
@ -1342,15 +1181,15 @@ soft_reset:
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
py_obj_t ret = rt_call_function_0(module_fun);
mp_obj_t ret = rt_call_function_0(module_fun);
printf("done! got: ");
py_obj_print(ret);
mp_obj_print(ret);
printf("\n");
nlr_pop();
} else {
// uncaught exception
printf("exception: ");
py_obj_print((py_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
}

View File

@ -1,6 +1,6 @@
#include <stdint.h>
#include "std.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "gc.h"
#if 0

View File

@ -13,6 +13,7 @@
typedef int32_t machine_int_t; // must be pointer size
typedef uint32_t machine_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef float machine_float_t;
machine_float_t machine_sqrt(machine_float_t x);

View File

@ -11,7 +11,7 @@
#include "std.h"
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "systick.h"
#include "nlr.h"
@ -19,6 +19,7 @@
#include "lexer.h"
#include "parse.h"
#include "compile.h"
#include "obj.h"
#include "runtime.h"
#include "cc3k/ccspi.h"
@ -28,27 +29,27 @@
#include "cc3k/wlan.h"
#include "cc3k/nvmem.h"
py_obj_t pyb_wlan_connect(int n_args, const py_obj_t *args) {
mp_obj_t pyb_wlan_connect(int n_args, const mp_obj_t *args) {
const char *ap;
const char *key;
if (n_args == 2) {
ap = qstr_str(py_obj_get_qstr(args[0]));
key = qstr_str(py_obj_get_qstr(args[1]));
ap = qstr_str(mp_obj_get_qstr(args[0]));
key = qstr_str(mp_obj_get_qstr(args[1]));
} else {
ap = "Rama3";
key = "underthechristmastree";
ap = "your-ssid";
key = "your-password";
}
// might want to set wlan_ioctl_set_connection_policy
int ret = wlan_connect(WLAN_SEC_WPA2, ap, strlen(ap), NULL, (byte*)key, strlen(key));
return py_obj_new_int(ret);
return mp_obj_new_int(ret);
}
py_obj_t pyb_wlan_disconnect(void) {
mp_obj_t pyb_wlan_disconnect(void) {
int ret = wlan_disconnect();
return py_obj_new_int(ret);
return mp_obj_new_int(ret);
}
py_obj_t decode_addr(unsigned char *ip, int nBytes) {
mp_obj_t decode_addr(unsigned char *ip, int nBytes) {
char data[64] = "";
if (nBytes == 4) {
snprintf(data, 64, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
@ -57,21 +58,21 @@ py_obj_t decode_addr(unsigned char *ip, int nBytes) {
} else if (nBytes == 32) {
snprintf(data, 64, "%s", ip);
}
return py_obj_new_str(qstr_from_strn_copy(data, strlen(data)));
return mp_obj_new_str(qstr_from_strn_copy(data, strlen(data)));
}
void _wlan_getIP_get_address(py_obj_t object, qstr q_attr, unsigned char *ip, int nBytes) {
void _wlan_getIP_get_address(mp_obj_t object, qstr q_attr, unsigned char *ip, int nBytes) {
rt_store_attr(object, q_attr, decode_addr(ip, nBytes));
}
py_obj_t pyb_wlan_get_ip(void) {
mp_obj_t pyb_wlan_get_ip(void) {
tNetappIpconfigRetArgs ipconfig;
netapp_ipconfig(&ipconfig);
/* If byte 1 is 0 we don't have a valid address */
if (ipconfig.aucIP[3] == 0) return py_const_none;
if (ipconfig.aucIP[3] == 0) return mp_const_none;
py_obj_t data = py_module_new(); // TODO should really be a class
mp_obj_t data = mp_module_new(); // TODO should really be a class
_wlan_getIP_get_address(data, qstr_from_str_static("ip"), &ipconfig.aucIP[0], 4);
_wlan_getIP_get_address(data, qstr_from_str_static("subnet"), &ipconfig.aucSubnetMask[0], 4);
_wlan_getIP_get_address(data, qstr_from_str_static("gateway"), &ipconfig.aucDefaultGateway[0], 4);
@ -84,16 +85,16 @@ py_obj_t pyb_wlan_get_ip(void) {
}
uint32_t last_ip = 0; // XXX such a hack!
py_obj_t pyb_wlan_get_host(py_obj_t host_name) {
const char *host = qstr_str(py_obj_get_qstr(host_name));
mp_obj_t pyb_wlan_get_host(mp_obj_t host_name) {
const char *host = qstr_str(mp_obj_get_qstr(host_name));
uint32_t ip;
if (gethostbyname(host, strlen(host), &ip) < 0) {
printf("gethostbyname failed\n");
return py_const_none;
return mp_const_none;
}
if (ip == 0) {
// unknown host
return py_const_none;
return mp_const_none;
}
last_ip = ip;
byte ip_data[4];
@ -104,19 +105,17 @@ py_obj_t pyb_wlan_get_host(py_obj_t host_name) {
return decode_addr(ip_data, 4);
}
py_obj_t py_obj_new_exception_2(qstr, const char *, void*, void*);
py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) {
if (host_name == py_const_none) {
mp_obj_t pyb_wlan_http_get(mp_obj_t host_name, mp_obj_t host_path) {
if (host_name == mp_const_none) {
last_ip = (192 << 24) | (168 << 16) | (0 << 8) | (3);
} else {
if (pyb_wlan_get_host(host_name) == py_const_none) {
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "unknown host", NULL, NULL));
if (pyb_wlan_get_host(host_name) == mp_const_none) {
nlr_jump(mp_obj_new_exception_msg(qstr_from_str_static("WlanError"), "unknown host"));
}
}
int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd, NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd));
}
//printf("socket seemed to work\n");
//sys_tick_delay_ms(200);
@ -127,13 +126,13 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) {
remote.sin_addr.s_addr = htonl(last_ip);
int ret = connect(sd, (sockaddr*)&remote, sizeof(sockaddr));
if (ret != 0) {
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "connect failed: %d", (void*)ret, NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "connect failed: %d", (void*)ret));
}
//printf("connect seemed to work\n");
//sys_tick_delay_ms(200);
vstr_t *vstr = vstr_new();
vstr_printf(vstr, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: PYBv2\r\n\r\n", qstr_str(py_obj_get_qstr(host_path)), qstr_str(py_obj_get_qstr(host_name)));
vstr_printf(vstr, "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: PYBv2\r\n\r\n", qstr_str(mp_obj_get_qstr(host_path)), qstr_str(mp_obj_get_qstr(host_name)));
const char *query = vstr_str(vstr);
// send query
@ -148,7 +147,7 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) {
ret = send(sd, query + sent, strlen(query + sent), 0);
//printf("sent %d bytes\n", ret);
if (ret < 0) {
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "send failed", NULL, NULL));
nlr_jump(mp_obj_new_exception_msg(qstr_from_str_static("WlanError"), "send failed"));
}
sent += ret;
//sys_tick_delay_ms(200);
@ -159,7 +158,7 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) {
//sys_tick_delay_ms(5000);
// receive reply
py_obj_t py_ret = py_const_none;
mp_obj_t mp_ret = mp_const_none;
{
//printf("doing receive\n");
char buf[64];
@ -185,33 +184,33 @@ py_obj_t pyb_wlan_http_get(py_obj_t host_name, py_obj_t host_path) {
// read data
ret = recv(sd, buf, 64, 0);
if (ret < 0) {
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "recv failed %d", (void*)ret, NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "recv failed %d", (void*)ret));
}
vstr_add_strn(vstr, buf, ret);
}
py_ret = py_obj_new_str(qstr_from_str_take(vstr_str(vstr)));
mp_ret = mp_obj_new_str(qstr_from_str_take(vstr_str(vstr)));
}
closesocket(sd);
return py_ret;
return mp_ret;
}
py_obj_t pyb_wlan_serve(void) {
mp_obj_t pyb_wlan_serve(void) {
printf("serve socket\n");
int sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("serve socket got %d\n", sd);
sys_tick_delay_ms(500);
if (sd < 0) {
printf("socket fail\n");
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd, NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "socket failed: %d", (void*)sd));
}
/*
if (setsockopt(sd, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, SOCK_ON, sizeof(SOCK_ON)) < 0) {
printf("couldn't set socket as non-blocking\n");
return py_const_none;
return mp_const_none;
}
*/
@ -226,7 +225,7 @@ py_obj_t pyb_wlan_serve(void) {
sys_tick_delay_ms(100);
if (ret != 0) {
printf("bind fail\n");
nlr_jump(py_obj_new_exception_2(qstr_from_str_static("WlanError"), "bind failed: %d", (void*)ret, NULL));
nlr_jump(mp_obj_new_exception_msg_1_arg(qstr_from_str_static("WlanError"), "bind failed: %d", (void*)ret));
}
printf("bind seemed to work\n");
@ -268,7 +267,7 @@ py_obj_t pyb_wlan_serve(void) {
closesocket(fd);
closesocket(sd);
return py_const_none;
return mp_const_none;
}
//*****************************************************************************
@ -344,7 +343,7 @@ void pyb_wlan_init(void) {
SpiInit();
wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch, ReadWlanInterruptPin, WlanInterruptEnable, WlanInterruptDisable, WriteWlanPin);
py_obj_t m = py_module_new();
mp_obj_t m = mp_module_new();
rt_store_attr(m, qstr_from_str_static("connect"), rt_make_function_var(0, pyb_wlan_connect));
rt_store_attr(m, qstr_from_str_static("disconnect"), rt_make_function_0(pyb_wlan_disconnect));
rt_store_attr(m, qstr_from_str_static("ip"), rt_make_function_0(pyb_wlan_get_ip));

160
stm/servo.c Normal file
View File

@ -0,0 +1,160 @@
#include <stdio.h>
#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include <stm32f4xx_tim.h>
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "servo.h"
// PWM
// TIM2 and TIM5 have CH1, CH2, CH3, CH4 on PA0-PA3 respectively
// they are both 32-bit counters
// 16-bit prescaler
// TIM2_CH3 also on PB10 (used below)
void servo_init(void) {
// TIM2 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// for PB10
/*
// GPIOB Configuration: TIM2_CH3 (PB10)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Connect TIM2 pins to AF1
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
*/
// for PA0, PA1, PA2, PA3
{
// GPIOA Configuration: TIM2_CH0, TIM2_CH1 (PA0, PA1)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Connect TIM2 pins to AF1
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM2);
}
// Compute the prescaler value so TIM2 runs at 100kHz
uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 100000) - 1;
// Time base configuration
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 2000; // timer cycles at 50Hz
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// PWM Mode configuration
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 150; // units of 10us
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure); // channel 1
TIM_OC2Init(TIM2, &TIM_OCInitStructure); // channel 2
TIM_OC3Init(TIM2, &TIM_OCInitStructure); // channel 3
TIM_OC4Init(TIM2, &TIM_OCInitStructure); // channel 4
// ?
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 1
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 2
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 3
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); // channel 4
// ?
TIM_ARRPreloadConfig(TIM2, ENABLE);
// TIM2 enable counter
TIM_Cmd(TIM2, ENABLE);
}
/******************************************************************************/
/* Micro Python bindings */
mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value) {
int p = mp_obj_get_int(port);
int v = mp_obj_get_int(value);
if (v < 50) { v = 50; }
if (v > 250) { v = 250; }
switch (p) {
case 1: TIM2->CCR1 = v; break;
case 2: TIM2->CCR2 = v; break;
case 3: TIM2->CCR3 = v; break;
case 4: TIM2->CCR4 = v; break;
}
return mp_const_none;
}
mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse) {
int pe = mp_obj_get_int(period);
int pu = mp_obj_get_int(pulse);
TIM2->ARR = pe;
TIM2->CCR3 = pu;
return mp_const_none;
}
typedef struct _pyb_servo_obj_t {
mp_obj_base_t base;
uint servo_id;
} pyb_servo_obj_t;
static void servo_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
pyb_servo_obj_t *self = self_in;
print(env, "<Servo %lu>", self->servo_id);
}
static mp_obj_t servo_obj_angle(mp_obj_t self_in, mp_obj_t angle) {
pyb_servo_obj_t *self = self_in;
machine_int_t v = 152 + 85.0 * mp_obj_get_float(angle) / 90.0;
if (v < 65) { v = 65; }
if (v > 210) { v = 210; }
switch (self->servo_id) {
case 1: TIM2->CCR1 = v; break;
case 2: TIM2->CCR2 = v; break;
case 3: TIM2->CCR3 = v; break;
case 4: TIM2->CCR4 = v; break;
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(servo_obj_angle_obj, servo_obj_angle);
static const mp_obj_type_t servo_obj_type = {
{ &mp_const_type },
"Servo",
servo_obj_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{ "angle", &servo_obj_angle_obj },
{ NULL, NULL },
}
};
mp_obj_t pyb_Servo(mp_obj_t servo_id) {
pyb_servo_obj_t *o = m_new_obj(pyb_servo_obj_t);
o->base.type = &servo_obj_type;
o->servo_id = mp_obj_get_int(servo_id);
return o;
}

5
stm/servo.h Normal file
View File

@ -0,0 +1,5 @@
void servo_init(void);
mp_obj_t pyb_servo_set(mp_obj_t port, mp_obj_t value);
mp_obj_t pyb_pwm_set(mp_obj_t period, mp_obj_t pulse);
mp_obj_t pyb_Servo(mp_obj_t servo_id);

View File

@ -267,6 +267,9 @@ void TIM6_DAC_IRQHandler(void) {
}
#include "std.h"
#include "misc.h"
#include "mpconfig.h"
#include "obj.h"
#include "led.h"
// EXTI
// for USRSW on A13

View File

@ -3,6 +3,8 @@
#include "misc.h"
#include "systick.h"
#include "mpconfig.h"
#include "obj.h"
#include "led.h"
#include "flash.h"
#include "storage.h"

View File

@ -7,37 +7,38 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "parse.h"
#include "compile.h"
#include "obj.h"
#include "runtime.h"
#include "timer.h"
// TIM6 is used as an internal interrup to schedule something at a specific rate
py_obj_t timer_py_callback;
mp_obj_t timer_py_callback;
py_obj_t timer_py_set_callback(py_obj_t f) {
mp_obj_t timer_py_set_callback(mp_obj_t f) {
timer_py_callback = f;
return py_const_none;
return mp_const_none;
}
py_obj_t timer_py_set_period(py_obj_t period) {
TIM6->ARR = py_obj_get_int(period) & 0xffff;
return py_const_none;
mp_obj_t timer_py_set_period(mp_obj_t period) {
TIM6->ARR = mp_obj_get_int(period) & 0xffff;
return mp_const_none;
}
py_obj_t timer_py_set_prescaler(py_obj_t prescaler) {
TIM6->PSC = py_obj_get_int(prescaler) & 0xffff;
return py_const_none;
mp_obj_t timer_py_set_prescaler(mp_obj_t prescaler) {
TIM6->PSC = mp_obj_get_int(prescaler) & 0xffff;
return mp_const_none;
}
py_obj_t timer_py_get_value(void) {
return py_obj_new_int(TIM6->CNT & 0xfffff);
mp_obj_t timer_py_get_value(void) {
return mp_obj_new_int(TIM6->CNT & 0xfffff);
}
void timer_init(void) {
timer_py_callback = py_const_none;
timer_py_callback = mp_const_none;
// TIM6 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
@ -71,7 +72,7 @@ void timer_init(void) {
TIM_Cmd(TIM6, ENABLE);
// Python interface
py_obj_t m = py_module_new();
mp_obj_t m = mp_module_new();
rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_1(timer_py_set_callback));
rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_1(timer_py_set_period));
rt_store_attr(m, qstr_from_str_static("prescaler"), rt_make_function_1(timer_py_set_prescaler));
@ -80,7 +81,7 @@ void timer_init(void) {
}
void timer_interrupt(void) {
if (timer_py_callback != py_const_none) {
if (timer_py_callback != mp_const_none) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
// XXX what to do if the GC is in the middle of running??
@ -89,7 +90,7 @@ void timer_interrupt(void) {
} else {
// uncaught exception
printf("exception in timer interrupt\n");
py_obj_print((py_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
}
}

View File

@ -31,6 +31,25 @@ PY_O = \
runtime.o \
map.o \
obj.o \
objbool.o \
objboundmeth.o \
objcell.o \
objclass.o \
objclosure.o \
objcomplex.o \
objdict.o \
objexcept.o \
objfloat.o \
objfun.o \
objgenerator.o \
objinstance.o \
objlist.o \
objnone.o \
objrange.o \
objset.o \
objstr.o \
objtuple.o \
objtype.o \
builtin.o \
vm.o \
showbc.o \
@ -42,6 +61,8 @@ PROG = py
$(PROG): $(BUILD) $(OBJ)
$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
strip $(PROG)
size $(PROG)
$(BUILD):
mkdir $@
@ -52,7 +73,7 @@ $(BUILD)/%.o: %.c
$(BUILD)/%.o: $(PYSRC)/%.s
$(AS) -o $@ $<
$(BUILD)/%.o: $(PYSRC)/%.c mpyconfig.h
$(BUILD)/%.o: $(PYSRC)/%.c mpconfig.h
$(CC) $(CFLAGS) -c -o $@ $<
$(BUILD)/emitnx64.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h
@ -65,7 +86,7 @@ $(BUILD)/emitnthumb.o: $(PYSRC)/emitnative.c $(PYSRC)/emit.h
$(BUILD)/vm.o: $(PYSRC)/vm.c
$(CC) $(CFLAGS) -O3 -c -o $@ $<
$(BUILD)/main.o: mpyconfig.h
$(BUILD)/main.o: mpconfig.h
$(BUILD)/parse.o: $(PYSRC)/grammar.h
$(BUILD)/compile.o: $(PYSRC)/grammar.h
$(BUILD)/emitcpy.o: $(PYSRC)/emit.h

View File

@ -17,7 +17,7 @@ unichar str_buf_next_char(str_buf_t *sb) {
if (sb->src_cur < sb->src_end) {
return *sb->src_cur++;
} else {
return PY_LEXER_CHAR_EOF;
return MP_LEXER_CHAR_EOF;
}
}
@ -30,16 +30,16 @@ void str_buf_free(str_buf_t *sb) {
}
}
py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str) {
mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str) {
str_buf_t *sb = m_new(str_buf_t, 1);
sb->free = free_str;
sb->src_beg = str;
sb->src_cur = str;
sb->src_end = str + len;
return py_lexer_new(src_name, sb, (py_lexer_stream_next_char_t)str_buf_next_char, (py_lexer_stream_close_t)str_buf_free);
return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_char_t)str_buf_next_char, (mp_lexer_stream_close_t)str_buf_free);
}
py_lexer_t *py_lexer_new_from_file(const char *filename) {
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
printf("cannot open file %s\n", filename);
@ -51,5 +51,5 @@ py_lexer_t *py_lexer_new_from_file(const char *filename) {
read(fd, data, size);
close(fd);
return py_lexer_new_from_str_len(filename, data, size, true);
return mp_lexer_new_from_str_len(filename, data, size, true);
}

View File

@ -1,2 +1,2 @@
py_lexer_t *py_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str);
py_lexer_t *py_lexer_new_from_file(const char *filename);
mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, bool free_str);
mp_lexer_t *mp_lexer_new_from_file(const char *filename);

View File

@ -4,18 +4,19 @@
#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "mpconfig.h"
#include "lexer.h"
#include "lexerunix.h"
#include "parse.h"
#include "compile.h"
#include "runtime.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
#include "repl.h"
#include <readline/readline.h>
char *str_join(const char *s1, int sep_char, const char *s2) {
static char *str_join(const char *s1, int sep_char, const char *s2) {
int l1 = strlen(s1);
int l2 = strlen(s2);
char *s = m_new(char, l1 + l2 + 2);
@ -29,14 +30,14 @@ char *str_join(const char *s1, int sep_char, const char *s2) {
return s;
}
void do_repl(void) {
static void do_repl(void) {
for (;;) {
char *line = readline(">>> ");
if (line == NULL) {
// EOF
return;
}
if (py_repl_is_compound_stmt(line)) {
if (mp_repl_is_compound_stmt(line)) {
for (;;) {
char *line2 = readline("... ");
if (line2 == NULL || strlen(line2) == 0) {
@ -49,23 +50,23 @@ void do_repl(void) {
}
}
py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", line, strlen(line), false);
py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT);
py_lexer_free(lex);
mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", line, strlen(line), false);
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
mp_lexer_free(lex);
if (pn != PY_PARSE_NODE_NULL) {
//py_parse_node_show(pn, 0);
bool comp_ok = py_compile(pn, true);
if (pn != MP_PARSE_NODE_NULL) {
//mp_parse_node_show(pn, 0);
bool comp_ok = mp_compile(pn, true);
if (comp_ok) {
py_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun != py_const_none) {
mp_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun != mp_const_none) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
rt_call_function_0(module_fun);
nlr_pop();
} else {
// uncaught exception
py_obj_print((py_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
}
}
@ -75,32 +76,32 @@ void do_repl(void) {
}
void do_file(const char *file) {
py_lexer_t *lex = py_lexer_new_from_file(file);
mp_lexer_t *lex = mp_lexer_new_from_file(file);
//const char *pysrc = "def f():\n x=x+1\n print(42)\n";
//py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false);
//mp_lexer_t *lex = mp_lexer_from_str_len("<>", pysrc, strlen(pysrc), false);
if (lex == NULL) {
return;
}
if (0) {
// just tokenise
while (!py_lexer_is_kind(lex, PY_TOKEN_END)) {
py_token_show(py_lexer_cur(lex));
py_lexer_to_next(lex);
while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) {
mp_token_show(mp_lexer_cur(lex));
mp_lexer_to_next(lex);
}
py_lexer_free(lex);
mp_lexer_free(lex);
} else {
// compile
py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT);
py_lexer_free(lex);
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_lexer_free(lex);
if (pn != PY_PARSE_NODE_NULL) {
if (pn != MP_PARSE_NODE_NULL) {
//printf("----------------\n");
//parse_node_show(pn, 0);
//printf("----------------\n");
bool comp_ok = py_compile(pn, false);
bool comp_ok = mp_compile(pn, false);
//printf("----------------\n");
#if MICROPY_EMIT_CPYTHON
@ -110,19 +111,19 @@ void do_file(const char *file) {
#else
if (1 && comp_ok) {
// execute it
py_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun != py_const_none) {
mp_obj_t module_fun = rt_make_function_from_id(1);
if (module_fun != mp_const_none) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
py_obj_t ret = rt_call_function_0(module_fun);
mp_obj_t ret = rt_call_function_0(module_fun);
printf("done! got: ");
py_obj_print(ret);
mp_obj_print(ret);
printf("\n");
nlr_pop();
} else {
// uncaught exception
printf("exception: ");
py_obj_print((py_obj_t)nlr.ret_val);
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
}
}
@ -132,37 +133,58 @@ void do_file(const char *file) {
}
}
void test_print(py_obj_t o_in) {
printf("<test>");
typedef struct _test_obj_t {
mp_obj_base_t base;
bool value;
} test_obj_t;
static void test_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
test_obj_t *self = self_in;
print(env, "<test %d>", self->value);
}
py_obj_t test_get(py_obj_t o_in) {
py_obj_t d1;
py_obj_t d2;
py_user_get_data(o_in, (machine_uint_t*)&d1, (machine_uint_t*)&d2);
return d1;
static mp_obj_t test_get(mp_obj_t self_in) {
test_obj_t *self = self_in;
return mp_obj_new_int(self->value);
}
py_obj_t test_set(py_obj_t o_in, py_obj_t arg) {
py_user_set_data(o_in, (machine_uint_t)arg, (machine_uint_t)arg);
return py_const_none;
static mp_obj_t test_set(mp_obj_t self_in, mp_obj_t arg) {
test_obj_t *self = self_in;
self->value = mp_obj_get_int(arg);
return mp_const_none;
}
const py_user_info_t test_obj_info = {
static MP_DEFINE_CONST_FUN_OBJ_1(test_get_obj, test_get);
static MP_DEFINE_CONST_FUN_OBJ_2(test_set_obj, test_set);
static const mp_obj_type_t test_type = {
{ &mp_const_type },
"Test",
test_print,
{
{ "get", 0, test_get },
{ "set", 1, test_set },
{ NULL, 0, NULL },
test_print, // print
NULL, // call_n
NULL, // unary_op
NULL, // binary_op
NULL, // getiter
NULL, // iternext
{ // method list
{ "get", &test_get_obj },
{ "set", &test_set_obj },
{ NULL, NULL },
}
};
mp_obj_t test_obj_new(int value) {
test_obj_t *o = m_new_obj(test_obj_t);
o->base.type = &test_type;
o->value = value;
return o;
}
int main(int argc, char **argv) {
qstr_init();
rt_init();
rt_store_name(qstr_from_str_static("test"), py_obj_new_user(&test_obj_info, (machine_uint_t)py_obj_new_int(42), 0));
rt_store_name(qstr_from_str_static("test"), test_obj_new(42));
if (argc == 1) {
do_repl();

View File

@ -13,6 +13,7 @@
typedef int64_t machine_int_t; // must be pointer size
typedef uint64_t machine_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef double machine_float_t;
machine_float_t machine_sqrt(machine_float_t x);