From a39378db8ce05f8ab45b5ae0f3252c0a5322fd70 Mon Sep 17 00:00:00 2001 From: lemon Date: Thu, 25 Aug 2022 06:34:22 +0200 Subject: switch check --- src/parse.cff | 23 +++++++++++++++++++++++ src/set.hff | 6 ++++++ 2 files changed, 29 insertions(+) (limited to 'src') diff --git a/src/parse.cff b/src/parse.cff index d0c3da7..2611906 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -2176,6 +2176,13 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt { let cs Vec = {}; let f Block = {}; let elsep = #f; + + let seen Map = {}; + defer seen->clear(); + while !lexmatch(P, &tok, '}') { lexexpect(P, :kw_case); if lexmatch(P, &tok, :kw_else) { @@ -2196,6 +2203,10 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt { if !typematchestarg(ex.ty, e.ty) { err(P, e.loc, "bad case expression (%t, expected %t)", e.ty, ex.ty); } + if seen->get(e.u.IntLit.i) { + err(P, e.loc, "duplicate case expression (previously seen at %l)", *seen->get(e.u.IntLit.i)); + } + seen->put(e.u.IntLit.i, e.loc); es->push(e); if !lexmatch(P, #null, ',') { lexexpect(P, ';'); @@ -2214,6 +2225,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { let f Block = {}; let elsep = #f; + let seen Map = {}; + defer seen->clear(); + while !lexmatch(P, &tok, '}') { let c EUSwitchCase = {}; lexexpect(P, :kw_case); @@ -2231,6 +2248,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { fatal(P, tok.loc, "%t has no such variant %qT", test.ty, tok); } c.variant = c.fld - test.ty.u.Agg.flds.#ptr; + + if seen->get(c.variant) { + err(P, tok.loc, "duplicate case expression (previously seen at %l)", *seen->get(c.variant)); + } + seen->put(c.variant, tok.loc); + if c.fld.ty != #null and lexmatch(P, &tok, '*') { if !islvalue(test) { fatal(P, tok.loc, "cannot capture by pointer, test expression is not lvalue"); diff --git a/src/set.hff b/src/set.hff index 6a03e52..212d578 100644 --- a/src/set.hff +++ b/src/set.hff @@ -74,6 +74,12 @@ struct Set { fn put(self *Set, x T) void { self->intern(x); } + + fn clear(self *Set) void { + self.buf->clear(); + free(self.set); + *self = {}; + } } defmacro set_each(v, Set, &body) [ -- cgit v1.2.3