pub enum Expr {
Show 13 variants
LetRecIn {
kw: KwLetRec,
first: RecBinding,
ands: Vec<AndBinding>,
in_kw: KwIn,
body: Box<Expr>,
},
LetIn {
kw: KwLet,
name: BindName,
ascription: Option<RecAscription>,
leading_bar: Option<BarTok>,
params: Vec<Param>,
eq: DefEqTok,
value: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
LetPatternIn {
kw: KwLet,
pat: PatErased,
eq: DefEqTok,
value: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
If {
kw: KwIf,
cond: Box<Expr>,
then_kw: KwThen,
then_branch: Box<Expr>,
else_kw: KwElse,
else_branch: Box<Expr>,
},
Fun {
kw: KwFun,
params: Vec<PatBot>,
arrow: ArrowTok,
body: Box<Expr>,
},
FunRows {
kw: KwFun,
opts: CstOptBinders,
param: PatBot,
arrow: ArrowTok,
body: Box<Expr>,
},
Match {
kw: KwMatch,
scrutinee: Box<Expr>,
with_kw: KwWith,
leading_bar: Option<BarTok>,
first: MatchArm,
rest: Vec<BarArm>,
},
LetMutableIn {
kw: KwLetMutable,
name: VarTok,
arrow: OverwriteEqTok,
init: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
LetMathIn {
kw: KwLetMath,
cmd: HorzCmdTok,
params: Vec<Param>,
eq: DefEqTok,
value: Box<Expr>,
in_kw: KwIn,
body: Box<Expr>,
},
OpenIn {
kw: KwOpen,
name: CtorTok,
in_kw: KwIn,
body: Box<Expr>,
},
WhileDo {
kw: KwWhile,
cond: Box<Expr>,
do_kw: KwDo,
body: Box<Expr>,
},
Overwrite {
name: VarTok,
arrow: OverwriteEqTok,
value: ExprErased,
},
Ops(OpChain),
}Expand description
nxlet: a let/if/match/lambda-headed expression, falling through to
the flattened operator chain (Ops, OpChain) at the bottom.
Variant order is parse priority; Ops has no distinguishing leading
keyword, so it must stay last.
Variants§
LetRecIn
let-rec name param* = expr (and name param* = expr)* in body
LetIn
let name param* = expr in body (nxletsub’s LETNONREC case;
the bound TARGET is a plain variable — a general pattern target
is Expr::LetPatternIn, below — but param* is a full
patbot*, matching parser.mly’s nxnonrecdec (and this port’s
own TopLet/Fun/RecBinding, which already use PatBot here
too): e.g. hdecoset.satyh’s let deco _ _ _ _ = [] in ..
(Tier-2 decoration/graphics wave). Lowered by the same
elaborate::rec_clause_value single-clause path Fun’s doc
comment describes.
Fields
ascription: Option<RecAscription>Optional : ty ascription (let f : ty x = e in ..) —
parse-and-ignore, like RecBinding::ascription.
leading_bar: Option<BarTok>The | of nonrecdecargpart — see
super::TopLet::leading_bar, whose doc comment carries the
whole story; this is the expression-level twin.
LetPatternIn
let pat = value in body (nxnonrecdec’s zero-additional-
parameter case: the bound target is a general pattern, not
merely a variable name — SATySFi’s destructuring let, e.g.
let (_, acc) = pair in acc, used by the bundled
list.satyg’s mapi-adjacent). Kept as a SEPARATE variant from
Expr::LetIn above (rather than widening LetIn’s name: VarTok field to a pattern) because LetIn additionally curries
params for the ordinary let f x y = .. function-definition
shape, which upstream keys off the bound target being a plain
variable — the two shapes never overlap in real source (a
destructuring target is never itself applied to further curried
parameters). Must stay after LetIn: a bare-variable target
like let x = 1 in x parses as this variant too (PatBot::Var),
so LetIn (tried first, and not needing any pattern-lowering)
wins for every ordinary let, leaving this variant to match only
when the target isn’t a plain variable. Only the no-argpart
(no additional curried parameters after the pattern) form is
implemented — nxnonrecdec’s argpart has no use in the
bundled stdlib.
This variant is the port’s worst backtracking blow-up, and the
paragraph above is why: on a bare-variable target it is shadowed by
Expr::LetIn but still tried, so when a body deep inside a
let … in chain fails, every enclosing let re-derives the whole
failure a second time. Measured on a chain ending in a let with
no right-hand side, the parse costs exactly ×2 per let — 610,227
stream reads at twelve, 4,882,355 at fifteen, and it does not stop;
removing this variant collapses the same chain to 17 reads per
token. The repair is to factor the two variants into one with a
target that is a name-and-params or a pattern, which is a CST
change that reaches elaborate.rs. Until then
crate::stream::Budget bounds it, and a chain deeper than about
fifteen is reported as a give-up rather than diagnosed.
If
if cond then a else b (nxif; else is never optional in
this grammar, so there is no dangling-else ambiguity).
Fields
Fun
fun x y -> body (nxlambda’s LAMBDA argpats ARROW nxlor
production, parser.mly:713). argpats = list(patbot)
upstream — a lambda’s parameters are full patbots, not merely
variables (e.g. the bundled list.satyg’s mapi-adjacent:
fun (i, acc) x leftopt rightopt -> .., a tuple-DESTRUCTURING
first parameter), lowered by curry_lambda_abstract_pattern —
this port’s elaborate::rec_clause_value (shared with
multi-clause let-rec, which faces the exact same
arity-preserving pattern-currying problem) reproduces that
directly, so this field is PatBot, matching RecBinding’s.
FunRows
fun ?(l = x, …) p -> body — a SATySFi 0.1 labeled-optional
lambda unit (one ?(…) bundle + one positional param). This is
an additive 0.1 node: 0.0.6 has no ?(…) param bundle, so it
is reachable in a 0.0.6 parse only for input that used to be a
parse error (a leading ? cannot begin Fun’s Vec<PatBot>),
where elaborate rejects it under a V0_0 crate::version
gate. The V0_1 pipeline reaches it by lowering a cst_v1 param
bundle (multi-unit lambdas lower to a nested FunRows/Fun
chain). Placed right after Expr::Fun so a plain fun x -> …
still matches Fun first (its ?-headed opts cannot begin a
PatBot, so Fun cleanly backtracks here for a bundled unit).
Match
match scrutinee with [|] pat [when g] -> body (| pat [when g] -> body)*
Fields
LetMutableIn
let-mutable name <- init in body (nxletsub’s LETMUTABLE
case; init/body are both nxlet in parser.mly, simplified
here to a direct Expr self-loop like LetIn).
LetMathIn
let-math \cmd param* = expr in body (nxletsub’s LETMATH
case, parser.mly:688 — upstream’s ONLY command binding with an
expression-level in form; LETHORZ/LETVERT stay
top-level-only, see the module doc comment on
super::TopBinding::LetInline/LetBlock). Same shape as
super::TopBinding::LetMath — no leading context variable,
cmd reuses the plain HorzCmdTok token — plus the in body
suffix; Box<Expr> self-loops on the recurse root like LetIn.
Fields
cmd: HorzCmdTokOpenIn
open Name in body (nxletsub’s OPEN case).
WhileDo
while cond do body (nxwhl; body is nxwhl itself in
parser.mly, i.e. right-nested whiles — simplified here to a
plain Expr).
Overwrite
name <- value (nxlambda’s OVERWRITEEQ case). Starts with a
bare VarTok, which is also how Ops can start (x alone) —
must stay before Ops so backtracking tries the <- shape
first. value is nxlor in parser.mly; routed through
ExprErased here rather than mirrored precisely, both to keep
Expr a singleton SCC and because this is already a Var-headed
alternative sitting awkwardly among the keyword-headed ones.
Ops(OpChain)
The flattened binary-operator chain — see the module doc comment on precedence flattening. Must stay last (no leading keyword).
Trait Implementations§
Source§impl<__SyanMacro_Atom> Parse<__SyanMacro_Atom> for Exprwhere
__SyanMacro_Atom: Spanned + Clone,
KwLetRec: Parse<__SyanMacro_Atom>,
RecBinding: Parse<__SyanMacro_Atom>,
Vec<AndBinding>: Parse<__SyanMacro_Atom>,
KwIn: Parse<__SyanMacro_Atom>,
KwLet: Parse<__SyanMacro_Atom>,
BindName: Parse<__SyanMacro_Atom>,
Option<RecAscription>: Parse<__SyanMacro_Atom>,
Option<BarTok>: Parse<__SyanMacro_Atom>,
Vec<Param>: Parse<__SyanMacro_Atom>,
DefEqTok: Parse<__SyanMacro_Atom>,
PatErased: Parse<__SyanMacro_Atom>,
KwIf: Parse<__SyanMacro_Atom>,
KwThen: Parse<__SyanMacro_Atom>,
KwElse: Parse<__SyanMacro_Atom>,
KwFun: Parse<__SyanMacro_Atom>,
ArrowTok: Parse<__SyanMacro_Atom>,
CstOptBinders: Parse<__SyanMacro_Atom>,
KwMatch: Parse<__SyanMacro_Atom>,
KwWith: Parse<__SyanMacro_Atom>,
MatchArm: Parse<__SyanMacro_Atom>,
Vec<BarArm>: Parse<__SyanMacro_Atom>,
KwLetMutable: Parse<__SyanMacro_Atom>,
VarTok: Parse<__SyanMacro_Atom>,
OverwriteEqTok: Parse<__SyanMacro_Atom>,
KwLetMath: Parse<__SyanMacro_Atom>,
HorzCmdTok: Parse<__SyanMacro_Atom>,
KwOpen: Parse<__SyanMacro_Atom>,
CtorTok: Parse<__SyanMacro_Atom>,
KwWhile: Parse<__SyanMacro_Atom>,
KwDo: Parse<__SyanMacro_Atom>,
ExprErased: Parse<__SyanMacro_Atom>,
OpChain: Parse<__SyanMacro_Atom>,
Box<PatternParenBody>: Parse<__SyanMacro_Atom>,
Vec<PatListItem>: Parse<__SyanMacro_Atom>,
IntTok: Parse<__SyanMacro_Atom>,
KwTrue: Parse<__SyanMacro_Atom>,
KwFalse: Parse<__SyanMacro_Atom>,
LiteralTok: Parse<__SyanMacro_Atom>,
WildcardTok: Parse<__SyanMacro_Atom>,
UnitParen: Parse<__SyanMacro_Atom>,
ParenGroup<()>: GroupShape<__SyanMacro_Atom>,
ListGroup<()>: GroupShape<__SyanMacro_Atom>,
Self: ParseRanked8909385c15d27adc<(((),),), __SyanMacro_Atom>,
impl<__SyanMacro_Atom> Parse<__SyanMacro_Atom> for Exprwhere
__SyanMacro_Atom: Spanned + Clone,
KwLetRec: Parse<__SyanMacro_Atom>,
RecBinding: Parse<__SyanMacro_Atom>,
Vec<AndBinding>: Parse<__SyanMacro_Atom>,
KwIn: Parse<__SyanMacro_Atom>,
KwLet: Parse<__SyanMacro_Atom>,
BindName: Parse<__SyanMacro_Atom>,
Option<RecAscription>: Parse<__SyanMacro_Atom>,
Option<BarTok>: Parse<__SyanMacro_Atom>,
Vec<Param>: Parse<__SyanMacro_Atom>,
DefEqTok: Parse<__SyanMacro_Atom>,
PatErased: Parse<__SyanMacro_Atom>,
KwIf: Parse<__SyanMacro_Atom>,
KwThen: Parse<__SyanMacro_Atom>,
KwElse: Parse<__SyanMacro_Atom>,
KwFun: Parse<__SyanMacro_Atom>,
ArrowTok: Parse<__SyanMacro_Atom>,
CstOptBinders: Parse<__SyanMacro_Atom>,
KwMatch: Parse<__SyanMacro_Atom>,
KwWith: Parse<__SyanMacro_Atom>,
MatchArm: Parse<__SyanMacro_Atom>,
Vec<BarArm>: Parse<__SyanMacro_Atom>,
KwLetMutable: Parse<__SyanMacro_Atom>,
VarTok: Parse<__SyanMacro_Atom>,
OverwriteEqTok: Parse<__SyanMacro_Atom>,
KwLetMath: Parse<__SyanMacro_Atom>,
HorzCmdTok: Parse<__SyanMacro_Atom>,
KwOpen: Parse<__SyanMacro_Atom>,
CtorTok: Parse<__SyanMacro_Atom>,
KwWhile: Parse<__SyanMacro_Atom>,
KwDo: Parse<__SyanMacro_Atom>,
ExprErased: Parse<__SyanMacro_Atom>,
OpChain: Parse<__SyanMacro_Atom>,
Box<PatternParenBody>: Parse<__SyanMacro_Atom>,
Vec<PatListItem>: Parse<__SyanMacro_Atom>,
IntTok: Parse<__SyanMacro_Atom>,
KwTrue: Parse<__SyanMacro_Atom>,
KwFalse: Parse<__SyanMacro_Atom>,
LiteralTok: Parse<__SyanMacro_Atom>,
WildcardTok: Parse<__SyanMacro_Atom>,
UnitParen: Parse<__SyanMacro_Atom>,
ParenGroup<()>: GroupShape<__SyanMacro_Atom>,
ListGroup<()>: GroupShape<__SyanMacro_Atom>,
Self: ParseRanked8909385c15d27adc<(((),),), __SyanMacro_Atom>,
Source§type Error = <Expr as ParseRanked8909385c15d27adc<(((),),), __SyanMacro_Atom>>::Error
type Error = <Expr as ParseRanked8909385c15d27adc<(((),),), __SyanMacro_Atom>>::Error
<FieldTy as Parse<Atom>>::Error: Into<…> predicate re-creates a projection cycle on a
recursive field (E0275), which decycle’s bound-peeling does not break.