This commit is contained in:
xjc 2023-09-30 00:52:08 +08:00
commit acb8bdbef8
26 changed files with 597 additions and 1027 deletions

View File

@ -0,0 +1,8 @@
import PikaDebug as pdb
pdb.set_trace()
pdb.set_break('pdb_set_break', 48)
print('line 1')
print('line 2')
print('line 3')
print('line 4')
print('line 5')

View File

@ -4,3 +4,12 @@ class Debuger:
def set_trace(self): def set_trace(self):
pass pass
def set_trace():
pass
def set_break(module: str, pc_break: int):
pass
def reset_break(module: str, pc_break: int):
pass

View File

@ -1,56 +1,23 @@
#include "PikaVM.h" #include "PikaVM.h"
#include "dataStrs.h" #include "dataStrs.h"
extern volatile PikaObj* __pikaMain;
static enum shellCTRL __obj_shellLineHandler_debug(PikaObj* self,
char* input_line,
struct ShellConfig* config) {
/* continue */
if (strEqu("c", input_line)) {
return SHELL_CTRL_EXIT;
}
/* next */
if (strEqu("n", input_line)) {
return SHELL_CTRL_EXIT;
}
/* launch shell */
if (strEqu("sh", input_line)) {
/* exit pika shell */
pikaScriptShell((PikaObj*)__pikaMain);
return SHELL_CTRL_CONTINUE;
}
/* quit */
if (strEqu("q", input_line)) {
obj_setInt(self, "enable", 0);
return SHELL_CTRL_EXIT;
}
/* print */
if (strIsStartWith(input_line, "p ")) {
char* path = input_line + 2;
Arg* asm_buff = arg_newStr("B0\n1 REF ");
asm_buff = arg_strAppend(asm_buff, path);
asm_buff = arg_strAppend(asm_buff, "\n0 RUN print\n");
pikaVM_runAsm((PikaObj*)__pikaMain, arg_getStr(asm_buff));
arg_deinit(asm_buff);
return SHELL_CTRL_CONTINUE;
}
obj_run((PikaObj*)__pikaMain, input_line);
return SHELL_CTRL_CONTINUE;
}
void PikaDebug_Debuger___init__(PikaObj* self) { void PikaDebug_Debuger___init__(PikaObj* self) {
/* global enable contral */ /* global enable contral */
obj_setInt(self, "enable", 1); obj_setInt(self, "enable", 1);
} }
void PikaDebug_Debuger_set_trace(PikaObj* self) { void PikaDebug_Debuger_set_trace(PikaObj* self) {
if (!obj_getInt(self, "enable")) { pika_debug_set_trace(self);
return; }
}
struct ShellConfig cfg = { void PikaDebug_set_trace(PikaObj* self) {
.prefix = "(pika-debug) ", PikaDebug_Debuger_set_trace(self);
.handler = __obj_shellLineHandler_debug, }
.fn_getchar = __platform_getchar,
}; void PikaDebug_set_break(PikaObj* self, char* module, int pc_break) {
_do_pikaScriptShell(self, &cfg); pika_debug_set_break(module, pc_break);
}
void PikaDebug_reset_break(PikaObj* self, char* module, int pc_break) {
pika_debug_reset_break(module, pc_break);
} }

View File

@ -12,7 +12,8 @@
// "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
"args": [ "args": [
// "--gtest_filter=vm.keyword_2" // "--gtest_filter=vm.keyword_2"
"--gtest_filter=vm.exit_vm" // "--gtest_filter=compiler.find_break_point"
"--gtest_filter=pikaMain.REPL_pdb_set_break"
], ],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",

View File

@ -129,7 +129,7 @@
"editor.defaultFormatter": "tamasfe.even-better-toml" "editor.defaultFormatter": "tamasfe.even-better-toml"
}, },
"[python]": { "[python]": {
"editor.defaultFormatter": "ms-python.autopep8" "editor.defaultFormatter": "ms-python.python"
}, },
"[c]": { "[c]": {
"editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd"

View File

@ -4,3 +4,12 @@ class Debuger:
def set_trace(self): def set_trace(self):
pass pass
def set_trace():
pass
def set_break(module: str, pc_break: int):
pass
def reset_break(module: str, pc_break: int):
pass

View File

@ -1,4 +1,5 @@
import PikaStdLib, PikaStdDevice, PikaMath, PikaDebug, PikaCV, PikaNN import PikaDebug as pdb
import PikaStdLib, PikaStdDevice, PikaMath, PikaCV, PikaNN
import random, re, modbus, socket, unittest, binascii, ctypes, requests, mqtt import random, re, modbus, socket, unittest, binascii, ctypes, requests, mqtt
import pika_lua, pika_cjson, cjson_test, json import pika_lua, pika_cjson, cjson_test, json
import GTestTask, TempDevTest import GTestTask, TempDevTest

View File

@ -1,56 +1,23 @@
#include "PikaVM.h" #include "PikaVM.h"
#include "dataStrs.h" #include "dataStrs.h"
extern volatile PikaObj* __pikaMain;
static enum shellCTRL __obj_shellLineHandler_debug(PikaObj* self,
char* input_line,
struct ShellConfig* config) {
/* continue */
if (strEqu("c", input_line)) {
return SHELL_CTRL_EXIT;
}
/* next */
if (strEqu("n", input_line)) {
return SHELL_CTRL_EXIT;
}
/* launch shell */
if (strEqu("sh", input_line)) {
/* exit pika shell */
pikaScriptShell((PikaObj*)__pikaMain);
return SHELL_CTRL_CONTINUE;
}
/* quit */
if (strEqu("q", input_line)) {
obj_setInt(self, "enable", 0);
return SHELL_CTRL_EXIT;
}
/* print */
if (strIsStartWith(input_line, "p ")) {
char* path = input_line + 2;
Arg* asm_buff = arg_newStr("B0\n1 REF ");
asm_buff = arg_strAppend(asm_buff, path);
asm_buff = arg_strAppend(asm_buff, "\n0 RUN print\n");
pikaVM_runAsm((PikaObj*)__pikaMain, arg_getStr(asm_buff));
arg_deinit(asm_buff);
return SHELL_CTRL_CONTINUE;
}
obj_run((PikaObj*)__pikaMain, input_line);
return SHELL_CTRL_CONTINUE;
}
void PikaDebug_Debuger___init__(PikaObj* self) { void PikaDebug_Debuger___init__(PikaObj* self) {
/* global enable contral */ /* global enable contral */
obj_setInt(self, "enable", 1); obj_setInt(self, "enable", 1);
} }
void PikaDebug_Debuger_set_trace(PikaObj* self) { void PikaDebug_Debuger_set_trace(PikaObj* self) {
if (!obj_getInt(self, "enable")) { pika_debug_set_trace(self);
return; }
}
struct ShellConfig cfg = { void PikaDebug_set_trace(PikaObj* self) {
.prefix = "(pika-debug) ", PikaDebug_Debuger_set_trace(self);
.handler = __obj_shellLineHandler_debug, }
.fn_getchar = __platform_getchar,
}; void PikaDebug_set_break(PikaObj* self, char* module, int pc_break) {
_do_pikaScriptShell(self, &cfg); pika_debug_set_break(module, pc_break);
}
void PikaDebug_reset_break(PikaObj* self, char* module, int pc_break) {
pika_debug_reset_break(module, pc_break);
} }

View File

@ -8,7 +8,7 @@
#endif #endif
void (*global_do_sleep_ms)(uint32_t); void (*global_do_sleep_ms)(uint32_t);
extern volatile VMSignal g_PikaVMSignal; extern volatile VMState g_PikaVMState;
volatile int g_pika_local_timezone = 8; volatile int g_pika_local_timezone = 8;
static void _do_sleep_ms_tick(uint32_t ms) { static void _do_sleep_ms_tick(uint32_t ms) {

View File

@ -1,806 +0,0 @@
#include "test_common.h"
TEST_START
TEST(compiler, file) {
char* lines =
"len = calls.len()\n"
"mode = 'none'\n"
"info_index = 0\n"
"for i in range(0, len):\n"
" if len == 0:\n"
" break\n"
" if info_index == 0:\n"
" mode = calls[i]\n"
" info_index = 1\n"
" elif info_index == 1:\n"
" if mode == 'always':\n"
" todo = calls[i]\n"
" todo()\n"
" info_index = 0\n"
" elif mode == 'when':\n"
" when = calls[i]\n"
" info_index = 2\n"
" elif mode == 'period_ms':\n"
" period_ms = calls[i]\n"
" info_index = 2\n"
" elif info_index == 2:\n"
" if mode == 'when':\n"
" if when():\n"
" todo = calls[i]\n"
" todo()\n"
" info_index = 0\n"
" elif mode == 'period_ms':\n"
" todo = calls[i]\n"
" info_index = 3\n"
" elif info_index == 3:\n"
" if mode == 'period_ms':\n"
" if tick > calls[i]:\n"
" todo()\n"
" calls[i] = tick + period_ms\n"
" info_index = 0\n"
"\n";
pikaCompile("task.bin", lines);
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, task) {
char* lines =
"len = calls.len()\n"
"mode = 'none'\n"
"info_index = 0\n"
"for i in range(0, len):\n"
" if len == 0:\n"
" break\n"
" if info_index == 0:\n"
" mode = calls[i]\n"
" info_index = 1\n"
" elif info_index == 1:\n"
" if mode == 'always':\n"
" todo = calls[i]\n"
" todo()\n"
" info_index = 0\n"
" elif mode == 'when':\n"
" when = calls[i]\n"
" info_index = 2\n"
" elif mode == 'period_ms':\n"
" period_ms = calls[i]\n"
" info_index = 2\n"
" elif info_index == 2:\n"
" if mode == 'when':\n"
" if when():\n"
" todo = calls[i]\n"
" todo()\n"
" info_index = 0\n"
" elif mode == 'period_ms':\n"
" todo = calls[i]\n"
" info_index = 3\n"
" elif info_index == 3:\n"
" if mode == 'period_ms':\n"
" if tick > calls[i]:\n"
" todo()\n"
" calls[i] = tick + period_ms\n"
" info_index = 0\n"
"\n";
Args buffs = {0};
char* pikaAsm = pika_lines2Asm(&buffs, lines);
ByteCodeFrame bytecode_frame;
byteCodeFrame_init(&bytecode_frame);
byteCodeFrame_appendFromAsm(&bytecode_frame, pikaAsm);
/* do something */
byteCodeFrame_print(&bytecode_frame);
printf("Asm size: %d\r\n", (int)strGetSize(pikaAsm));
byteCodeFrame_printAsArray(&bytecode_frame);
/* deinit */
byteCodeFrame_deinit(&bytecode_frame);
strsDeinit(&buffs);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, demo1) {
char* lines = "append(__val)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, snake_file) {
char* lines =
"from PikaObj import *\n"
"import PikaStdLib\n"
"import machine \n"
"\n"
"# hardware init\n"
"lcd = machine.LCD()\n"
"lcd.init()\n"
"lcd.clear('white')\n"
"key = machine.KEY()\n"
"key.init()\n"
"time = machine.Time()\n"
"x_max = 120\n"
"y_max = 150\n"
"\n"
"# snake init\n"
"s = machine.Point()\n"
"w = 9\n"
"h = 9\n"
"s.x = 50\n"
"s.y = 10\n"
"len = 0\n"
"while len < 3:\n"
" b = s\n"
" i = 0\n"
" while i < len:\n"
" b = b.next\n"
" i = i + 1\n"
" b.next = machine.Point()\n"
" b.next.x = b.x - 10\n"
" b.next.y = b.y\n"
" b.next.prev = b\n"
" len = len + 1\n"
"# ring link\n"
"b.next = s\n"
"s.prev = b\n"
"\n"
"i = 0\n"
"b = s\n"
"while i < len:\n"
" lcd.fill(b.x, b.y, w, h, 'blue')\n"
" b = b.next\n"
" i = i + 1\n"
"\n"
"print('snake lengh')\n"
"print(len)\n"
"\n"
"# fruit init\n"
"f = machine.Point()\n"
"f.x = 30\n"
"f.y = 20\n"
"lcd.fill(f.x, f.y, w, h, 'green')\n"
"\n"
"# memory check\n"
"mem = PikaStdLib.MemChecker()\n"
"print('mem used max:')\n"
"mem.max()\n"
"\n"
"# main loop\n"
"d = 0\n"
"isUpdate = 1\n"
"isEat = 0\n"
"while True:\n"
" if isUpdate:\n"
" # isUpdate = 0\n"
" # check eat fruit\n"
" if f.x == s.x and f.y == s.y:\n"
" # have eat fruit\n"
" isEat = 1\n"
" f.x = f.x + 30\n"
" if f.x > x_max:\n"
" f.x = f.x - x_max\n"
" f.y = f.y + 30\n"
" if f.y > y_max:\n"
" f.y = f.y - y_max\n"
" lcd.fill(f.x, f.y, w, h, 'green')\n"
" # move snake by the direction\n"
" if d == 0:\n"
" x_new = s.x + 10\n"
" y_new = s.y\n"
" if x_new > x_max:\n"
" x_new = 0\n"
" elif d == 1:\n"
" x_new = s.x\n"
" y_new = s.y - 10\n"
" if y_new < 0:\n"
" y_new = y_max\n"
" elif d == 2:\n"
" x_new = s.x\n"
" y_new = s.y + 10\n"
" if y_new > y_max:\n"
" y_new = 0\n"
" elif d == 3:\n"
" x_new = s.x - 10\n"
" y_new = s.y\n"
" if x_new < 0:\n"
" x_new = x_max\n"
" if isEat:\n"
" isEat = 0\n"
" b_new = machine.Point()\n"
" b_new.x = x_new\n"
" b_new.y = y_new\n"
" b_new.prev = s.prev\n"
" b_new.next = s\n"
" s.prev.next = b_new\n"
" s.prev = b_new\n"
" s = b_new\n"
" len = len + 1\n"
" print('snake lengh')\n"
" print(len)\n"
" print('mem used max:')\n"
" mem.max()\n"
" # drow the snake and fruit\n"
" # clear last body\n"
" lcd.fill(s.prev.x, s.prev.y, w, h, 'white')\n"
" # new body\n"
" s.prev.x = x_new\n"
" s.prev.y = y_new\n"
" # head is last body\n"
" s = s.prev\n"
" lcd.fill(s.x, s.y, w, h, 'blue')\n"
" b = s\n"
" i = 0\n"
" # scan key\n"
" key_val = key.get()\n"
" if key_val == 0:\n"
" d = 0\n"
" isUpdate = 1\n"
" elif key_val == 1:\n"
" d = 1\n"
" isUpdate = 1\n"
" elif key_val == 2:\n"
" d = 2\n"
" isUpdate = 1\n"
" elif key_val == 3:\n"
" d = 3\n"
" isUpdate = 1\n";
pikaCompile("snake.bin", lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, import_bf_mem) {
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
char* lines =
"def mytest():\n"
" print('test')\n"
"\n";
ByteCodeFrame bf;
byteCodeFrame_init(&bf);
pika_lines2Bytes(&bf, lines);
obj_importModuleWithByteCodeFrame(pikaMain, "mtest", &bf);
byteCodeFrame_deinit(&bf);
obj_deinit(pikaMain);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, import_bf1) {
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
char* lines =
"def mytest():\n"
" print('test_import_bf1')\n"
"\n";
ByteCodeFrame bf;
byteCodeFrame_init(&bf);
pika_lines2Bytes(&bf, lines);
obj_importModuleWithByteCodeFrame(pikaMain, "mtest", &bf);
obj_run(pikaMain,
"mtest.mytest()\n"
"\n");
EXPECT_STREQ(log_buff[0], "test_import_bf1\r\n");
byteCodeFrame_deinit(&bf);
obj_deinit(pikaMain);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, import_bf2) {
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
char* lines =
"class Test:\n"
" def mytest(self):\n"
" print('test_import_bf2')\n"
"\n";
ByteCodeFrame bf;
byteCodeFrame_init(&bf);
pika_lines2Bytes(&bf, lines);
obj_importModuleWithByteCodeFrame(pikaMain, "mtest", &bf);
obj_run(pikaMain,
"m = mtest.Test()\n"
"m.mytest()\n"
"\n");
byteCodeFrame_deinit(&bf);
obj_deinit(pikaMain);
EXPECT_STREQ(log_buff[0], "test_import_bf2\r\n");
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, file1) {
pikaCompileFile("test/python/main.py");
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, file2) {
pikaCompileFile("test/python/main_snake_LCD.py");
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, init) {
LibObj* lib = New_LibObj(NULL);
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, lib_link_bytecode) {
LibObj* lib = New_LibObj(NULL);
LibObj_dynamicLink(lib, "module1", (uint8_t*)0x3344);
LibObj_dynamicLink(lib, "module2", (uint8_t*)0x33433);
LibObj_dynamicLink(lib, "module3", (uint8_t*)0x33433);
LibObj_dynamicLink(lib, "module4", (uint8_t*)0x33433);
LibObj_dynamicLink(lib, "module5", (uint8_t*)0x33433);
EXPECT_STREQ(obj_getStr(lib, "module1.name"), "module1");
EXPECT_EQ((uintptr_t)obj_getPtr(lib, "module1.bytecode"), 0x3344);
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, lib_push_file) {
LibObj* lib = New_LibObj(NULL);
LibObj_staticLinkFile(lib, "test/python/main.py.o");
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, lib_push_files) {
LibObj* lib = New_LibObj(NULL);
LibObj_staticLinkFile(lib, "test/python/main.py.o");
LibObj_staticLinkFile(lib, "test/python/main_snake_LCD.py.o");
LibObj_listModules(lib);
/* asset */
EXPECT_STREQ(log_buff[0], "main\r\n");
EXPECT_STREQ(log_buff[1], "main_snake_LCD\r\n");
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, lib_compile_link) {
LibObj* lib = New_LibObj(NULL);
pikaCompileFile("test/python/UnitTest.py");
pikaCompileFile("test/python/main.py");
pikaCompileFile("test/python/main_snake_LCD.py");
LibObj_staticLinkFile(lib, "test/python/UnitTest.py.o");
LibObj_staticLinkFile(lib, "test/python/main.py.o");
LibObj_staticLinkFile(lib, "test/python/main_snake_LCD.py.o");
LibObj_listModules(lib);
/* asset */
EXPECT_STREQ(log_buff[0], "UnitTest\r\n");
EXPECT_STREQ(log_buff[1], "main\r\n");
EXPECT_STREQ(log_buff[2], "main_snake_LCD\r\n");
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, compile_link_import) {
LibObj* lib = New_LibObj(NULL);
pikaCompileFile("test/python/test_module1.py");
LibObj_staticLinkFile(lib, "test/python/test_module1.py.o");
LibObj_listModules(lib);
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
obj_linkLibObj(pikaMain, lib);
obj_run(pikaMain,
"import test_module1\n"
"test_module1.mytest()\n");
/* asset */
EXPECT_STREQ(log_buff[0], "test_module_1_hello\r\n");
/* deinit */
obj_deinit(pikaMain);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, lib_to_file) {
LibObj* lib = New_LibObj(NULL);
pikaCompileFile("test/python/UnitTest.py");
pikaCompileFile("test/python/main.py");
pikaCompileFile("test/python/main_snake_LCD.py");
LibObj_staticLinkFile(lib, "test/python/UnitTest.py.o");
LibObj_staticLinkFile(lib, "test/python/main.py.o");
LibObj_staticLinkFile(lib, "test/python/main_snake_LCD.py.o");
LibObj_listModules(lib);
LibObj_linkFile(lib, "test/python/lib_to_file.py.a");
/* asset */
EXPECT_STREQ(log_buff[0], "UnitTest\r\n");
EXPECT_STREQ(log_buff[1], "main\r\n");
EXPECT_STREQ(log_buff[2], "main_snake_LCD\r\n");
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, save2) {
LibObj* lib = New_LibObj(NULL);
pikaCompileFile("test/python/test_module1.py");
pikaCompileFile("test/python/test_module2.py");
pikaCompileFile("test/python/test_module3.py");
LibObj_staticLinkFile(lib, "test/python/test_module1.py.o");
LibObj_staticLinkFile(lib, "test/python/test_module2.py.o");
LibObj_staticLinkFile(lib, "test/python/test_module3.py.o");
LibObj_listModules(lib);
LibObj_linkFile(lib, "test/python/test_module.py.a");
/* asset */
EXPECT_STREQ(log_buff[0], "test_module1\r\n");
EXPECT_STREQ(log_buff[1], "test_module2\r\n");
EXPECT_STREQ(log_buff[2], "test_module3\r\n");
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, load_file) {
/* compile */
LibObj* lib = New_LibObj(NULL);
LibObj_loadLibraryFile(lib, "test/python/test_module.py.a");
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
obj_linkLibObj(pikaMain, lib);
obj_run(pikaMain,
"import test_module1\n"
"import test_module2\n"
"import test_module3\n"
"test_module1.mytest()\n"
"test_module2.mytest()\n"
"test_module3.mytest()\n");
/* asset */
EXPECT_STREQ(log_buff[2], "test_module_1_hello\r\n");
EXPECT_STREQ(log_buff[1], "test_module_2_hello\r\n");
EXPECT_STREQ(log_buff[0], "test_module_3_hello\r\n");
/* deinit */
obj_deinit(pikaMain);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, load_no_file) {
/* compile */
LibObj* lib = New_LibObj(NULL);
int res = LibObj_loadLibraryFile(lib, "test/python/mian.py.o");
EXPECT_EQ(res, PIKA_RES_ERR_IO_ERROR);
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, load_err_file_type) {
/* compile */
LibObj* lib = New_LibObj(NULL);
int res = LibObj_loadLibraryFile(lib, "test/python/main.py.o");
EXPECT_EQ(res, PIKA_RES_ERR_OPERATION_FAILED);
/* deinit */
LibObj_deinit(lib);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(lib, lib_file_to_array) {
Lib_loadLibraryFileToArray("test/python/lib_to_file.py.a", "test/python");
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(make, maker) {
PikaMaker* maker = New_PikaMaker();
pikaMaker_deinit(maker);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(make, compile) {
PikaMaker* maker = New_PikaMaker();
pikaMaker_setPWD(maker, "package/pikascript/");
pikaMaker_compileModule(maker, "main");
pikaMaker_deinit(maker);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(make, depend) {
PikaMaker* maker = New_PikaMaker();
pikaMaker_setPWD(maker, "package/pikascript/");
pikaMaker_getDependencies(maker, "main");
pikaMaker_printStates(maker);
// char* uncompiled = pikaMaker_getFirstNocompiled(maker);
// EXPECT_STREQ(uncompiled, "test_module1");
pikaMaker_deinit(maker);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(make, compile_depend) {
PikaMaker* maker = New_PikaMaker();
pikaMaker_setPWD(maker, "package/pikascript/");
pikaMaker_getDependencies(maker, "main");
char* uncompiled = pikaMaker_getFirstNocompiled(maker);
pika_assert(NULL != uncompiled);
pikaMaker_compileModule(maker, uncompiled);
pikaMaker_getDependencies(maker, uncompiled);
uncompiled = pikaMaker_getFirstNocompiled(maker);
// EXPECT_STREQ(uncompiled, "test_module3");
pikaMaker_printStates(maker);
pikaMaker_deinit(maker);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(make, compile_depend_all) {
PikaMaker* maker = New_PikaMaker();
pikaMaker_setPWD(maker, "package/pikascript/");
pikaMaker_compileModuleWithDepends(maker, "main");
pikaMaker_printStates(maker);
pikaMaker_deinit(maker);
EXPECT_EQ(pikaMemNow(), 0);
}
// TEST(make, compile_link_all) {
// PikaMaker* maker = New_PikaMaker();
// pikaMaker_setPWD(maker, "package/pikascript/");
// pikaMaker_compileModuleWithDepends(maker, "main");
// pikaMaker_printStates(maker);
// pikaMaker_linkCompiledModules(maker, "pikaModules.py.a");
// pikaMaker_deinit(maker);
// EXPECT_EQ(pikaMemNow(), 0);
// }
TEST(compiler, __str__) {
char* lines = "@res_str = __str__()";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __len__) {
char* lines = "@res_len = __len__()";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __del__) {
char* lines = "__del__()";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, event_cb) {
char* lines = "_eventCallBack(_eventSignal)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, event_cb_lvgl) {
char* lines = "_res = eventCallBack(eventData)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __setitem__) {
char* lines = "__setitem__(__key, __val)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __getitem__) {
char* lines = "@res_item = __getitem__(__key)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __add__) {
char* lines = "@res_add = __add__(__others)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __eq__) {
char* lines = "@res_eq = __eq__(__others)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __iter__) {
char* lines = "@res_iter = __iter__()";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __sub__) {
char* lines = "@res_sub = __sub__(__others)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __contains__) {
char* lines = "@res_contains = __contains__(__others)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __callback) {
char* lines = "__callback(__frameBuffer, __isNewFrame)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, __list) {
char* lines =
"@res_list = []\n"
"for __item in __list:\n"
" @res_list.append(__item)\n"
"del __item\n"
"del __list\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, getattr) {
char* lines = "@res = __getattribute__(@name)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, getattr2) {
char* lines = "@res = __getattr__(@name)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, setattr) {
char* lines = "__setattr__(@name, @value)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, dict_update) {
char* lines =
"for @item in @other:\n"
" @self[@item] = @other[@item]\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, i_pp) {
char* lines =
"i = 0\n"
"while i < 10000:\n"
" i += 1\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, benchmark) {
char* lines =
"num = 0\n"
"i = 2\n"
"while i < 1000:\n"
" is_prime = 1\n"
" j = 2\n"
" while j < i:\n"
" if i%j==0 :\n"
" is_prime = 0\n"
" break\n"
" j += 1 \n"
" if is_prime:\n"
" num = num + i\n"
" i += 1\n"
"\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, for_print_1k) {
char* lines =
"for i in range(1000):\n"
" print(i)\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, bc_fn) {
char* lines =
"def test():\n"
" print('test')\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, starrd) {
char* lines = "@l = __len__()";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, starrd_get) {
char* lines = "@a = __getitem__(@d)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, thread_arg) {
char* lines = "thread(*args)";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, prime_100) {
char* lines =
"num = 0\n"
"i = 2\n"
"for i in range(2,100):\n"
" j=2\n"
" is_prime = 1\n"
" for j in range(2,i):\n"
" if i%j==0 :\n"
" is_prime = 0\n"
" break\n"
" if is_prime:\n"
" num = num + i\n"
"\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, getattr_fn) {
char* lines = "@res = @obj.@name\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, str_join) {
char* lines =
"@res_join = \"\"\n"
"@num = len(@val)\n"
"for i in range(@num):\n"
" @res_join += @val[i]\n"
" if i != @num - 1:\n"
" @res_join += @str\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, thread_void_arg) {
char* lines = "thread()";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, max) {
char* lines =
"@res_max = @list[0]\n"
"for @item in @list:\n"
" if @item > @res_max:\n"
" @res_max = @item\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, min) {
char* lines =
"@res_max = @list[0]\n"
"for @item in @list:\n"
" if @item < @res_max:\n"
" @res_max = @item\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, contains) {
char* lines =
"@res_contains = 0\n"
"for @item in @list:\n"
" if @item == @val:\n"
" @res_contains = 1\n"
" break\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST(compiler, fn1) {
char* lines = "@r = @f(@d)\n";
pika_lines2Array(lines);
EXPECT_EQ(pikaMemNow(), 0);
}
TEST_END

View File

@ -559,7 +559,7 @@ TEST(module, REPL_script) {
fclose((FILE*)f_getchar_fp); fclose((FILE*)f_getchar_fp);
/* collect */ /* collect */
/* assert */ /* assert */
EXPECT_STREQ(log_buff[4], "mem used max:\r\n"); EXPECT_STREQ(log_buff[3], "mem used max:\r\n");
/* deinit */ /* deinit */
obj_deinit(pikaMain); obj_deinit(pikaMain);
EXPECT_EQ(pikaMemNow(), 0); EXPECT_EQ(pikaMemNow(), 0);

View File

@ -2927,6 +2927,25 @@ TEST(pikaMain, REPL_key_down_over) {
EXPECT_EQ(pikaMemNow(), 0); EXPECT_EQ(pikaMemNow(), 0);
} }
TEST(pikaMain, REPL_pdb_set_break) {
char lines[] = "pdb.set_break('pdb_set_break', 36)\nn\nn\nn\n";
write_to_getchar_buffer(lines, strGetSize(lines));
/* init */
g_PikaMemInfo.heapUsedMax = 0;
PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
extern unsigned char pikaModules_py_a[];
obj_linkLibrary(pikaMain, pikaModules_py_a);
pikaVM_runSingleFile(pikaMain, "test/python/builtins/pdb_set_break.py");
/* run */
__platform_printf("BEGIN\r\n");
/* collect */
/* assert */
// EXPECT_STREQ(log_buff[1], "2\r\n");
/* deinit */
obj_deinit(pikaMain);
EXPECT_EQ(pikaMemNow(), 0);
}
#endif #endif
#if PIKA_SHELL_FILTER_ENABLE #if PIKA_SHELL_FILTER_ENABLE

View File

@ -51,3 +51,26 @@ PIKA_WEAK void pika_hook_unused_stack_arg(PikaVMFrame* vm, Arg* arg) {
arg_print(arg, pika_true, "\r\n"); arg_print(arg, pika_true, "\r\n");
} }
} }
#define GETCHAR_BUFFER_SIZE 1024
uint8_t getchar_buffer[GETCHAR_BUFFER_SIZE] = {0};
size_t getchar_buffer_index = 0;
int write_to_getchar_buffer(const char* str, size_t size) {
if (size > GETCHAR_BUFFER_SIZE - getchar_buffer_index) {
return -1;
}
memcpy(getchar_buffer + getchar_buffer_index, str, size);
getchar_buffer_index += size;
return 0;
}
char pika_platform_getchar(void) {
if (getchar_buffer_index > 0) {
char c = getchar_buffer[0];
memmove(getchar_buffer, getchar_buffer + 1, getchar_buffer_index - 1);
getchar_buffer_index--;
return c;
}
return getchar();
}

View File

@ -1,4 +1,6 @@
#include <stdio.h>
#define LOG_BUFF_MAX 100 #define LOG_BUFF_MAX 100
#define LOG_SIZE 512 #define LOG_SIZE 512
void mem_pool_deinit(void); void mem_pool_deinit(void);
void mem_pool_init(void); void mem_pool_init(void);
int write_to_getchar_buffer(const char* str, size_t size);

View File

@ -1,7 +1,5 @@
import PikaUI as ui import PikaUI as ui
from PikaStdLib import MemChecker as mem from PikaStdLib import MemChecker as mem
class MainContainer(ui.Container): class MainContainer(ui.Container):
def onclick_next(self, event): def onclick_next(self, event):
print('Page1: onclick_next') print('Page1: onclick_next')

View File

@ -0,0 +1,8 @@
import PikaDebug as pdb
pdb.set_trace()
pdb.set_break('pdb_set_break', 48)
print('line 1')
print('line 2')
print('line 3')
print('line 4')
print('line 5')

View File

@ -37,13 +37,14 @@
#include "dataQueue.h" #include "dataQueue.h"
#include "dataString.h" #include "dataString.h"
#include "dataStrs.h" #include "dataStrs.h"
#include "PikaParser.h"
#if __linux #if __linux
#include "signal.h" #include "signal.h"
#include "termios.h" #include "termios.h"
#include "unistd.h" #include "unistd.h"
#endif #endif
extern volatile VMSignal g_PikaVMSignal; extern volatile VMState g_PikaVMState;
volatile PikaObjState g_PikaObjState = { volatile PikaObjState g_PikaObjState = {
.helpModulesCmodule = NULL, .helpModulesCmodule = NULL,
.inRootObj = pika_false, .inRootObj = pika_false,
@ -1790,7 +1791,9 @@ enum shellCTRL _inner_do_obj_runChar(PikaObj* self,
} }
shell->lineBuff[shell->line_position] = '\0'; shell->lineBuff[shell->line_position] = '\0';
ctrl = shell->handler(self, shell->lineBuff, shell); ctrl = shell->handler(self, shell->lineBuff, shell);
if (SHELL_CTRL_EXIT != ctrl) {
pika_platform_printf("%s", shell->prefix); pika_platform_printf("%s", shell->prefix);
}
__clearBuff(shell); __clearBuff(shell);
goto __exit; goto __exit;
} }
@ -2032,7 +2035,9 @@ static enum shellCTRL __obj_shellLineHandler_REPL(PikaObj* self,
return SHELL_CTRL_EXIT; return SHELL_CTRL_EXIT;
} }
/* run single line */ /* run single line */
_pikaVM_runPyLines(self, input_line, pika_true); pikaVM_run_ex_cfg cfg = {0};
cfg.in_repl = pika_true;
pikaVM_run_ex(self, input_line, &cfg);
return SHELL_CTRL_CONTINUE; return SHELL_CTRL_CONTINUE;
} }
@ -2542,6 +2547,17 @@ PikaObj* obj_importModuleWithByteCode(PikaObj* self,
pikaVM_runByteCode(obj_getObj((PikaObj*)__pikaMain, name), pikaVM_runByteCode(obj_getObj((PikaObj*)__pikaMain, name),
(uint8_t*)byteCode); (uint8_t*)byteCode);
PikaObj* module_obj = obj_getObj((PikaObj*)__pikaMain, name);
PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE};
pikaVM_runBytecode_ex_cfg cfg = {0};
cfg.globals = module_obj;
cfg.locals = module_obj;
cfg.name = name;
cfg.vm_thread = &vm_thread;
cfg.is_const_bytecode = pika_true;
pikaVM_runByteCode_ex(module_obj, byteCode, &cfg);
} }
if (self != (PikaObj*)__pikaMain) { if (self != (PikaObj*)__pikaMain) {
/* import to other module context */ /* import to other module context */
@ -2617,7 +2633,16 @@ int obj_runModule(PikaObj* self, char* module_name) {
if (NULL == bytecode) { if (NULL == bytecode) {
return 1; return 1;
} }
pikaVM_runByteCode(self, bytecode);
PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE};
pikaVM_runBytecode_ex_cfg cfg = {0};
cfg.globals = self;
cfg.locals = self;
cfg.name = module_name;
cfg.vm_thread = &vm_thread;
cfg.is_const_bytecode = pika_true;
pikaVM_runByteCode_ex(self, bytecode, &cfg);
return 0; return 0;
} }
@ -2791,8 +2816,8 @@ static void _thread_event(void* arg) {
while (1) { while (1) {
pika_GIL_ENTER(); pika_GIL_ENTER();
#if PIKA_EVENT_ENABLE #if PIKA_EVENT_ENABLE
if (g_PikaVMSignal.event_thread_exit) { if (g_PikaVMState.event_thread_exit) {
g_PikaVMSignal.event_thread_exit_done = 1; g_PikaVMState.event_thread_exit_done = 1;
break; break;
} }
#endif #endif
@ -2814,11 +2839,11 @@ PIKA_RES _do_pika_eventListener_send(PikaEventListener* self,
#else #else
_RETURN_WHEN_NOT_ZERO(pika_GIL_ENTER(), -1); _RETURN_WHEN_NOT_ZERO(pika_GIL_ENTER(), -1);
#if PIKA_EVENT_THREAD_ENABLE #if PIKA_EVENT_THREAD_ENABLE
if (!g_PikaVMSignal.event_thread) { if (!g_PikaVMState.event_thread) {
/* using multi thread */ /* using multi thread */
if (_VM_is_first_lock()) { if (_VM_is_first_lock()) {
// avoid _VMEvent_pickupEvent() in _time.c as soon as possible // avoid _VMEvent_pickupEvent() in _time.c as soon as possible
g_PikaVMSignal.event_thread = pika_platform_thread_init( g_PikaVMState.event_thread = pika_platform_thread_init(
"pika_event", _thread_event, NULL, PIKA_EVENT_THREAD_STACK_SIZE, "pika_event", _thread_event, NULL, PIKA_EVENT_THREAD_STACK_SIZE,
PIKA_THREAD_PRIO, PIKA_THREAD_TICK); PIKA_THREAD_PRIO, PIKA_THREAD_TICK);
pika_debug("event thread init"); pika_debug("event thread init");
@ -2870,11 +2895,11 @@ Arg* pika_eventListener_sendSignalAwaitResult(PikaEventListener* self,
while (1) { while (1) {
}; };
#else #else
extern volatile VMSignal g_PikaVMSignal; extern volatile VMState g_PikaVMState;
int tail = g_PikaVMSignal.cq.tail; int tail = g_PikaVMState.cq.tail;
pika_eventListener_sendSignal(self, eventId, eventSignal); pika_eventListener_sendSignal(self, eventId, eventSignal);
while (1) { while (1) {
Arg* res = g_PikaVMSignal.cq.res[tail]; Arg* res = g_PikaVMState.cq.res[tail];
pika_platform_thread_yield(); pika_platform_thread_yield();
if (NULL != res) { if (NULL != res) {
return res; return res;
@ -4443,3 +4468,73 @@ size_t pikaDict_getBytesSize(PikaDict* self, char* name) {
void pikaDict_deinit(PikaDict* self) { void pikaDict_deinit(PikaDict* self) {
obj_deinit(self); obj_deinit(self);
} }
PIKA_RES insert_label_at_line(const char* filename,
int N,
char* buff,
int buff_size) {
FILE* file = pika_platform_fopen(filename, "r");
if (!file) {
return PIKA_RES_ERR_IO_ERROR;
}
int line_count = 1;
int buff_index = 0;
char ch;
while ((pika_platform_fread(&ch, 1, 1, file)) != 0) {
if (line_count == N) {
char* label = "#!label\n";
int label_length = strGetSize(label);
if (buff_index + label_length >= buff_size) {
pika_platform_fclose(file);
return PIKA_RES_ERR_IO_ERROR; // Insufficient buffer size
}
strCopy(buff + buff_index, label);
buff_index += label_length;
line_count++; // Skip this line since we're adding a label
}
if (ch == '\n') {
line_count++;
}
if (buff_index >=
buff_size - 1) { // -1 to leave space for null terminator
pika_platform_fclose(file);
return PIKA_RES_ERR_IO_ERROR; // Insufficient buffer size
}
buff[buff_index] = ch;
buff_index++;
}
buff[buff_index] = '\0'; // Null terminate the buffer
pika_platform_fclose(file);
return PIKA_RES_OK;
}
int32_t pika_debug_find_break_point_pc(char* pyFile, uint32_t pyLine) {
ByteCodeFrame bytecode_frame;
byteCodeFrame_init(&bytecode_frame);
char* file_buff = pikaMalloc(PIKA_READ_FILE_BUFF_SIZE);
FILE* file = pika_platform_fopen(pyFile, "r");
if (!file) {
goto __exit;
}
if (PIKA_RES_OK != insert_label_at_line(pyFile, pyLine, file_buff,
PIKA_READ_FILE_BUFF_SIZE)) {
goto __exit;
}
pika_lines2Bytes(&bytecode_frame, file_buff);
__exit:
if (NULL != file) {
pika_platform_fclose(file);
}
byteCodeFrame_deinit(&bytecode_frame);
pikaFree(file_buff, PIKA_READ_FILE_BUFF_SIZE);
return bytecode_frame.label_pc;
}

View File

@ -69,8 +69,11 @@ struct InstructArray {
typedef struct ByteCodeFrame ByteCodeFrame; typedef struct ByteCodeFrame ByteCodeFrame;
struct ByteCodeFrame { struct ByteCodeFrame {
char* name;
Hash name_hash;
ConstPool const_pool; ConstPool const_pool;
InstructArray instruct_array; InstructArray instruct_array;
int32_t label_pc;
}; };
typedef struct NativeProperty NativeProperty; typedef struct NativeProperty NativeProperty;
@ -459,6 +462,8 @@ struct ShellConfig {
ShellHistory* history; ShellHistory* history;
#endif #endif
pika_bool no_echo; pika_bool no_echo;
PikaObj* locals;
PikaObj* globals;
}; };
#if PIKA_SHELL_HISTORY_ENABLE #if PIKA_SHELL_HISTORY_ENABLE
@ -808,6 +813,8 @@ uint32_t pikaGC_printFreeList(void);
int pika_GIL_EXIT(void); int pika_GIL_EXIT(void);
int pika_GIL_ENTER(void); int pika_GIL_ENTER(void);
int32_t pika_debug_find_break_point_pc(char* pyFile, uint32_t pyLine);
typedef PikaObj PikaList; typedef PikaObj PikaList;
typedef PikaObj PikaTuple; typedef PikaObj PikaTuple;
typedef PikaObj PikaDict; typedef PikaObj PikaDict;

View File

@ -2954,6 +2954,11 @@ char* parser_lines2Target(Parser* self, char* sPyLines) {
__parse_line: __parse_line:
/* parse single Line to Asm */ /* parse single Line to Asm */
if (strEqu(sLine, "#!label")) {
self->bytecode_frame->label_pc =
self->bytecode_frame->instruct_array.size;
goto __next_line;
}
sBackendCode = parser_line2Target(self, sLine); sBackendCode = parser_line2Target(self, sLine);
__parse_after: __parse_after:
if (NULL == sBackendCode) { if (NULL == sBackendCode) {

View File

@ -103,6 +103,7 @@ struct Parser {
pika_bool isGenBytecode; pika_bool isGenBytecode;
ByteCodeFrame* bytecode_frame; ByteCodeFrame* bytecode_frame;
uint8_t thisBlockDeepth; uint8_t thisBlockDeepth;
uint32_t label_pc;
}; };
typedef struct LexToken LexToken; typedef struct LexToken LexToken;

View File

@ -38,8 +38,8 @@
#endif #endif
static pika_platform_thread_mutex_t g_pikaGIL = {0}; static pika_platform_thread_mutex_t g_pikaGIL = {0};
volatile VMSignal g_PikaVMSignal = {.signal_ctrl = VM_SIGNAL_CTRL_NONE, volatile VMState g_PikaVMState = {
.signal_ctrl = VM_SIGNAL_CTRL_NONE,
.vm_cnt = 0, .vm_cnt = 0,
#if PIKA_EVENT_ENABLE #if PIKA_EVENT_ENABLE
.cq = .cq =
@ -50,8 +50,12 @@ volatile VMSignal g_PikaVMSignal = {.signal_ctrl = VM_SIGNAL_CTRL_NONE,
}, },
.event_pickup_cnt = 0, .event_pickup_cnt = 0,
.event_thread = NULL, .event_thread = NULL,
.event_thread_exit = pika_false .event_thread_exit = pika_false,
#endif
#if PIKA_DEBUG_BREAK_POINT_MAX > 0
.break_module_hash = {0},
.break_point_pc = {0},
.break_point_cnt = 0,
#endif #endif
}; };
extern volatile PikaObjState g_PikaObjState; extern volatile PikaObjState g_PikaObjState;
@ -127,14 +131,14 @@ int _VM_is_first_lock(void) {
} }
int _VMEvent_getVMCnt(void) { int _VMEvent_getVMCnt(void) {
return g_PikaVMSignal.vm_cnt; return g_PikaVMState.vm_cnt;
} }
int _VMEvent_getEventPickupCnt(void) { int _VMEvent_getEventPickupCnt(void) {
#if !PIKA_EVENT_ENABLE #if !PIKA_EVENT_ENABLE
return -1; return -1;
#else #else
return g_PikaVMSignal.event_pickup_cnt; return g_PikaVMState.event_pickup_cnt;
#endif #endif
} }
@ -209,21 +213,21 @@ void _VMEvent_deinit(void) {
pika_platform_panic_handle(); pika_platform_panic_handle();
#else #else
for (int i = 0; i < PIKA_EVENT_LIST_SIZE; i++) { for (int i = 0; i < PIKA_EVENT_LIST_SIZE; i++) {
if (NULL != g_PikaVMSignal.cq.res[i]) { if (NULL != g_PikaVMState.cq.res[i]) {
arg_deinit(g_PikaVMSignal.cq.res[i]); arg_deinit(g_PikaVMState.cq.res[i]);
g_PikaVMSignal.cq.res[i] = NULL; g_PikaVMState.cq.res[i] = NULL;
} }
if (NULL != g_PikaVMSignal.cq.data[i]) { if (NULL != g_PikaVMState.cq.data[i]) {
arg_deinit(g_PikaVMSignal.cq.data[i]); arg_deinit(g_PikaVMState.cq.data[i]);
g_PikaVMSignal.cq.data[i] = NULL; g_PikaVMState.cq.data[i] = NULL;
} }
} }
if (NULL != g_PikaVMSignal.event_thread) { if (NULL != g_PikaVMState.event_thread) {
g_PikaVMSignal.event_thread_exit = 1; g_PikaVMState.event_thread_exit = 1;
pika_platform_thread_destroy(g_PikaVMSignal.event_thread); pika_platform_thread_destroy(g_PikaVMState.event_thread);
g_PikaVMSignal.event_thread = NULL; g_PikaVMState.event_thread = NULL;
pika_GIL_EXIT(); pika_GIL_EXIT();
while (!g_PikaVMSignal.event_thread_exit_done) { while (!g_PikaVMState.event_thread_exit_done) {
pika_platform_thread_yield(); pika_platform_thread_yield();
} }
pika_GIL_ENTER(); pika_GIL_ENTER();
@ -243,24 +247,23 @@ PIKA_RES __eventListener_pushEvent(PikaEventListener* lisener,
arg_setType(eventData, ARG_TYPE_OBJECT); arg_setType(eventData, ARG_TYPE_OBJECT);
} }
/* push to event_cq_buff */ /* push to event_cq_buff */
if (_ecq_isFull(&g_PikaVMSignal.cq)) { if (_ecq_isFull(&g_PikaVMState.cq)) {
// pika_debug("event_cq_buff is full"); // pika_debug("event_cq_buff is full");
arg_deinit(eventData); arg_deinit(eventData);
return PIKA_RES_ERR_SIGNAL_EVENT_FULL; return PIKA_RES_ERR_SIGNAL_EVENT_FULL;
} }
if (g_PikaVMSignal.cq.res[g_PikaVMSignal.cq.tail] != NULL) { if (g_PikaVMState.cq.res[g_PikaVMState.cq.tail] != NULL) {
arg_deinit(g_PikaVMSignal.cq.res[g_PikaVMSignal.cq.tail]); arg_deinit(g_PikaVMState.cq.res[g_PikaVMState.cq.tail]);
g_PikaVMSignal.cq.res[g_PikaVMSignal.cq.tail] = NULL; g_PikaVMState.cq.res[g_PikaVMState.cq.tail] = NULL;
} }
if (g_PikaVMSignal.cq.data[g_PikaVMSignal.cq.tail] != NULL) { if (g_PikaVMState.cq.data[g_PikaVMState.cq.tail] != NULL) {
arg_deinit(g_PikaVMSignal.cq.data[g_PikaVMSignal.cq.tail]); arg_deinit(g_PikaVMState.cq.data[g_PikaVMState.cq.tail]);
g_PikaVMSignal.cq.data[g_PikaVMSignal.cq.tail] = NULL; g_PikaVMState.cq.data[g_PikaVMState.cq.tail] = NULL;
} }
g_PikaVMSignal.cq.id[g_PikaVMSignal.cq.tail] = eventId; g_PikaVMState.cq.id[g_PikaVMState.cq.tail] = eventId;
g_PikaVMSignal.cq.data[g_PikaVMSignal.cq.tail] = eventData; g_PikaVMState.cq.data[g_PikaVMState.cq.tail] = eventData;
g_PikaVMSignal.cq.listener[g_PikaVMSignal.cq.tail] = lisener; g_PikaVMState.cq.listener[g_PikaVMState.cq.tail] = lisener;
g_PikaVMSignal.cq.tail = g_PikaVMState.cq.tail = (g_PikaVMState.cq.tail + 1) % PIKA_EVENT_LIST_SIZE;
(g_PikaVMSignal.cq.tail + 1) % PIKA_EVENT_LIST_SIZE;
return PIKA_RES_OK; return PIKA_RES_OK;
#endif #endif
} }
@ -275,15 +278,14 @@ PIKA_RES __eventListener_popEvent(PikaEventListener** lisener_p,
return PIKA_RES_ERR_OPERATION_FAILED; return PIKA_RES_ERR_OPERATION_FAILED;
#else #else
/* pop from event_cq_buff */ /* pop from event_cq_buff */
if (_ecq_isEmpty(&g_PikaVMSignal.cq)) { if (_ecq_isEmpty(&g_PikaVMState.cq)) {
return PIKA_RES_ERR_SIGNAL_EVENT_EMPTY; return PIKA_RES_ERR_SIGNAL_EVENT_EMPTY;
} }
*id = g_PikaVMSignal.cq.id[g_PikaVMSignal.cq.head]; *id = g_PikaVMState.cq.id[g_PikaVMState.cq.head];
*data = g_PikaVMSignal.cq.data[g_PikaVMSignal.cq.head]; *data = g_PikaVMState.cq.data[g_PikaVMState.cq.head];
*lisener_p = g_PikaVMSignal.cq.listener[g_PikaVMSignal.cq.head]; *lisener_p = g_PikaVMState.cq.listener[g_PikaVMState.cq.head];
*head = g_PikaVMSignal.cq.head; *head = g_PikaVMState.cq.head;
g_PikaVMSignal.cq.head = g_PikaVMState.cq.head = (g_PikaVMState.cq.head + 1) % PIKA_EVENT_LIST_SIZE;
(g_PikaVMSignal.cq.head + 1) % PIKA_EVENT_LIST_SIZE;
return PIKA_RES_OK; return PIKA_RES_OK;
#endif #endif
} }
@ -303,23 +305,23 @@ void __VMEvent_pickupEvent(char* info) {
int head; int head;
if (PIKA_RES_OK == __eventListener_popEvent(&event_lisener, &event_id, if (PIKA_RES_OK == __eventListener_popEvent(&event_lisener, &event_id,
&event_data, &head)) { &event_data, &head)) {
g_PikaVMSignal.event_pickup_cnt++; g_PikaVMState.event_pickup_cnt++;
pika_debug("pickup_info: %s", info); pika_debug("pickup_info: %s", info);
pika_debug("pickup_cnt: %d", g_PikaVMSignal.event_pickup_cnt); pika_debug("pickup_cnt: %d", g_PikaVMSignal.event_pickup_cnt);
Arg* res = Arg* res =
__eventListener_runEvent(event_lisener, event_id, event_data); __eventListener_runEvent(event_lisener, event_id, event_data);
g_PikaVMSignal.cq.res[head] = res; g_PikaVMState.cq.res[head] = res;
g_PikaVMSignal.event_pickup_cnt--; g_PikaVMState.event_pickup_cnt--;
} }
#endif #endif
} }
VM_SIGNAL_CTRL VMSignal_getCtrl(void) { VM_SIGNAL_CTRL VMSignal_getCtrl(void) {
return g_PikaVMSignal.signal_ctrl; return g_PikaVMState.signal_ctrl;
} }
void pika_vm_exit(void) { void pika_vm_exit(void) {
g_PikaVMSignal.signal_ctrl = VM_SIGNAL_CTRL_EXIT; g_PikaVMState.signal_ctrl = VM_SIGNAL_CTRL_EXIT;
} }
void pika_vm_exit_await(void) { void pika_vm_exit_await(void) {
@ -333,7 +335,7 @@ void pika_vm_exit_await(void) {
} }
void pika_vmSignal_setCtrlClear(void) { void pika_vmSignal_setCtrlClear(void) {
g_PikaVMSignal.signal_ctrl = VM_SIGNAL_CTRL_NONE; g_PikaVMState.signal_ctrl = VM_SIGNAL_CTRL_NONE;
} }
/* head declare start */ /* head declare start */
@ -401,6 +403,21 @@ static int PikaVMFrame_getInvokeDeepthNow(PikaVMFrame* vm) {
return instructUnit_getInvokeDeepth(ins_unit); return instructUnit_getInvokeDeepth(ins_unit);
} }
pika_bool PikaVMFrame_checkBreakPoint(PikaVMFrame* vm) {
#if !PIKA_DEBUG_BREAK_POINT_MAX
return pika_false;
#else
if (g_PikaVMState.break_point_cnt == 0) {
return pika_false;
}
if (NULL == vm->bytecode_frame->name) {
return pika_false;
}
Hash module_hash = byteCodeFrame_getNameHash(vm->bytecode_frame);
return pika_debug_check_break_hash(module_hash, vm->pc);
#endif
}
static int32_t PikaVMFrame_getAddrOffsetOfJmpBack(PikaVMFrame* vm) { static int32_t PikaVMFrame_getAddrOffsetOfJmpBack(PikaVMFrame* vm) {
int offset = 0; int offset = 0;
int blockDeepthGot = -1; int blockDeepthGot = -1;
@ -731,7 +748,7 @@ Arg* _vm_get(PikaVMFrame* vm, PikaObj* self, Arg* aKey, Arg* aObj) {
0x73, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x00, /* const pool */ 0x73, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x00, /* const pool */
}; };
if (NULL != vm) { if (NULL != vm) {
aRes = _do_pikaVM_runByteCodeReturn(oArg, oArg, oArg, aRes = pikaVM_runByteCode_exReturn(oArg, oArg, oArg,
(uint8_t*)bytes, vm->vm_thread, (uint8_t*)bytes, vm->vm_thread,
pika_true, "@res_item"); pika_true, "@res_item");
} else { } else {
@ -1811,6 +1828,13 @@ InstructUnit* byteCodeFrame_findInsForward(ByteCodeFrame* bcframe,
pika_true); pika_true);
} }
Hash byteCodeFrame_getNameHash(ByteCodeFrame* bcframe) {
if (0 == bcframe->name_hash) {
bcframe->name_hash = hash_time33(bcframe->name);
}
return bcframe->name_hash;
}
InstructUnit* byteCodeFrame_findInsUnitBackward(ByteCodeFrame* bcframe, InstructUnit* byteCodeFrame_findInsUnitBackward(ByteCodeFrame* bcframe,
int32_t pc_start, int32_t pc_start,
enum InstructIndex index, enum InstructIndex index,
@ -3565,6 +3589,70 @@ const VM_instruct_handler VM_instruct_handler_table[__INSTRUCTION_CNT] = {
}; };
#endif #endif
extern volatile PikaObj* __pikaMain;
static enum shellCTRL __obj_shellLineHandler_debug(PikaObj* self,
char* input_line,
struct ShellConfig* config) {
/* continue */
if (strEqu("c", input_line)) {
return SHELL_CTRL_EXIT;
}
/* next */
if (strEqu("n", input_line)) {
return SHELL_CTRL_EXIT;
}
/* launch shell */
if (strEqu("sh", input_line)) {
/* exit pika shell */
pikaScriptShell((PikaObj*)__pikaMain);
return SHELL_CTRL_CONTINUE;
}
/* quit */
if (strEqu("q", input_line)) {
obj_setInt(self, "enable", 0);
return SHELL_CTRL_EXIT;
}
/* print */
if (strIsStartWith(input_line, "p ")) {
char* path = input_line + 2;
Arg* asm_buff = arg_newStr("print(");
asm_buff = arg_strAppend(asm_buff, path);
asm_buff = arg_strAppend(asm_buff, ")\n");
pikaVM_run_ex_cfg cfg = {0};
cfg.globals = config->globals;
cfg.in_repl = pika_true;
pikaVM_run_ex(config->locals, arg_getStr(asm_buff), &cfg);
arg_deinit(asm_buff);
return SHELL_CTRL_CONTINUE;
}
pikaVM_run_ex_cfg cfg = {0};
cfg.globals = config->globals;
cfg.in_repl = pika_true;
pikaVM_run_ex(config->locals, input_line, &cfg);
return SHELL_CTRL_CONTINUE;
}
void pika_debug_set_trace(PikaObj* self) {
if (!obj_getInt(self, "enable")) {
return;
}
char* name = "stdin";
pika_assert(NULL != self->vmFrame);
if (NULL != self->vmFrame->bytecode_frame->name) {
name = self->vmFrame->bytecode_frame->name;
}
pika_platform_printf("%s:%d\n", name, self->vmFrame->pc);
struct ShellConfig cfg = {
.prefix = "(Pdb-pika) ",
.handler = __obj_shellLineHandler_debug,
.fn_getchar = __platform_getchar,
.locals = self->vmFrame->locals,
.globals = self->vmFrame->globals,
};
_do_pikaScriptShell(self, &cfg);
shConfig_deinit(&cfg);
}
static int pikaVM_runInstructUnit(PikaObj* self, static int pikaVM_runInstructUnit(PikaObj* self,
PikaVMFrame* vm, PikaVMFrame* vm,
InstructUnit* ins_unit) { InstructUnit* ins_unit) {
@ -3576,6 +3664,9 @@ static int pikaVM_runInstructUnit(PikaObj* self,
char* data = PikaVMFrame_getConstWithInstructUnit(vm, ins_unit); char* data = PikaVMFrame_getConstWithInstructUnit(vm, ins_unit);
/* run instruct */ /* run instruct */
pika_assert(NULL != vm->vm_thread); pika_assert(NULL != vm->vm_thread);
if (PikaVMFrame_checkBreakPoint(vm)) {
pika_debug_set_trace(self);
}
#if PIKA_INSTRUCT_EXTENSION_ENABLE #if PIKA_INSTRUCT_EXTENSION_ENABLE
const VMInstruction* ins = instructUnit_getInstruct(instruct); const VMInstruction* ins = instructUnit_getInstruct(instruct);
@ -3751,14 +3842,16 @@ static ByteCodeFrame* _cache_bcf_fn_bc(PikaObj* self, uint8_t* bytecode) {
return _cache_bytecodeframe(self); return _cache_bytecodeframe(self);
} }
VMParameters* _pikaVM_runPyLines(PikaObj* self, VMParameters* pikaVM_run_ex(PikaObj* self,
char* py_lines, char* py_lines,
pika_bool in_repl) { pikaVM_run_ex_cfg* cfg) {
VMParameters* globals = NULL;
ByteCodeFrame bytecode_frame_stack = {0}; ByteCodeFrame bytecode_frame_stack = {0};
ByteCodeFrame* bytecode_frame_p = NULL; ByteCodeFrame* bytecode_frame_p = NULL;
uint8_t is_use_heap_bytecode = 0; uint8_t is_use_heap_bytecode = 0;
PikaObj* globals = self;
if (NULL != cfg->globals) {
globals = cfg->globals;
}
/* /*
* the first obj_run, cache bytecode to heap, to support 'def' and * the first obj_run, cache bytecode to heap, to support 'def' and
* 'class' * 'class'
@ -3779,7 +3872,11 @@ VMParameters* _pikaVM_runPyLines(PikaObj* self,
goto __exit; goto __exit;
} }
/* run byteCode */ /* run byteCode */
globals = _pikaVM_runByteCodeFrame(self, bytecode_frame_p, in_repl); if (NULL != cfg->module_name) {
byteCodeFrame_setName(bytecode_frame_p, cfg->module_name);
}
globals = _pikaVM_runByteCodeFrameGlobals(self, globals, bytecode_frame_p,
cfg->in_repl);
goto __exit; goto __exit;
__exit: __exit:
if (!is_use_heap_bytecode) { if (!is_use_heap_bytecode) {
@ -3788,12 +3885,9 @@ __exit:
return globals; return globals;
} }
VMParameters* _do_pikaVM_runByteCode(PikaObj* self, VMParameters* pikaVM_runByteCode_ex(PikaObj* self,
VMParameters* locals,
VMParameters* globals,
uint8_t* bytecode, uint8_t* bytecode,
PikaVMThread* vm_thread, pikaVM_runBytecode_ex_cfg* cfg) {
pika_bool is_const_bytecode) {
ByteCodeFrame bytecode_frame_stack = {0}; ByteCodeFrame bytecode_frame_stack = {0};
ByteCodeFrame* bytecode_frame_p = NULL; ByteCodeFrame* bytecode_frame_p = NULL;
uint8_t is_use_heap_bytecode = 1; uint8_t is_use_heap_bytecode = 1;
@ -3807,24 +3901,24 @@ VMParameters* _do_pikaVM_runByteCode(PikaObj* self,
/* get bytecode_ptr from stack */ /* get bytecode_ptr from stack */
bytecode_frame_p = &bytecode_frame_stack; bytecode_frame_p = &bytecode_frame_stack;
/* no def/class ins, no need cache bytecode */ /* no def/class ins, no need cache bytecode */
is_const_bytecode = pika_true; cfg->is_const_bytecode = pika_true;
} }
/* load or generate byte code frame */ /* load or generate byte code frame */
/* load bytecode */ /* load bytecode */
_do_byteCodeFrame_loadByteCode(bytecode_frame_p, bytecode, _do_byteCodeFrame_loadByteCode(bytecode_frame_p, bytecode, cfg->name,
is_const_bytecode); cfg->is_const_bytecode);
/* run byteCode */ /* run byteCode */
globals = _pikaVM_runByteCodeFrameWithState(self, locals, globals, cfg->globals = _pikaVM_runByteCodeFrameWithState(
bytecode_frame_p, 0, vm_thread); self, cfg->locals, cfg->globals, bytecode_frame_p, 0, cfg->vm_thread);
goto __exit; goto __exit;
__exit: __exit:
if (!is_use_heap_bytecode) { if (!is_use_heap_bytecode) {
byteCodeFrame_deinit(&bytecode_frame_stack); byteCodeFrame_deinit(&bytecode_frame_stack);
} }
return globals; return cfg->globals;
} }
VMParameters* pikaVM_runByteCodeFile(PikaObj* self, char* filename) { VMParameters* pikaVM_runByteCodeFile(PikaObj* self, char* filename) {
@ -3852,21 +3946,33 @@ VMParameters* pikaVM_runSingleFile(PikaObj* self, char* filename) {
char* lines = (char*)arg_getBytes(file_arg); char* lines = (char*)arg_getBytes(file_arg);
lines = strsFilePreProcess(&buffs, lines); lines = strsFilePreProcess(&buffs, lines);
/* clear the void line */ /* clear the void line */
VMParameters* res = pikaVM_run(self, lines); pikaVM_run_ex_cfg cfg = {0};
cfg.in_repl = pika_false;
char* module_name = strsPathGetFileName(&buffs, filename);
module_name = strsPopToken(&buffs, &module_name, '.');
cfg.module_name = module_name;
VMParameters* res = pikaVM_run_ex(self, lines, &cfg);
arg_deinit(file_arg); arg_deinit(file_arg);
strsDeinit(&buffs); strsDeinit(&buffs);
return res; return res;
} }
VMParameters* pikaVM_run(PikaObj* self, char* py_lines) { VMParameters* pikaVM_run(PikaObj* self, char* py_lines) {
return _pikaVM_runPyLines(self, py_lines, pika_false); pikaVM_run_ex_cfg cfg = {0};
cfg.in_repl = pika_false;
return pikaVM_run_ex(self, py_lines, &cfg);
} }
VMParameters* pikaVM_runByteCode(PikaObj* self, const uint8_t* bytecode) { VMParameters* pikaVM_runByteCode(PikaObj* self, const uint8_t* bytecode) {
PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE, PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE}; .try_result = TRY_RESULT_NONE};
return _do_pikaVM_runByteCode(self, self, self, (uint8_t*)bytecode, pikaVM_runBytecode_ex_cfg cfg = {0};
&vm_thread, pika_true); cfg.locals = self;
cfg.globals = self;
cfg.name = NULL;
cfg.vm_thread = &vm_thread;
cfg.is_const_bytecode = pika_true;
return pikaVM_runByteCode_ex(self, (uint8_t*)bytecode, &cfg);
} }
Arg* pikaVM_runByteCodeReturn(PikaObj* self, Arg* pikaVM_runByteCodeReturn(PikaObj* self,
@ -3884,15 +3990,19 @@ Arg* pikaVM_runByteCodeReturn(PikaObj* self,
return ret; return ret;
} }
Arg* _do_pikaVM_runByteCodeReturn(PikaObj* self, Arg* pikaVM_runByteCode_exReturn(PikaObj* self,
VMParameters* locals, VMParameters* locals,
VMParameters* globals, VMParameters* globals,
uint8_t* bytecode, uint8_t* bytecode,
PikaVMThread* vm_thread, PikaVMThread* vm_thread,
pika_bool is_const_bytecode, pika_bool is_const_bytecode,
char* return_name) { char* return_name) {
_do_pikaVM_runByteCode(self, locals, globals, bytecode, vm_thread, pikaVM_runBytecode_ex_cfg cfg = {0};
is_const_bytecode); cfg.locals = locals;
cfg.globals = globals;
cfg.vm_thread = vm_thread;
cfg.is_const_bytecode = is_const_bytecode;
pikaVM_runByteCode_ex(self, bytecode, &cfg);
Arg* ret = args_getArg(self->list, return_name); Arg* ret = args_getArg(self->list, return_name);
if (NULL == ret) { if (NULL == ret) {
return NULL; return NULL;
@ -3907,8 +4017,12 @@ Arg* _do_pikaVM_runByteCodeReturn(PikaObj* self,
VMParameters* pikaVM_runByteCodeInconstant(PikaObj* self, uint8_t* bytecode) { VMParameters* pikaVM_runByteCodeInconstant(PikaObj* self, uint8_t* bytecode) {
PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE, PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE}; .try_result = TRY_RESULT_NONE};
return _do_pikaVM_runByteCode(self, self, self, (uint8_t*)bytecode, pikaVM_runBytecode_ex_cfg cfg = {0};
&vm_thread, pika_false); cfg.locals = self;
cfg.globals = self;
cfg.vm_thread = &vm_thread;
cfg.is_const_bytecode = pika_false;
return pikaVM_runByteCode_ex(self, (uint8_t*)bytecode, &cfg);
} }
void constPool_update(ConstPool* self) { void constPool_update(ConstPool* self) {
@ -4017,11 +4131,14 @@ void byteCodeFrame_init(ByteCodeFrame* self) {
can not init */ can not init */
constPool_init(&(self->const_pool)); constPool_init(&(self->const_pool));
instructArray_init(&(self->instruct_array)); instructArray_init(&(self->instruct_array));
self->name = NULL;
self->label_pc = -1;
} }
extern const char magic_code_pyo[4]; extern const char magic_code_pyo[4];
void _do_byteCodeFrame_loadByteCode(ByteCodeFrame* self, void _do_byteCodeFrame_loadByteCode(ByteCodeFrame* self,
uint8_t* bytes, uint8_t* bytes,
char* name,
pika_bool is_const) { pika_bool is_const) {
if (bytes[0] == magic_code_pyo[0] && bytes[1] == magic_code_pyo[1] && if (bytes[0] == magic_code_pyo[0] && bytes[1] == magic_code_pyo[1] &&
bytes[2] == magic_code_pyo[2] && bytes[3] == magic_code_pyo[3]) { bytes[2] == magic_code_pyo[2] && bytes[3] == magic_code_pyo[3]) {
@ -4037,6 +4154,7 @@ void _do_byteCodeFrame_loadByteCode(ByteCodeFrame* self,
self->const_pool.size = *const_size_p; self->const_pool.size = *const_size_p;
self->const_pool.content_start = self->const_pool.content_start =
(char*)((uintptr_t)const_size_p + sizeof(*const_size_p)); (char*)((uintptr_t)const_size_p + sizeof(*const_size_p));
byteCodeFrame_setName(self, name);
if (!is_const) { if (!is_const) {
pika_assert(NULL == self->instruct_array.arg_buff); pika_assert(NULL == self->instruct_array.arg_buff);
pika_assert(NULL == self->instruct_array.arg_buff); pika_assert(NULL == self->instruct_array.arg_buff);
@ -4051,13 +4169,23 @@ void _do_byteCodeFrame_loadByteCode(ByteCodeFrame* self,
pika_assert(NULL != self->const_pool.content_start); pika_assert(NULL != self->const_pool.content_start);
} }
void byteCodeFrame_setName(ByteCodeFrame* self, char* name) {
if (name != NULL && self->name == NULL) {
self->name = pika_platform_malloc(strGetSize(name) + 1);
pika_platform_memcpy(self->name, name, strGetSize(name) + 1);
}
}
void byteCodeFrame_loadByteCode(ByteCodeFrame* self, uint8_t* bytes) { void byteCodeFrame_loadByteCode(ByteCodeFrame* self, uint8_t* bytes) {
_do_byteCodeFrame_loadByteCode(self, bytes, pika_true); _do_byteCodeFrame_loadByteCode(self, bytes, NULL, pika_true);
} }
void byteCodeFrame_deinit(ByteCodeFrame* self) { void byteCodeFrame_deinit(ByteCodeFrame* self) {
constPool_deinit(&(self->const_pool)); constPool_deinit(&(self->const_pool));
instructArray_deinit(&(self->instruct_array)); instructArray_deinit(&(self->instruct_array));
if (NULL != self->name) {
pika_platform_free(self->name);
}
} }
void instructArray_init(InstructArray* self) { void instructArray_init(InstructArray* self) {
@ -4313,13 +4441,13 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
int size = bytecode_frame->instruct_array.size; int size = bytecode_frame->instruct_array.size;
/* locals is the local scope */ /* locals is the local scope */
if (g_PikaVMSignal.vm_cnt == 0) { if (g_PikaVMState.vm_cnt == 0) {
pika_vmSignal_setCtrlClear(); pika_vmSignal_setCtrlClear();
} }
PikaVMFrame* vm = PikaVMFrame* vm =
PikaVMFrame_create(locals, globals, bytecode_frame, pc, vm_thread); PikaVMFrame_create(locals, globals, bytecode_frame, pc, vm_thread);
vm->in_repl = in_repl; vm->in_repl = in_repl;
g_PikaVMSignal.vm_cnt++; g_PikaVMState.vm_cnt++;
while (vm->pc < size) { while (vm->pc < size) {
if (vm->pc == VM_PC_EXIT) { if (vm->pc == VM_PC_EXIT) {
break; break;
@ -4332,6 +4460,7 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
vm->vm_thread->error_code = 0; vm->vm_thread->error_code = 0;
vm->vm_thread->line_error_code = 0; vm->vm_thread->line_error_code = 0;
} }
self->vmFrame = vm;
vm->pc = pikaVM_runInstructUnit(self, vm, this_ins_unit); vm->pc = pikaVM_runInstructUnit(self, vm, this_ins_unit);
vm->ins_cnt++; vm->ins_cnt++;
#if PIKA_INSTRUCT_HOOK_ENABLE #if PIKA_INSTRUCT_HOOK_ENABLE
@ -4376,12 +4505,71 @@ static VMParameters* __pikaVM_runByteCodeFrameWithState(
} }
PikaVMFrame_solveUnusedStack(vm); PikaVMFrame_solveUnusedStack(vm);
stack_deinit(&(vm->stack)); stack_deinit(&(vm->stack));
g_PikaVMSignal.vm_cnt--; g_PikaVMState.vm_cnt--;
VMParameters* result = locals; VMParameters* result = locals;
pikaFree(vm, sizeof(PikaVMFrame)); pikaFree(vm, sizeof(PikaVMFrame));
self->vmFrame = NULL;
return result; return result;
} }
pika_bool pika_debug_check_break(char* module_name, int pc_break) {
Hash h = hash_time33(module_name);
for (int i = 0; i < g_PikaVMState.break_point_cnt; i++) {
if (g_PikaVMState.break_module_hash[i] == h &&
g_PikaVMState.break_point_pc[i] == pc_break) {
return pika_true;
}
}
return pika_false;
}
pika_bool pika_debug_check_break_hash(Hash module_hash, int pc_break) {
for (int i = 0; i < g_PikaVMState.break_point_cnt; i++) {
if (g_PikaVMState.break_module_hash[i] == module_hash &&
g_PikaVMState.break_point_pc[i] == pc_break) {
return pika_true;
}
}
return pika_false;
}
PIKA_RES pika_debug_set_break(char* module_name, int pc_break) {
if (pika_debug_check_break(module_name, pc_break)) {
return PIKA_RES_OK;
}
if (g_PikaVMState.break_point_cnt >= PIKA_DEBUG_BREAK_POINT_MAX) {
return PIKA_RES_ERR_RUNTIME_ERROR;
}
Hash h = hash_time33(module_name);
g_PikaVMState.break_module_hash[g_PikaVMState.break_point_cnt] = h;
g_PikaVMState.break_point_pc[g_PikaVMState.break_point_cnt] = pc_break;
g_PikaVMState.break_point_cnt++;
return PIKA_RES_OK;
}
PIKA_RES pika_debug_reset_break(char* module_name, int pc_break) {
if (!pika_debug_check_break(module_name, pc_break)) {
return PIKA_RES_OK;
}
Hash h = hash_time33(module_name);
for (int i = 0; i < g_PikaVMState.break_point_cnt; i++) {
if (g_PikaVMState.break_module_hash[i] == h &&
g_PikaVMState.break_point_pc[i] == pc_break) {
// Move subsequent break points one position forward
for (int j = i; j < g_PikaVMState.break_point_cnt - 1; j++) {
g_PikaVMState.break_module_hash[j] =
g_PikaVMState.break_module_hash[j + 1];
g_PikaVMState.break_point_pc[j] =
g_PikaVMState.break_point_pc[j + 1];
}
// Decrease the count of break points
g_PikaVMState.break_point_cnt--;
return PIKA_RES_OK;
}
}
return PIKA_RES_ERR_RUNTIME_ERROR;
}
static VMParameters* _pikaVM_runByteCodeFrameWithState( static VMParameters* _pikaVM_runByteCodeFrameWithState(
PikaObj* self, PikaObj* self,
VMParameters* locals, VMParameters* locals,
@ -4402,6 +4590,16 @@ VMParameters* _pikaVM_runByteCodeFrame(PikaObj* self,
0, &vm_thread, in_repl); 0, &vm_thread, in_repl);
} }
VMParameters* _pikaVM_runByteCodeFrameGlobals(PikaObj* self,
PikaObj* globals,
ByteCodeFrame* byteCode_frame,
pika_bool in_repl) {
PikaVMThread vm_thread = {.try_state = TRY_STATE_NONE,
.try_result = TRY_RESULT_NONE};
return __pikaVM_runByteCodeFrameWithState(
self, self, globals, byteCode_frame, 0, &vm_thread, in_repl);
}
VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, VMParameters* pikaVM_runByteCodeFrame(PikaObj* self,
ByteCodeFrame* byteCode_frame) { ByteCodeFrame* byteCode_frame) {
return _pikaVM_runByteCodeFrame(self, byteCode_frame, pika_false); return _pikaVM_runByteCodeFrame(self, byteCode_frame, pika_false);

View File

@ -95,8 +95,8 @@ typedef struct JmpBufCQ {
} JmpBufCQ; } JmpBufCQ;
#endif #endif
typedef struct VMSignal VMSignal; typedef struct VMState VMState;
struct VMSignal { struct VMState {
VM_SIGNAL_CTRL signal_ctrl; VM_SIGNAL_CTRL signal_ctrl;
int vm_cnt; int vm_cnt;
#if PIKA_EVENT_ENABLE #if PIKA_EVENT_ENABLE
@ -106,6 +106,11 @@ struct VMSignal {
pika_bool event_thread_exit; pika_bool event_thread_exit;
pika_bool event_thread_exit_done; pika_bool event_thread_exit_done;
#endif #endif
#if PIKA_DEBUG_BREAK_POINT_MAX > 0
Hash break_module_hash[PIKA_DEBUG_BREAK_POINT_MAX];
uint32_t break_point_pc[PIKA_DEBUG_BREAK_POINT_MAX];
int break_point_cnt;
#endif
}; };
typedef Arg* (*VM_instruct_handler)(PikaObj* self, typedef Arg* (*VM_instruct_handler)(PikaObj* self,
@ -136,6 +141,10 @@ VMParameters* pikaVM_runAsm(PikaObj* self, char* pikaAsm);
VMParameters* _pikaVM_runByteCodeFrame(PikaObj* self, VMParameters* _pikaVM_runByteCodeFrame(PikaObj* self,
ByteCodeFrame* byteCode_frame, ByteCodeFrame* byteCode_frame,
pika_bool in_repl); pika_bool in_repl);
VMParameters* _pikaVM_runByteCodeFrameGlobals(PikaObj* self,
PikaObj* globals,
ByteCodeFrame* byteCode_frame,
pika_bool in_repl);
VMParameters* pikaVM_runByteCodeFrame(PikaObj* self, VMParameters* pikaVM_runByteCodeFrame(PikaObj* self,
ByteCodeFrame* byteCode_frame); ByteCodeFrame* byteCode_frame);
@ -208,6 +217,14 @@ static inline char* PikaVMFrame_getConstWithInstructUnit(
instructUnit_getConstPoolIndex(ins_unit)); instructUnit_getConstPoolIndex(ins_unit));
} }
pika_bool PikaVMFrame_checkBreakPoint(PikaVMFrame* vm);
typedef struct {
PikaObj* globals;
pika_bool in_repl;
char* module_name;
} pikaVM_run_ex_cfg;
char* constPool_getNow(ConstPool* self); char* constPool_getNow(ConstPool* self);
char* constPool_getNext(ConstPool* self); char* constPool_getNext(ConstPool* self);
char* constPool_getByIndex(ConstPool* self, uint16_t index); char* constPool_getByIndex(ConstPool* self, uint16_t index);
@ -215,6 +232,7 @@ void constPool_print(ConstPool* self);
void byteCodeFrame_init(ByteCodeFrame* bf); void byteCodeFrame_init(ByteCodeFrame* bf);
void byteCodeFrame_deinit(ByteCodeFrame* bf); void byteCodeFrame_deinit(ByteCodeFrame* bf);
void byteCodeFrame_setName(ByteCodeFrame* self, char* name);
size_t byteCodeFrame_getSize(ByteCodeFrame* bf); size_t byteCodeFrame_getSize(ByteCodeFrame* bf);
InstructUnit* byteCodeFrame_findInstructUnit(ByteCodeFrame* bcframe, InstructUnit* byteCodeFrame_findInstructUnit(ByteCodeFrame* bcframe,
int32_t iPcStart, int32_t iPcStart,
@ -229,6 +247,7 @@ InstructUnit* byteCodeFrame_findInsForward(ByteCodeFrame* bcframe,
int32_t pc_start, int32_t pc_start,
enum InstructIndex index, enum InstructIndex index,
int32_t* p_offset); int32_t* p_offset);
Hash byteCodeFrame_getNameHash(ByteCodeFrame* bcframe);
void instructArray_init(InstructArray* ins_array); void instructArray_init(InstructArray* ins_array);
void instructArray_deinit(InstructArray* ins_array); void instructArray_deinit(InstructArray* ins_array);
void instructArray_append(InstructArray* ins_array, InstructUnit* ins_unit); void instructArray_append(InstructArray* ins_array, InstructUnit* ins_unit);
@ -287,7 +306,7 @@ VMParameters* pikaVM_runByteCodeInconstant(PikaObj* self, uint8_t* bytecode);
Arg* pikaVM_runByteCodeReturn(PikaObj* self, Arg* pikaVM_runByteCodeReturn(PikaObj* self,
const uint8_t* bytecode, const uint8_t* bytecode,
char* returnName); char* returnName);
Arg* _do_pikaVM_runByteCodeReturn(PikaObj* self, Arg* pikaVM_runByteCode_exReturn(PikaObj* self,
VMParameters* locals, VMParameters* locals,
VMParameters* globals, VMParameters* globals,
uint8_t* bytecode, uint8_t* bytecode,
@ -306,14 +325,22 @@ Arg* _vm_slice(PikaVMFrame* vm,
Arg* obj, Arg* obj,
Arg* start, Arg* start,
int step); int step);
VMParameters* _do_pikaVM_runByteCode(PikaObj* self,
VMParameters* locals, typedef struct {
VMParameters* globals, VMParameters* locals;
VMParameters* globals;
char* name;
PikaVMThread* vm_thread;
pika_bool is_const_bytecode;
} pikaVM_runBytecode_ex_cfg;
VMParameters* pikaVM_runByteCode_ex(PikaObj* self,
uint8_t* bytecode, uint8_t* bytecode,
PikaVMThread* vm_thread, pikaVM_runBytecode_ex_cfg* cfg);
pika_bool is_const_bytecode);
void _do_byteCodeFrame_loadByteCode(ByteCodeFrame* self, void _do_byteCodeFrame_loadByteCode(ByteCodeFrame* self,
uint8_t* bytes, uint8_t* bytes,
char* name,
pika_bool is_const); pika_bool is_const);
Arg* _vm_get(PikaVMFrame* vm, PikaObj* self, Arg* key, Arg* obj); Arg* _vm_get(PikaVMFrame* vm, PikaObj* self, Arg* key, Arg* obj);
VM_SIGNAL_CTRL VMSignal_getCtrl(void); VM_SIGNAL_CTRL VMSignal_getCtrl(void);
@ -332,6 +359,11 @@ void __VMEvent_pickupEvent(char* info);
void _pikaVM_yield(void); void _pikaVM_yield(void);
int _VM_lock_init(void); int _VM_lock_init(void);
int _VM_is_first_lock(void); int _VM_is_first_lock(void);
PIKA_RES pika_debug_set_break(char* module_name, int pc_break);
void pika_debug_set_trace(PikaObj* self);
PIKA_RES pika_debug_reset_break(char* module_name, int pc_break);
pika_bool pika_debug_check_break_hash(Hash module_hash, int pc_break);
pika_bool pika_debug_check_break(char* module_name, int pc_break);
#define _VMEvent_pickupEvent() __VMEvent_pickupEvent(__FILE__) #define _VMEvent_pickupEvent() __VMEvent_pickupEvent(__FILE__)
@ -339,9 +371,9 @@ typedef struct {
PikaObj* lreg[PIKA_REGIST_SIZE]; PikaObj* lreg[PIKA_REGIST_SIZE];
} VMLocals; } VMLocals;
VMParameters* _pikaVM_runPyLines(PikaObj* self, VMParameters* pikaVM_run_ex(PikaObj* self,
char* py_lines, char* py_lines,
pika_bool in_repl); pikaVM_run_ex_cfg* cfg);
#endif #endif

View File

@ -2,4 +2,4 @@
#define PIKA_VERSION_MINOR 12 #define PIKA_VERSION_MINOR 12
#define PIKA_VERSION_MICRO 6 #define PIKA_VERSION_MICRO 6
#define PIKA_EDIT_TIME "2023/09/27 22:21:23" #define PIKA_EDIT_TIME "2023/09/30 00:30:20"

View File

@ -290,6 +290,10 @@ extern "C" {
#define PIKA_DEBUG_ENABLE 0 #define PIKA_DEBUG_ENABLE 0
#endif #endif
#ifndef PIKA_DEBUG_BREAK_POINT_MAX
#define PIKA_DEBUG_BREAK_POINT_MAX 8
#endif
#ifndef PIKA_FILEIO_ENABLE #ifndef PIKA_FILEIO_ENABLE
#define PIKA_FILEIO_ENABLE 1 #define PIKA_FILEIO_ENABLE 1
#endif #endif

View File

@ -40,7 +40,7 @@ void PikaStdData_List___init__(PikaObj *self) {}
void PikaStdData_List_append(PikaObj *self, Arg *arg) {} void PikaStdData_List_append(PikaObj *self, Arg *arg) {}
void PikaStdData_Dict___init__(PikaObj *self) {} void PikaStdData_Dict___init__(PikaObj *self) {}
void PikaStdData_Dict_set(PikaObj *self, char *key, Arg *val) {} void PikaStdData_Dict_set(PikaObj *self, char *key, Arg *val) {}
PikaObj *New_builtins_object(Args *args){return NULL;}; PikaObj *New_builtins_object(Args *args) { return NULL; };
PikaObj *New_PikaStdLib_SysObj(Args *args) { return NULL; }; PikaObj *New_PikaStdLib_SysObj(Args *args) { return NULL; };
PikaObj *New_builtins(Args *args) { return NULL; }; PikaObj *New_builtins(Args *args) { return NULL; };
PikaObj *New_builtins_RangeObj(Args *args) { return NULL; } PikaObj *New_builtins_RangeObj(Args *args) { return NULL; }
@ -50,6 +50,23 @@ char *string_slice(Args *outBuffs, char *str, int start, int end) {
} }
int PikaStdData_FILEIO_init(PikaObj *self, char *path, char *mode) { return 0; } int PikaStdData_FILEIO_init(PikaObj *self, char *path, char *mode) { return 0; }
static int handle_breakpoint_option(int argc, char **argv, int i) {
if (0 == strcmp(argv[i], "--break-point")) {
if (i + 2 < argc) {
uint32_t pc =
pika_debug_find_break_point_pc(argv[i + 1], atoi(argv[i + 2]));
// printf("break point pc: %d\r\n", pc);
/* json output */
printf("{\"pc\":%d}\r\n", pc);
return 0;
} else {
printf("Invalid --break-point option usage.\n");
return -1;
}
}
return -1;
}
static int _do_main(int argc, char **argv) { static int _do_main(int argc, char **argv) {
int parc = argc - 1; int parc = argc - 1;
PikaMaker *maker = New_PikaMaker(); PikaMaker *maker = New_PikaMaker();
@ -68,6 +85,11 @@ static int _do_main(int argc, char **argv) {
/* delete --xxx yyy */ /* delete --xxx yyy */
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
int res = handle_breakpoint_option(argc, argv, i);
if (0 == res) {
return 0;
}
if (0 == strcmp(argv[i], "--add-file")) { if (0 == strcmp(argv[i], "--add-file")) {
// printf("before delete: %d\r\n", parc); // printf("before delete: %d\r\n", parc);
// for (int j = 0; j < parc; j++) { // for (int j = 0; j < parc; j++) {