pub enum IrExprKind {
Show 25 variants
Const(ConstVal),
Local(String),
Global(GlobalRef),
StoreQuery(String),
Record {
fields: Vec<(String, IrExpr)>,
},
Variant {
tag: String,
payload: Vec<IrExpr>,
},
Field {
base: Box<IrExpr>,
field: String,
},
List {
elems: Vec<IrExpr>,
},
Block {
stmts: Vec<IrStmt>,
tail: Box<IrExpr>,
},
If {
cond: Box<IrExpr>,
then_: Box<IrExpr>,
else_: Box<IrExpr>,
},
Match {
scrutinee: Box<IrExpr>,
arms: Vec<IrArm>,
exhaustive: Exhaustive,
form: MatchForm,
},
And {
lhs: Box<IrExpr>,
rhs: Box<IrExpr>,
},
Or {
lhs: Box<IrExpr>,
rhs: Box<IrExpr>,
},
Not {
operand: Box<IrExpr>,
},
BinOp {
op: IrBinOp,
lhs: Box<IrExpr>,
rhs: Box<IrExpr>,
},
Neg {
operand: Box<IrExpr>,
},
InterpStr {
parts: Vec<IrInterpPart>,
},
Return {
value: Box<IrExpr>,
},
HttpResultNotFound,
RefinedCheck {
value: Box<IrExpr>,
base: BaseType,
refinement: Option<Refinement>,
},
Call {
callee: Callee,
targs: Vec<TyId>,
args: Vec<IrExpr>,
},
Lambda {
params: Vec<String>,
body: Box<IrExpr>,
captures: Vec<String>,
},
Await {
effect: Box<IrExpr>,
},
Send {
effect: Box<IrExpr>,
},
Pure {
value: Box<IrExpr>,
},
}Expand description
A lowered expression’s shape. Every node kind from Part 6.2 exists here
(Decision D); bynk_lower implements real construction only for the
subset named in design/tracks/the-ir.md’s own P6.1 row — every other
arm is a named todo!() in the lowering pass, not a missing variant
here.
Variants§
Const(ConstVal)
A literal value.
Local(String)
Reading a function-scoped local or parameter, by name (Decision B —
no LocalId arena exists).
Global(GlobalRef)
A bare reference to something with no scope of its own — narrowly
scoped per Decision C; see GlobalRef.
StoreQuery(String)
A bare store Map[K, V] field name used as a value, not a
method-call receiver (Callee::Store/Callee::Query already lower
those separately) and not a Cell (those are bound into scope as an
ordinary IrExprKind::Local, v0.81’s “implicit deref” rule — see
bynk_lower::lower_handler_body_ir’s own doc comment). The
checker types this expression Ty::Query(V) (ADR 0120) without
ever binding the name into its own value scope
(bynk-check/src/checker.rs’s ExprKind::Ident dispatch,
ctx.lookup(...).is_none() && ctx.store_fields.get(...), checked
before falling through to check_ident) — a lazy query over the
field’s current values, not a snapshot. Reached two ways: a bare
argument position (lines.joinOn(orders, ...)) and, unrecognised
until this variant existed, the receiver of a
.entries/.keys/.values IrExprKind::Field (ADR 0184) —
ExprKind::FieldAccess’s own lowering always lowers its receiver
unconditionally, so a bare store-map field reached there the same
unbound-ident path an argument-position reference does. Log
deliberately not covered here (review of #1240): unlike Map,
bynk-check never special-cases StoreField::Log in a bare-value or
FieldAccess dispatch, so a bare Log value is not checker-legal
today — the same bucket Set/Cache are already in. Carries only
the field’s own name — every consumer already has the enclosing
IrItem::Agent’s state: Vec<StoreFieldIr> to look the kind back up
in, the same “identity, not a copy” posture
Callee::Store::field/GlobalRef::tag already established.
Record
Record construction. fields is always complete — every field the
record declares is present, exactly once, a shorthand field ({ x })
resolved to its full (name, value) pair during lowering same as
every other field — and ordered by evaluation order, left to
right: a reader walking fields in order reproduces the same
left-to-right effect sequencing a value expression’s own evaluation
has, so this is never re-sorted to, say, the record’s own declared
field order once evaluation order and declaration order diverge
(RecordSpread’s own lowering, ir/lower.rs’s
lower_record_spread_ir, is the one producer where they can).
P6.39: def: Arc<TypeDecl> dropped — zero production readers
(verified), only test assertions. fields alone is this variant’s
whole payload now.
Variant
Sum-variant construction — a user-declared sum’s own constructor
(Circle(n)/Shape.Circle(n), driven by Callee::Ctor) and, as
of the #1225 ADR, the four built-in constructors Ok/Err/Some/
None too, which Callee::Ctor can never classify (no
Arc<TypeDecl> exists for Option/Result — Callee::Ctor’s own
two minting sites, bynk-check/src/checker/calls.rs, can only ever
resolve a real TypeBody::Sum declaration by name, and Ok/Err/
Some/None are dedicated ExprKind variants entirely, checked
through check_ok/check_err/check_some/check_none with no
Callee ever recorded).
No sum identity field, deliberately — an earlier draft carried
sum: Arc<TypeDecl> (mirroring GlobalRef/Record::def’s own
declaration-identity convention), which is exactly what made
Ok/Err/Some/None unrepresentable: no TypeDecl exists for a
built-in sum, so a real fix would either need a synthetic decl (no
established path for one, and a new kind of “fake but not fake”
value this module would need to invent) or would have to widen sum
into an Arc<TypeDecl>-or-built-in enum for the sake of a case that
doesn’t need declaration identity at all. #1225’s own resolution: the
wrapping IrExpr::ty — already present on every node (R6.1) —
already carries this exact identity as a TyId, uniformly, for both
a user sum (Ty::Named { kind: Sum, .. }) and a built-in one
(Ty::Option/Ty::Result), since a constructor call’s own checked
type is the sum it constructs. Mirrors IrPat::Variant’s own
scrutinee_ty: TyId precedent exactly — the one field this module
already had to solve the identical problem for, on the
pattern-matching side — rather than introducing a second, redundant
copy of the same TyId one level in. A consumer needing the sum’s
own tag/payload shape calls bynk_check::checker::variants_of
(already pub for precisely this, checker.rs:4323) against the
enclosing IrExpr::ty — the same function IrPat::Variant’s own
lowering already calls, proven to resolve a user sum, Result,
Option, ActorSum, and HttpResult alike with no special-casing
gap for the built-in cases.
Field
Field access on a record value.
List
A list literal.
Block
A { ... } block: statements, then a tail value.
If
if cond { then } else { else } — both branches always present (an
else-less if already carries a synthesised unit else at the AST
level, Block::is_synth_unit).
Match
Pattern matching. scrutinee/arms/exhaustive/form are all
real, constructible values as of P6.5 (#1159) — arms/exhaustive
built by calling P6.4’s own lower_pattern_ir/lower_arm_ir/
lower_exhaustive_ir verbatim (#1157), form by reusing the
shipped string emitter’s own match_needs_if_chain/
pattern_has_nested_test (Decision B) rather than re-deriving an
equivalent predicate over IrPat’s own (slightly different)
recursive shape.
And
lhs && rhs — short-circuit, structurally (R6.3, already true of the
existing string-based emitter; this tree shape makes it true of the
IR too, not just the emission-time machinery threaded to preserve it).
Or
lhs || rhs.
Not
!operand.
BinOp
Comparison/arithmetic (#1189): Eq/NotEq/Lt/LtEq/Gt/GtEq/
Add/Sub/Mul/Div — every bynk_syntax::ast::BinOp member
except And/Or/Implies, which stay their own dedicated
variants above (Decision A, #1189: And/Or exist as their own
nodes specifically to make short-circuit evaluation a structural
property of the tree — R6.3 — and Implies desugars away entirely;
none of that applies to a strict, both-operands-always-evaluated
arithmetic/comparison operator, so one shared, op-tagged variant
covers all ten without ten near-duplicate variants/lowering arms).
lhs/rhs are lowered independently — no is-binding propagation
exists for these operators, unlike And.
Neg
-operand (#1189) — bynk_syntax::ast::UnaryOp::Neg’s own
counterpart to Not above; the checker requires an Int operand and
returns Int (check_unary, bynk-check/src/checker/expressions.rs).
InterpStr
An interpolated string (#1189) — bynk_syntax::ast::ExprKind::InterpStr’s
alternating chunk/hole run, each hole an ordinary lowered expression
(the checker’s own hole rule restricts a hole to a scalar or
scalar-refinement type; this module does not re-derive that
restriction, only carries the already-checked result). Always typed
String.
Fields
parts: Vec<IrInterpPart>Return
A function/handler body’s own tail value, in return position. Built,
not parsed — Bynk has no return keyword; this node is constructed
only by lower::lower_fn_body_ir wrapping a body block’s tail (the
? operator’s early-return desugar is P6.3’s row, a second future
producer of this same node).
HttpResultNotFound
The HttpResult.NotFound sentinel Option[T]?’s own desugar
early-returns on None (ADR 0177) — bynk_lower::lower_question_ir’s
own construction, never sourced from user syntax (no bynk source
text spells HttpResult.NotFound; the shipped string emitter
hand-writes this exact text as boilerplate, emitter/lower.rs’s own
ExprKind::Question arm). Deliberately its own zero-payload variant,
not routed through GlobalRef: that type resolves a source
identifier against TypedCommons::types, and HttpResult is a
checker built-in with no TypeDecl there to resolve against at all
(GlobalRef’s own doc comment already names this exact case as
out of its scope, “dropped during implementation”).
RefinedCheck
A refined-type/inline-predicate boolean check — value is Quantity
(Quantity a declared refined type) or _ where predicate’s own
predicate half. refinement/base are bynk_syntax::ast values
reused verbatim, not decomposed into IrExprKind boolean primitives
— the same “reused, not adapted” posture IrPat::Refined (P6.4,
#1157) already committed to for the identical payload, one variant
case at a time (PredKind’s own closed set — InRange/MinLength/
Matches/…) rather than an open-ended expression tree, so nothing
about this construction contradicts R6.7’s own “desugar once”
mandate the way an arbitrary un-desugared sub-expression would;
decomposing PredKind itself into BinOp/Call primitives is real,
separate, deferred work (mirrors the base-type check the shipped
string emitter’s own refined_check_as_bool always prepends when
base is Int/Float — folded into this one node rather than a
second sibling, since the two are never meaningfully separable at a
call site: every real reader wants “is this refined value valid,” not
the base-type and predicate halves independently).
Call
A call, classified by P6.0’s Callee — no adaptation needed here,
Callee already resolves identity the way this module’s other
DefId-shaped slots do. Lowering deferred to P6.2.
Lambda
A lambda. Lowering deferred to P6.2, alongside Call (a lambda’s
only use today is as a kernel-method argument, Callee::Kernel
territory).
Await
<- effect — await an Effect[T]’s value.
Send
~> effect — fire-and-forget; typed Unit.
Pure
Effect.pure(value) — introduce a synchronous value as Effect[T].
Trait Implementations§
Source§impl Clone for IrExprKind
impl Clone for IrExprKind
Source§fn clone(&self) -> IrExprKind
fn clone(&self) -> IrExprKind
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for IrExprKind
impl RefUnwindSafe for IrExprKind
impl Send for IrExprKind
impl Sync for IrExprKind
impl Unpin for IrExprKind
impl UnsafeUnpin for IrExprKind
impl UnwindSafe for IrExprKind
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling [Attribute] value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi [Quirk] value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the [Condition] value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);