Update compiler.c

This commit is contained in:
blueloveTH 2024-07-05 13:38:07 +08:00
parent 8a257199a3
commit 84004349db

View File

@ -1,5 +1,6 @@
#include "pocketpy/compiler/compiler.h"
#include "pocketpy/compiler/lexer.h"
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/sourcedata.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/common/strname.h"
@ -2016,6 +2017,105 @@ static Error* consume_type_hints(Compiler* self) {
return NULL;
}
static Error* compile_stmt(Compiler* self);
static Error* compile_block_body(Compiler* self, PrattCallback callback) {
Error* err;
assert(callback != NULL);
consume(TK_COLON);
if(curr()->type != TK_EOL && curr()->type != TK_EOF) {
while(true) {
check(compile_stmt(self));
bool possible = curr()->type != TK_EOL && curr()->type != TK_EOF;
if(prev()->type != TK_SEMICOLON || !possible) break;
}
return NULL;
}
bool need_more_lines;
bool consumed = match_newlines_repl(self, &need_more_lines);
if(need_more_lines) return NeedMoreLines();
if(!consumed) return SyntaxError("expected a new line after ':'");
consume(TK_INDENT);
while(curr()->type != TK_DEDENT) {
match_newlines();
check(callback(self));
match_newlines();
}
consume(TK_DEDENT);
return NULL;
}
static Error* compile_if_stmt(Compiler* self) {
Error* err;
check(EXPR(self)); // condition
Ctx__s_emit_top(ctx());
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, prev()->line);
err = compile_block_body(self, compile_stmt);
if(err) return err;
if(match(TK_ELIF)) {
int exit_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, prev()->line);
Ctx__patch_jump(ctx(), patch);
check(compile_if_stmt(self));
Ctx__patch_jump(ctx(), exit_patch);
} else if(match(TK_ELSE)) {
int exit_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, prev()->line);
Ctx__patch_jump(ctx(), patch);
check(compile_block_body(self, compile_stmt));
Ctx__patch_jump(ctx(), exit_patch);
} else {
Ctx__patch_jump(ctx(), patch);
}
return NULL;
}
static Error* compile_while_loop(Compiler* self) {
Error* err;
CodeBlock* block = Ctx__enter_block(ctx(), CodeBlockType_WHILE_LOOP);
check(EXPR(self)); // condition
Ctx__s_emit_top(ctx());
int patch = Ctx__emit_(ctx(), OP_POP_JUMP_IF_FALSE, BC_NOARG, prev()->line);
check(compile_block_body(self, compile_stmt));
Ctx__emit_virtual(ctx(), OP_LOOP_CONTINUE, Ctx__get_loop(ctx()), BC_KEEPLINE, true);
Ctx__patch_jump(ctx(), patch);
Ctx__exit_block(ctx());
// optional else clause
if(match(TK_ELSE)) {
check(compile_block_body(self, compile_stmt));
block->end2 = ctx()->co->codes.count;
}
return NULL;
}
static Error* compile_for_loop(Compiler* self) {
Error* err;
check(EXPR_VARS(self)); // [vars]
consume(TK_IN);
check(EXPR_TUPLE(self)); // [vars, iter]
Ctx__s_emit_top(ctx()); // [vars]
Ctx__emit_(ctx(), OP_GET_ITER_NEW, BC_NOARG, BC_KEEPLINE);
CodeBlock* block = Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP);
int for_codei = Ctx__emit_(ctx(), OP_FOR_ITER, ctx()->curr_iblock, BC_KEEPLINE);
Expr* vars = Ctx__s_popx(ctx());
bool ok = vtemit_store(vars, ctx());
vtdelete(vars);
if(!ok) return SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
// TODO: ??
// ctx()->try_merge_for_iter_store(for_codei);
check(compile_block_body(self, compile_stmt));
Ctx__emit_virtual(ctx(), OP_LOOP_CONTINUE, Ctx__get_loop(ctx()), BC_KEEPLINE, true);
Ctx__exit_block(ctx());
// optional else clause
if(match(TK_ELSE)) {
check(compile_block_body(self, compile_stmt));
block->end2 = ctx()->co->codes.count;
}
return NULL;
}
Error* try_compile_assignment(Compiler* self, bool* is_assign) {
Error* err;
switch(curr()->type) {
@ -2129,9 +2229,9 @@ static Error* compile_stmt(Compiler* self) {
}
break;
/*************************************************/
// case TK_IF: check(compile_if_stmt()); break;
// case TK_WHILE: check(compile_while_loop()); break;
// case TK_FOR: check(compile_for_loop()); break;
case TK_IF: check(compile_if_stmt(self)); break;
case TK_WHILE: check(compile_while_loop(self)); break;
case TK_FOR: check(compile_for_loop(self)); break;
// case TK_IMPORT: check(compile_normal_import()); break;
// case TK_FROM: check(compile_from_import()); break;
// case TK_DEF: check(compile_function()); break;