diff options
| author | 2022-08-19 08:45:52 +0200 | |
|---|---|---|
| committer | 2022-08-19 08:45:52 +0200 | |
| commit | b6c31ebc4a33831c8f59e43984f3af950d418b88 (patch) | |
| tree | 9d20b1398e2b7b4c5a8f5e9d9a9023919187d473 /src | |
| parent | 3481ab142293bd82fdd59e3ec86dd66352e457c3 (diff) | |
tagged unions
Diffstat (limited to 'src')
| -rw-r--r-- | src/cffc.hff | 1 | ||||
| -rw-r--r-- | src/parse.cff | 18 |
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"); } |