aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-19 08:45:52 +0200
committerlemon <lsof@mailbox.org>2022-08-19 08:45:52 +0200
commitb6c31ebc4a33831c8f59e43984f3af950d418b88 (patch)
tree9d20b1398e2b7b4c5a8f5e9d9a9023919187d473 /src
parent3481ab142293bd82fdd59e3ec86dd66352e457c3 (diff)
tagged unions
Diffstat (limited to 'src')
-rw-r--r--src/cffc.hff1
-rw-r--r--src/parse.cff18
2 files changed, 18 insertions, 1 deletions
diff --git a/src/cffc.hff b/src/cffc.hff
index eff95e4..686de57 100644
--- a/src/cffc.hff
+++ b/src/cffc.hff
@@ -168,6 +168,7 @@ struct Expr {
Call struct { lhs *Expr, args [#]Expr },
ZeroIni,
EnumIni struct { name *const u8, val i64 },
+ EUnionIni struct { var *const AggField, ex *Expr },
AggIni struct { flds [#]*const AggField, exs [#]Expr },
ArrIni struct { idxs [#]u32, exs [#]Expr, maxn i64 },
Stmt [#]Stmt,
diff --git a/src/parse.cff b/src/parse.cff
index 84df71a..0aa9fb9 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -1226,6 +1226,7 @@ fn pexprimary(P *Parser) Expr {
fatal(P, tok.loc, "cannot infer type for variant");
}
let ty = P.targty;
+ P.targty = #null;
if ty->is(:Enum) {
let name = (tok = lexexpects(P, :ident, "variant name")).u.ident;
let i i64 #?;
@@ -1240,7 +1241,22 @@ fn pexprimary(P *Parser) Expr {
} while #f;
ex = { tok.loc, ty, :EnumIni { name, i }};
} else if ty->is(:Agg) and ty.u.Agg.kind == :EUnion {
- assert(#f, "NYI");
+ let name = (tok = lexexpects(P, :ident, "variant name")).u.ident;
+ let fld = findaggfield(ty, name);
+ if fld == #null {
+ fatal(P, tok.loc, "%t has no such variant %qT", ty, tok);
+ }
+ let iex *Expr = #null;
+ if lexpeek(P).t == '(' or lexpeek(P).t == '{' {
+ P.targty = fld.ty;
+ iex = exprdup(P.alloc, parseexpr(P));
+ if fld.ty == #null {
+ fatal(P, iex.loc, "%t variant %qT is empty", ty, tok);
+ }
+ } else if fld.ty {
+ fatal(P, P.tokloc, "%t variant %qT must be initialized", ty, tok);
+ }
+ ex = { tok.loc, ty, :EUnionIni { fld, iex }};
} else {
fatal(P, tok.loc, "cannot infer type for variant");
}