Skip to content

Commit

Permalink
Implement else
Browse files Browse the repository at this point in the history
  • Loading branch information
cpq committed May 4, 2021
1 parent 598b7b4 commit ecae62c
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ int main(void) {
- No `!=`, `==`. Use `!==`, `===`
- No `var`, no `const`. Use `let`. Strict mode only
- No `do`, `switch`, `for`. Use `while`
- No `else`, only `if`. No ternary operator `a ? b : c`
- No ternary operator `a ? b : c`
- No arrays, closures, prototypes, `this`, `new`, `delete`, `instanceof`
- No standard library: no `Date`, `Regexp`, `Function`, `String`, `Number`
- Strings are binary data chunks, not Unicode strings
Expand Down
15 changes: 11 additions & 4 deletions elk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1104,11 +1104,18 @@ static jsval_t js_if(struct js *js) {
if (next(js) != TOK_LPAREN) return js_err(js, "parse error");
jsval_t cond = js_expr(js, TOK_RPAREN, TOK_EOF);
if (js->tok != TOK_RPAREN) return js_err(js, "parse error");
uint8_t flags = js->flags;
bool noexec = js->flags & F_NOEXEC;
bool cond_true = js_truthy(js, cond);
if (!cond_true) js->flags |= F_NOEXEC;
jsval_t res = js_block_or_stmt(js);
if (!cond_true && !(flags & F_NOEXEC)) js->flags &= ~F_NOEXEC;
if (!cond_true && !noexec) js->flags &= ~F_NOEXEC;
if (lookahead(js) == TOK_ELSE) {
next(js);
if (cond_true) js->flags |= F_NOEXEC;
res = js_block_or_stmt(js);
if (cond_true && !noexec) js->flags &= ~F_NOEXEC;
}
// printf("IF: else %d\n", lookahead(js) == TOK_ELSE);
return res;
}

Expand Down Expand Up @@ -1158,8 +1165,8 @@ static jsval_t js_stmt(struct js *js, uint8_t etok) {
case TOK_CASE: case TOK_CATCH: case TOK_CLASS: case TOK_CONST:
case TOK_DEFAULT: case TOK_DELETE: case TOK_DO: case TOK_FINALLY:
case TOK_FOR: case TOK_IN: case TOK_INSTANCEOF: case TOK_NEW:
case TOK_ELSE: case TOK_SWITCH: case TOK_THIS: case TOK_THROW:
case TOK_TRY: case TOK_VAR: case TOK_VOID: case TOK_WITH: case TOK_YIELD:
case TOK_SWITCH: case TOK_THIS: case TOK_THROW: case TOK_TRY:
case TOK_VAR: case TOK_VOID: case TOK_WITH: case TOK_YIELD:
return js_err(js, "'%.*s' not implemented", (int) js->tlen, js->code + js->toff);
case TOK_CONTINUE: return js_continue(js);
case TOK_BREAK: return js_break(js);
Expand Down
9 changes: 9 additions & 0 deletions test/unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ static void test_flow(void) {
assert(ev(js, "a = b = 0; while (b++ < 10) while (a < b) a++; a", "10"));
assert(ev(js, "a = 0; while (1) { if (a++ < 10) continue; break;} a", "11"));
assert(ev(js, "a=b=0; while (b++<10) {true;a++;} a", "10"));
assert(ev(js, "a=b=0; if (false) b++; else b--; b", "-1"));
assert(ev(js, "a=b=0; if (false) {b++;} else {b--;} b", "-1"));
assert(ev(js, "a=b=0; if (false) {2;b++;} else {2;b--;} b", "-1"));
assert(ev(js, "a=b=0; if (true) b++; else b--; b", "1"));
assert(ev(js, "a=b=0; if (true) {2;b++;} else {2;b--;} b", "1"));
assert(ev(js, "a=0; if (1) a=1; else if (0) a=2; a;", "1"));
assert(ev(js, "a=0; if (0) a=1; else if (1) a=2; a;", "2"));
assert(ev(js, "a=0; if (0){7;a=1;}else if (1){7;a=2;} a;", "2"));
assert(ev(js, "a=0; if(0){7;a=1;}else if(0){5;a=2;}else{3;a=3;} a;", "3"));
}

static void test_scopes(void) {
Expand Down

0 comments on commit ecae62c

Please sign in to comment.