Skip to main content

OperationKind

Enum OperationKind 

Source
pub enum OperationKind {
Show 16 variants AddFunction { sig_id: SigId, stage_id: StageId, effects: EffectSet, budget_cost: Option<u64>, }, RemoveFunction { sig_id: SigId, last_stage_id: StageId, }, ModifyBody { sig_id: SigId, from_stage_id: StageId, to_stage_id: StageId, from_budget: Option<u64>, to_budget: Option<u64>, }, RenameSymbol { from: SigId, to: SigId, body_stage_id: StageId, }, ChangeEffectSig { sig_id: SigId, from_stage_id: StageId, to_stage_id: StageId, from_effects: EffectSet, to_effects: EffectSet, from_budget: Option<u64>, to_budget: Option<u64>, }, AddImport { in_file: String, module: ModuleRef, alias: Option<String>, }, RemoveImport { in_file: String, module: ModuleRef, }, AddType { sig_id: SigId, stage_id: StageId, }, RemoveType { sig_id: SigId, last_stage_id: StageId, }, ModifyType { sig_id: SigId, from_stage_id: StageId, to_stage_id: StageId, }, Merge { resolved: usize, }, InlineLet { sig_id: SigId, from_stage_id: StageId, to_stage_id: StageId, let_node: String, binding_name: String, from_budget: Option<u64>, to_budget: Option<u64>, }, RenameLocal { sig_id: SigId, from_stage_id: StageId, to_stage_id: StageId, let_node: String, old_name: String, new_name: String, from_budget: Option<u64>, to_budget: Option<u64>, }, ReplaceMatchArm { sig_id: SigId, from_stage_id: StageId, to_stage_id: StageId, match_node: String, arm_index: usize, from_budget: Option<u64>, to_budget: Option<u64>, }, Candidate { sig_id: SigId, stage_id: StageId, }, Promote { sig_id: SigId, winner_candidate: OpId, winner_stage_id: StageId, supersedes: Vec<OpId>, from_stage_id: Option<StageId>, from_budget: Option<u64>, to_budget: Option<u64>, },
}
Expand description

The kinds of operations that produce stage transitions. Mirrors the initial set in #129; new kinds (MoveBetweenFiles, SplitFunction, ExtractType) can be added later as long as they’re appended at the end of this enum or use explicit #[serde(rename = "...")] tags so existing OpIds stay stable.

Variants§

§

AddFunction

New function published. effects is the effect set declared in the signature; tracked here (not just inside the stage) so #130’s write-time gate has a cheap path to check effect changes without rehydrating the AST.

budget_cost (#247) records the function’s declared [budget(N)] cost. Optional with skip_serializing_if, so pre-#247 ops without a declared budget continue to hash to their original OpId (additive serialization, same trick intent_id uses). None means the function declared no budget effect; Some(n) is the literal n from [budget(n)].

Fields

§sig_id: SigId
§stage_id: StageId
§effects: EffectSet
§budget_cost: Option<u64>
§

RemoveFunction

Function removed; last_stage_id is the head before the remove (so blame can walk the predecessor without scanning).

Fields

§sig_id: SigId
§last_stage_id: StageId
§

ModifyBody

Function body changed; signature unchanged.

from_budget / to_budget (#247) record the declared [budget(N)] on each side. Same Option + skip discipline as AddFunction.budget_cost — pre-#247 ops keep their OpIds. The pair is what lex op log --budget-drift reads to surface “budget grew/shrank” diffs without rehydrating stages.

Fields

§sig_id: SigId
§from_stage_id: StageId
§to_stage_id: StageId
§from_budget: Option<u64>
§to_budget: Option<u64>
§

RenameSymbol

Symbol renamed. The body hash is preserved (body_stage_id) so two renames of the same body collapse to the same OpId and lex blame walks the rename as a single causal event rather than delete + add.

Fields

§from: SigId
§body_stage_id: StageId
§

ChangeEffectSig

Effect signature changed. Captures both old and new effect sets so the write-time gate (#130) can verify importers haven’t silently broken.

from_budget / to_budget (#247) capture the declared [budget(N)] on each side. ChangeEffectSig usually fires because the effect list changed; #247 makes budget drift visible without forcing a full effect-set diff.

Fields

§sig_id: SigId
§from_stage_id: StageId
§to_stage_id: StageId
§from_effects: EffectSet
§to_effects: EffectSet
§from_budget: Option<u64>
§to_budget: Option<u64>
§

AddImport

Import added to a file. in_file is the canonical path (relative to the repo root, forward-slashes) so two machines hashing the same edit get the same OpId.

Fields

§in_file: String
§module: ModuleRef
§alias: Option<String>

The binding the module is imported under (import "std.sql" as sql"sql"). Lex requires an alias on every import, but this is None whenever it equals the module’s default alias (the last path segment) — the common case — so those AddImports serialize exactly as before and keep their original OpId (additive serialization, same trick as budget_cost). Only a non-default alias (import "./error" as e) is carried explicitly. Without it, export-git cannot reconstruct a compilable module — the reference alone doesn’t say what name the body binds.

§

RemoveImport

Fields

§in_file: String
§module: ModuleRef
§

AddType

Fields

§sig_id: SigId
§stage_id: StageId
§

RemoveType

Fields

§sig_id: SigId
§last_stage_id: StageId
§

ModifyType

Fields

§sig_id: SigId
§from_stage_id: StageId
§to_stage_id: StageId
§

Merge

Merge of two branch heads. Carries only an informational count of resolved sigs so two structurally identical merges of different sizes don’t collide on op_id; the per-sig deltas live in OperationRecord::produces (StageTransition::Merge).

Fields

§resolved: usize
§

InlineLet

Typed transform: inlined a let x := v; body by substituting v for every unshadowed x in body, then replacing the entire Let node with the substituted body (#280). The op records the let-binding’s position and the inlined name; the actual substituted value lives in the content-addressed to_stage_id so the op_id stays compact.

Fields

§sig_id: SigId
§from_stage_id: StageId
§to_stage_id: StageId
§let_node: String
§binding_name: String
§from_budget: Option<u64>
§to_budget: Option<u64>
§

RenameLocal

Typed transform: renamed a let-bound local within a fn body (#280). Records the old/new identifiers and the position of the let-binding in the AST. Body-shape-stable: the renamed stage typically hashes near the original.

Fields

§sig_id: SigId
§from_stage_id: StageId
§to_stage_id: StageId
§let_node: String

Path-style NodeId of the Let expression at the time of the transform.

§old_name: String
§new_name: String
§from_budget: Option<u64>
§to_budget: Option<u64>
§

ReplaceMatchArm

Typed transform: replaced one arm’s body in a Match expression (#280). Semantically a ModifyBody, but the op records which arm changed and where in the AST — so the op log reads as a semantic edit history rather than as opaque hash-to-hash bytes.

match_node is the lex_ast::ids::NodeId of the Match expression at the time of the transform. NodeIds aren’t stable across structural edits — they’re audit-trail metadata, not re-derivation keys. The authoritative record of the new stage is to_stage_id (content-addressed).

from_budget/to_budget follow the same skip_if_none discipline as Self::ModifyBody: pre-#280 ops continue hashing to their original OpIds.

Fields

§sig_id: SigId
§from_stage_id: StageId
§to_stage_id: StageId
§match_node: String

Path-style NodeId of the Match expression that was modified, captured at transform time. See lex_ast::ids::NodeId for the format.

§arm_index: usize
§from_budget: Option<u64>
§to_budget: Option<u64>
§

Candidate

Multi-agent coordination: a stage proposed for a sig without advancing the branch (#294). Multiple agents can land Candidate ops on the same sig concurrently without contention — they all chain off the current head and don’t move it. Used together with Self::Promote to model bake-offs: several agents propose, one is promoted.

The Operation’s intent_id is expected to be set so downstream consumers can distinguish proposals by author. (The schema doesn’t enforce this; the gate does.)

Fields

§sig_id: SigId
§stage_id: StageId
§

Promote

Multi-agent coordination: promotes a previously-landed Self::Candidate op as the new head for its sig (#294). Carries the list of other candidates this Promote supersedes so the op log explicitly records the bake-off shape.

Acts as a ModifyBody (or AddFunction when the sig has no head) for branch-head purposes — transition_for_kind returns the appropriate StageTransition.

Fields

§sig_id: SigId
§winner_candidate: OpId

Op id of the Self::Candidate being promoted.

§winner_stage_id: StageId

Stage id of the winner (duplicates the candidate’s stage_id for fast lookup; saves a log round-trip for lex op show).

§supersedes: Vec<OpId>

Every other live Candidate for sig_id at the time of promotion. Sorted by op_id for canonical-form stability. After this Promote lands, none of these op_ids appear in [Store::list_candidates].

§from_stage_id: Option<StageId>

Current branch head stage for sig_id, or None if the sig had no head (the Promote is creating it). None is serialized as missing for canonical stability across “first promote on a sig” vs “later promote”.

§from_budget: Option<u64>
§to_budget: Option<u64>

Implementations§

Source§

impl OperationKind

Source

pub fn merge_target(&self) -> Option<(SigId, Option<StageId>)>

The (SigId, Option<StageId>) an op kind targets, as used by StageTransition::Merge::entries. Used by the merge-commit path (#134) to translate a Resolution::Custom { op } into the head-map delta the merge op records:

  • Adds → (sig, Some(stage_id))
  • Modifies → (sig, Some(to_stage_id))
  • Removes → (sig, None)
  • Renames → (to_sig, Some(body_stage_id))
  • AddImport / RemoveImport / nested MergeNone (no single sig→stage delta)
Source

pub fn budget_delta(&self) -> (Option<u64>, Option<u64>)

(from_budget, to_budget) for ops that carry a budget delta (#247). (None, None) for ops where the budget isn’t part of the canonical payload — RemoveFunction, RenameSymbol, imports, and merges. AddFunction reports (None, Some(cost)) for “this is the initial cost.” Used by lex op show, lex op log --budget-drift, and lex audit --budget.

Source

pub fn budget_sig(&self) -> Option<&SigId>

The SigId an op touches if it carries a budget — used for per-sig audit rollups in lex audit --budget. Returns None for ops without a relevant budget (the same set as the _ => (None, None) arm of Self::budget_delta).

Trait Implementations§

Source§

impl Clone for OperationKind

Source§

fn clone(&self) -> OperationKind

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for OperationKind

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for OperationKind

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for OperationKind

Source§

impl PartialEq for OperationKind

Source§

fn eq(&self, other: &OperationKind) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for OperationKind

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for OperationKind

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.