diff options
58 files changed, 869 insertions, 475 deletions
@@ -55,7 +55,8 @@ Then to test it: Debian/Ubuntu/Mint derivative Linux distros will require build-essentials and libreadline-dev packages installed. To build FFI (Foreign Function Interface) -module (recommended, enable in unix/mpconfigport.mk), libffi-dev is required. +module, libffi-dev package is required. If you have problems with some +dependencies, they can be disabled in unix/mpconfigport.mk . The STM version --------------- diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h index 7f4c37890..dfb6312a8 100644 --- a/bare-arm/mpconfigport.h +++ b/bare-arm/mpconfigport.h @@ -11,6 +11,10 @@ #define MICROPY_ENABLE_REPL_HELPERS (0) #define MICROPY_ENABLE_LEXER_UNIX (0) #define MICROPY_ENABLE_SOURCE_LINE (0) +#define MICROPY_ENABLE_MOD_IO (0) +#define MICROPY_ENABLE_MOD_STRUCT (0) +#define MICROPY_ENABLE_MOD_SYS (0) +#define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) #define MICROPY_PATH_MAX (512) diff --git a/examples/asmled.py b/examples/asmled.py index e0d6c73ce..917d9ba03 100644 --- a/examples/asmled.py +++ b/examples/asmled.py @@ -1,4 +1,5 @@ # flash LED #1 using inline assembler +# this version is overly verbose and uses word stores @micropython.asm_thumb def flash_led(r0): movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xffff) @@ -13,69 +14,72 @@ def flash_led(r0): label(loop1) # turn LED on - str(r2, r1, 0) + str(r2, [r1, 0]) # delay for a bit movw(r4, 5599900 & 0xffff) movt(r4, (5599900 >> 16) & 0xffff) label(delay_on) - subs(r4, r4, 1) + sub(r4, r4, 1) cmp(r4, 0) bgt(delay_on) # turn LED off - str(r3, r1, 0) + str(r3, [r1, 0]) # delay for a bit movw(r4, 5599900 & 0xffff) movt(r4, (5599900 >> 16) & 0xffff) label(delay_off) - subs(r4, r4, 1) + sub(r4, r4, 1) cmp(r4, 0) bgt(delay_off) # loop r0 times - subs(r0, r0, 1) + sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) -# flash LED #1 using inline assembler -# this version uses the convenience assembler operation 'movwt' +# flash LED #2 using inline assembler +# this version uses half-word sortes, and the convenience assembler operation 'movwt' @micropython.asm_thumb def flash_led_v2(r0): - movwt(r1, stm.GPIOA + stm.GPIO_BSRRL) - movwt(r2, 1 << 13) - movwt(r3, 1 << (16 + 13)) + # get the GPIOA address in r1 + movwt(r1, stm.GPIOA) + + # get the bit mask for PA14 (the pin LED #2 is on) + movw(r2, 1 << 14) b(loop_entry) label(loop1) # turn LED on - str(r2, r1, 0) + strh(r2, [r1, stm.GPIO_BSRRL]) # delay for a bit movwt(r4, 5599900) label(delay_on) - subs(r4, r4, 1) + sub(r4, r4, 1) cmp(r4, 0) bgt(delay_on) # turn LED off - str(r3, r1, 0) + strh(r2, [r1, stm.GPIO_BSRRH]) # delay for a bit movwt(r4, 5599900) label(delay_off) - subs(r4, r4, 1) + sub(r4, r4, 1) cmp(r4, 0) bgt(delay_off) # loop r0 times - subs(r0, r0, 1) + sub(r0, r0, 1) label(loop_entry) cmp(r0, 0) bgt(loop1) +flash_led(5) flash_led_v2(5) diff --git a/examples/asmsum.py b/examples/asmsum.py new file mode 100644 index 000000000..07e71c738 --- /dev/null +++ b/examples/asmsum.py @@ -0,0 +1,57 @@ +@micropython.asm_thumb +def asm_sum_words(r0, r1): + + # r0 = len + # r1 = ptr + # r2 = sum + # r3 = dummy + mov(r2, 0) + + b(loop_entry) + + label(loop1) + ldr(r3, [r1, 0]) + add(r2, r2, r3) + + add(r1, r1, 4) + sub(r0, r0, 1) + + label(loop_entry) + cmp(r0, 0) + bgt(loop1) + + mov(r0, r2) + +@micropython.asm_thumb +def asm_sum_bytes(r0, r1): + + # r0 = len + # r1 = ptr + # r2 = sum + # r3 = dummy + mov(r2, 0) + + b(loop_entry) + + label(loop1) + ldrb(r3, [r1, 0]) + add(r2, r2, r3) + + add(r1, r1, 1) + sub(r0, r0, 1) + + label(loop_entry) + cmp(r0, 0) + bgt(loop1) + + mov(r0, r2) + +import array + +b = array.array('l', (100, 200, 300, 400)) +n = asm_sum_words(len(b), b) +print(b, n) + +b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80)) +n = asm_sum_bytes(len(b), b) +print(b, n) diff --git a/py/asmthumb.c b/py/asmthumb.c index 1cd971c76..6bf6d6658 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -230,33 +230,33 @@ STATIC int get_label_dest(asm_thumb_t *as, uint label) { return as->label_offsets[label]; } -#define OP_MOVS_RLO_I8(rlo_dest, i8_src) (0x2000 | ((rlo_dest) << 8) | (i8_src)) +#define OP_FORMAT_2(op, rlo_dest, rlo_src, src_b) ((op) | ((src_b) << 6) | ((rlo_src) << 3) | (rlo_dest)) -// the i8_src value will be zero extended into the r32 register! -void asm_thumb_movs_rlo_i8(asm_thumb_t *as, uint rlo_dest, int i8_src) { +void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b) { assert(rlo_dest < REG_R8); - // movs rlo_dest, #i8_src - asm_thumb_write_op16(as, OP_MOVS_RLO_I8(rlo_dest, i8_src)); + assert(rlo_src < REG_R8); + asm_thumb_write_op16(as, OP_FORMAT_2(op, rlo_dest, rlo_src, src_b)); } -#define OP_MOVW (0xf240) -#define OP_MOVT (0xf2c0) +#define OP_FORMAT_3(op, rlo, i8) ((op) | ((rlo) << 8) | (i8)) -// if loading lo half with movw, the i16 value will be zero extended into the r32 register! -STATIC void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) { - assert(reg_dest < REG_R15); - // mov[wt] reg_dest, #i16_src - asm_thumb_write_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff)); +void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8) { + assert(rlo < REG_R8); + asm_thumb_write_op16(as, OP_FORMAT_3(op, rlo, i8)); } -// the i16_src value will be zero extended into the r32 register! -void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) { - asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i16_src); +#define OP_FORMAT_4(op, rlo_dest, rlo_src) ((op) | ((rlo_src) << 3) | (rlo_dest)) + +void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src) { + assert(rlo_dest < REG_R8); + assert(rlo_src < REG_R8); + asm_thumb_write_op16(as, OP_FORMAT_4(op, rlo_dest, rlo_src)); } -// the i16_src value will be zero extended into the r32 register! -void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) { - asm_thumb_mov_reg_i16(as, OP_MOVT, reg_dest, i16_src); +#define OP_FORMAT_9_10(op, rlo_dest, rlo_base, offset) ((op) | (((offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest)) + +void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset) { + asm_thumb_write_op16(as, OP_FORMAT_9_10(op, rlo_dest, rlo_base, offset)); } void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) { @@ -275,42 +275,24 @@ void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) { asm_thumb_write_op16(as, 0x4600 | op_lo); } -#define OP_ADD_RLO_RLO_RLO(rlo_dest, rlo_src_a, rlo_src_b) (0x1800 | ((rlo_src_b) << 6) | ((rlo_src_a) << 3) | (rlo_dest)) - -void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) { - asm_thumb_write_op16(as, OP_ADD_RLO_RLO_RLO(rlo_dest, rlo_src_a, rlo_src_b)); -} - -#define OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src) (0x1e00 | ((i3_src) << 6) | ((rlo_src) << 3) | (rlo_dest)) - -void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src) { - assert(rlo_dest < REG_R8); - assert(rlo_src < REG_R8); - asm_thumb_write_op16(as, OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src)); -} - -#define OP_CMP_REG_REG(rlo_a, rlo_b) (0x4280 | ((rlo_b) << 3) | (rlo_a)) - -void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b) { - asm_thumb_write_op16(as, OP_CMP_REG_REG(rlo_a, rlo_b)); -} - -#define OP_CMP_RLO_I8(rlo, i8) (0x2800 | ((rlo) << 8) | (i8)) +#define OP_MOVW (0xf240) +#define OP_MOVT (0xf2c0) -void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { - assert(rlo < REG_R8); - asm_thumb_write_op16(as, OP_CMP_RLO_I8(rlo, i8)); +// if loading lo half with movw, the i16 value will be zero extended into the r32 register! +STATIC void asm_thumb_mov_reg_i16(asm_thumb_t *as, uint mov_op, uint reg_dest, int i16_src) { + assert(reg_dest < REG_R15); + // mov[wt] reg_dest, #i16_src + asm_thumb_write_op32(as, mov_op | ((i16_src >> 1) & 0x0400) | ((i16_src >> 12) & 0xf), ((i16_src << 4) & 0x7000) | (reg_dest << 8) | (i16_src & 0xff)); } -#define OP_LDR_RLO_RLO_I5(rlo_dest, rlo_base, word_offset) (0x6800 | (((word_offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest)) -#define OP_STR_RLO_RLO_I5(rlo_dest, rlo_base, word_offset) (0x6000 | (((word_offset) << 6) & 0x07c0) | ((rlo_base) << 3) | (rlo_dest)) - -void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset) { - asm_thumb_write_op16(as, OP_LDR_RLO_RLO_I5(rlo_dest, rlo_base, word_offset)); +// the i16_src value will be zero extended into the r32 register! +void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) { + asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i16_src); } -void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset) { - asm_thumb_write_op16(as, OP_STR_RLO_RLO_I5(rlo_src, rlo_base, word_offset)); +// the i16_src value will be zero extended into the r32 register! +void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src) { + asm_thumb_mov_reg_i16(as, OP_MOVT, reg_dest, i16_src); } void asm_thumb_ite_ge(asm_thumb_t *as) { @@ -353,7 +335,7 @@ void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32) { void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32) { if (reg_dest < 8 && UNSIGNED_FIT8(i32)) { - asm_thumb_movs_rlo_i8(as, reg_dest, i32); + asm_thumb_mov_rlo_i8(as, reg_dest, i32); } else if (UNSIGNED_FIT16(i32)) { asm_thumb_mov_reg_i16(as, OP_MOVW, reg_dest, i32); } else { @@ -452,7 +434,7 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp asm_thumb_mov_reg_i32(as, reg_temp, (machine_uint_t)fun_ptr); asm_thumb_write_op16(as, OP_BLX(reg_temp)); } else if (1) { - asm_thumb_write_op16(as, OP_LDR_RLO_RLO_I5(reg_temp, REG_R7, fun_id)); + asm_thumb_write_op16(as, OP_FORMAT_9_10(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, REG_R7, fun_id)); asm_thumb_write_op16(as, OP_BLX(reg_temp)); } else { // use SVC diff --git a/py/asmthumb.h b/py/asmthumb.h index de376fd2c..6b4f5506b 100644 --- a/py/asmthumb.h +++ b/py/asmthumb.h @@ -58,16 +58,93 @@ void asm_thumb_label_assign(asm_thumb_t *as, uint label); // argument order follows ARM, in general dest is first // note there is a difference between movw and mov.w, and many others! -void asm_thumb_movs_rlo_i8(asm_thumb_t *as, uint rlo_dest, int i8_src); +// FORMAT 2: add/subtract + +#define ASM_THUMB_FORMAT_2_ADD (0x1800) +#define ASM_THUMB_FORMAT_2_SUB (0x1a00) +#define ASM_THUMB_FORMAT_2_REG_OPERAND (0x0000) +#define ASM_THUMB_FORMAT_2_IMM_OPERAND (0x0400) + +void asm_thumb_format_2(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src, int src_b); + +static inline void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) + { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); } +static inline void asm_thumb_add_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src) + { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_ADD | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); } +static inline void asm_thumb_sub_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) + { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_REG_OPERAND, rlo_dest, rlo_src_a, rlo_src_b); } +static inline void asm_thumb_sub_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, int i3_src) + { asm_thumb_format_2(as, ASM_THUMB_FORMAT_2_SUB | ASM_THUMB_FORMAT_2_IMM_OPERAND, rlo_dest, rlo_src_a, i3_src); } + +// FORMAT 3: move/compare/add/subtract immediate +// These instructions all do zero extension of the i8 value + +#define ASM_THUMB_FORMAT_3_MOV (0x2000) +#define ASM_THUMB_FORMAT_3_CMP (0x2800) +#define ASM_THUMB_FORMAT_3_ADD (0x3000) +#define ASM_THUMB_FORMAT_3_SUB (0x3800) + +void asm_thumb_format_3(asm_thumb_t *as, uint op, uint rlo, int i8); + +static inline void asm_thumb_mov_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_MOV, rlo, i8); } +static inline void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_CMP, rlo, i8); } +static inline void asm_thumb_add_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_ADD, rlo, i8); } +static inline void asm_thumb_sub_rlo_i8(asm_thumb_t *as, uint rlo, int i8) { asm_thumb_format_3(as, ASM_THUMB_FORMAT_3_SUB, rlo, i8); } + +// FORMAT 4: ALU operations + +#define ASM_THUMB_FORMAT_4_AND (0x4000) +#define ASM_THUMB_FORMAT_4_EOR (0x4040) +#define ASM_THUMB_FORMAT_4_LSL (0x4080) +#define ASM_THUMB_FORMAT_4_LSR (0x40c0) +#define ASM_THUMB_FORMAT_4_ASR (0x4100) +#define ASM_THUMB_FORMAT_4_ADC (0x4140) +#define ASM_THUMB_FORMAT_4_SBC (0x4180) +#define ASM_THUMB_FORMAT_4_ROR (0x41c0) +#define ASM_THUMB_FORMAT_4_TST (0x4200) +#define ASM_THUMB_FORMAT_4_NEG (0x4240) +#define ASM_THUMB_FORMAT_4_CMP (0x4280) +#define ASM_THUMB_FORMAT_4_CMN (0x42c0) +#define ASM_THUMB_FORMAT_4_ORR (0x4300) +#define ASM_THUMB_FORMAT_4_MUL (0x4340) +#define ASM_THUMB_FORMAT_4_BIC (0x4380) +#define ASM_THUMB_FORMAT_4_MVN (0x43c0) + +void asm_thumb_format_4(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_src); + +static inline void asm_thumb_cmp_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src) { asm_thumb_format_4(as, ASM_THUMB_FORMAT_4_CMP, rlo_dest, rlo_src); } + +// FORMAT 9: load/store with immediate offset +// For word transfers the offset must be aligned, and >>2 + +// FORMAT 10: load/store halfword +// The offset must be aligned, and >>1 +// The load is zero extended into the register + +#define ASM_THUMB_FORMAT_9_STR (0x6000) +#define ASM_THUMB_FORMAT_9_LDR (0x6800) +#define ASM_THUMB_FORMAT_9_WORD_TRANSFER (0x0000) +#define ASM_THUMB_FORMAT_9_BYTE_TRANSFER (0x1000) + +#define ASM_THUMB_FORMAT_10_STRH (0x8000) +#define ASM_THUMB_FORMAT_10_LDRH (0x8800) + +void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint offset); + +static inline void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset) + { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_src, rlo_base, word_offset); } +static inline void asm_thumb_strb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset) + { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_src, rlo_base, byte_offset); } +static inline void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset) + { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_dest, rlo_base, word_offset); } +static inline void asm_thumb_ldrb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset) + { asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER , rlo_dest, rlo_base, byte_offset); } + +// TODO convert these to above format style + +void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src); void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src); void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src); -void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src); -void asm_thumb_add_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b); -void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src); -void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b); -void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8); -void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset); -void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset); void asm_thumb_ite_ge(asm_thumb_t *as); void asm_thumb_b_n(asm_thumb_t *as, uint label); void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label); diff --git a/py/builtin.h b/py/builtin.h index a29844498..743f748da 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -35,6 +35,9 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj); MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_op_contains_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_op_getitem_obj); + extern const mp_obj_module_t mp_module___main__; extern const mp_obj_module_t mp_module_array; extern const mp_obj_module_t mp_module_collections; @@ -42,3 +45,4 @@ extern const mp_obj_module_t mp_module_io; extern const mp_obj_module_t mp_module_math; extern const mp_obj_module_t mp_module_micropython; extern const mp_obj_module_t mp_module_struct; +extern const mp_obj_module_t mp_module_sys; diff --git a/py/builtinevex.c b/py/builtinevex.c index fc3a60182..ae8253737 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -25,13 +25,16 @@ STATIC mp_obj_t parse_compile_execute(mp_obj_t o_in, mp_parse_input_kind_t parse // parse the string mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, parse_input_kind, &parse_error_kind); - mp_lexer_free(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error; raise exception - nlr_raise(mp_parse_make_exception(parse_error_kind)); + mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind); + mp_lexer_free(lex); + nlr_raise(exc); } + mp_lexer_free(lex); + // compile the string mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false); mp_parse_node_free(pn); diff --git a/py/builtinimport.c b/py/builtinimport.c index 697244878..3f63768ad 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -28,8 +28,6 @@ #define PATH_SEP_CHAR '/' -mp_obj_t mp_sys_path; - mp_import_stat_t stat_dir_or_file(vstr_t *path) { //printf("stat %s\n", vstr_str(path)); mp_import_stat_t stat = mp_import_stat(vstr_str(path)); @@ -48,9 +46,9 @@ mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) { // extract the list of paths uint path_num = 0; mp_obj_t *path_items; - if (mp_sys_path != MP_OBJ_NULL) { - mp_obj_list_get(mp_sys_path, &path_num, &path_items); - } +#if MICROPY_ENABLE_MOD_SYS + mp_obj_list_get(mp_sys_path, &path_num, &path_items); +#endif if (path_num == 0) { // mp_sys_path is empty, so just use the given file name @@ -100,15 +98,18 @@ void do_load(mp_obj_t module_obj, vstr_t *file) { // parse the imported script mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); - mp_lexer_free(lex); if (pn == MP_PARSE_NODE_NULL) { // parse error; clean up and raise exception + mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind); + mp_lexer_free(lex); mp_locals_set(old_locals); mp_globals_set(old_globals); - nlr_raise(mp_parse_make_exception(parse_error_kind)); + nlr_raise(exc); } + mp_lexer_free(lex); + // compile the imported script mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false); mp_parse_node_free(pn); diff --git a/py/builtintables.c b/py/builtintables.c index e2007f3b4..8edc69987 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -126,7 +126,7 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = { #if MICROPY_ENABLE_MOD_IO { MP_OBJ_NEW_QSTR(MP_QSTR_io), (mp_obj_t)&mp_module_io }, #endif - { MP_OBJ_NEW_QSTR(MP_QSTR_collections), (mp_obj_t)&mp_module_collections }, + { MP_OBJ_NEW_QSTR(MP_QSTR__collections), (mp_obj_t)&mp_module_collections }, #if MICROPY_ENABLE_MOD_STRUCT { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_struct }, #endif @@ -134,6 +134,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = { #if MICROPY_ENABLE_FLOAT { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&mp_module_math }, #endif +#if MICROPY_ENABLE_MOD_SYS + { MP_OBJ_NEW_QSTR(MP_QSTR_sys), (mp_obj_t)&mp_module_sys }, +#endif // extra builtin modules as defined by a port MICROPY_EXTRA_BUILTIN_MODULES diff --git a/py/compile.c b/py/compile.c index f397501f1..7a3d810f9 100644 --- a/py/compile.c +++ b/py/compile.c @@ -10,11 +10,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" -#include "scope.h" #include "runtime0.h" -#include "emit.h" -#include "emitglue.h" #include "obj.h" +#include "emitglue.h" +#include "scope.h" +#include "emit.h" #include "compile.h" #include "runtime.h" #include "builtin.h" @@ -283,7 +283,7 @@ STATIC void compile_decrease_except_level(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, comp->source_file, mp_emit_glue_get_unique_code_id(), emit_options); + scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options); scope->parent = comp->scope_cur; scope->next = NULL; if (comp->scope_head == NULL) { @@ -3454,7 +3454,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is #endif // !MICROPY_EMIT_CPYTHON // free the scopes - uint unique_code_id = module_scope->unique_code_id; + mp_raw_code_t *outer_raw_code = module_scope->raw_code; for (scope_t *s = module_scope; s;) { scope_t *next = s->next; scope_free(s); @@ -3471,12 +3471,11 @@ mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, uint emit_opt, bool is } else { #if MICROPY_EMIT_CPYTHON // can't create code, so just return true - (void)unique_code_id; // to suppress warning that unique_code_id is unused + (void)outer_raw_code; // to suppress warning that outer_raw_code is unused return mp_const_true; #else // return function that executes the outer module - // we can free the unique_code slot because no-one has reference to this unique_code_id anymore - return mp_make_function_from_id_and_free(unique_code_id, MP_OBJ_NULL, MP_OBJ_NULL); + return mp_make_function_from_raw_code(outer_raw_code, MP_OBJ_NULL, MP_OBJ_NULL); #endif } } diff --git a/py/emitbc.c b/py/emitbc.c index d1d59ef4a..2d71d8685 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -9,10 +9,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" -#include "emitglue.h" #include "bc0.h" struct _emit_t { @@ -65,6 +66,10 @@ STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_writ } } +STATIC void emit_align_code_info_to_machine_word(emit_t* emit) { + emit->code_info_offset = (emit->code_info_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1)); +} + STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) { byte* c = emit_get_cur_to_write_code_info(emit, 4); // TODO variable length encoding for qstr @@ -98,6 +103,10 @@ STATIC byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_writ } } +STATIC void emit_align_byte_code_to_machine_word(emit_t* emit) { + emit->byte_code_offset = (emit->byte_code_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1)); +} + STATIC void emit_write_byte_code_byte(emit_t* emit, byte b1) { byte* c = emit_get_cur_to_write_byte_code(emit, 1); c[0] = b1; @@ -158,6 +167,14 @@ STATIC void emit_write_byte_code_byte_uint(emit_t* emit, byte b, uint num) { emit_write_byte_code_uint(emit, num); } +// aligns the pointer so it is friendly to GC +STATIC void emit_write_byte_code_byte_ptr(emit_t* emit, byte b, void *ptr) { + emit_write_byte_code_byte(emit, b); + emit_align_byte_code_to_machine_word(emit); + machine_uint_t *c = (machine_uint_t*)emit_get_cur_to_write_byte_code(emit, sizeof(machine_uint_t)); + *c = (machine_uint_t)ptr; +} + /* currently unused STATIC void emit_write_byte_code_byte_uint_uint(emit_t* emit, byte b, uint num1, uint num2) { emit_write_byte_code_byte(emit, b); @@ -178,7 +195,7 @@ STATIC void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, uint } else { byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3; } - byte* c = emit_get_cur_to_write_byte_code(emit, 3); + byte *c = emit_get_cur_to_write_byte_code(emit, 3); c[0] = b1; c[1] = byte_code_offset; c[2] = byte_code_offset >> 8; @@ -269,19 +286,20 @@ STATIC void emit_bc_end_pass(emit_t *emit) { } emit_write_code_info_bytes_lines(emit, 0, 0); // end of line number info + emit_align_code_info_to_machine_word(emit); // align so that following byte_code is aligned if (emit->pass == PASS_2) { // calculate size of code in bytes emit->code_info_size = emit->code_info_offset; emit->byte_code_size = emit->byte_code_offset; - emit->code_base = m_new(byte, emit->code_info_size + emit->byte_code_size); + emit->code_base = m_new0(byte, emit->code_info_size + emit->byte_code_size); } else if (emit->pass == PASS_3) { qstr *arg_names = m_new(qstr, emit->scope->num_params); for (int i = 0; i < emit->scope->num_params; i++) { arg_names[i] = emit->scope->id_info[i].qstr; } - mp_emit_glue_assign_byte_code(emit->scope->unique_code_id, emit->code_base, + mp_emit_glue_assign_byte_code(emit->scope->raw_code, emit->code_base, emit->code_info_size + emit->byte_code_size, emit->scope->num_params, emit->scope->num_locals, emit->scope->scope_flags, arg_names); @@ -733,7 +751,7 @@ STATIC void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) { STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_bc_pre(emit, 1); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION, scope->raw_code); } else { if (n_pos_defaults == 0) { // load dummy entry for non-existent positional default tuple @@ -744,14 +762,14 @@ STATIC void emit_bc_make_function(emit_t *emit, scope_t *scope, uint n_pos_defau emit_bc_load_null(emit); } emit_bc_pre(emit, -1); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_FUNCTION_DEFARGS, scope->raw_code); } } STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) { if (n_pos_defaults == 0 && n_kw_defaults == 0) { emit_bc_pre(emit, 0); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE, scope->raw_code); } else { if (n_pos_defaults == 0) { // load dummy entry for non-existent positional default tuple @@ -763,7 +781,7 @@ STATIC void emit_bc_make_closure(emit_t *emit, scope_t *scope, uint n_pos_defaul emit_bc_rot_two(emit); } emit_bc_pre(emit, -2); - emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->unique_code_id); + emit_write_byte_code_byte_ptr(emit, MP_BC_MAKE_CLOSURE_DEFARGS, scope->raw_code); } } diff --git a/py/emitcommon.c b/py/emitcommon.c index 044ec3463..62d8bd18a 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -7,8 +7,10 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" -#include "scope.h" #include "runtime0.h" +#include "obj.h" +#include "emitglue.h" +#include "scope.h" #include "emit.h" #define EMIT(fun, ...) (emit_method_table->fun(emit, __VA_ARGS__)) diff --git a/py/emitcpy.c b/py/emitcpy.c index 5866d474e..010219d12 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -9,6 +9,8 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" diff --git a/py/emitglue.c b/py/emitglue.c index bcc9b2cca..ce296f432 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -23,46 +23,11 @@ #define DEBUG_OP_printf(...) (void)0 #endif -typedef enum { - MP_CODE_UNUSED, - MP_CODE_RESERVED, - MP_CODE_BYTE, - MP_CODE_NATIVE, - MP_CODE_INLINE_ASM, -} mp_code_kind_t; - -typedef struct _mp_code_t { - mp_code_kind_t kind : 8; - uint scope_flags : 8; - uint n_args : 16; - union { - struct { - byte *code; - uint len; - } u_byte; - struct { - mp_fun_t fun; - } u_native; - struct { - void *fun; - } u_inline_asm; - }; - qstr *arg_names; -} mp_code_t; - -STATIC machine_uint_t unique_codes_alloc = 0; -STATIC machine_uint_t unique_codes_total = 0; // always >= unique_codes_alloc -STATIC mp_code_t *unique_codes = NULL; - #ifdef WRITE_CODE FILE *fp_write_code = NULL; #endif void mp_emit_glue_init(void) { - unique_codes_alloc = 0; - unique_codes_total = 0; - unique_codes = NULL; - #ifdef WRITE_CODE fp_write_code = fopen("out-code", "wb"); #endif @@ -74,50 +39,24 @@ void mp_emit_glue_deinit(void) { fclose(fp_write_code); } #endif - - m_del(mp_code_t, unique_codes, unique_codes_alloc); -} - -uint mp_emit_glue_get_unique_code_id(void) { - // look for an existing unused slot - for (uint i = 0; i < unique_codes_alloc; i++) { - if (unique_codes[i].kind == MP_CODE_UNUSED) { - unique_codes[i].kind = MP_CODE_RESERVED; - return i; - } - } - // no existing slot - // return next available id, memory will be allocated later - return unique_codes_total++; } -STATIC void mp_emit_glue_alloc_unique_codes(void) { - if (unique_codes_total > unique_codes_alloc) { - DEBUG_printf("allocate more unique codes: " UINT_FMT " -> %u\n", unique_codes_alloc, unique_codes_total); - // increase size of unique_codes table (all new entries are already reserved) - unique_codes = m_renew(mp_code_t, unique_codes, unique_codes_alloc, unique_codes_total); - for (uint i = unique_codes_alloc; i < unique_codes_total; i++) { - unique_codes[i].kind = MP_CODE_RESERVED; - } - unique_codes_alloc = unique_codes_total; - } +mp_raw_code_t *mp_emit_glue_new_raw_code(void) { + mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1); + rc->kind = MP_CODE_RESERVED; + return rc; } -void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) { - mp_emit_glue_alloc_unique_codes(); - - assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED); - unique_codes[unique_code_id].kind = MP_CODE_BYTE; - unique_codes[unique_code_id].scope_flags = scope_flags; - unique_codes[unique_code_id].n_args = n_args; - unique_codes[unique_code_id].u_byte.code = code; - unique_codes[unique_code_id].u_byte.len = len; - unique_codes[unique_code_id].arg_names = arg_names; - - //printf("byte code: %d bytes\n", len); +void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names) { + rc->kind = MP_CODE_BYTE; + rc->scope_flags = scope_flags; + rc->n_args = n_args; + rc->u_byte.code = code; + rc->u_byte.len = len; + rc->arg_names = arg_names; #ifdef DEBUG_PRINT - DEBUG_printf("assign byte code: id=%d code=%p len=%u n_args=%d n_locals=%d\n", unique_code_id, code, len, n_args, n_locals); + DEBUG_printf("assign byte code: code=%p len=%u n_args=%d n_locals=%d\n", code, len, n_args, n_locals); for (int i = 0; i < 128 && i < len; i++) { if (i > 0 && i % 16 == 0) { DEBUG_printf("\n"); @@ -131,19 +70,14 @@ void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, in #endif } -void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, int n_args) { - mp_emit_glue_alloc_unique_codes(); - - assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED); - unique_codes[unique_code_id].kind = MP_CODE_NATIVE; - unique_codes[unique_code_id].scope_flags = 0; - unique_codes[unique_code_id].n_args = n_args; - unique_codes[unique_code_id].u_native.fun = fun; - - //printf("native code: %d bytes\n", len); +void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) { + rc->kind = MP_CODE_NATIVE; + rc->scope_flags = 0; + rc->n_args = n_args; + rc->u_native.fun = fun; #ifdef DEBUG_PRINT - DEBUG_printf("assign native code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args); + DEBUG_printf("assign native code: fun=%p len=%u n_args=%d\n", fun, len, n_args); byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code for (int i = 0; i < 128 && i < len; i++) { if (i > 0 && i % 16 == 0) { @@ -162,17 +96,14 @@ void mp_emit_glue_assign_native_code(uint unique_code_id, void *fun, uint len, i #endif } -void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint len, int n_args) { - mp_emit_glue_alloc_unique_codes(); - - assert(unique_code_id < unique_codes_alloc && unique_codes[unique_code_id].kind == MP_CODE_RESERVED); - unique_codes[unique_code_id].kind = MP_CODE_INLINE_ASM; - unique_codes[unique_code_id].scope_flags = 0; - unique_codes[unique_code_id].n_args = n_args; - unique_codes[unique_code_id].u_inline_asm.fun = fun; +void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *fun, uint len, int n_args) { + rc->kind = MP_CODE_INLINE_ASM; + rc->scope_flags = 0; + rc->n_args = n_args; + rc->u_inline_asm.fun = fun; #ifdef DEBUG_PRINT - DEBUG_printf("assign inline asm code: id=%d fun=%p len=%u n_args=%d\n", unique_code_id, fun, len, n_args); + DEBUG_printf("assign inline asm code: fun=%p len=%u n_args=%d\n", fun, len, n_args); byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code for (int i = 0; i < 128 && i < len; i++) { if (i > 0 && i % 16 == 0) { @@ -191,12 +122,9 @@ void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *fun, uint le #endif } -mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) { - DEBUG_OP_printf("make_function_from_id %d\n", unique_code_id); - if (unique_code_id >= unique_codes_total) { - // illegal code id - return mp_const_none; - } +mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) { + DEBUG_OP_printf("make_function_from_raw_code %p\n", rc); + assert(rc != NULL); // def_args must be MP_OBJ_NULL or a tuple assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple)); @@ -204,49 +132,36 @@ mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj // TODO implement default kw args assert(def_kw_args == MP_OBJ_NULL); - // make the function, depending on the code kind - mp_code_t *c = &unique_codes[unique_code_id]; + // make the function, depending on the raw code kind mp_obj_t fun; - switch (c->kind) { + switch (rc->kind) { case MP_CODE_BYTE: - fun = mp_obj_new_fun_bc(c->scope_flags, c->arg_names, c->n_args, def_args, c->u_byte.code); + fun = mp_obj_new_fun_bc(rc->scope_flags, rc->arg_names, rc->n_args, def_args, rc->u_byte.code); break; case MP_CODE_NATIVE: - fun = mp_make_function_n(c->n_args, c->u_native.fun); + fun = mp_make_function_n(rc->n_args, rc->u_native.fun); break; case MP_CODE_INLINE_ASM: - fun = mp_obj_new_fun_asm(c->n_args, c->u_inline_asm.fun); + fun = mp_obj_new_fun_asm(rc->n_args, rc->u_inline_asm.fun); break; default: - // code id was never assigned (this should not happen) + // raw code was never set (this should not happen) assert(0); return mp_const_none; } // check for generator functions and if so wrap in generator object - if ((c->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { + if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { fun = mp_obj_new_gen_wrap(fun); } return fun; } -mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args) { - mp_obj_t f = mp_make_function_from_id(unique_code_id, def_args, def_kw_args); - - // in some cases we can free the unique_code slot - // any dynamically allocated memory is now owned by the fun object - mp_code_t *c = &unique_codes[unique_code_id]; - memset(c, 0, sizeof *c); // make sure all pointers are zeroed - c->kind = MP_CODE_UNUSED; - - return f; -} - -mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) { - DEBUG_OP_printf("make_closure_from_id %d\n", unique_code_id); +mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args) { + DEBUG_OP_printf("make_closure_from_raw_code %p\n", rc); // make function object - mp_obj_t ffun = mp_make_function_from_id(unique_code_id, def_args, def_kw_args); + mp_obj_t ffun = mp_make_function_from_raw_code(rc, def_args, def_kw_args); // wrap function in closure object return mp_obj_new_closure(ffun, closure_tuple); } diff --git a/py/emitglue.h b/py/emitglue.h index 8f69951c2..2f9960bfa 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -1,8 +1,40 @@ // These variables and functions glue the code emitters to the runtime. +typedef enum { + MP_CODE_UNUSED, + MP_CODE_RESERVED, + MP_CODE_BYTE, + MP_CODE_NATIVE, + MP_CODE_INLINE_ASM, +} mp_raw_code_kind_t; + +typedef struct _mp_code_t { + mp_raw_code_kind_t kind : 8; + uint scope_flags : 8; + uint n_args : 16; + union { + struct { + byte *code; + uint len; + } u_byte; + struct { + mp_fun_t fun; + } u_native; + struct { + void *fun; + } u_inline_asm; + }; + qstr *arg_names; +} mp_raw_code_t; + void mp_emit_glue_init(void); void mp_emit_glue_deinit(void); -uint mp_emit_glue_get_unique_code_id(void); -void mp_emit_glue_assign_byte_code(uint unique_code_id, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names); -void mp_emit_glue_assign_native_code(uint unique_code_id, void *f, uint len, int n_args); -void mp_emit_glue_assign_inline_asm_code(uint unique_code_id, void *f, uint len, int n_args); + +mp_raw_code_t *mp_emit_glue_new_raw_code(void); + +void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, int n_args, int n_locals, uint scope_flags, qstr *arg_names); +void mp_emit_glue_assign_native_code(mp_raw_code_t *rc, void *f, uint len, int n_args); +void mp_emit_glue_assign_inline_asm_code(mp_raw_code_t *rc, void *f, uint len, int n_args); + +mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args); +mp_obj_t mp_make_closure_from_raw_code(mp_raw_code_t *rc, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args); diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 58aeed1f6..812e702af 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -9,14 +9,23 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" -#include "emitglue.h" #include "asmthumb.h" #if MICROPY_EMIT_INLINE_THUMB +typedef enum { + PN_none = 0, +#define DEF_RULE(rule, comp, kind, ...) PN_##rule, +#include "grammar.h" +#undef DEF_RULE + PN_maximum_number_of, +} pn_kind_t; + struct _emit_inline_asm_t { uint16_t pass; uint16_t success; @@ -64,7 +73,7 @@ STATIC bool emit_inline_thumb_end_pass(emit_inline_asm_t *emit) { if (emit->pass == PASS_3) { void *f = asm_thumb_get_code(emit->as); - mp_emit_glue_assign_inline_asm_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); + mp_emit_glue_assign_inline_asm_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); } return emit->success; @@ -120,15 +129,15 @@ STATIC const reg_name_t reg_name_table[] = { {15, "pc\0"}, }; -STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *pn_args, uint wanted_arg_num, uint max_reg) { - if (MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) { - qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); +STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint max_reg) { + if (MP_PARSE_NODE_IS_ID(pn)) { + qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn); const char *reg_str = qstr_str(reg_qstr); for (uint i = 0; i < sizeof(reg_name_table) / sizeof(reg_name_table[0]); i++) { const reg_name_t *r = ®_name_table[i]; if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) { if (r->reg > max_reg) { - emit_inline_thumb_error(emit, "'%s' expects at most r%d in position %d\n", op, max_reg, wanted_arg_num); + emit_inline_thumb_error(emit, "'%s' expects at most r%d\n", op, max_reg); return 0; } else { return r->reg; @@ -136,16 +145,16 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t } } } - emit_inline_thumb_error(emit, "'%s' expects a register in position %d\n", op, wanted_arg_num); + emit_inline_thumb_error(emit, "'%s' expects a register\n", op); return 0; } -STATIC int get_arg_i(emit_inline_asm_t *emit, const char *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])) { - emit_inline_thumb_error(emit, "'%s' expects an integer in position %d\n", op, wanted_arg_num); +STATIC int get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int fit_mask) { + if (!MP_PARSE_NODE_IS_SMALL_INT(pn)) { + emit_inline_thumb_error(emit, "'%s' expects an integer\n", op); return 0; } - int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn_args[wanted_arg_num]); + int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn); if ((i & (~fit_mask)) != 0) { emit_inline_thumb_error(emit, "'%s' integer 0x%x does not fit in mask 0x%x\n", op, i, fit_mask); return 0; @@ -153,12 +162,34 @@ STATIC int get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *p return i; } -STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *pn_args, int wanted_arg_num) { - if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) { - emit_inline_thumb_error(emit, "'%s' expects a label in position %d\n", op, wanted_arg_num); +STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) { + if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_bracket)) { + goto bad_arg; + } + mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; + if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) { + goto bad_arg; + } + pns = (mp_parse_node_struct_t*)pns->nodes[0]; + if (MP_PARSE_NODE_STRUCT_NUM_NODES(pns) != 2) { + goto bad_arg; + } + + *pn_base = pns->nodes[0]; + *pn_offset = pns->nodes[1]; + return true; + +bad_arg: + emit_inline_thumb_error(emit, "'%s' expects an address of the form [a, b]\n", op); + return false; +} + +STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { + if (!MP_PARSE_NODE_IS_ID(pn)) { + emit_inline_thumb_error(emit, "'%s' expects a label\n", op); return 0; } - qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]); + qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn); for (int i = 0; i < emit->max_num_labels; i++) { if (emit->label_lookup[i] == label_qstr) { return i; @@ -212,7 +243,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m } else if (n_args == 1) { if (strcmp(op_str, "b") == 0) { - int label_num = get_arg_label(emit, op_str, pn_args, 0); + int label_num = get_arg_label(emit, op_str, pn_args[0]); // TODO check that this succeeded, ie branch was within range asm_thumb_b_n(emit->as, label_num); } else if (op_str[0] == 'b' && op_len == 3) { @@ -225,7 +256,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m if (cc == -1) { goto unknown_op; } - int label_num = get_arg_label(emit, op_str, pn_args, 0); + int label_num = get_arg_label(emit, op_str, pn_args[0]); // TODO check that this succeeded, ie branch was within range asm_thumb_bcc_n(emit->as, cc, label_num); } else { @@ -233,59 +264,131 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m } } else if (n_args == 2) { - if (strcmp(op_str, "mov") == 0) { - uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7); - uint rlo_src = get_arg_reg(emit, op_str, pn_args, 1, 7); - asm_thumb_mov_reg_reg(emit->as, rlo_dest, rlo_src); - } else if (strcmp(op_str, "movs") == 0) { - uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7); - int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xff); - asm_thumb_movs_rlo_i8(emit->as, rlo_dest, i_src); - } else if (strcmp(op_str, "movw") == 0) { - uint reg_dest = get_arg_reg(emit, op_str, pn_args, 0, 15); - int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xffff); - asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src); - } else if (strcmp(op_str, "movt") == 0) { - uint reg_dest = get_arg_reg(emit, op_str, pn_args, 0, 15); - int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xffff); - asm_thumb_movt_reg_i16(emit->as, reg_dest, i_src); - } else if (strcmp(op_str, "movwt") == 0) { - // this is a convenience instruction - // we clear the MSB since it might be set from extracting the small int value - uint reg_dest = get_arg_reg(emit, op_str, pn_args, 0, 15); - int i_src = get_arg_i(emit, op_str, pn_args, 1, 0xffffffff); - asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src & 0xffff); - asm_thumb_movt_reg_i16(emit->as, reg_dest, (i_src >> 16) & 0x7fff); - } else if (strcmp(op_str, "cmp") == 0) { - uint rlo = get_arg_reg(emit, op_str, pn_args, 0, 7); - int i8 = get_arg_i(emit, op_str, pn_args, 1, 0xff); - asm_thumb_cmp_rlo_i8(emit->as, rlo, i8); + if (MP_PARSE_NODE_IS_ID(pn_args[1])) { + // second arg is a register (or should be) + uint op_code; + if (strcmp(op_str, "mov") == 0) { + uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); + uint reg_src = get_arg_reg(emit, op_str, pn_args[1], 15); + asm_thumb_mov_reg_reg(emit->as, reg_dest, reg_src); + } else if (strcmp(op_str, "and") == 0) { + op_code = ASM_THUMB_FORMAT_4_AND; + uint reg_dest, reg_src; + op_format_4: + reg_dest = get_arg_reg(emit, op_str, pn_args[0], 7); + reg_src = get_arg_reg(emit, op_str, pn_args[1], 7); + asm_thumb_format_4(emit->as, op_code, reg_dest, reg_src); + // TODO probably uses less ROM if these ops are in a lookup table + } else if (strcmp(op_str, "and") == 0) { op_code = ASM_THUMB_FORMAT_4_AND; goto op_format_4; + } else if (strcmp(op_str, "eor") == 0) { op_code = ASM_THUMB_FORMAT_4_EOR; goto op_format_4; + } else if (strcmp(op_str, "lsl") == 0) { op_code = ASM_THUMB_FORMAT_4_LSL; goto op_format_4; + } else if (strcmp(op_str, "lsr") == 0) { op_code = ASM_THUMB_FORMAT_4_LSR; goto op_format_4; + } else if (strcmp(op_str, "asr") == 0) { op_code = ASM_THUMB_FORMAT_4_ASR; goto op_format_4; + } else if (strcmp(op_str, "adc") == 0) { op_code = ASM_THUMB_FORMAT_4_ADC; goto op_format_4; + } else if (strcmp(op_str, "sbc") == 0) { op_code = ASM_THUMB_FORMAT_4_SBC; goto op_format_4; + } else if (strcmp(op_str, "ror") == 0) { op_code = ASM_THUMB_FORMAT_4_ROR; goto op_format_4; + } else if (strcmp(op_str, "tst") == 0) { op_code = ASM_THUMB_FORMAT_4_TST; goto op_format_4; + } else if (strcmp(op_str, "neg") == 0) { op_code = ASM_THUMB_FORMAT_4_NEG; goto op_format_4; + } else if (strcmp(op_str, "cmp") == 0) { op_code = ASM_THUMB_FORMAT_4_CMP; goto op_format_4; + } else if (strcmp(op_str, "cmn") == 0) { op_code = ASM_THUMB_FORMAT_4_CMN; goto op_format_4; + } else if (strcmp(op_str, "orr") == 0) { op_code = ASM_THUMB_FORMAT_4_ORR; goto op_format_4; + } else if (strcmp(op_str, "mul") == 0) { op_code = ASM_THUMB_FORMAT_4_MUL; goto op_format_4; + } else if (strcmp(op_str, "bic") == 0) { op_code = ASM_THUMB_FORMAT_4_BIC; goto op_format_4; + } else if (strcmp(op_str, "mvn") == 0) { op_code = ASM_THUMB_FORMAT_4_MVN; goto op_format_4; + } else { + goto unknown_op; + } } else { - goto unknown_op; + // second arg is not a register + uint op_code; + if (strcmp(op_str, "mov") == 0) { + op_code = ASM_THUMB_FORMAT_3_MOV; + uint rlo_dest, i8_src; + op_format_3: + rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); + i8_src = get_arg_i(emit, op_str, pn_args[1], 0xff); + asm_thumb_format_3(emit->as, op_code, rlo_dest, i8_src); + } else if (strcmp(op_str, "cmp") == 0) { + op_code = ASM_THUMB_FORMAT_3_CMP; + goto op_format_3; + } else if (strcmp(op_str, "add") == 0) { + op_code = ASM_THUMB_FORMAT_3_ADD; + goto op_format_3; + } else if (strcmp(op_str, "sub") == 0) { + op_code = ASM_THUMB_FORMAT_3_SUB; + goto op_format_3; + } else if (strcmp(op_str, "movw") == 0) { + uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); + int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff); + asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src); + } else if (strcmp(op_str, "movt") == 0) { + uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); + int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffff); + asm_thumb_movt_reg_i16(emit->as, reg_dest, i_src); + } else if (strcmp(op_str, "movwt") == 0) { + // this is a convenience instruction + // we clear the MSB since it might be set from extracting the small int value + uint reg_dest = get_arg_reg(emit, op_str, pn_args[0], 15); + int i_src = get_arg_i(emit, op_str, pn_args[1], 0xffffffff); + asm_thumb_movw_reg_i16(emit->as, reg_dest, i_src & 0xffff); + asm_thumb_movt_reg_i16(emit->as, reg_dest, (i_src >> 16) & 0x7fff); + } else if (strcmp(op_str, "ldr") == 0) { + op_code = ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER; + uint rlo_dest, rlo_base, i5; + mp_parse_node_t pn_base, pn_offset; + op_format_9_10: + rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); + if (get_arg_addr(emit, op_str, pn_args[1], &pn_base, &pn_offset)) { + rlo_base = get_arg_reg(emit, op_str, pn_base, 7); + if (op_code & ASM_THUMB_FORMAT_9_BYTE_TRANSFER) { + i5 = get_arg_i(emit, op_str, pn_offset, 0x1f); + } else if (op_code & ASM_THUMB_FORMAT_10_STRH) { // also catches LDRH + i5 = get_arg_i(emit, op_str, pn_offset, 0x3e) >> 1; + } else { + i5 = get_arg_i(emit, op_str, pn_offset, 0x7c) >> 2; + } + asm_thumb_format_9_10(emit->as, op_code, rlo_dest, rlo_base, i5); + } + } else if (strcmp(op_str, "ldrb") == 0) { + op_code = ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER; + goto op_format_9_10; + } else if (strcmp(op_str, "ldrh") == 0) { + op_code = ASM_THUMB_FORMAT_10_LDRH; + goto op_format_9_10; + } else if (strcmp(op_str, "str") == 0) { + op_code = ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER; + goto op_format_9_10; + } else if (strcmp(op_str, "strb") == 0) { + op_code = ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER; + goto op_format_9_10; + } else if (strcmp(op_str, "strh") == 0) { + op_code = ASM_THUMB_FORMAT_10_STRH; + goto op_format_9_10; + } else { + goto unknown_op; + } } } else if (n_args == 3) { + uint op_code; if (strcmp(op_str, "add") == 0) { - uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7); - uint rlo_src_a = get_arg_reg(emit, op_str, pn_args, 1, 7); - uint rlo_src_b = get_arg_reg(emit, op_str, pn_args, 2, 7); - asm_thumb_add_rlo_rlo_rlo(emit->as, rlo_dest, rlo_src_a, rlo_src_b); - } else if (strcmp(op_str, "subs") == 0) { - uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7); - uint rlo_src = get_arg_reg(emit, op_str, pn_args, 1, 7); - int i3_src = get_arg_i(emit, op_str, pn_args, 2, 0x7); - asm_thumb_subs_rlo_rlo_i3(emit->as, rlo_dest, rlo_src, i3_src); - } else if (strcmp(op_str, "ldr") == 0) { - // TODO maybe use ldr(rd, [rb, 4]) syntax? - uint rlo_dest = get_arg_reg(emit, op_str, pn_args, 0, 7); - uint rlo_base = get_arg_reg(emit, op_str, pn_args, 1, 7); - int i5 = get_arg_i(emit, op_str, pn_args, 2, 0x7c); - asm_thumb_ldr_rlo_rlo_i5(emit->as, rlo_dest, rlo_base, i5 >> 2); - } else if (strcmp(op_str, "str") == 0) { - uint rlo_src = get_arg_reg(emit, op_str, pn_args, 0, 7); - uint rlo_base = get_arg_reg(emit, op_str, pn_args, 1, 7); - int i5 = get_arg_i(emit, op_str, pn_args, 2, 0x7c); - asm_thumb_str_rlo_rlo_i5(emit->as, rlo_src, rlo_base, i5 >> 2); + op_code = ASM_THUMB_FORMAT_2_ADD; + uint rlo_dest, rlo_src; + op_format_2: + rlo_dest = get_arg_reg(emit, op_str, pn_args[0], 7); + rlo_src = get_arg_reg(emit, op_str, pn_args[1], 7); + int src_b; + if (MP_PARSE_NODE_IS_ID(pn_args[2])) { + op_code |= ASM_THUMB_FORMAT_2_REG_OPERAND; + src_b = get_arg_reg(emit, op_str, pn_args[2], 7); + } else { + op_code |= ASM_THUMB_FORMAT_2_IMM_OPERAND; + src_b = get_arg_i(emit, op_str, pn_args[2], 0x7); + } + asm_thumb_format_2(emit->as, op_code, rlo_dest, rlo_src, src_b); + } else if (strcmp(op_str, "sub") == 0) { + op_code = ASM_THUMB_FORMAT_2_SUB; + goto op_format_2; } else { goto unknown_op; } diff --git a/py/emitnative.c b/py/emitnative.c index 29da5b8c9..3046aef4d 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -27,11 +27,11 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" -#include "emitglue.h" -#include "obj.h" #include "runtime.h" #if 0 // print debugging info @@ -283,10 +283,10 @@ STATIC void emit_native_end_pass(emit_t *emit) { if (emit->pass == PASS_3) { #if N_X64 void *f = asm_x64_get_code(emit->as); - mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_x64_get_code_size(emit->as), emit->scope->num_params); + mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_x64_get_code_size(emit->as), emit->scope->num_params); #elif N_THUMB void *f = asm_thumb_get_code(emit->as); - mp_emit_glue_assign_native_code(emit->scope->unique_code_id, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); + mp_emit_glue_assign_native_code(emit->scope->raw_code, f, asm_thumb_get_code_size(emit->as), emit->scope->num_params); #endif } } @@ -1020,7 +1020,7 @@ STATIC void emit_native_for_iter(emit_t *emit, uint label) { asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1); asm_x64_jcc_label(emit->as, JCC_JE, label); #elif N_THUMB - asm_thumb_cmp_reg_reg(emit->as, REG_RET, REG_TEMP1); + asm_thumb_cmp_rlo_rlo(emit->as, REG_RET, REG_TEMP1); asm_thumb_bcc_label(emit->as, THUMB_CC_EQ, label); #endif emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); @@ -1067,10 +1067,10 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { asm_x64_cmp_r64_with_r64(emit->as, REG_ARG_3, REG_ARG_2); asm_x64_setcc_r8(emit->as, JCC_JL, REG_RET); #elif N_THUMB - asm_thumb_cmp_reg_reg(emit->as, REG_ARG_2, REG_ARG_3); + asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, REG_ARG_3); asm_thumb_ite_ge(emit->as); - asm_thumb_movs_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1 - asm_thumb_movs_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1 + asm_thumb_mov_rlo_i8(emit->as, REG_RET, 0); // if r0 >= r1 + asm_thumb_mov_rlo_i8(emit->as, REG_RET, 1); // if r0 < r1 #endif emit_post_push_reg(emit, VTYPE_BOOL, REG_RET); } else { @@ -1188,7 +1188,9 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_d // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them assert(n_pos_defaults == 0 && n_kw_defaults == 0); emit_native_pre(emit); - emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_ID, mp_make_function_from_id, scope->unique_code_id, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); + assert(0); + // TODO we need to store the raw_code ptr aligned within the code for the GC + emit_call_with_3_imm_args(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } diff --git a/py/emitpass1.c b/py/emitpass1.c index ad86588e2..01156bfbe 100644 --- a/py/emitpass1.c +++ b/py/emitpass1.c @@ -7,6 +7,8 @@ #include "qstr.h" #include "lexer.h" #include "parse.h" +#include "obj.h" +#include "emitglue.h" #include "scope.h" #include "runtime0.h" #include "emit.h" diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 81b003545..e0917b336 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -10,6 +10,7 @@ if platform.python_version_tuple()[0] == '2': from htmlentitydefs import codepoint2name elif platform.python_version_tuple()[0] == '3': from html.entities import codepoint2name +codepoint2name[ord('-')] = 'hyphen'; # add some custom names to map characters that aren't in HTML codepoint2name[ord('.')] = 'dot' @@ -23,10 +24,17 @@ def compute_hash(qstr): hash = (hash * 33) ^ ord(char) return hash & 0xffff +# given a list of (name,regex) pairs, find the first one that matches the given line +def re_match(regexs, line): + for name, regex in regexs: + match = re.match(regex, line) + if match: + return name, match + return None, None + def do_work(infiles): # read the qstrs in from the input files qstrs = {} - cpp_header_blocks = 3 for infile in infiles: with open(infile, 'rt') as f: line_number = 0 @@ -34,23 +42,19 @@ def do_work(infiles): line_number += 1 line = line.strip() - # ignore blank lines and comments - if len(line) == 0 or line.startswith('//'): + # ignore blank lines, comments and preprocessor directives + if len(line) == 0 or line.startswith('//') or line.startswith('#'): continue - # We'll have 3 line-number lines for py/qstrdefs.h - initial, leaving it to - # go into other headers, and returning to it. - if line.startswith('# ') and 'py/qstrdefs.h' in line: - cpp_header_blocks -= 1 - continue - if cpp_header_blocks != 0: - continue - - # verify line is of the correct form - match = re.match(r'Q\((.+)\)$', line) - if not match: + # work out what kind of line it is + match_kind, match = re_match([('qstr', r'Q\((.+)\)$'), ('cdecl', r'(typedef|extern) [A-Za-z0-9_* ]+;$')], line) + if match_kind is None: + # unknown line format print('({}:{}) bad qstr format, got {}'.format(infile, line_number, line), file=sys.stderr) return False + elif match_kind != 'qstr': + # not a line with a qstr + continue # get the qstr value qstr = match.group(1) diff --git a/py/modcollections.c b/py/modcollections.c index dbd1896f2..11845a00c 100644 --- a/py/modcollections.c +++ b/py/modcollections.c @@ -5,7 +5,7 @@ #include "builtin.h" STATIC const mp_map_elem_t mp_module_collections_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_collections) }, + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR__collections) }, { MP_OBJ_NEW_QSTR(MP_QSTR_namedtuple), (mp_obj_t)&mp_namedtuple_obj }, }; @@ -22,6 +22,6 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = { const mp_obj_module_t mp_module_collections = { .base = { &mp_type_module }, - .name = MP_QSTR_collections, + .name = MP_QSTR__collections, .globals = (mp_obj_dict_t*)&mp_module_collections_globals, }; diff --git a/py/modsys.c b/py/modsys.c new file mode 100644 index 000000000..59539b3b9 --- /dev/null +++ b/py/modsys.c @@ -0,0 +1,50 @@ +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "builtin.h" +#include "runtime.h" +#include "objlist.h" + +#if MICROPY_ENABLE_MOD_SYS + +// These should be implemented by ports, specific types don't matter, +// only addresses. +struct _dummy_t; +extern struct _dummy_t mp_sys_stdin_obj; +extern struct _dummy_t mp_sys_stdout_obj; +extern struct _dummy_t mp_sys_stderr_obj; + +mp_obj_list_t mp_sys_path_obj; +mp_obj_list_t mp_sys_argv_obj; + +STATIC const mp_map_elem_t mp_module_sys_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_sys) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_path), (mp_obj_t)&mp_sys_path_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_argv), (mp_obj_t)&mp_sys_argv_obj }, + +#if MICROPY_MOD_SYS_STDFILES + { MP_OBJ_NEW_QSTR(MP_QSTR_stdin), (mp_obj_t)&mp_sys_stdin_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_stdout), (mp_obj_t)&mp_sys_stdout_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_stderr), (mp_obj_t)&mp_sys_stderr_obj }, +#endif +}; + +STATIC const mp_obj_dict_t mp_module_sys_globals = { + .base = {&mp_type_dict}, + .map = { + .all_keys_are_qstrs = 1, + .table_is_fixed_array = 1, + .used = sizeof(mp_module_sys_globals_table) / sizeof(mp_map_elem_t), + .alloc = sizeof(mp_module_sys_globals_table) / sizeof(mp_map_elem_t), + .table = (mp_map_elem_t*)mp_module_sys_globals_table, + }, +}; + +const mp_obj_module_t mp_module_sys = { + .base = { &mp_type_module }, + .name = MP_QSTR_sys, + .globals = (mp_obj_dict_t*)&mp_module_sys_globals, +}; + +#endif diff --git a/py/mpconfig.h b/py/mpconfig.h index 2c118b4bb..cbe18b409 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -120,6 +120,15 @@ typedef double mp_float_t; #define MICROPY_ENABLE_MOD_STRUCT (1) #endif +// Whether to provide "sys" module +#ifndef MICROPY_ENABLE_MOD_SYS +#define MICROPY_ENABLE_MOD_SYS (1) +#endif + +#ifndef MICROPY_MOD_SYS_STDFILES +#define MICROPY_MOD_SYS_STDFILES (0) +#endif + // Whether to support slice object and correspondingly // slice subscript operators #ifndef MICROPY_ENABLE_SLICE @@ -110,7 +110,7 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) { return 1; // needs to hash to same as the integer 1, since True==1 } else if (MP_OBJ_IS_SMALL_INT(o_in)) { return MP_OBJ_SMALL_INT_VALUE(o_in); - } else if (MP_OBJ_IS_STR(o_in)) { + } else if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) { return mp_obj_str_get_hash(o_in); } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_NoneType)) { return (machine_int_t)o_in; @@ -333,11 +333,11 @@ mp_obj_t mp_identity(mp_obj_t self) { MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); bool mp_get_buffer(mp_obj_t obj, buffer_info_t *bufinfo) { - mp_obj_base_t *o = (mp_obj_base_t *)obj; - if (o->type->buffer_p.get_buffer == NULL) { + mp_obj_type_t *type = mp_obj_get_type(obj); + if (type->buffer_p.get_buffer == NULL) { return false; } - o->type->buffer_p.get_buffer(o, bufinfo, BUFFER_READ); + type->buffer_p.get_buffer(obj, bufinfo, BUFFER_READ); if (bufinfo->buf == NULL) { return false; } @@ -454,6 +454,8 @@ machine_int_t mp_obj_tuple_hash(mp_obj_t self_in); mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args); // list +struct _mp_obj_list_t; +void mp_obj_list_init(struct _mp_obj_list_t *o, uint n); mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items); void mp_obj_list_set_len(mp_obj_t self_in, uint len); diff --git a/py/objdict.c b/py/objdict.c index 8bdd0026a..2c56540d1 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -10,6 +10,7 @@ #include "objtuple.h" #include "runtime0.h" #include "runtime.h" +#include "builtin.h" STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur); STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in); @@ -137,12 +138,6 @@ STATIC bool dict_store_item(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { return true; } -STATIC mp_obj_t dict_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) { - return dict_binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in); -} - -STATIC MP_DEFINE_CONST_FUN_OBJ_2(dict_getitem_obj, dict_getitem); - /******************************************************************************/ /* dict iterator */ @@ -501,7 +496,7 @@ STATIC const mp_map_elem_t dict_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_setdefault), (mp_obj_t)&dict_setdefault_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&dict_update_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_values), (mp_obj_t)&dict_values_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&dict_getitem_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR___getitem__), (mp_obj_t)&mp_op_getitem_obj }, }; STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); diff --git a/py/objfun.c b/py/objfun.c index dd4b7347c..8fadbc611 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -229,7 +229,8 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o if (n_args > self->n_args) { // given more than enough arguments if (!self->takes_var_args) { - goto arg_error; + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, + "function takes %d positional arguments but %d were given", self->n_args, n_args)); } // put extra arguments in varargs tuple *extra_args = mp_obj_new_tuple(n_args - self->n_args, args + self->n_args); @@ -249,7 +250,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o extra_args -= self->n_args - n_args; n_extra_args += self->n_args - n_args; } else { - goto arg_error; + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, + "function takes at least %d positional arguments but %d were given", + self->n_args - self->n_def_args, n_args)); } } } @@ -344,9 +347,6 @@ continue2:; } else { // MP_VM_RETURN_EXCEPTION nlr_raise(result); } - -arg_error: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes %d positional arguments but %d were given", self->n_args, n_args)); } const mp_obj_type_t mp_type_fun_bc = { @@ -422,26 +422,36 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { // pointer to the string (it's probably constant though!) uint l; return (machine_uint_t)mp_obj_str_get_data(obj, &l); + } else { + mp_obj_type_t *type = mp_obj_get_type(obj); + if (0) { #if MICROPY_ENABLE_FLOAT - } else if (MP_OBJ_IS_TYPE(obj, &mp_type_float)) { - // convert float to int (could also pass in float registers) - return (machine_int_t)mp_obj_float_get(obj); + } else if (type == &mp_type_float) { + // convert float to int (could also pass in float registers) + return (machine_int_t)mp_obj_float_get(obj); #endif - } else if (MP_OBJ_IS_TYPE(obj, &mp_type_tuple)) { - // pointer to start of tuple (could pass length, but then could use len(x) for that) - uint len; - mp_obj_t *items; - mp_obj_tuple_get(obj, &len, &items); - return (machine_uint_t)items; - } else if (MP_OBJ_IS_TYPE(obj, &mp_type_list)) { - // pointer to start of list (could pass length, but then could use len(x) for that) - uint len; - mp_obj_t *items; - mp_obj_list_get(obj, &len, &items); - return (machine_uint_t)items; - } else { - // just pass along a pointer to the object - return (machine_uint_t)obj; + } else if (type == &mp_type_tuple) { + // pointer to start of tuple (could pass length, but then could use len(x) for that) + uint len; + mp_obj_t *items; + mp_obj_tuple_get(obj, &len, &items); + return (machine_uint_t)items; + } else if (type == &mp_type_list) { + // pointer to start of list (could pass length, but then could use len(x) for that) + uint len; + mp_obj_t *items; + mp_obj_list_get(obj, &len, &items); + return (machine_uint_t)items; + } else { + buffer_info_t bufinfo; + if (mp_get_buffer(obj, &bufinfo)) { + // supports the buffer protocol, return a pointer to the data + return (machine_uint_t)bufinfo.buf; + } else { + // just pass along a pointer to the object + return (machine_uint_t)obj; + } + } } } diff --git a/py/objint.c b/py/objint.c index 69954168d..2eabff8d4 100644 --- a/py/objint.c +++ b/py/objint.c @@ -265,18 +265,27 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_ return MP_OBJ_NULL; } +// this is a classmethod STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) { + // TODO: Support long ints + // TODO: Support byteorder param (assumes 'little' at the moment) + // TODO: Support signed param (assumes signed=False at the moment) + + // get the buffer info buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo); + mp_get_buffer_raise(args[1], &bufinfo); - assert(bufinfo.len >= sizeof(machine_int_t)); - // TODO: Support long ints - // TODO: Support byteorder param - // TODO: Support signed param - return mp_obj_new_int_from_uint(*(machine_uint_t*)bufinfo.buf); + // convert the bytes to an integer + machine_uint_t value = 0; + for (const byte* buf = bufinfo.buf + bufinfo.len - 1; buf >= (byte*)bufinfo.buf; buf--) { + value = (value << 8) | *buf; + } + + return mp_obj_new_int_from_uint(value); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_obj, 1, 3, int_from_bytes); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 3, int_from_bytes); +STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, (const mp_obj_t)&int_from_bytes_fun_obj); STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) { machine_int_t val = mp_obj_int_get_checked(args[0]); diff --git a/py/objlist.c b/py/objlist.c index 531e4b85b..fa7d2bc1c 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -8,13 +8,7 @@ #include "obj.h" #include "runtime0.h" #include "runtime.h" - -typedef struct _mp_obj_list_t { - mp_obj_base_t base; - machine_uint_t alloc; - machine_uint_t len; - mp_obj_t *items; -} mp_obj_list_t; +#include "objlist.h" STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur); STATIC mp_obj_list_t *list_new(uint n); @@ -39,6 +33,15 @@ STATIC void list_print(void (*print)(void *env, const char *fmt, ...), void *env print(env, "]"); } +STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { + mp_obj_t iter = mp_getiter(iterable); + mp_obj_t item; + while ((item = mp_iternext(iter)) != MP_OBJ_NULL) { + mp_obj_list_append(list, item); + } + return list; +} + STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { // TODO check n_kw == 0 @@ -50,13 +53,9 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp case 1: { // make list from iterable - mp_obj_t iterable = mp_getiter(args[0]); + // TODO: optimize list/tuple mp_obj_t list = mp_obj_new_list(0, NULL); - mp_obj_t item; - while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) { - mp_obj_list_append(list, item); - } - return list; + return list_extend_from_iter(list, args[0]); } default: @@ -173,18 +172,21 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); - assert(MP_OBJ_IS_TYPE(arg_in, &mp_type_list)); - mp_obj_list_t *self = self_in; - mp_obj_list_t *arg = arg_in; + if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) { + mp_obj_list_t *self = self_in; + mp_obj_list_t *arg = arg_in; + + if (self->len + arg->len > self->alloc) { + // TODO: use alloc policy for "4" + self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); + self->alloc = self->len + arg->len + 4; + } - if (self->len + arg->len > self->alloc) { - // TODO: use alloc policy for "4" - self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4); - self->alloc = self->len + arg->len + 4; + memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); + self->len += arg->len; + } else { + list_extend_from_iter(self_in, arg_in); } - - memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len); - self->len += arg->len; return mp_const_none; // return None, as per CPython } @@ -363,12 +365,16 @@ const mp_obj_type_t mp_type_list = { .locals_dict = (mp_obj_t)&list_locals_dict, }; -STATIC mp_obj_list_t *list_new(uint n) { - mp_obj_list_t *o = m_new_obj(mp_obj_list_t); +void mp_obj_list_init(mp_obj_list_t *o, uint n) { o->base.type = &mp_type_list; o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n; o->len = n; o->items = m_new(mp_obj_t, o->alloc); +} + +STATIC mp_obj_list_t *list_new(uint n) { + mp_obj_list_t *o = m_new_obj(mp_obj_list_t); + mp_obj_list_init(o, n); return o; } diff --git a/py/objlist.h b/py/objlist.h new file mode 100644 index 000000000..cc8d7de26 --- /dev/null +++ b/py/objlist.h @@ -0,0 +1,6 @@ +typedef struct _mp_obj_list_t { + mp_obj_base_t base; + machine_uint_t alloc; + machine_uint_t len; + mp_obj_t *items; +} mp_obj_list_t; diff --git a/py/objset.c b/py/objset.c index 05d064a04..bdc8d7f38 100644 --- a/py/objset.c +++ b/py/objset.c @@ -9,6 +9,7 @@ #include "obj.h" #include "runtime.h" #include "runtime0.h" +#include "builtin.h" typedef struct _mp_obj_set_t { mp_obj_base_t base; @@ -445,6 +446,7 @@ STATIC const mp_map_elem_t set_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR___contains__), (mp_obj_t)&mp_op_contains_obj }, }; STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); diff --git a/py/objstr.c b/py/objstr.c index e55a2edd5..d933fa5e3 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -1298,6 +1298,34 @@ STATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) { return str_partitioner(self_in, arg, -1); } +#if MICROPY_CPYTHON_COMPAT +// These methods are superfluous in the presense of str() and bytes() +// constructors. +// TODO: should accept kwargs too +STATIC mp_obj_t bytes_decode(uint n_args, const mp_obj_t *args) { + mp_obj_t new_args[2]; + if (n_args == 1) { + new_args[0] = args[0]; + new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8); + args = new_args; + n_args++; + } + return str_make_new(NULL, n_args, 0, args); +} + +// TODO: should accept kwargs too +STATIC mp_obj_t str_encode(uint n_args, const mp_obj_t *args) { + mp_obj_t new_args[2]; + if (n_args == 1) { + new_args[0] = args[0]; + new_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_utf_hyphen_8); + args = new_args; + n_args++; + } + return bytes_make_new(NULL, n_args, 0, args); +} +#endif + STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, int flags) { if (flags == BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); @@ -1312,6 +1340,10 @@ STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, in } } +#if MICROPY_CPYTHON_COMPAT +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode); +#endif STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index); @@ -1327,6 +1359,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition); STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition); STATIC const mp_map_elem_t str_locals_dict_table[] = { +#if MICROPY_CPYTHON_COMPAT + { MP_OBJ_NEW_QSTR(MP_QSTR_decode), (mp_obj_t)&bytes_decode_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj }, +#endif { MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&str_index_obj }, @@ -1444,7 +1480,8 @@ STATIC void bad_implicit_conversion(mp_obj_t self_in) { } uint mp_obj_str_get_hash(mp_obj_t self_in) { - if (MP_OBJ_IS_STR(self_in)) { + // TODO: This has too big overhead for hash accessor + if (MP_OBJ_IS_STR(self_in) || MP_OBJ_IS_TYPE(self_in, &mp_type_bytes)) { GET_STR_HASH(self_in, h); return h; } else { diff --git a/py/opmethods.c b/py/opmethods.c new file mode 100644 index 000000000..af2524cf2 --- /dev/null +++ b/py/opmethods.c @@ -0,0 +1,20 @@ +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "runtime0.h" +#include "builtin.h" + +STATIC mp_obj_t op_getitem(mp_obj_t lhs_in, mp_obj_t rhs_in) { + mp_obj_type_t *type = mp_obj_get_type(lhs_in); + return type->binary_op(MP_BINARY_OP_SUBSCR, lhs_in, rhs_in); +} +MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); + +STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { + mp_obj_type_t *type = mp_obj_get_type(lhs_in); + return type->binary_op(MP_BINARY_OP_IN, lhs_in, rhs_in); +} +MP_DEFINE_CONST_FUN_OBJ_2(mp_op_contains_obj, op_contains); diff --git a/py/parsehelper.c b/py/parsehelper.c index e069657b1..d467399a1 100644 --- a/py/parsehelper.c +++ b/py/parsehelper.c @@ -38,20 +38,30 @@ void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_ } } -mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind) { - // TODO add source file and line number to exception? +mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) { + // make exception object + mp_obj_t exc; switch (parse_error_kind) { case MP_PARSE_ERROR_MEMORY: - return mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY); + exc = mp_obj_new_exception_msg(&mp_type_MemoryError, STR_MEMORY); + break; case MP_PARSE_ERROR_UNEXPECTED_INDENT: - return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT); + exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNEXPECTED_INDENT); + break; case MP_PARSE_ERROR_UNMATCHED_UNINDENT: - return mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT); + exc = mp_obj_new_exception_msg(&mp_type_IndentationError, STR_UNMATCHED_UNINDENT); + break; case MP_PARSE_ERROR_INVALID_SYNTAX: default: - return mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX); + exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, STR_INVALID_SYNTAX); + break; } + + // add traceback to give info about file name and location + mp_obj_exception_add_traceback(exc, mp_lexer_source_name(lex), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column); + + return exc; } diff --git a/py/parsehelper.h b/py/parsehelper.h index 1de70d19d..b8f8c106d 100644 --- a/py/parsehelper.h +++ b/py/parsehelper.h @@ -1,2 +1,2 @@ void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind); -mp_obj_t mp_parse_make_exception(mp_parse_error_kind_t parse_error_kind); +mp_obj_t mp_parse_make_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind); @@ -69,6 +69,7 @@ PY_O_BASENAME = \ objtuple.o \ objtype.o \ objzip.o \ + opmethods.o \ sequence.o \ stream.o \ binary.o \ @@ -82,6 +83,7 @@ PY_O_BASENAME = \ modmath.o \ modmicropython.o \ modstruct.o \ + modsys.o \ vm.o \ showbc.o \ repl.o \ diff --git a/py/qstrdefs.h b/py/qstrdefs.h index d52b870e6..b332e22fa 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -17,6 +17,7 @@ Q(__path__) Q(__repl_print__) Q(__bool__) +Q(__contains__) Q(__enter__) Q(__exit__) Q(__len__) @@ -90,7 +91,7 @@ Q(calcsize) #endif Q(chr) Q(classmethod) -Q(collections) +Q(_collections) Q(complex) Q(dict) Q(dir) @@ -263,3 +264,16 @@ Q(<setcomp>) Q(<genexpr>) Q(<string>) Q(<stdin>) + +#if MICROPY_CPYTHON_COMPAT +Q(encode) +Q(decode) +Q(utf-8) +#endif + +#if MICROPY_ENABLE_MOD_SYS +Q(argv) +Q(stdin) +Q(stdout) +Q(stderr) +#endif diff --git a/py/runtime.c b/py/runtime.c index 053367e3f..a507f97f3 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -53,17 +53,6 @@ void mp_init(void) { // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New()) dict_locals = dict_globals = &dict_main; - -#if MICROPY_CPYTHON_COMPAT - // Precreate sys module, so "import sys" didn't throw exceptions. - mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys); - // Avoid warning of unused var - (void)m_sys; -#endif - // init sys.path - // for efficiency, left to platform-specific startup code - //mp_sys_path = mp_obj_new_list(0, NULL); - //mp_store_attr(m_sys, MP_QSTR_path, mp_sys_path); } void mp_deinit(void) { @@ -1143,7 +1132,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = { mp_obj_dict_store, mp_obj_new_set, mp_obj_set_store, - mp_make_function_from_id, + mp_make_function_from_raw_code, mp_call_function_n_kw_for_native, mp_call_method_n_kw, mp_getiter, diff --git a/py/runtime.h b/py/runtime.h index 867d63352..1d60181e7 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -29,12 +29,9 @@ mp_obj_t mp_load_const_dec(qstr qstr); mp_obj_t mp_load_const_str(qstr qstr); mp_obj_t mp_load_const_bytes(qstr qstr); -mp_obj_t mp_make_function_from_id(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args); -mp_obj_t mp_make_function_from_id_and_free(uint unique_code_id, mp_obj_t def_args, mp_obj_t def_kw_args); mp_obj_t mp_make_function_n(int n_args, void *fun); // fun must have the correct signature for n_args fixed arguments mp_obj_t mp_make_function_var(int n_args_min, mp_fun_var_t fun); mp_obj_t mp_make_function_var_between(int n_args_min, int n_args_max, mp_fun_var_t fun); // min and max are inclusive -mp_obj_t mp_make_closure_from_id(uint unique_code_id, mp_obj_t closure_tuple, mp_obj_t def_args, mp_obj_t def_kw_args); mp_obj_t mp_call_function_0(mp_obj_t fun); mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg); @@ -60,8 +57,12 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th mp_obj_t mp_make_raise_obj(mp_obj_t o); -extern mp_obj_t mp_sys_path; mp_map_t *mp_loaded_modules_get(void); mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level); mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); + +extern struct _mp_obj_list_t mp_sys_path_obj; +extern struct _mp_obj_list_t mp_sys_argv_obj; +#define mp_sys_path ((mp_obj_t)&mp_sys_path_obj) +#define mp_sys_argv ((mp_obj_t)&mp_sys_argv_obj) diff --git a/py/runtime0.h b/py/runtime0.h index 6ee70aa01..eef370679 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -86,7 +86,7 @@ typedef enum { MP_F_STORE_MAP, MP_F_BUILD_SET, MP_F_STORE_SET, - MP_F_MAKE_FUNCTION_FROM_ID, + MP_F_MAKE_FUNCTION_FROM_RAW_CODE, MP_F_CALL_FUNCTION_N_KW_FOR_NATIVE, MP_F_CALL_METHOD_N_KW, MP_F_GETITER, diff --git a/py/scope.c b/py/scope.c index 51701727e..391ad5da8 100644 --- a/py/scope.c +++ b/py/scope.c @@ -6,10 +6,12 @@ #include "misc.h" #include "mpconfig.h" #include "qstr.h" +#include "obj.h" #include "parse.h" +#include "emitglue.h" #include "scope.h" -scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options) { +scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options) { scope_t *scope = m_new0(scope_t, 1); scope->kind = kind; scope->pn = pn; @@ -41,7 +43,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint default: assert(0); } - scope->unique_code_id = unique_code_id; + scope->raw_code = mp_emit_glue_new_raw_code(); scope->emit_options = emit_options; scope->id_info_alloc = 8; scope->id_info = m_new(id_info_t, scope->id_info_alloc); diff --git a/py/scope.h b/py/scope.h index 07b41fe72..6e0990ea9 100644 --- a/py/scope.h +++ b/py/scope.h @@ -29,7 +29,7 @@ typedef struct _scope_t { mp_parse_node_t pn; qstr source_file; qstr simple_name; - uint unique_code_id; + mp_raw_code_t *raw_code; uint8_t scope_flags; // see runtime0.h uint8_t emit_options; // see compile.h uint16_t num_params; @@ -41,7 +41,7 @@ typedef struct _scope_t { id_info_t *id_info; } scope_t; -scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint unique_code_id, uint emit_options); +scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint emit_options); void scope_free(scope_t *scope); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added); id_info_t *scope_find(scope_t *scope, qstr qstr); diff --git a/py/showbc.c b/py/showbc.c index 615d1fe0d..25b1b2ffb 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -22,6 +22,11 @@ qstr = (qstr << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ } +#define DECODE_PTR do { \ + ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \ + unum = *(machine_uint_t*)ip; \ + ip += sizeof(machine_uint_t); \ +} while (0) void mp_byte_code_print(const byte *ip, int len) { const byte *ip_start = ip; @@ -389,22 +394,22 @@ void mp_byte_code_print(const byte *ip, int len) { break; case MP_BC_MAKE_FUNCTION: - DECODE_UINT; + DECODE_PTR; printf("MAKE_FUNCTION " UINT_FMT, unum); break; case MP_BC_MAKE_FUNCTION_DEFARGS: - DECODE_UINT; + DECODE_PTR; printf("MAKE_FUNCTION_DEFARGS " UINT_FMT, unum); break; case MP_BC_MAKE_CLOSURE: - DECODE_UINT; + DECODE_PTR; printf("MAKE_CLOSURE " UINT_FMT, unum); break; case MP_BC_MAKE_CLOSURE_DEFARGS: - DECODE_UINT; + DECODE_PTR; printf("MAKE_CLOSURE_DEFARGS " UINT_FMT, unum); break; @@ -7,6 +7,7 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "emitglue.h" #include "runtime.h" #include "bc0.h" #include "bc.h" @@ -29,20 +30,25 @@ typedef enum { UNWIND_JUMP, } mp_unwind_reason_t; -#define DECODE_UINT { \ +#define DECODE_UINT do { \ unum = 0; \ do { \ unum = (unum << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ -} +} while (0) #define DECODE_ULABEL do { unum = (ip[0] | (ip[1] << 8)); ip += 2; } while (0) #define DECODE_SLABEL do { unum = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2; } while (0) -#define DECODE_QSTR { \ +#define DECODE_QSTR do { \ qst = 0; \ do { \ qst = (qst << 7) + (*ip & 0x7f); \ } while ((*ip++ & 0x80) != 0); \ -} +} while (0) +#define DECODE_PTR do { \ + ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \ + unum = *(machine_uint_t*)ip; \ + ip += sizeof(machine_uint_t); \ +} while (0) #define PUSH(val) *++sp = (val) #define POP() (*sp--) #define TOP() (*sp) @@ -704,29 +710,29 @@ unwind_jump: break; case MP_BC_MAKE_FUNCTION: - DECODE_UINT; - PUSH(mp_make_function_from_id(unum, MP_OBJ_NULL, MP_OBJ_NULL)); + DECODE_PTR; + PUSH(mp_make_function_from_raw_code((mp_raw_code_t*)unum, MP_OBJ_NULL, MP_OBJ_NULL)); break; case MP_BC_MAKE_FUNCTION_DEFARGS: - DECODE_UINT; + DECODE_PTR; // Stack layout: def_tuple def_dict <- TOS obj1 = POP(); - SET_TOP(mp_make_function_from_id(unum, TOP(), obj1)); + SET_TOP(mp_make_function_from_raw_code((mp_raw_code_t*)unum, TOP(), obj1)); break; case MP_BC_MAKE_CLOSURE: - DECODE_UINT; + DECODE_PTR; // Stack layout: closure_tuple <- TOS - SET_TOP(mp_make_closure_from_id(unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL)); + SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, TOP(), MP_OBJ_NULL, MP_OBJ_NULL)); break; case MP_BC_MAKE_CLOSURE_DEFARGS: - DECODE_UINT; + DECODE_PTR; // Stack layout: def_tuple def_dict closure_tuple <- TOS obj1 = POP(); obj2 = POP(); - SET_TOP(mp_make_closure_from_id(unum, obj1, TOP(), obj2)); + SET_TOP(mp_make_closure_from_raw_code((mp_raw_code_t*)unum, obj1, TOP(), obj2)); break; case MP_BC_CALL_FUNCTION: diff --git a/stm/main.c b/stm/main.c index 636f90021..d7f2624c3 100644 --- a/stm/main.c +++ b/stm/main.c @@ -239,11 +239,10 @@ soft_reset: // Micro Python init qstr_init(); mp_init(); - mp_obj_t def_path[3]; - def_path[0] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_); - def_path[1] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_src); - def_path[2] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib); - mp_sys_path = mp_obj_new_list(3, def_path); + mp_obj_list_init(mp_sys_path, 0); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib)); + mp_obj_list_init(mp_sys_argv, 0); exti_init(); diff --git a/stmhal/dac.c b/stmhal/dac.c index 22622d474..5e809412e 100644 --- a/stmhal/dac.c +++ b/stmhal/dac.c @@ -180,12 +180,8 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { // set TIM6 to trigger the DAC at the given frequency TIM6_Config(mp_obj_get_int(args[2])); - mp_obj_type_t *type = mp_obj_get_type(args[1]); - if (type->buffer_p.get_buffer == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "buffer argument must support buffer protocol")); - } buffer_info_t bufinfo; - type->buffer_p.get_buffer(args[1], &bufinfo, BUFFER_READ); + mp_get_buffer_raise(args[1], &bufinfo); __DMA1_CLK_ENABLE(); diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 9528a3c3c..65bc3600e 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -143,16 +143,13 @@ STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args) { machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1; machine_uint_t mem_addr = mp_obj_get_int(args[2]); HAL_StatusTypeDef status; - mp_obj_type_t *type = mp_obj_get_type(args[3]); - if (type->buffer_p.get_buffer != NULL) { - buffer_info_t bufinfo; - type->buffer_p.get_buffer(args[3], &bufinfo, BUFFER_READ); - status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, 200); - } else if (MP_OBJ_IS_INT(args[3])) { + if (MP_OBJ_IS_INT(args[3])) { uint8_t data[1] = {mp_obj_get_int(args[3])}; status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, 1, 200); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "data argument must be an integer or support the buffer protocol")); + buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo); + status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, 200); } //printf("Write got %d\n", status); diff --git a/stmhal/main.c b/stmhal/main.c index 29c704b10..2f40f140a 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -263,10 +263,10 @@ soft_reset: // Micro Python init qstr_init(); mp_init(); - mp_obj_t def_path[2]; - def_path[0] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_); - def_path[1] = MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib); - mp_sys_path = mp_obj_new_list(2, def_path); + mp_obj_list_init(mp_sys_path, 0); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib)); + mp_obj_list_init(mp_sys_argv, 0); readline_init(); diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index a6cb5adb6..c564a0f19 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -32,7 +32,7 @@ #include "ff.h" // get lots of info about the board -STATIC mp_obj_t pyb_info(void) { +STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) { // get and print unique id; 96 bits { byte *id = (byte*)0x1fff7a10; @@ -89,10 +89,15 @@ STATIC mp_obj_t pyb_info(void) { printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512)); } + if (n_args == 1) { + // arg given means dump gc allocation table + gc_dump_alloc_table(); + } + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_info_obj, pyb_info); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info); // sync all file systems STATIC mp_obj_t pyb_sync(void) { diff --git a/tests/basics/list1.py b/tests/basics/list1.py index 122f61d49..a0c8afc4f 100644 --- a/tests/basics/list1.py +++ b/tests/basics/list1.py @@ -13,6 +13,8 @@ print(x) x.extend([100, 200]) print(x) +x.extend(range(3)) +print(x) x += [2, 1] print(x) diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index 1e194472f..98628cc54 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -1,4 +1,7 @@ -from collections import namedtuple +try: + from collections import namedtuple +except ImportError: + from _collections import namedtuple T = namedtuple("Tup", "foo bar") # CPython prints fully qualified name, what we don't bother to do so far diff --git a/tools/pip-micropython b/tools/pip-micropython index fab880983..d5b84b0e2 100755 --- a/tools/pip-micropython +++ b/tools/pip-micropython @@ -30,6 +30,21 @@ fi # installed if it's already installed for main python distribution. if [ ! -d /tmp/pip-micropy-venv ]; then virtualenv --no-site-packages /tmp/pip-micropy-venv + # distutils, setuptools, pip are buggy and allow target packages affect + # their execution environment. For example, if distribution they install + # has re.py, they will import that instead of system re. So, we need + # to remove current dir from sys.path, but that appear to be quite uneasy + # with CPython, so we hook __import__ and exterminate it persistently. + # See also https://bitbucket.org/pypa/setuptools/issue/187/ + cat > $(ls -1d /tmp/pip-micropy-venv/lib/python*/)/sitecustomize.py <<EOF +import sys +import __builtin__ +old_imp = __import__ +def new_imp(*a, **kw): + if not sys.path[0]: sys.path.pop(0) + return old_imp(*a, **kw) +__builtin__.__import__ = new_imp +EOF fi . /tmp/pip-micropy-venv/bin/activate diff --git a/unix-cpy/mpconfigport.h b/unix-cpy/mpconfigport.h index 752df4f49..7d0e3258e 100644 --- a/unix-cpy/mpconfigport.h +++ b/unix-cpy/mpconfigport.h @@ -22,5 +22,3 @@ typedef unsigned int machine_uint_t; // must be pointer size typedef void *machine_ptr_t; // must be of pointer size typedef const void *machine_const_ptr_t; // must be of pointer size typedef double machine_float_t; - -machine_float_t machine_sqrt(machine_float_t x); diff --git a/unix/file.c b/unix/file.c index fa7be791a..a0a865a26 100644 --- a/unix/file.c +++ b/unix/file.c @@ -146,9 +146,6 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open); -void file_init() { - mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys); - mp_store_attr(m_sys, MP_QSTR_stdin, fdfile_new(STDIN_FILENO)); - mp_store_attr(m_sys, MP_QSTR_stdout, fdfile_new(STDOUT_FILENO)); - mp_store_attr(m_sys, MP_QSTR_stderr, fdfile_new(STDERR_FILENO)); -} +const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&rawfile_type}, .fd = STDIN_FILENO }; +const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&rawfile_type}, .fd = STDOUT_FILENO }; +const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&rawfile_type}, .fd = STDERR_FILENO }; diff --git a/unix/main.c b/unix/main.c index f18e40a7f..e582244b3 100644 --- a/unix/main.c +++ b/unix/main.c @@ -42,7 +42,6 @@ long heap_size = 128*1024 * (sizeof(machine_uint_t) / 4); // Stack top at the start of program void *stack_top; -void file_init(); void microsocket_init(); void time_init(); void ffi_init(); @@ -326,7 +325,7 @@ int main(int argc, char **argv) { p++; } } - mp_sys_path = mp_obj_new_list(path_num, NULL); + mp_obj_list_init(mp_sys_path, path_num); mp_obj_t *path_items; mp_obj_list_get(mp_sys_path, &path_num, &path_items); path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); @@ -348,10 +347,7 @@ int main(int argc, char **argv) { p = p1 + 1; } - mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys); - mp_store_attr(m_sys, MP_QSTR_path, mp_sys_path); - mp_obj_t py_argv = mp_obj_new_list(0, NULL); - mp_store_attr(m_sys, MP_QSTR_argv, py_argv); + mp_obj_list_init(mp_sys_argv, 0); mp_store_name(qstr_from_str("test"), test_obj_new(42)); mp_store_name(qstr_from_str("mem_info"), mp_make_function_n(0, mem_info)); @@ -360,7 +356,6 @@ int main(int argc, char **argv) { mp_store_name(qstr_from_str("gc"), (mp_obj_t)&pyb_gc_obj); #endif - file_init(); microsocket_init(); #if MICROPY_MOD_TIME time_init(); @@ -418,7 +413,7 @@ int main(int argc, char **argv) { free(basedir); for (int i = a; i < argc; i++) { - mp_obj_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); + mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); } do_file(argv[a]); executed = true; diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index e2f2a69e1..832bdb05f 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -13,6 +13,7 @@ #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_PATH_MAX (PATH_MAX) +#define MICROPY_MOD_SYS_STDFILES (1) // type definitions for the specific machine diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk index d30be8b98..bfb01a71f 100644 --- a/unix/mpconfigport.mk +++ b/unix/mpconfigport.mk @@ -7,4 +7,4 @@ MICROPY_USE_READLINE = 1 MICROPY_MOD_TIME = 1 # ffi module requires libffi (libffi-dev Debian package) -MICROPY_MOD_FFI = 0 +MICROPY_MOD_FFI = 1 diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h index a4772a2be..42f20d265 100644 --- a/unix/qstrdefsport.h +++ b/unix/qstrdefsport.h @@ -2,10 +2,6 @@ Q(Test) -Q(argv) -Q(stdin) -Q(stdout) -Q(stderr) Q(rawsocket) Q(socket) Q(sockaddr_in) |
