diff --git a/port/linux/test/VM-test.cpp b/port/linux/test/VM-test.cpp index d997a5649..55fcef24c 100644 --- a/port/linux/test/VM-test.cpp +++ b/port/linux/test/VM-test.cpp @@ -522,3 +522,52 @@ TEST(VM, equ) { ASSERT_FLOAT_EQ(c, 1); EXPECT_EQ(pikaMemNow(), 0); } + +TEST(VM, if_elif) { + char* line = (char*) + "a = 2\n" + "b = 0\n" + "if a > 1:\n" + " b = 1\n" + "elif a > 0:\n" + " b = 2\n" + "\n" + ; + Args* buffs = New_strBuff(); + char* pikaAsm = Parser_multiLineToAsm(buffs, line); + printf("%s", pikaAsm); + PikaObj* self = newRootObj((char*)"root", New_PikaStdLib_SysObj); + Parameters* globals = pikaVM_runAsm(self, pikaAsm); + + int b = args_getInt(globals->list, (char*)"b"); + obj_deinit(self); + args_deinit(buffs); + // obj_deinit(globals); + ASSERT_FLOAT_EQ(b, 1); + EXPECT_EQ(pikaMemNow(), 0); +} + +TEST(VM, if_else) { + char* line = (char*) + "a = 0\n" + "b = 0\n" + "if a > 1:\n" + " b = 1\n" + "else:\n" + " b = 2\n" + "\n" + ; + Args* buffs = New_strBuff(); + char* pikaAsm = Parser_multiLineToAsm(buffs, line); + printf("%s", pikaAsm); + PikaObj* self = newRootObj((char*)"root", New_PikaStdLib_SysObj); + Parameters* globals = pikaVM_runAsm(self, pikaAsm); + + int b = args_getInt(globals->list, (char*)"b"); + obj_deinit(self); + args_deinit(buffs); + // obj_deinit(globals); + ASSERT_FLOAT_EQ(b, 2); + EXPECT_EQ(pikaMemNow(), 0); +} + diff --git a/port/linux/test/parse-test.cpp b/port/linux/test/parse-test.cpp index c8d52e129..06f34151f 100644 --- a/port/linux/test/parse-test.cpp +++ b/port/linux/test/parse-test.cpp @@ -1300,3 +1300,77 @@ TEST(parser, annotation_block) { args_deinit(buffs); EXPECT_EQ(pikaMemNow(), 0); } + +TEST(parser, if_elif_else) { + pikaMemInfo.heapUsedMax = 0; + Args* buffs = New_strBuff(); + char* lines = (char*) + "if a > 1:\n" + " b = 1\n" + "elif a > 2:\n" + " b = 2\n" + " if a > 1:\n" + " b = 1\n" + " elif a > 2:\n" + " b = 2\n" + " else:\n" + " b = 3\n" + "\n" + "else:\n" + " b = 3\n" + "\n" + ; + printf("%s", lines); + char* pikaAsm = Parser_multiLineToAsm(buffs, (char*)lines); + printf("%s", pikaAsm); + EXPECT_STREQ(pikaAsm,(char *) + "B0\n" + "1 REF a\n" + "1 NUM 1\n" + "0 OPT >\n" + "0 JEZ 1\n" + "B1\n" + "0 NUM 1\n" + "0 OUT b\n" + "B0\n" + "0 NEL 1\n" + "1 REF a\n" + "1 NUM 2\n" + "0 OPT >\n" + "0 JEZ 1\n" + "B1\n" + "0 NUM 2\n" + "0 OUT b\n" + "B1\n" + "1 REF a\n" + "1 NUM 1\n" + "0 OPT >\n" + "0 JEZ 1\n" + "B2\n" + "0 NUM 1\n" + "0 OUT b\n" + "B1\n" + "0 NEL 1\n" + "1 REF a\n" + "1 NUM 2\n" + "0 OPT >\n" + "0 JEZ 1\n" + "B2\n" + "0 NUM 2\n" + "0 OUT b\n" + "B1\n" + "0 NEL 1\n" + "B2\n" + "0 NUM 3\n" + "0 OUT b\n" + "B0\n" + "B0\n" + "0 NEL 1\n" + "B1\n" + "0 NUM 3\n" + "0 OUT b\n" + "B0\n" + ); + args_deinit(buffs); + EXPECT_EQ(pikaMemNow(), 0); +} \ No newline at end of file diff --git a/src/PikaParser.c b/src/PikaParser.c index bbed56762..ac650d910 100644 --- a/src/PikaParser.c +++ b/src/PikaParser.c @@ -984,50 +984,57 @@ char* AST_toPikaAsm(AST* ast, Args* buffs) { /* "deepth" is invoke deepth, not the blockDeepth */ obj_setInt(ast, "deepth", 0); - /* parse ast to asm main process */ - pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm); - /* match block */ + uint8_t is_block_matched = 0; if (strEqu(obj_getStr(ast, "block"), "while")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 2\n"); - goto block_matched; + is_block_matched = 1; + goto exit; } if (strEqu(obj_getStr(ast, "block"), "if")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n"); - goto block_matched; + is_block_matched = 1; + goto exit; } if (strEqu(obj_getStr(ast, "block"), "else")) { - uint8_t blockDeepth = obj_getInt(ast, "blockDeepth"); - char __REF_else[] = "0 REF __else0\n"; - __REF_else[12] = blockDeepth + '0'; - /* skip if __else is 0 */ - pikaAsm = strsAppend(runBuffs, pikaAsm, __REF_else); - pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n"); - goto block_matched; + pikaAsm = strsAppend(runBuffs, pikaAsm, "0 NEL 1\n"); + goto exit; } if (strEqu(obj_getStr(ast, "block"), "elif")) { - uint8_t blockDeepth = obj_getInt(ast, "blockDeepth"); - char __REF_else[] = "0 REF __else0\n"; - __REF_else[12] = blockDeepth + '0'; + /* skip if __else is 0 */ + pikaAsm = strsAppend(runBuffs, pikaAsm, "0 NEL 1\n"); + /* parse stmt ast */ + pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm); /* skip if stmt is 0 */ pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n"); - /* skip if __else is 0 */ - pikaAsm = strsAppend(runBuffs, pikaAsm, __REF_else); - pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n"); - goto block_matched; + is_block_matched = 1; + goto exit; } if (strEqu(obj_getStr(ast, "block"), "def")) { pikaAsm = strsAppend(runBuffs, pikaAsm, "0 DEF "); pikaAsm = strsAppend(runBuffs, pikaAsm, obj_getStr(ast, "declear")); pikaAsm = strsAppend(runBuffs, pikaAsm, "\n"); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JMP 1\n"); - goto block_matched; + is_block_matched = 1; + goto exit; } if (obj_isArgExist(ast, "return")) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 RET\n"); - goto block_matched; + is_block_matched = 1; + goto exit; } -block_matched: +exit: + if (!is_block_matched) { + /* parse stmt ast */ + pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm); + } + /* output pikaAsm */ pikaAsm = strsCopy(buffs, pikaAsm); args_deinit(runBuffs); diff --git a/src/PikaVM.c b/src/PikaVM.c index eadeeb857..c8df716e4 100644 --- a/src/PikaVM.c +++ b/src/PikaVM.c @@ -43,7 +43,7 @@ static int32_t getLineSize(char* str) { i++; } } -enum Instruct { NON, REF, RUN, STR, OUT, NUM, JMP, JEZ, OPT, DEF, RET }; +enum Instruct { NON, REF, RUN, STR, OUT, NUM, JMP, JEZ, OPT, DEF, RET, NEL }; static char* strs_getLine(Args* buffs, char* code) { int32_t lineSize = getLineSize(code); @@ -94,6 +94,10 @@ static enum Instruct getInstruct(char* line) { /* return */ return RET; } + if (0 == strncmp(line + 2, "NEL", 3)) { + /* not else */ + return NEL; + } return NON; } @@ -174,13 +178,24 @@ Arg* pikaVM_runInstruct(PikaObj* self, arg_deinit(assertArg); char __else[] = "__else0"; __else[6] = '0' + thisBlockDeepth; + args_setInt(self->list, __else, !assert); if (0 == assert) { /* set __else flag */ - args_setInt(self->list, __else, 1); *jmp = fast_atoi(data); } - /* set __else flag to ezro */ - args_setInt(self->list, __else, 0); + return NULL; + } + if (instruct == NEL) { + int offset = 0; + int thisBlockDeepth = + getThisBlockDeepth(asmStart, programConter, &offset); + char __else[] = "__else0"; + __else[6] = '0' + thisBlockDeepth; + if (0 == args_getInt(self->list, __else)) { + /* set __else flag */ + *jmp = fast_atoi(data); + } + return NULL; } if (instruct == OPT) { Arg* outArg = NULL;