From 1e6337bc711d0821900076c5db13d26922ffe33f Mon Sep 17 00:00:00 2001 From: lyon Date: Tue, 29 Aug 2023 13:56:48 +0800 Subject: [PATCH] suppot REPL/NORMAL MODE for unused stack val --- port/linux/.vscode/launch.json | 2 +- port/linux/package/pikascript/main.py | 2 +- port/linux/test/pika_config_gtest.c | 8 ++ port/linux/test/test_common.h | 45 ++++++++ src/PikaObj.c | 2 +- src/PikaVM.c | 45 ++++++-- src/PikaVM.h | 8 ++ src/PikaVersion.h | 2 +- src/pika_adapter_rtt.h | 160 +++++++++++++------------- 9 files changed, 177 insertions(+), 97 deletions(-) diff --git a/port/linux/.vscode/launch.json b/port/linux/.vscode/launch.json index 62642f4ae..f8e1e9b01 100644 --- a/port/linux/.vscode/launch.json +++ b/port/linux/.vscode/launch.json @@ -12,7 +12,7 @@ // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", "args": [ // "--gtest_filter=vm.keyword_2" - "--gtest_filter=builtin.eq" + "--gtest_filter=builtin.repl_mode" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/port/linux/package/pikascript/main.py b/port/linux/package/pikascript/main.py index 8e7c1725e..1175db500 100644 --- a/port/linux/package/pikascript/main.py +++ b/port/linux/package/pikascript/main.py @@ -4,7 +4,7 @@ import pika_lua, pika_cjson, cjson_test, json import GTestTask, TempDevTest import cb_test import configparser, network, math, struct -import test_module1, test_cmodule, test_module4, import_test, test +import test_module1, test_cmodule, test_module4, import_test import hashlib, hmac, aes, base64, time, os, zlib import _thread, weakref, eventloop import this diff --git a/port/linux/test/pika_config_gtest.c b/port/linux/test/pika_config_gtest.c index cd14d8b20..7bef7a326 100644 --- a/port/linux/test/pika_config_gtest.c +++ b/port/linux/test/pika_config_gtest.c @@ -2,6 +2,7 @@ #include #include #include "dataMemory.h" +#include "PikaVM.h" char log_buff[LOG_BUFF_MAX][LOG_SIZE] = {0}; uint32_t log_index = 0; @@ -43,3 +44,10 @@ void __pks_hook_instruct(void) { g_hook_cnt++; g_hook_func(); } + +volatile pika_bool g_always_repl_mode = pika_true; +PIKA_WEAK void pika_hook_unused_stack_arg(VMState* vm, Arg* arg) { + if (vm->run_state->in_repl || g_always_repl_mode) { + arg_print(arg, pika_true, "\r\n"); + } +} diff --git a/port/linux/test/test_common.h b/port/linux/test/test_common.h index a3cfee601..6c6acceaf 100644 --- a/port/linux/test/test_common.h +++ b/port/linux/test/test_common.h @@ -54,6 +54,16 @@ static char _f_getchar(void) { pika_assert(0); return -1; } + +static char _fmem_getchar(void) { + char c = 0; + size_t n = fread(&c, 1, 1, (FILE*)_f_getchar_fp); + if (n > 0) { + return c; + } + return 0; +} + void pikaScriptShell_withGetchar(PikaObj* self, sh_getchar getchar_fn); } @@ -93,6 +103,28 @@ void pikaScriptShell_withGetchar(PikaObj* self, sh_getchar getchar_fn); EXPECT_EQ(pikaMemNow(), 0); \ } +#define TEST_RUN_LINES_REPL(_test_suite_, _test_name_, _lines_) \ + TEST(_test_suite_, _test_name_) { \ + /* init */ \ + extern volatile pika_bool g_always_repl_mode; \ + g_always_repl_mode = pika_false; \ + g_PikaMemInfo.heapUsedMax = 0; \ + PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain); \ + extern unsigned char pikaModules_py_a[]; \ + obj_linkLibrary(pikaMain, pikaModules_py_a); \ + /* run */ \ + __platform_printf("BEGIN\r\n"); \ + _f_getchar_fp = fmemopen((void*)_lines_, strlen(_lines_), "rb"); \ + pikaScriptShell_withGetchar(pikaMain, _fmem_getchar); \ + fclose((FILE*)_f_getchar_fp); \ + /* collect */ \ + /* assert */ \ + /* deinit */ \ + obj_deinit(pikaMain); \ + EXPECT_EQ(pikaMemNow(), 0); \ + g_always_repl_mode = pika_true; \ + } + #define TEST_RUN_SINGLE_FILE_ASSERT(_test_suite_, _test_name_, _file_name_, \ __expt__) \ TEST(_test_suite_, _test_name_) { \ @@ -193,6 +225,19 @@ void pikaScriptShell_withGetchar(PikaObj* self, sh_getchar getchar_fn); EXPECT_EQ(pikaMemNow(), 0); \ } +#define TEST_RUN_LINES_EXCEPT_OUTPUT2(_test_suite_, _test_name_, _lines_, \ + _except_output1_, _except_output2_) \ + TEST(_test_suite_, _test_name_) { \ + PikaObj* self = newRootObj("root", New_PikaMain); \ + extern unsigned char pikaModules_py_a[]; \ + obj_linkLibrary(self, pikaModules_py_a); \ + obj_run(self, (_lines_)); /* collect */ /* assert */ \ + EXPECT_STREQ(log_buff[0], (_except_output1_)); \ + EXPECT_STREQ(log_buff[1], (_except_output2_)); \ + obj_deinit(self); \ + EXPECT_EQ(pikaMemNow(), 0); \ + } + #if USE_GOOGLE_TEST #include "gtest/gtest.h" #define TEST_START diff --git a/src/PikaObj.c b/src/PikaObj.c index 7632b552c..96a5f1b13 100644 --- a/src/PikaObj.c +++ b/src/PikaObj.c @@ -2023,7 +2023,7 @@ static enum shellCTRL __obj_shellLineHandler_REPL(PikaObj* self, return SHELL_CTRL_EXIT; } /* run single line */ - obj_run(self, input_line); + _pikaVM_runPyLines(self, input_line, pika_true); return SHELL_CTRL_CONTINUE; } diff --git a/src/PikaVM.c b/src/PikaVM.c index 735f28e59..255ce503f 100644 --- a/src/PikaVM.c +++ b/src/PikaVM.c @@ -1160,7 +1160,8 @@ Arg* obj_runMethodArg(PikaObj* self, PikaObj* method_args_obj, Arg* method_arg) { RunState run_state = {.try_state = TRY_STATE_NONE, - .try_result = TRY_RESULT_NONE}; + .try_result = TRY_RESULT_NONE, + .in_repl = pika_false}; return obj_runMethodArgWithState(self, method_args_obj, method_arg, &run_state); } @@ -1891,7 +1892,8 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self, PikaObj* oBuiltin = NULL; arg_newReg(arg_reg1, 32); RunState tSubRunState = {.try_state = vm->run_state->try_state, - .try_result = TRY_RESULT_NONE}; + .try_result = TRY_RESULT_NONE, + .in_repl = pika_false}; pika_assert(NULL != vm->run_state); if (NULL != sRunPath) { @@ -3652,7 +3654,9 @@ static ByteCodeFrame* _cache_bcf_fn_bc(PikaObj* self, uint8_t* bytecode) { return _cache_bytecodeframe(self); } -static VMParameters* _pikaVM_runPyLines(PikaObj* self, char* py_lines) { +VMParameters* _pikaVM_runPyLines(PikaObj* self, + char* py_lines, + pika_bool in_repl) { VMParameters* globals = NULL; ByteCodeFrame bytecode_frame_stack = {0}; ByteCodeFrame* bytecode_frame_p = NULL; @@ -3678,7 +3682,7 @@ static VMParameters* _pikaVM_runPyLines(PikaObj* self, char* py_lines) { goto __exit; } /* run byteCode */ - globals = pikaVM_runByteCodeFrame(self, bytecode_frame_p); + globals = _pikaVM_runByteCodeFrame(self, bytecode_frame_p, in_repl); goto __exit; __exit: if (!is_use_heap_bytecode) { @@ -3758,12 +3762,13 @@ VMParameters* pikaVM_runSingleFile(PikaObj* self, char* filename) { } VMParameters* pikaVM_run(PikaObj* self, char* py_lines) { - return _pikaVM_runPyLines(self, py_lines); + return _pikaVM_runPyLines(self, py_lines, pika_false); } VMParameters* pikaVM_runByteCode(PikaObj* self, const uint8_t* bytecode) { RunState run_state = {.try_state = TRY_STATE_NONE, - .try_result = TRY_RESULT_NONE}; + .try_result = TRY_RESULT_NONE, + .in_repl = pika_false}; return _do_pikaVM_runByteCode(self, self, self, (uint8_t*)bytecode, &run_state, pika_true); } @@ -3805,7 +3810,8 @@ Arg* _do_pikaVM_runByteCodeReturn(PikaObj* self, VMParameters* pikaVM_runByteCodeInconstant(PikaObj* self, uint8_t* bytecode) { RunState run_state = {.try_state = TRY_STATE_NONE, - .try_result = TRY_RESULT_NONE}; + .try_result = TRY_RESULT_NONE, + .in_repl = pika_false}; return _do_pikaVM_runByteCode(self, self, self, (uint8_t*)bytecode, &run_state, pika_false); } @@ -4151,6 +4157,12 @@ void byteCodeFrame_print(ByteCodeFrame* self) { self->const_pool.size + self->instruct_array.size); } +PIKA_WEAK void pika_hook_unused_stack_arg(VMState* vm, Arg* arg) { + if (vm->run_state->in_repl) { + arg_print(arg, pika_true, "\r\n"); + } +} + void VMState_solveUnusedStack(VMState* vm) { uint8_t top = stack_getTop(&(vm->stack)); for (int i = 0; i < top; i++) { @@ -4164,7 +4176,7 @@ void VMState_solveUnusedStack(VMState* vm) { arg_deinit(arg); continue; } - arg_print(arg, pika_true, "\r\n"); + pika_hook_unused_stack_arg(vm, arg); arg_deinit(arg); } } @@ -4273,14 +4285,23 @@ static VMParameters* _pikaVM_runByteCodeFrameWithState( return result; } -VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, - ByteCodeFrame* byteCode_frame) { - RunState run_state = {.try_state = TRY_STATE_NONE, - .try_result = TRY_RESULT_NONE}; +VMParameters* _pikaVM_runByteCodeFrame(PikaObj* self, + ByteCodeFrame* byteCode_frame, + pika_bool in_repl) { + RunState run_state = { + .try_state = TRY_STATE_NONE, + .try_result = TRY_RESULT_NONE, + .in_repl = in_repl, + }; return _pikaVM_runByteCodeFrameWithState(self, self, self, byteCode_frame, 0, &run_state); } +VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, + ByteCodeFrame* byteCode_frame) { + return _pikaVM_runByteCodeFrame(self, byteCode_frame, pika_false); +} + void constPool_printAsArray(ConstPool* self) { uint8_t* const_size_str = (uint8_t*)&(self->size); pika_platform_printf("0x%02x, ", *(const_size_str)); diff --git a/src/PikaVM.h b/src/PikaVM.h index 9c0214688..221cc62fc 100644 --- a/src/PikaVM.h +++ b/src/PikaVM.h @@ -69,6 +69,7 @@ typedef struct RunState RunState; struct RunState { TRY_STATE try_state; TRY_RESULT try_result; + pika_bool in_repl; }; typedef struct VMState VMState; @@ -186,6 +187,9 @@ struct VMInstructionSet { VMParameters* pikaVM_run(PikaObj* self, char* pyLine); VMParameters* pikaVM_runAsm(PikaObj* self, char* pikaAsm); +VMParameters* _pikaVM_runByteCodeFrame(PikaObj* self, + ByteCodeFrame* byteCode_frame, + pika_bool in_repl); VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, ByteCodeFrame* byteCode_frame); @@ -386,6 +390,10 @@ typedef struct { PikaObj* lreg[PIKA_REGIST_SIZE]; } VMLocals; +VMParameters* _pikaVM_runPyLines(PikaObj* self, + char* py_lines, + pika_bool in_repl); + #endif #ifdef __cplusplus diff --git a/src/PikaVersion.h b/src/PikaVersion.h index 7965b3f3e..534161c20 100644 --- a/src/PikaVersion.h +++ b/src/PikaVersion.h @@ -2,4 +2,4 @@ #define PIKA_VERSION_MINOR 12 #define PIKA_VERSION_MICRO 5 -#define PIKA_EDIT_TIME "2023/08/17 23:33:21" +#define PIKA_EDIT_TIME "2023/08/29 13:56:27" diff --git a/src/pika_adapter_rtt.h b/src/pika_adapter_rtt.h index d09f6f196..d7e9b9cca 100644 --- a/src/pika_adapter_rtt.h +++ b/src/pika_adapter_rtt.h @@ -7,29 +7,31 @@ extern "C" { #include "PikaPlatform.h" #define __PIKA_ADAPTER_RTT_H__ -typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ -typedef int8_t rt_int8_t; /**< 8bit integer type */ -typedef int16_t rt_int16_t; /**< 16bit integer type */ -typedef int32_t rt_int32_t; /**< 32bit integer type */ -typedef uint8_t rt_uint8_t; /**< 8bit unsigned integer type */ -typedef uint16_t rt_uint16_t; /**< 16bit unsigned integer type */ -typedef uint32_t rt_uint32_t; /**< 32bit unsigned integer type */ -typedef int64_t rt_int64_t; /**< 64bit integer type */ -typedef uint64_t rt_uint64_t; /**< 64bit unsigned integer type */ -typedef size_t rt_size_t; /**< Type for size number */ -typedef ssize_t rt_ssize_t; /**< Used for a count of bytes or an error indication */ +typedef signed long + ssize_t; /* Used for a count of bytes or an error indication. */ +typedef int8_t rt_int8_t; /**< 8bit integer type */ +typedef int16_t rt_int16_t; /**< 16bit integer type */ +typedef int32_t rt_int32_t; /**< 32bit integer type */ +typedef uint8_t rt_uint8_t; /**< 8bit unsigned integer type */ +typedef uint16_t rt_uint16_t; /**< 16bit unsigned integer type */ +typedef uint32_t rt_uint32_t; /**< 32bit unsigned integer type */ +typedef int64_t rt_int64_t; /**< 64bit integer type */ +typedef uint64_t rt_uint64_t; /**< 64bit unsigned integer type */ +typedef size_t rt_size_t; /**< Type for size number */ +typedef ssize_t + rt_ssize_t; /**< Used for a count of bytes or an error indication */ /* RT-Thread basic data type definitions */ -typedef int rt_bool_t; /**< boolean type */ -typedef signed long rt_base_t; /**< Nbit CPU related date type */ -typedef unsigned long rt_ubase_t; /**< Nbit unsigned CPU related data type */ -typedef rt_base_t rt_err_t; /**< Type for error number */ -typedef rt_uint32_t rt_time_t; /**< Type for time stamp */ -typedef rt_uint32_t rt_tick_t; /**< Type for tick count */ -typedef rt_base_t rt_flag_t; /**< Type for flags */ -typedef rt_ubase_t rt_dev_t; /**< Type for device */ -typedef rt_base_t rt_off_t; /**< Type for offset */ -#define rt_inline static __inline +typedef int rt_bool_t; /**< boolean type */ +typedef signed long rt_base_t; /**< Nbit CPU related date type */ +typedef unsigned long rt_ubase_t; /**< Nbit unsigned CPU related data type */ +typedef rt_base_t rt_err_t; /**< Type for error number */ +typedef rt_uint32_t rt_time_t; /**< Type for time stamp */ +typedef rt_uint32_t rt_tick_t; /**< Type for tick count */ +typedef rt_base_t rt_flag_t; /**< Type for flags */ +typedef rt_ubase_t rt_dev_t; /**< Type for device */ +typedef rt_base_t rt_off_t; /**< Type for offset */ +#define rt_inline static __inline #define RT_NULL 0 /* boolean type definitions */ @@ -72,88 +74,84 @@ typedef rt_base_t rt_off_t; /**< Type for offset */ /** * Double List structure */ -struct rt_list_node -{ - struct rt_list_node *next; /**< point to next node. */ - struct rt_list_node *prev; /**< point to prev node. */ +struct rt_list_node { + struct rt_list_node* next; /**< point to next node. */ + struct rt_list_node* prev; /**< point to prev node. */ }; -typedef struct rt_list_node rt_list_t; /**< Type for lists. */ +typedef struct rt_list_node rt_list_t; /**< Type for lists. */ /** * Base structure of Kernel object */ -struct rt_object -{ +struct rt_object { #if RT_NAME_MAX > 0 - char name[RT_NAME_MAX]; /**< dynamic name of kernel object */ + char name[RT_NAME_MAX]; /**< dynamic name of kernel object */ #else - const char *name; /**< static name of kernel object */ -#endif /* RT_NAME_MAX > 0 */ - rt_uint8_t type; /**< type of kernel object */ - rt_uint8_t flag; /**< flag of kernel object */ - rt_list_t list; /**< list node of kernel object */ + const char* name; /**< static name of kernel object */ +#endif /* RT_NAME_MAX > 0 */ + rt_uint8_t type; /**< type of kernel object */ + rt_uint8_t flag; /**< flag of kernel object */ + rt_list_t list; /**< list node of kernel object */ }; -typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */ +typedef struct rt_object* rt_object_t; /**< Type for kernel objects. */ /** * device (I/O) class type */ -enum rt_device_class_type -{ - RT_Device_Class_Char = 0, /**< character device */ - RT_Device_Class_Block, /**< block device */ - RT_Device_Class_NetIf, /**< net interface */ - RT_Device_Class_MTD, /**< memory device */ - RT_Device_Class_CAN, /**< CAN device */ - RT_Device_Class_RTC, /**< RTC device */ - RT_Device_Class_Sound, /**< Sound device */ - RT_Device_Class_Graphic, /**< Graphic device */ - RT_Device_Class_I2CBUS, /**< I2C bus device */ - RT_Device_Class_USBDevice, /**< USB slave device */ - RT_Device_Class_USBHost, /**< USB host bus */ - RT_Device_Class_USBOTG, /**< USB OTG bus */ - RT_Device_Class_SPIBUS, /**< SPI bus device */ - RT_Device_Class_SPIDevice, /**< SPI device */ - RT_Device_Class_SDIO, /**< SDIO bus device */ - RT_Device_Class_PM, /**< PM pseudo device */ - RT_Device_Class_Pipe, /**< Pipe device */ - RT_Device_Class_Portal, /**< Portal device */ - RT_Device_Class_Timer, /**< Timer device */ - RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ - RT_Device_Class_Sensor, /**< Sensor device */ - RT_Device_Class_Touch, /**< Touch device */ - RT_Device_Class_PHY, /**< PHY device */ - RT_Device_Class_Security, /**< Security device */ - RT_Device_Class_WLAN, /**< WLAN device */ - RT_Device_Class_Pin, /**< Pin device */ - RT_Device_Class_ADC, /**< ADC device */ - RT_Device_Class_DAC, /**< DAC device */ - RT_Device_Class_WDT, /**< WDT device */ - RT_Device_Class_PWM, /**< PWM device */ - RT_Device_Class_Bus, /**< Bus device */ - RT_Device_Class_Unknown /**< unknown device */ +enum rt_device_class_type { + RT_Device_Class_Char = 0, /**< character device */ + RT_Device_Class_Block, /**< block device */ + RT_Device_Class_NetIf, /**< net interface */ + RT_Device_Class_MTD, /**< memory device */ + RT_Device_Class_CAN, /**< CAN device */ + RT_Device_Class_RTC, /**< RTC device */ + RT_Device_Class_Sound, /**< Sound device */ + RT_Device_Class_Graphic, /**< Graphic device */ + RT_Device_Class_I2CBUS, /**< I2C bus device */ + RT_Device_Class_USBDevice, /**< USB slave device */ + RT_Device_Class_USBHost, /**< USB host bus */ + RT_Device_Class_USBOTG, /**< USB OTG bus */ + RT_Device_Class_SPIBUS, /**< SPI bus device */ + RT_Device_Class_SPIDevice, /**< SPI device */ + RT_Device_Class_SDIO, /**< SDIO bus device */ + RT_Device_Class_PM, /**< PM pseudo device */ + RT_Device_Class_Pipe, /**< Pipe device */ + RT_Device_Class_Portal, /**< Portal device */ + RT_Device_Class_Timer, /**< Timer device */ + RT_Device_Class_Miscellaneous, /**< Miscellaneous device */ + RT_Device_Class_Sensor, /**< Sensor device */ + RT_Device_Class_Touch, /**< Touch device */ + RT_Device_Class_PHY, /**< PHY device */ + RT_Device_Class_Security, /**< Security device */ + RT_Device_Class_WLAN, /**< WLAN device */ + RT_Device_Class_Pin, /**< Pin device */ + RT_Device_Class_ADC, /**< ADC device */ + RT_Device_Class_DAC, /**< DAC device */ + RT_Device_Class_WDT, /**< WDT device */ + RT_Device_Class_PWM, /**< PWM device */ + RT_Device_Class_Bus, /**< Bus device */ + RT_Device_Class_Unknown /**< unknown device */ }; -typedef struct rt_device *rt_device_t; +typedef struct rt_device* rt_device_t; /** * Device structure */ -struct rt_device -{ - struct rt_object parent; /**< inherit from rt_object */ - enum rt_device_class_type type; /**< device type */ - rt_uint16_t flag; /**< device flag */ - rt_uint16_t open_flag; /**< device open flag */ +struct rt_device { + struct rt_object parent; /**< inherit from rt_object */ + enum rt_device_class_type type; /**< device type */ + rt_uint16_t flag; /**< device flag */ + rt_uint16_t open_flag; /**< device open flag */ - rt_uint8_t ref_count; /**< reference count */ - rt_uint8_t device_id; /**< 0 - 255 */ + rt_uint8_t ref_count; /**< reference count */ + rt_uint8_t device_id; /**< 0 - 255 */ /* device call back */ rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size); - rt_err_t (*tx_complete)(rt_device_t dev, void *buffer); + rt_err_t (*tx_complete)(rt_device_t dev, void* buffer); - const struct rt_device_ops *ops; - void *user_data; /**< device private data */ + const struct rt_device_ops* ops; + void* user_data; /**< device private data */ }; #endif