support elif and else

This commit is contained in:
lyon 2021-12-14 22:17:37 +08:00
parent b6bb611d17
commit 484b6a1860
4 changed files with 171 additions and 26 deletions

View File

@ -522,3 +522,52 @@ TEST(VM, equ) {
ASSERT_FLOAT_EQ(c, 1); ASSERT_FLOAT_EQ(c, 1);
EXPECT_EQ(pikaMemNow(), 0); 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);
}

View File

@ -1300,3 +1300,77 @@ TEST(parser, annotation_block) {
args_deinit(buffs); args_deinit(buffs);
EXPECT_EQ(pikaMemNow(), 0); 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);
}

View File

@ -984,50 +984,57 @@ char* AST_toPikaAsm(AST* ast, Args* buffs) {
/* "deepth" is invoke deepth, not the blockDeepth */ /* "deepth" is invoke deepth, not the blockDeepth */
obj_setInt(ast, "deepth", 0); obj_setInt(ast, "deepth", 0);
/* parse ast to asm main process */
pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm);
/* match block */ /* match block */
uint8_t is_block_matched = 0;
if (strEqu(obj_getStr(ast, "block"), "while")) { 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"); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 2\n");
goto block_matched; is_block_matched = 1;
goto exit;
} }
if (strEqu(obj_getStr(ast, "block"), "if")) { 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"); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n");
goto block_matched; is_block_matched = 1;
goto exit;
} }
if (strEqu(obj_getStr(ast, "block"), "else")) { if (strEqu(obj_getStr(ast, "block"), "else")) {
uint8_t blockDeepth = obj_getInt(ast, "blockDeepth"); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 NEL 1\n");
char __REF_else[] = "0 REF __else0\n"; goto exit;
__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;
} }
if (strEqu(obj_getStr(ast, "block"), "elif")) { if (strEqu(obj_getStr(ast, "block"), "elif")) {
uint8_t blockDeepth = obj_getInt(ast, "blockDeepth"); /* skip if __else is 0 */
char __REF_else[] = "0 REF __else0\n"; pikaAsm = strsAppend(runBuffs, pikaAsm, "0 NEL 1\n");
__REF_else[12] = blockDeepth + '0'; /* parse stmt ast */
pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm);
/* skip if stmt is 0 */ /* skip if stmt is 0 */
pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n"); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n");
/* skip if __else is 0 */ is_block_matched = 1;
pikaAsm = strsAppend(runBuffs, pikaAsm, __REF_else); goto exit;
pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JEZ 1\n");
goto block_matched;
} }
if (strEqu(obj_getStr(ast, "block"), "def")) { if (strEqu(obj_getStr(ast, "block"), "def")) {
pikaAsm = strsAppend(runBuffs, pikaAsm, "0 DEF "); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 DEF ");
pikaAsm = strsAppend(runBuffs, pikaAsm, obj_getStr(ast, "declear")); pikaAsm = strsAppend(runBuffs, pikaAsm, obj_getStr(ast, "declear"));
pikaAsm = strsAppend(runBuffs, pikaAsm, "\n"); pikaAsm = strsAppend(runBuffs, pikaAsm, "\n");
pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JMP 1\n"); pikaAsm = strsAppend(runBuffs, pikaAsm, "0 JMP 1\n");
goto block_matched; is_block_matched = 1;
goto exit;
} }
if (obj_isArgExist(ast, "return")) { if (obj_isArgExist(ast, "return")) {
/* parse stmt ast */
pikaAsm = AST_appandPikaAsm(ast, ast, runBuffs, pikaAsm);
pikaAsm = strsAppend(runBuffs, pikaAsm, "0 RET\n"); 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 */ /* output pikaAsm */
pikaAsm = strsCopy(buffs, pikaAsm); pikaAsm = strsCopy(buffs, pikaAsm);
args_deinit(runBuffs); args_deinit(runBuffs);

View File

@ -43,7 +43,7 @@ static int32_t getLineSize(char* str) {
i++; 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) { static char* strs_getLine(Args* buffs, char* code) {
int32_t lineSize = getLineSize(code); int32_t lineSize = getLineSize(code);
@ -94,6 +94,10 @@ static enum Instruct getInstruct(char* line) {
/* return */ /* return */
return RET; return RET;
} }
if (0 == strncmp(line + 2, "NEL", 3)) {
/* not else */
return NEL;
}
return NON; return NON;
} }
@ -174,13 +178,24 @@ Arg* pikaVM_runInstruct(PikaObj* self,
arg_deinit(assertArg); arg_deinit(assertArg);
char __else[] = "__else0"; char __else[] = "__else0";
__else[6] = '0' + thisBlockDeepth; __else[6] = '0' + thisBlockDeepth;
args_setInt(self->list, __else, !assert);
if (0 == assert) { if (0 == assert) {
/* set __else flag */ /* set __else flag */
args_setInt(self->list, __else, 1);
*jmp = fast_atoi(data); *jmp = fast_atoi(data);
} }
/* set __else flag to ezro */ return NULL;
args_setInt(self->list, __else, 0); }
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) { if (instruct == OPT) {
Arg* outArg = NULL; Arg* outArg = NULL;