diff options
| author | 2022-08-16 05:42:36 +0200 | |
|---|---|---|
| committer | 2022-08-16 05:42:36 +0200 | |
| commit | 04c7892134d49f3b295a51cc741affe9f02e374d (patch) | |
| tree | c94c4501b9d448c057bd736ee7b718daefcb304f /bootstrap | |
| parent | 5bc23671b5569d86196643f58f4f70997383b4a4 (diff) | |
nullish coalescing operator ??
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/cgen.c | 2 | ||||
| -rw-r--r-- | bootstrap/parse.c | 37 |
2 files changed, 28 insertions, 11 deletions
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index 665bdc5..15fab93 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -222,7 +222,7 @@ genexpr(struct expr *ex) { pri("(%e)%c", ex->unop.child, ex->unop.op); break; case Ebinop: - pri("(%e %c %e)", ex->binop.lhs, ex->binop.op, ex->binop.rhs); + pri("((%e) %c (%e))", ex->binop.lhs, ex->binop.op == '?\?' ? '?:' : ex->binop.op, ex->binop.rhs); break; case Econd: pri("((%e) ? (%e) : (%e))", ex->cond.test, ex->cond.t, ex->cond.f); diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 08f83a8..2eda662 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -439,9 +439,13 @@ lex(struct parser *P) { switch ((c = chr(P))) { case '(': case ')': case '[': case ']': case '{': case '}': case ',': - case ';': case '?': case '~': + case ';': case '~': tok.t = c; return tok; + case '?': + if (chrmatch(P, '?')) tok.t = '\?\?'; + else tok.t = '?'; + return tok; case '.': if (chrmatch(P, '.')) { if (chr(P) != '.') @@ -1720,20 +1724,33 @@ pexlog(struct parser *P) { if (P->used_targty) return ex; tok = lexpeek(P); tokt = tok.t; - if (tokt != TKkw_and && tokt != TKkw_or) + if (tokt != TKkw_and && tokt != TKkw_or && tokt != '?\?') return ex; while (lexmatch(P, &tok, tokt)) { struct expr rhs = pexcmp(P); - if (ex.ty->t != TYbool || rhs.ty->t != TYbool) - fatal(P, tok.span, - "invalid operands %t and %t to binary operator %k", + if (tokt == '?\?') { + const struct type *ty = typeof2(ex.ty, rhs.ty); + if (ex.ty->t != TYptr || rhs.ty->t != TYptr || !ty) + fatal(P, tok.span, + "invalid operands %t and %t to binary operator %k", ex.ty, rhs.ty, tok.t); - ex = (struct expr) { - Ebinop, tok.span, ty_bool, .binop = { - tokt == TKkw_and ? 'and' : 'or', exprdup(ex), exprdup(rhs) - } - }; + ex = (struct expr) { + Ebinop, tok.span, ty, .binop = { + '?\?', exprdup(ex), exprdup(rhs) + } + }; + } else { + if (ex.ty->t != TYbool || rhs.ty->t != TYbool) + fatal(P, tok.span, + "invalid operands %t and %t to binary operator %k", + ex.ty, rhs.ty, tok.t); + ex = (struct expr) { + Ebinop, tok.span, ty_bool, .binop = { + tokt == TKkw_and ? 'and' : 'or', exprdup(ex), exprdup(rhs) + } + }; + } } |