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);
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);
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 */
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);

View File

@ -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;