diff options
| -rw-r--r-- | uscript/parser.c | 57 | ||||
| -rw-r--r-- | uscript/vm.c | 2 |
2 files changed, 50 insertions, 9 deletions
diff --git a/uscript/parser.c b/uscript/parser.c index d3f1432..5740474 100644 --- a/uscript/parser.c +++ b/uscript/parser.c @@ -156,7 +156,7 @@ void expect(struct parser *p, u16 tok, const char *err) } static -void declare_variable(struct parser *p, struct token name) +int declare_variable(struct parser *p, struct token name) { if (da_len(p->fp->locals) > UINT8_MAX) show_error(p, name, "too many locals"); @@ -165,6 +165,21 @@ void declare_variable(struct parser *p, struct token name) slot.name = name; slot.captured = false; da_append(struct variable, &p->fp->locals, slot); + + return da_len(p->fp->locals) - 1; +} + +static +int declare_named_variable(struct parser *p, const char* name) +{ + struct token token; + token.start = name; + token.len = (int)strlen(name); + token.line = p->cur.line; + token.col = p->cur.col; + token.kind = TOKEN_IDENT; + token.val = create_zilch(); + return declare_variable(p, token); } static @@ -663,6 +678,7 @@ void if_stat(struct parser *p, bool is_elseif) expr(p); int jump = begin_jump(p, BC_FALSEY_JMP); + parser_add_byte(p, BC_POP); if (!is_elseif) expect(p, ':', "expected ':' to begin 'if' block"); @@ -683,6 +699,7 @@ void if_stat(struct parser *p, bool is_elseif) int else_jump = begin_jump(p, BC_JMP); end_jump(p, jump); + parser_add_byte(p, BC_POP); // The only reason "elseif" was chosen over "else if" is because it // reduces indentation in this one single spot. @@ -705,9 +722,6 @@ void if_stat(struct parser *p, bool is_elseif) static void loop_stat(struct parser *p) { - // For now, we will just support loop <cond>. loop <var> in <expr> - // needs a lot to happen before it can be implemented. - struct token begin = p->prev; struct loop loop; @@ -721,10 +735,36 @@ void loop_stat(struct parser *p) int exit_jump = -1; if (!consume(p, ':')) { - expr(p); - exit_jump = begin_jump(p, BC_FALSEY_JMP); + if (consume(p, TOKEN_LET)) { + expect(p, TOKEN_IDENT, "expected identifier"); + struct token ident = p->prev; + + expect(p, TOKEN_IN, "expected 'in'"); + + expr(p); + + int iter = declare_named_variable(p, "<iter>"); + + begin_scope(p); + loop.start = da_len(p->fp->proto->bytecode) - 1; + + parser_add_byte(p, BC_GET_LOCAL); + parser_add_byte(p, (u8)iter); + parser_add_byte(p, BC_CALL); + parser_add_byte(p, 0); + + exit_jump = begin_jump(p, BC_FALSEY_JMP); + + declare_variable(p, ident); + } else { + expr(p); + exit_jump = begin_jump(p, BC_FALSEY_JMP); + parser_add_byte(p, BC_POP); + } expect(p, ':', "expected ':' to begin 'loop' block"); + } else { + begin_scope(p); } if (consume(p, '<')) { @@ -734,14 +774,15 @@ void loop_stat(struct parser *p) expect(p, '>', "expected '>' after loop label"); } - begin_scope(p); while (p->cur.kind != TOKEN_END && p->cur.kind != TOKEN_EOF) stat(p); end_scope(p); add_loop(p, loop.start); - if (exit_jump != -1) + if (exit_jump != -1) { end_jump(p, exit_jump); + parser_add_byte(p, BC_POP); + } for (int i = 0; i < da_len(loop.breaks); i++) end_jump(p, loop.breaks[i]); diff --git a/uscript/vm.c b/uscript/vm.c index d68e850..18f1eaf 100644 --- a/uscript/vm.c +++ b/uscript/vm.c @@ -403,7 +403,7 @@ void us_exec(struct us_func *func) } case BC_FALSEY_JMP: { u16 jmp = read_short(); - if (as_bool(vm_pop())) + if (as_bool(vm_peek())) break; i += jmp; break; |
