aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff60
1 files changed, 59 insertions, 1 deletions
diff --git a/src/parse.cff b/src/parse.cff
index 613b4ae..7ce605c 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -646,7 +646,10 @@ fn parseenum(P *Parser, name *const u8, lax bool) *const Type {
break;
}
}
- let intty *const Type = #null;
+ let intty *const Type =
+ max < 1u64 << ((g_targ.intsize * 8) - 1) ? ty_int
+ : max < 1u64 << 31 ? ty_i32
+ : ty_i64;
static id int = 0;
return interntype({ .u: :Enum { intty, name, lax, id++, vals->move(P.alloc) }});
}
@@ -1788,6 +1791,58 @@ fn pstfor(P *Parser) Stmt {
return { loc, :For { ini, test, next, body, P.loopid }};
}
+fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt {
+ let tok Tok #?;
+ let cs Vec<ISwitchCase> = {};
+ let f [#]Stmt = {};
+ let elsep = #f;
+ while !lexmatch(P, &tok, '}') {
+ lexexpect(P, :kw_case);
+ if lexmatch(P, &tok, :kw_else) {
+ if elsep {
+ err(P, tok.loc, "duplicate else case");
+ }
+ elsep = #t;
+ f = parseblock0(P);
+ continue;
+ }
+ let es Vec<Expr> = {};
+ do {
+ let e = parseexpr(P);
+ if !fold(&e) {
+ err(P, e.loc, "expected compile-time expression");
+ }
+ if !typematchestarg(ex.ty, e.ty) {
+ err(P, e.loc, "bad case expression (%t, expected %t)", e.ty, ex.ty);
+ }
+ es->push(e);
+ if !lexmatch(P, #null, ',') {
+ lexexpect(P, ';');
+ break;
+ }
+ } while !lexmatch(P, #null, ';');
+ cs->push({ es->move(P.alloc), parseblock0(P) });
+ }
+
+ return { loc, :ISwitch { ex, cs->move(P.alloc), f }};
+}
+
+fn pstswitch(P *Parser) Stmt {
+ let loc = P.tokloc;
+ let tok Tok #?;
+ if lexmatch(P, &tok, '{') {
+ } else {
+ let ex = parseexpr(P);
+ lexexpect(P, '{');
+ if ex.ty->is(:Int) or ex.ty->is(:Enum) {
+ return pstiswitch(P, loc, ex);
+ } else if ex.ty->is(:Agg) and ex.ty.u.Agg.kind == :EUnion {
+ } else {
+ fatal(P, tok.loc, "invalid switch test expression type (%t)", ex.ty);
+ }
+ }
+}
+
fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void {
let tok Tok = {};
switch {
@@ -1825,6 +1880,9 @@ fn parsestmts(P *Parser, yield StmtYielder, yarg *void) void {
lexexpect(P, ';');
return yield({ tok.loc, :Continue(P.curloop) }, yarg);
+ case lexmatch(P, &tok, :kw_switch);
+ return yield(pstswitch(P), yarg);
+
case isdecltokt(tok.t);
struct Arg {
P *Parser,