Browse Source

Split qstr into pools, and put initial pool in ROM.

Qstr's are now split into a linked-list of qstr pools.  This has 2
benefits: the first pool can be in ROM (huge benefit, since we no longer
use RAM for the core qstrs), and subsequent pools use m_new for the next
pool instead of m_renew (thus avoiding a huge single table for all the
qstrs).

Still would be better to use a hash table, but this scheme takes us part
of the way (eventually convert the pools to hash tables).

Also fixed bug with import.

Also improved the way the module code is referenced (not magic number 1
anymore).
pull/73/head
Damien George 11 years ago
parent
commit
eb7bfcb286
  1. 25
      py/builtin.c
  2. 5
      py/builtinimport.c
  3. 76
      py/compile.c
  4. 13
      py/mpqstr.h
  5. 63
      py/mpqstrraw.h
  6. 13
      py/obj.c
  7. 7
      py/objclass.c
  8. 3
      py/objdict.c
  9. 11
      py/objfun.c
  10. 3
      py/objgenerator.c
  11. 3
      py/objinstance.c
  12. 3
      py/objlist.c
  13. 7
      py/objstr.c
  14. 101
      py/qstr.c
  15. 157
      py/runtime.c
  16. 15
      py/runtime.h
  17. 2
      py/runtime0.h
  18. 3
      stm/main.c
  19. 7
      unix/main.c

25
py/builtin.c

@ -8,6 +8,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -91,7 +92,7 @@ mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args) {
switch (n_args) {
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));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bool() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
@ -147,7 +148,7 @@ mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
str[1] = '\0';
return mp_obj_new_str(qstr_from_str_take(str, 2));
} else {
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "chr() arg not in range(0x110000)"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "chr() arg not in range(0x110000)"));
}
}
@ -165,7 +166,7 @@ mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args);
} else {
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)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
}
}
@ -235,7 +236,7 @@ mp_obj_t mp_builtin_len(mp_obj_t o_in) {
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
len = mp_obj_dict_len(o_in);
} else {
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)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
}
return MP_OBJ_NEW_SMALL_INT(len);
}
@ -254,7 +255,7 @@ mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args) {
}
return list;
}
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));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "list() takes at most 1 argument (%d given)", (void*)(machine_int_t)n_args));
}
}
@ -270,7 +271,7 @@ mp_obj_t mp_builtin_max(int n_args, const mp_obj_t *args) {
}
}
if (max_obj == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "max() arg is an empty sequence"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "max() arg is an empty sequence"));
}
return max_obj;
} else {
@ -297,7 +298,7 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
}
}
if (min_obj == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_ValueError, "min() arg is an empty sequence"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_ValueError, "min() arg is an empty sequence"));
}
return min_obj;
} else {
@ -315,7 +316,7 @@ mp_obj_t mp_builtin_min(int n_args, const mp_obj_t *args) {
static mp_obj_t mp_builtin_next(mp_obj_t o) {
mp_obj_t ret = rt_iternext(o);
if (ret == mp_const_stop_iteration) {
nlr_jump(mp_obj_new_exception(qstr_from_str_static("StopIteration")));
nlr_jump(mp_obj_new_exception(MP_QSTR_StopIteration));
} else {
return ret;
}
@ -328,7 +329,7 @@ mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
if (strlen(str) == 1) {
return mp_obj_new_int(str[0]);
} else {
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)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "ord() expected a character, but string of length %d found", (void*)(machine_int_t)strlen(str)));
}
}
@ -336,7 +337,7 @@ 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(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "pow expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
}
}
@ -362,7 +363,7 @@ mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args) {
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));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "range expected at most 3 arguments, got %d", (void*)(machine_int_t)n_args));
}
}
@ -391,7 +392,7 @@ mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
switch (n_args) {
case 1: value = mp_obj_new_int(0); break;
case 2: value = args[1]; break;
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));
default: nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "sum expected at most 2 arguments, got %d", (void*)(machine_int_t)n_args));
}
mp_obj_t iterable = rt_getiter(args[0]);
mp_obj_t item;

5
py/builtinimport.c

@ -58,7 +58,9 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) {
return mp_const_none;
}
if (!mp_compile(pn, false)) {
mp_obj_t module_fun = mp_compile(pn, false);
if (module_fun == mp_const_none) {
// TODO handle compile error correctly
rt_locals_set(old_locals);
rt_globals_set(old_globals);
@ -66,7 +68,6 @@ mp_obj_t mp_builtin___import__(int n, mp_obj_t *args) {
}
// complied successfully, execute it
mp_obj_t module_fun = rt_make_function_from_id(1); // TODO we should return from mp_compile the unique_code_id for the module
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
rt_call_function_0(module_fun);

76
py/compile.c

@ -7,6 +7,7 @@
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "lexer.h"
#include "parse.h"
#include "scope.h"
@ -38,20 +39,6 @@ typedef enum {
#define EMIT_OPT_ASM_THUMB (4)
typedef struct _compiler_t {
qstr qstr___class__;
qstr qstr___locals__;
qstr qstr___name__;
qstr qstr___module__;
qstr qstr___qualname__;
qstr qstr___doc__;
qstr qstr_assertion_error;
qstr qstr_micropython;
qstr qstr_byte_code;
qstr qstr_native;
qstr qstr_viper;
qstr qstr_asm_thumb;
qstr qstr_range;
bool is_repl;
pass_kind_t pass;
bool had_error; // try to keep compiler clean from nlr
@ -202,7 +189,7 @@ static int comp_next_label(compiler_t *comp) {
}
static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options);
scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(), emit_options);
scope->parent = comp->scope_cur;
scope->next = NULL;
if (comp->scope_head == NULL) {
@ -903,7 +890,7 @@ qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint
// returns true if it was a built-in decorator (even if the built-in had an error)
static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) {
if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
return false;
}
@ -913,16 +900,16 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
}
qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
if (attr == comp->qstr_byte_code) {
if (attr == MP_QSTR_byte_code) {
*emit_options = EMIT_OPT_BYTE_CODE;
#if MICROPY_EMIT_NATIVE
} else if (attr == comp->qstr_native) {
} else if (attr == MP_QSTR_native) {
*emit_options = EMIT_OPT_NATIVE_PYTHON;
} else if (attr == comp->qstr_viper) {
} else if (attr == MP_QSTR_viper) {
*emit_options = EMIT_OPT_VIPER;
#endif
#if MICROPY_EMIT_INLINE_THUMB
} else if (attr == comp->qstr_asm_thumb) {
} else if (attr == MP_QSTR_asm_thumb) {
*emit_options = EMIT_OPT_ASM_THUMB;
#endif
} else {
@ -1329,7 +1316,7 @@ void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
int l_end = comp_next_label(comp);
c_if_cond(comp, pns->nodes[0], true, l_end);
EMIT(load_id, comp->qstr_assertion_error);
EMIT(load_id, MP_QSTR_assertion_error);
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
// assertion message
compile_node(comp, pns->nodes[1]);
@ -1495,7 +1482,7 @@ void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
// for viper it will be much, much faster
if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) {
mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == comp->qstr_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
mp_parse_node_t *args;
int n_args = list_get(&pn_range_args, PN_arglist, &args);
@ -1743,7 +1730,7 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
// for REPL, evaluate then print the expression
EMIT(load_id, qstr_from_str_static("__repl_print__"));
EMIT(load_id, MP_QSTR___repl_print__);
compile_node(comp, pns->nodes[0]);
EMIT(call_function, 1, 0, false, false);
EMIT(pop_top);
@ -2683,7 +2670,7 @@ void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
if (kind == MP_PARSE_NODE_STRING) {
compile_node(comp, pns->nodes[0]); // a doc string
// store doc string
EMIT(store_id, comp->qstr___doc__);
EMIT(store_id, MP_QSTR___doc__);
}
}
}
@ -2796,35 +2783,35 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
if (comp->pass == PASS_1) {
bool added;
id_info_t *id_info = scope_find_or_add_id(scope, comp->qstr___class__, &added);
id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
assert(added);
id_info->kind = ID_INFO_KIND_LOCAL;
id_info = scope_find_or_add_id(scope, comp->qstr___locals__, &added);
id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
assert(added);
id_info->kind = ID_INFO_KIND_LOCAL;
id_info->param = true;
scope->num_params = 1; // __locals__ is the parameter
}
EMIT(load_id, comp->qstr___locals__);
EMIT(load_id, MP_QSTR___locals__);
EMIT(store_locals);
EMIT(load_id, comp->qstr___name__);
EMIT(store_id, comp->qstr___module__);
EMIT(load_id, MP_QSTR___name__);
EMIT(store_id, MP_QSTR___module__);
EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
EMIT(store_id, comp->qstr___qualname__);
EMIT(store_id, MP_QSTR___qualname__);
check_for_doc_string(comp, pns->nodes[2]);
compile_node(comp, pns->nodes[2]); // 2 is class body
id_info_t *id = scope_find(scope, comp->qstr___class__);
id_info_t *id = scope_find(scope, MP_QSTR___class__);
assert(id != NULL);
if (id->kind == ID_INFO_KIND_LOCAL) {
EMIT(load_const_tok, MP_TOKEN_KW_NONE);
} else {
#if MICROPY_EMIT_CPYTHON
EMIT(load_closure, comp->qstr___class__, 0); // XXX check this is the correct local num
EMIT(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
#else
EMIT(load_fast, comp->qstr___class__, 0); // XXX check this is the correct local num
EMIT(load_fast, MP_QSTR___class__, 0); // XXX check this is the correct local num
#endif
}
EMIT(return_value);
@ -2917,7 +2904,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
scope->num_locals = 0;
for (int i = 0; i < scope->id_info_len; i++) {
id_info_t *id = &scope->id_info[i];
if (scope->kind == SCOPE_CLASS && id->qstr == comp->qstr___class__) {
if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
// __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
continue;
}
@ -3021,20 +3008,6 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
compiler_t *comp = m_new(compiler_t, 1);
comp->qstr___class__ = qstr_from_str_static("__class__");
comp->qstr___locals__ = qstr_from_str_static("__locals__");
comp->qstr___name__ = qstr_from_str_static("__name__");
comp->qstr___module__ = qstr_from_str_static("__module__");
comp->qstr___qualname__ = qstr_from_str_static("__qualname__");
comp->qstr___doc__ = qstr_from_str_static("__doc__");
comp->qstr_assertion_error = qstr_from_str_static("AssertionError");
comp->qstr_micropython = qstr_from_str_static("micropython");
comp->qstr_byte_code = qstr_from_str_static("byte_code");
comp->qstr_native = qstr_from_str_static("native");
comp->qstr_viper = qstr_from_str_static("viper");
comp->qstr_asm_thumb = qstr_from_str_static("asm_thumb");
comp->qstr_range = qstr_from_str_static("range");
comp->is_repl = is_repl;
comp->had_error = false;
@ -3048,10 +3021,10 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
pn = fold_constants(pn);
// set the outer scope
scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
// compile pass 1
comp->emit = emit_pass1_new(comp->qstr___class__);
comp->emit = emit_pass1_new(MP_QSTR___class__);
comp->emit_method_table = &emit_pass1_method_table;
comp->emit_inline_asm = NULL;
comp->emit_inline_asm_method_table = NULL;
@ -3162,10 +3135,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
} else {
#if MICROPY_EMIT_CPYTHON
// can't create code, so just return true
(void)module_scope; // to suppress warning that module_scope is unused
return mp_const_true;
#else
// return function that executes the outer module
return rt_make_function_from_id(1);
return rt_make_function_from_id(module_scope->unique_code_id);
#endif
}
}

13
py/mpqstr.h

@ -0,0 +1,13 @@
// See mpqstrraw.h for a list of qstr's that are available as constants.
// Reference them as MP_QSTR_xxxx.
//
// Note: it would be possible to define MP_QSTR_xxx as qstr_from_str_static("xxx")
// for qstrs that are referenced this way, but you don't want to have them in ROM.
enum {
MP_QSTR_nil = 0,
#define Q(id) MP_QSTR_##id,
#include "mpqstrraw.h"
#undef Q
MP_QSTR_number_of,
} category_t;

63
py/mpqstrraw.h

@ -0,0 +1,63 @@
// All the qstr definitions in this file are available as constants.
// That is, they are in ROM and you can reference them simple as MP_QSTR_xxxx.
Q(__build_class__)
Q(__class__)
Q(__doc__)
Q(__init__)
Q(__locals__)
Q(__main__)
Q(__module__)
Q(__name__)
Q(__next__)
Q(__qualname__)
Q(__repl_print__)
Q(assertion_error)
Q(micropython)
Q(byte_code)
Q(native)
Q(viper)
Q(asm_thumb)
Q(StopIteration)
Q(AttributeError)
Q(IndexError)
Q(KeyError)
Q(NameError)
Q(TypeError)
Q(SyntaxError)
Q(ValueError)
Q(abs)
Q(all)
Q(any)
Q(bool)
Q(callable)
Q(chr)
Q(complex)
Q(dict)
Q(divmod)
Q(float)
Q(hash)
Q(int)
Q(iter)
Q(len)
Q(list)
Q(max)
Q(min)
Q(next)
Q(ord)
Q(pow)
Q(print)
Q(range)
Q(set)
Q(sum)
Q(type)
Q(append)
Q(pop)
Q(sort)
Q(join)
Q(format)

13
py/obj.c

@ -7,6 +7,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -144,7 +145,7 @@ machine_float_t mp_obj_get_float(mp_obj_t arg) {
} else if (MP_OBJ_IS_TYPE(arg, &float_type)) {
return mp_obj_float_get(arg);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
}
}
@ -164,7 +165,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
} else if (MP_OBJ_IS_TYPE(arg, &complex_type)) {
mp_obj_complex_get(arg, real, imag);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
}
}
#endif
@ -188,11 +189,11 @@ mp_obj_t *mp_obj_get_array_fixed_n(mp_obj_t o_in, machine_int_t n) {
mp_obj_list_get(o_in, &seq_len, &seq_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));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_IndexError, "requested length %d but object has length %d", (void*)n, (void*)(machine_uint_t)seq_len));
}
return seq_items;
} else {
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)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o_in)));
}
}
@ -204,10 +205,10 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
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));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_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)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "%s indices must be integers, not %s", type->name, mp_obj_get_type_str(index)));
}
}

7
py/objclass.c

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
@ -25,7 +26,7 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
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);
mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, MP_QSTR___init__, false);
if (init_fn != NULL) {
// call __init__ function
@ -40,13 +41,13 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
m_del(mp_obj_t, args2, n_args + 1);
}
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)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_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));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "function takes 0 positional arguments but %d were given", (void*)(machine_int_t)n_args));
}
}

3
py/objdict.c

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -42,7 +43,7 @@ mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// 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>"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
} else {
return elem->value;
}

11
py/objfun.c

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "map.h"
#include "runtime.h"
@ -24,7 +25,7 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
// 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));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_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
@ -47,9 +48,9 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
// 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)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_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));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_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
@ -141,7 +142,7 @@ 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));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_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));
}
// optimisation: allow the compiler to optimise this tail call for
@ -250,7 +251,7 @@ 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));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_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;

3
py/objgenerator.c

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "bc.h"
@ -29,7 +30,7 @@ mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
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));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_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));
}
return mp_obj_new_gen_instance(bc_code, self->n_state, n_args, args);

3
py/objinstance.c

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime.h"
#include "map.h"
@ -44,7 +45,7 @@ mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) {
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)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_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) {

3
py/objlist.c

@ -6,6 +6,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -81,7 +82,7 @@ static mp_obj_t list_pop(int n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(args[0], &list_type));
mp_obj_list_t *self = args[0];
if (self->len == 0) {
nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "pop from empty list"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "pop from empty list"));
}
uint index = mp_get_index(self->base.type, self->len, n_args == 1 ? mp_obj_new_int(-1) : args[1]);
mp_obj_t ret = self->items[index];

7
py/objstr.c

@ -7,6 +7,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -61,7 +62,7 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
} else {
// Message doesn't match CPython, but we don't have so much bytes as they
// to spend them on verbose wording
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "index must be int"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int"));
}
case RT_BINARY_OP_ADD:
@ -134,7 +135,7 @@ mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
return mp_obj_new_str(qstr_from_str_take(joined_str, required_len + 1));
bad_arg:
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "?str.join expecting a list of str's"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's"));
}
void vstr_printf_wrapper(void *env, const char *fmt, ...) {
@ -158,7 +159,7 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) {
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"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range"));
}
mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]);
arg_i++;

101
py/qstr.c

@ -2,55 +2,110 @@
#include <string.h>
#include "misc.h"
#include "mpqstr.h"
static int qstrs_alloc;
static int qstrs_len;
static const char **qstrs;
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
// ultimately we will replace this with a static hash table of some kind
// also probably need to include the length in the string data, to allow null bytes in the string
#if 0 // print debugging info
#include <stdio.h>
#define DEBUG_printf(args...) printf(args)
#else // don't print debugging info
#define DEBUG_printf(args...) (void)0
#endif
typedef struct _qstr_pool_t {
struct _qstr_pool_t *prev;
uint total_prev_len;
uint alloc;
uint len;
const char *qstrs[];
} qstr_pool_t;
const static qstr_pool_t const_pool = {
NULL, // no previous pool
0, // no previous pool
10, // set so that the first dynamically allocated pool is twice this size; must be <= the len (just below)
MP_QSTR_number_of, // corresponds to number of strings in array just below
{
"nil", // must be first, since 0 qstr is nil
#define Q(id) #id,
#include "mpqstrraw.h"
#undef Q
},
};
static qstr_pool_t *last_pool = (qstr_pool_t*)&const_pool; // we won't modify the const_pool since it has no allocated room left
void qstr_init(void) {
qstrs_alloc = 400;
qstrs_len = 1;
qstrs = m_new(const char*, qstrs_alloc);
qstrs[0] = "nil";
// nothing to do!
}
static qstr qstr_add(const char *str) {
if (qstrs_len >= qstrs_alloc) {
qstrs = m_renew(const char*, qstrs, qstrs_alloc, qstrs_alloc * 2);
qstrs_alloc *= 2;
DEBUG_printf("QSTR: add %s\n", str);
// make sure we have room in the pool for a new qstr
if (last_pool->len >= last_pool->alloc) {
qstr_pool_t *pool = m_new_obj_var(qstr_pool_t, const char*, last_pool->alloc * 2);
pool->prev = last_pool;
pool->total_prev_len = last_pool->total_prev_len + last_pool->len;
pool->alloc = last_pool->alloc * 2;
pool->len = 0;
last_pool = pool;
DEBUG_printf("QSTR: allocate new pool of size %d\n", last_pool->alloc);
}
qstrs[qstrs_len++] = str;
return qstrs_len - 1;
// add the new qstr
last_pool->qstrs[last_pool->len++] = str;
// return id for the newly-added qstr
return last_pool->total_prev_len + last_pool->len - 1;
}
qstr qstr_from_str_static(const char *str) {
for (int i = 0; i < qstrs_len; i++) {
if (strcmp(qstrs[i], str) == 0) {
return i;
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) {
if (strcmp(*qstr, str) == 0) {
return pool->total_prev_len + (qstr - pool->qstrs);
}
}
}
return qstr_add(str);
}
qstr qstr_from_str_take(char *str, int alloc_len) {
for (int i = 0; i < qstrs_len; i++) {
if (strcmp(qstrs[i], str) == 0) {
m_del(char, str, alloc_len);
return i;
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) {
if (strcmp(*qstr, str) == 0) {
m_del(char, str, alloc_len);
return pool->total_prev_len + (qstr - pool->qstrs);
}
}
}
return qstr_add(str);
}
qstr qstr_from_strn_copy(const char *str, int len) {
for (int i = 0; i < qstrs_len; i++) {
if (strncmp(qstrs[i], str, len) == 0 && qstrs[i][len] == '\0') {
return i;
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
for (const char **qstr = pool->qstrs, **qstr_top = pool->qstrs + pool->len; qstr < qstr_top; qstr++) {
if (strncmp(*qstr, str, len) == 0 && (*qstr)[len] == '\0') {
return pool->total_prev_len + (qstr - pool->qstrs);
}
}
}
return qstr_add(strndup(str, len));
}
// convert qstr id to pointer to its string
const char *qstr_str(qstr qstr) {
return qstrs[qstr];
// search
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
if (qstr >= pool->total_prev_len) {
return pool->qstrs[qstr - pool->total_prev_len];
}
}
// not found, return nil
return const_pool.qstrs[0];
}

157
py/runtime.c

@ -11,6 +11,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@ -27,22 +28,6 @@
#define DEBUG_OP_printf(args...) (void)0
#endif
// TODO make these predefined so they don't take up RAM
qstr rt_q_append;
qstr rt_q_pop;
qstr rt_q_sort;
qstr rt_q_join;
qstr rt_q_format;
qstr rt_q___build_class__;
qstr rt_q___next__;
qstr rt_q_AttributeError;
qstr rt_q_IndexError;
qstr rt_q_KeyError;
qstr rt_q_NameError;
qstr rt_q_TypeError;
qstr rt_q_SyntaxError;
qstr rt_q_ValueError;
// locals and globals need to be pointers because they can be the same in outer module scope
static mp_map_t *map_locals;
static mp_map_t *map_globals;
@ -83,74 +68,58 @@ FILE *fp_write_code = NULL;
#endif
void rt_init(void) {
rt_q_append = qstr_from_str_static("append");
rt_q_pop = qstr_from_str_static("pop");
rt_q_sort = qstr_from_str_static("sort");
rt_q_join = qstr_from_str_static("join");
rt_q_format = qstr_from_str_static("format");
rt_q___build_class__ = qstr_from_str_static("__build_class__");
rt_q___next__ = qstr_from_str_static("__next__");
rt_q_AttributeError = qstr_from_str_static("AttributeError");
rt_q_IndexError = qstr_from_str_static("IndexError");
rt_q_KeyError = qstr_from_str_static("KeyError");
rt_q_NameError = qstr_from_str_static("NameError");
rt_q_TypeError = qstr_from_str_static("TypeError");
rt_q_SyntaxError = qstr_from_str_static("SyntaxError");
rt_q_ValueError = qstr_from_str_static("ValueError");
// locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
map_locals = map_globals = mp_map_new(MP_MAP_QSTR, 1);
mp_qstr_map_lookup(map_globals, qstr_from_str_static("__name__"), true)->value = mp_obj_new_str(qstr_from_str_static("__main__"));
mp_qstr_map_lookup(map_globals, MP_QSTR___name__, true)->value = mp_obj_new_str(MP_QSTR___main__);
// init built-in hash table
mp_map_init(&map_builtins, MP_MAP_QSTR, 3);
// built-in exceptions (TODO, make these proper classes)
mp_qstr_map_lookup(&map_builtins, rt_q_AttributeError, true)->value = mp_obj_new_exception(rt_q_AttributeError);
mp_qstr_map_lookup(&map_builtins, rt_q_IndexError, true)->value = mp_obj_new_exception(rt_q_IndexError);
mp_qstr_map_lookup(&map_builtins, rt_q_KeyError, true)->value = mp_obj_new_exception(rt_q_KeyError);
mp_qstr_map_lookup(&map_builtins, rt_q_NameError, true)->value = mp_obj_new_exception(rt_q_NameError);
mp_qstr_map_lookup(&map_builtins, rt_q_TypeError, true)->value = mp_obj_new_exception(rt_q_TypeError);
mp_qstr_map_lookup(&map_builtins, rt_q_SyntaxError, true)->value = mp_obj_new_exception(rt_q_SyntaxError);
mp_qstr_map_lookup(&map_builtins, rt_q_ValueError, true)->value = mp_obj_new_exception(rt_q_ValueError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_AttributeError, true)->value = mp_obj_new_exception(MP_QSTR_AttributeError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_IndexError, true)->value = mp_obj_new_exception(MP_QSTR_IndexError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_KeyError, true)->value = mp_obj_new_exception(MP_QSTR_KeyError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_NameError, true)->value = mp_obj_new_exception(MP_QSTR_NameError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_TypeError, true)->value = mp_obj_new_exception(MP_QSTR_TypeError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_SyntaxError, true)->value = mp_obj_new_exception(MP_QSTR_SyntaxError);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_ValueError, true)->value = mp_obj_new_exception(MP_QSTR_ValueError);
// built-in core functions
mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("__repl_print__"), true)->value = rt_make_function_1(mp_builtin___repl_print__);
mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, true)->value = rt_make_function_2(mp_builtin___build_class__);
mp_qstr_map_lookup(&map_builtins, MP_QSTR___repl_print__, true)->value = rt_make_function_1(mp_builtin___repl_print__);
// built-in user functions
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("abs"), true)->value = rt_make_function_1(mp_builtin_abs);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("all"), true)->value = rt_make_function_1(mp_builtin_all);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("any"), true)->value = rt_make_function_1(mp_builtin_any);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("bool"), true)->value = rt_make_function_var(0, mp_builtin_bool);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("callable"), true)->value = rt_make_function_1(mp_builtin_callable);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("chr"), true)->value = rt_make_function_1(mp_builtin_chr);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_abs, true)->value = rt_make_function_1(mp_builtin_abs);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_all, true)->value = rt_make_function_1(mp_builtin_all);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_any, true)->value = rt_make_function_1(mp_builtin_any);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_bool, true)->value = rt_make_function_var(0, mp_builtin_bool);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_callable, true)->value = rt_make_function_1(mp_builtin_callable);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_chr, true)->value = rt_make_function_1(mp_builtin_chr);
#if MICROPY_ENABLE_FLOAT
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("complex"), true)->value = (mp_obj_t)&mp_builtin_complex_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_complex, true)->value = (mp_obj_t)&mp_builtin_complex_obj;
#endif
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("dict"), true)->value = rt_make_function_0(mp_builtin_dict);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("divmod"), true)->value = rt_make_function_2(mp_builtin_divmod);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_dict, true)->value = rt_make_function_0(mp_builtin_dict);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_divmod, true)->value = rt_make_function_2(mp_builtin_divmod);
#if MICROPY_ENABLE_FLOAT
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("float"), true)->value = (mp_obj_t)&mp_builtin_float_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_float, true)->value = (mp_obj_t)&mp_builtin_float_obj;
#endif
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("hash"), true)->value = (mp_obj_t)&mp_builtin_hash_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("int"), true)->value = (mp_obj_t)&mp_builtin_int_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("iter"), true)->value = (mp_obj_t)&mp_builtin_iter_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("len"), true)->value = rt_make_function_1(mp_builtin_len);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("list"), true)->value = rt_make_function_var(0, mp_builtin_list);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("max"), true)->value = rt_make_function_var(1, mp_builtin_max);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("min"), true)->value = rt_make_function_var(1, mp_builtin_min);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("next"), true)->value = (mp_obj_t)&mp_builtin_next_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("ord"), true)->value = rt_make_function_1(mp_builtin_ord);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("pow"), true)->value = rt_make_function_var(2, mp_builtin_pow);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("print"), true)->value = rt_make_function_var(0, mp_builtin_print);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("range"), true)->value = rt_make_function_var(1, mp_builtin_range);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("set"), true)->value = (mp_obj_t)&mp_builtin_set_obj;
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("sum"), true)->value = rt_make_function_var(1, mp_builtin_sum);
mp_qstr_map_lookup(&map_builtins, qstr_from_str_static("type"), true)->value = (mp_obj_t)&mp_builtin_type_obj;
next_unique_code_id = 2; // 1 is reserved for the __main__ module scope
mp_qstr_map_lookup(&map_builtins, MP_QSTR_hash, true)->value = (mp_obj_t)&mp_builtin_hash_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_int, true)->value = (mp_obj_t)&mp_builtin_int_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_iter, true)->value = (mp_obj_t)&mp_builtin_iter_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_len, true)->value = rt_make_function_1(mp_builtin_len);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_list, true)->value = rt_make_function_var(0, mp_builtin_list);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_max, true)->value = rt_make_function_var(1, mp_builtin_max);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_min, true)->value = rt_make_function_var(1, mp_builtin_min);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_next, true)->value = (mp_obj_t)&mp_builtin_next_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_ord, true)->value = rt_make_function_1(mp_builtin_ord);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_pow, true)->value = rt_make_function_var(2, mp_builtin_pow);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_print, true)->value = rt_make_function_var(0, mp_builtin_print);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_range, true)->value = rt_make_function_var(1, mp_builtin_range);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_set, true)->value = (mp_obj_t)&mp_builtin_set_obj;
mp_qstr_map_lookup(&map_builtins, MP_QSTR_sum, true)->value = rt_make_function_var(1, mp_builtin_sum);
mp_qstr_map_lookup(&map_builtins, MP_QSTR_type, true)->value = (mp_obj_t)&mp_builtin_type_obj;
next_unique_code_id = 1; // 0 indicates "no code"
unique_codes = NULL;
#ifdef WRITE_CODE
@ -166,12 +135,8 @@ void rt_deinit(void) {
#endif
}
int rt_get_unique_code_id(bool is_main_module) {
if (is_main_module) {
return 1;
} else {
return next_unique_code_id++;
}
int rt_get_unique_code_id(void) {
return next_unique_code_id++;
}
static void alloc_unique_codes(void) {
@ -186,7 +151,7 @@ static void alloc_unique_codes(void) {
void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, int n_stack, bool is_generator) {
alloc_unique_codes();
assert(unique_code_id < next_unique_code_id);
assert(1 <= unique_code_id && unique_code_id < next_unique_code_id);
unique_codes[unique_code_id].kind = MP_CODE_BYTE;
unique_codes[unique_code_id].n_args = n_args;
unique_codes[unique_code_id].n_locals = n_locals;
@ -355,7 +320,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) {
}
}
if (*s != 0) {
nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "invalid syntax for number"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "invalid syntax for number"));
}
if (exp_neg) {
exp_val = -exp_val;
@ -373,7 +338,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) {
return mp_obj_new_float(dec_val);
}
#else
nlr_jump(mp_obj_new_exception_msg(rt_q_SyntaxError, "decimal numbers not supported"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_SyntaxError, "decimal numbers not supported"));
#endif
}
@ -391,7 +356,7 @@ mp_obj_t rt_load_name(qstr qstr) {
if (elem == NULL) {
elem = mp_qstr_map_lookup(&map_builtins, qstr, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr)));
}
}
}
@ -405,7 +370,7 @@ mp_obj_t rt_load_global(qstr qstr) {
if (elem == NULL) {
elem = mp_qstr_map_lookup(&map_builtins, qstr, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_NameError, "name '%s' is not defined", qstr_str(qstr)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr)));
}
}
return elem->value;
@ -413,9 +378,9 @@ mp_obj_t rt_load_global(qstr qstr) {
mp_obj_t rt_load_build_class(void) {
DEBUG_OP_printf("load_build_class\n");
mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, rt_q___build_class__, false);
mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, false);
if (elem == NULL) {
nlr_jump(mp_obj_new_exception_msg(rt_q_NameError, "name '__build_class__' is not defined"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_NameError, "name '__build_class__' is not defined"));
}
return elem->value;
}
@ -465,7 +430,7 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
}
}
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "bad operand type for unary operator: '%s'", o->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "bad operand type for unary operator: '%s'", o->type->name));
}
}
@ -544,7 +509,7 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
// TODO specify in error message what the operator is
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "unsupported operand type for binary operator: '%s'", mp_obj_get_type_str(lhs)));
}
mp_obj_t rt_compare_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
@ -693,13 +658,13 @@ mp_obj_t rt_call_function_n(mp_obj_t fun_in, int n_args, const mp_obj_t *args) {
DEBUG_OP_printf("calling function %p(n_args=%d, args=%p)\n", fun_in, n_args, args);
if (MP_OBJ_IS_SMALL_INT(fun_in)) {
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not callable"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not callable"));
} else {
mp_obj_base_t *fun = fun_in;
if (fun->type->call_n != NULL) {
return fun->type->call_n(fun_in, n_args, args);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not callable", fun->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not callable", fun->type->name));
}
}
}
@ -756,14 +721,14 @@ void rt_unpack_sequence(mp_obj_t seq_in, uint num, mp_obj_t *items) {
mp_obj_list_get(seq_in, &seq_len, &seq_items);
}
if (seq_len < num) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "need more than %d values to unpack", (void*)(machine_uint_t)seq_len));
} else if (seq_len > num) {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "too many values to unpack (expected %d)", (void*)(machine_uint_t)num));
}
memcpy(items, seq_items, num * sizeof(mp_obj_t));
} else {
// TODO call rt_getiter and extract via rt_iternext
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in)));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(seq_in)));
}
}
@ -807,12 +772,12 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
}
no_attr:
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
DEBUG_OP_printf("load method %s\n", qstr_str(attr));
if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == rt_q___next__) {
if (MP_OBJ_IS_TYPE(base, &gen_instance_type) && attr == MP_QSTR___next__) {
dest[1] = (mp_obj_t)&mp_builtin_next_obj;
dest[0] = base;
return;
@ -850,7 +815,7 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
mp_map_t *globals = mp_obj_module_get_globals(base);
mp_qstr_map_lookup(globals, attr, true)->value = value;
} else {
nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
}
}
@ -869,26 +834,26 @@ void rt_store_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
mp_obj_t rt_getiter(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "'int' object is not iterable"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "'int' object is not iterable"));
} else {
mp_obj_base_t *o = o_in;
if (o->type->getiter != NULL) {
return o->type->getiter(o_in);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "'%s' object is not iterable", o->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "'%s' object is not iterable", o->type->name));
}
}
}
mp_obj_t rt_iternext(mp_obj_t o_in) {
if (MP_OBJ_IS_SMALL_INT(o_in)) {
nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "? 'int' object is not iterable"));
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "? 'int' object is not iterable"));
} else {
mp_obj_base_t *o = o_in;
if (o->type->iternext != NULL) {
return o->type->iternext(o_in);
} else {
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_TypeError, "? '%s' object is not iterable", o->type->name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "? '%s' object is not iterable", o->type->name));
}
}
}

15
py/runtime.h

@ -1,18 +1,3 @@
extern qstr rt_q_append;
extern qstr rt_q_pop;
extern qstr rt_q_sort;
extern qstr rt_q_join;
extern qstr rt_q_format;
extern qstr rt_q___build_class__;
extern qstr rt_q___next__;
extern qstr rt_q_AttributeError;
extern qstr rt_q_IndexError;
extern qstr rt_q_KeyError;
extern qstr rt_q_NameError;
extern qstr rt_q_TypeError;
extern qstr rt_q_SyntaxError;
extern qstr rt_q_ValueError;
int rt_is_true(mp_obj_t arg);
mp_obj_t rt_load_const_dec(qstr qstr);

2
py/runtime0.h

@ -81,7 +81,7 @@ 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);
int rt_get_unique_code_id(void);
void rt_assign_byte_code(int unique_code_id, byte *code, uint len, int n_args, int n_locals, 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);

3
stm/main.c

@ -15,6 +15,7 @@
#include "misc.h"
#include "ff.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "nlr.h"
#include "misc.h"
#include "lexer.h"
@ -621,7 +622,7 @@ mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
}
pin_error:
nlr_jump(mp_obj_new_exception_msg_1_arg(rt_q_ValueError, "pin %s does not exist", pin_name));
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not exist", pin_name));
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);

7
unix/main.c

@ -217,6 +217,13 @@ int main(int argc, char **argv) {
rt_store_name(qstr_from_str_static("test"), test_obj_new(42));
/*
printf("bytes:\n");
printf(" total %d\n", m_get_total_bytes_allocated());
printf(" cur %d\n", m_get_current_bytes_allocated());
printf(" peak %d\n", m_get_peak_bytes_allocated());
*/
if (argc == 1) {
do_repl();
} else if (argc == 2) {

Loading…
Cancel
Save