aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-16 05:42:36 +0200
committerlemon <lsof@mailbox.org>2022-08-16 05:42:36 +0200
commit04c7892134d49f3b295a51cc741affe9f02e374d (patch)
treec94c4501b9d448c057bd736ee7b718daefcb304f /bootstrap
parent5bc23671b5569d86196643f58f4f70997383b4a4 (diff)
nullish coalescing operator ??
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/cgen.c2
-rw-r--r--bootstrap/parse.c37
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)
+ }
+ };
+ }
}