You've already forked Core2forAWS-MicroPython
mirror of
https://github.com/m5stack/Core2forAWS-MicroPython.git
synced 2026-05-20 10:30:31 -07:00
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:
+1
-1
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
+176
-145
File diff suppressed because it is too large
Load Diff
+27
-24
@@ -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);
|
||||
|
||||
+614
-614
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1 +1 @@
|
||||
bool py_compile(py_parse_node_t pn, bool is_repl);
|
||||
bool mp_compile(mp_parse_node_t pn, bool is_repl);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+93
-93
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -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))
|
||||
|
||||
+5
-5
@@ -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");
|
||||
|
||||
+16
-16
@@ -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,
|
||||
|
||||
+16
-14
@@ -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);
|
||||
|
||||
+2
-2
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
+91
-91
@@ -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;
|
||||
}
|
||||
|
||||
+117
-123
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user