pub struct Scope { /* private fields */ }Expand description
Variable scope with nested frames and last-result tracking.
Variables are looked up from innermost to outermost frame.
The ? variable always refers to the last command result.
The frames field is wrapped in Arc for copy-on-write (COW) semantics.
Cloning a Scope is O(1) — just bumps the Arc refcount. Mutations use
Arc::make_mut to clone the inner data only when shared. This matters
because execute_pipeline snapshots the scope into ExecContext (clone)
and syncs it back (clone) on every command.
Implementations§
Source§impl Scope
impl Scope
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new scope with one empty frame.
pid defaults to 0 (sentinel). The owning Kernel calls set_pid()
during construction to assign the real session identifier.
Sourcepub fn set_pid(&mut self, pid: u64)
pub fn set_pid(&mut self, pid: u64)
Set the kaish session identifier ($$). Called by the Kernel during
construction to thread the assigned counter value into the scope.
Also used by kaish-clear to preserve $$ across a session reset.
Sourcepub fn push_frame(&mut self)
pub fn push_frame(&mut self)
Push a new scope frame (for entering a loop, tool call, etc.)
Sourcepub fn pop_frame(&mut self)
pub fn pop_frame(&mut self)
Pop the innermost scope frame.
Panics if attempting to pop the last frame.
Sourcepub fn set(&mut self, name: impl Into<String>, value: Value)
pub fn set(&mut self, name: impl Into<String>, value: Value)
Set a variable in the current (innermost) frame.
Use this for local variable declarations.
The name is NFC-normalized here, which is what makes the scope’s keys
canonical no matter which door bound them. Parse-time normalization
covers the four written spellings of a name; this covers every runtime
binder — for, read, unset, scatter --as, and the embedder’s own
initial_vars — without each having to remember.
Sourcepub fn set_global(&mut self, name: impl Into<String>, value: Value)
pub fn set_global(&mut self, name: impl Into<String>, value: Value)
Set a variable with global semantics (shell default).
If the variable exists in any frame, update it there. Otherwise, create it in the outermost (root) frame. Use this for non-local variable assignments.
Sourcepub fn get(&self, name: &str) -> Option<&Value>
pub fn get(&self, name: &str) -> Option<&Value>
Get a variable by name, searching from innermost to outermost frame.
Sourcepub fn remove(&mut self, name: &str) -> Option<Value>
pub fn remove(&mut self, name: &str) -> Option<Value>
Remove a variable, searching from innermost to outermost frame.
Returns the removed value if found, None otherwise.
Sourcepub fn set_last_result(&mut self, result: ExecResult)
pub fn set_last_result(&mut self, result: ExecResult)
Set the last command result (accessible via $?).
Sourcepub fn last_result(&self) -> &ExecResult
pub fn last_result(&self) -> &ExecResult
Get the last command result.
Sourcepub fn note_cmdsubst_code(&mut self, code: i64)
pub fn note_cmdsubst_code(&mut self, code: i64)
Note the exit code of a command substitution that just completed. Overwritten by each later substitution, so the last one performed wins.
Sourcepub fn clear_cmdsubst_code(&mut self)
pub fn clear_cmdsubst_code(&mut self)
Forget any noted command-substitution code. Called before evaluating an assignment’s value so an earlier statement’s substitution cannot leak into this one’s status.
Sourcepub fn take_cmdsubst_code(&mut self) -> Option<i64>
pub fn take_cmdsubst_code(&mut self) -> Option<i64>
Take the noted command-substitution code, leaving none.
Sourcepub fn set_positional(
&mut self,
script_name: impl Into<String>,
args: Vec<String>,
)
pub fn set_positional( &mut self, script_name: impl Into<String>, args: Vec<String>, )
Set the positional parameters ($0, $1-$9, $@, $#).
The script_name becomes $0, and args become $1, $2, etc.
Sourcepub fn save_positional(&self) -> (String, Vec<String>)
pub fn save_positional(&self) -> (String, Vec<String>)
Save current positional parameters for later restoration.
Returns (script_name, args) tuple that can be passed to set_positional.
Sourcepub fn get_positional(&self, n: usize) -> Option<&str>
pub fn get_positional(&self, n: usize) -> Option<&str>
Get a positional parameter by index ($0-$9).
$0 returns the script name, $1-$9 return arguments.
Sourcepub fn error_exit_enabled(&self) -> bool
pub fn error_exit_enabled(&self) -> bool
Check if error-exit mode is active (set -e and not suppressed).
Returns false when inside the left side of && or || chains,
matching bash behavior where those operators handle failure themselves.
Sourcepub fn set_error_exit(&mut self, enabled: bool)
pub fn set_error_exit(&mut self, enabled: bool)
Set error-exit mode (set -e / set +e).
Sourcepub fn suppress_errexit(&mut self)
pub fn suppress_errexit(&mut self)
Suppress errexit temporarily (for &&/|| left side).
Sourcepub fn unsuppress_errexit(&mut self)
pub fn unsuppress_errexit(&mut self)
Unsuppress errexit (after &&/|| left side completes).
Sourcepub fn set_show_ast(&mut self, enabled: bool)
pub fn set_show_ast(&mut self, enabled: bool)
Set AST display mode (kaish-ast -on / kaish-ast -off).
Sourcepub fn trash_enabled(&self) -> bool
pub fn trash_enabled(&self) -> bool
Check if trash mode is enabled (set -o trash).
Sourcepub fn set_trash_enabled(&mut self, enabled: bool)
pub fn set_trash_enabled(&mut self, enabled: bool)
Set trash mode (set -o trash / set +o trash).
Sourcepub fn trash_max_size(&self) -> u64
pub fn trash_max_size(&self) -> u64
Get the maximum file size for trash (bytes).
Sourcepub fn set_trash_max_size(&mut self, size: u64)
pub fn set_trash_max_size(&mut self, size: u64)
Set the maximum file size for trash (bytes).
Sourcepub fn glob_enabled(&self) -> bool
pub fn glob_enabled(&self) -> bool
Check if glob expansion is enabled (set -o glob, default true).
Sourcepub fn set_glob_enabled(&mut self, enabled: bool)
pub fn set_glob_enabled(&mut self, enabled: bool)
Set glob expansion mode (set -o glob / set +o glob).
Sourcepub fn export(&mut self, name: impl Into<String>)
pub fn export(&mut self, name: impl Into<String>)
Mark a variable as exported (visible to child processes).
The variable doesn’t need to exist yet; it will be exported when set.
Sourcepub fn is_exported(&self, name: &str) -> bool
pub fn is_exported(&self, name: &str) -> bool
Check if a variable is marked for export.
Sourcepub fn set_exported(&mut self, name: impl Into<String>, value: Value)
pub fn set_exported(&mut self, name: impl Into<String>, value: Value)
Set a variable in the innermost frame and mark it as exported.
Used for frame-scoped overlays (execute_with_vars, FOO=bar cmd) and
for seeding root-frame exports at construction. For the export
builtin’s assignment form use set_exported_global
so the value survives a function return (shared-scope semantics).
Sourcepub fn set_exported_global(&mut self, name: impl Into<String>, value: Value)
pub fn set_exported_global(&mut self, name: impl Into<String>, value: Value)
Set a variable with global (shared-scope) semantics and mark it as
exported. This is export NAME=VALUE: like a plain assignment, the value
updates an existing variable wherever it lives or lands in the root frame,
so it persists past a function return rather than dying with the
function’s frame.
Sourcepub fn exported_vars(&self) -> Vec<(String, Value)>
pub fn exported_vars(&self) -> Vec<(String, Value)>
Get all exported variables with their values.
Only returns variables that exist and are marked for export.
Sourcepub fn exported_names(&self) -> Vec<&str>
pub fn exported_names(&self) -> Vec<&str>
Get all exported variable names.
Sourcepub fn resolve_path(&self, path: &VarPath) -> Result<Value, PathError>
pub fn resolve_path(&self, path: &VarPath) -> Result<Value, PathError>
Resolve a variable path: ${VAR}, ${xs[0]}, ${r[key]}, ${a[b][c]}.
The first segment is the root name; the rest are bracket subscripts,
walked left to right into the root’s Value::Json. A subscript landing
on a JSON scalar unwraps to a native Value (envelope-free); a subscript
landing on a collection stays Value::Json. $? resolves to the
previous command’s exit code (bare only).
Traversal borrows into the root’s JSON tree and clones only the selected
leaf (a slice builds a new list); the whole-root clone is never taken, so
repeated ${u[$k]} in a loop stays O(depth), not O(root size). The
per-hop classification lives in resolve_step, shared with the future
lvalue-write walk so read and write can never diverge.
Errors distinguish an undefined root (soft) from a loud path error (see
PathError).
Sourcepub fn walk_write(
&mut self,
path: &VarPath,
value: Value,
) -> Result<(), PathError>
pub fn walk_write( &mut self, path: &VarPath, value: Value, ) -> Result<(), PathError>
Write a value into a collection lvalue path: xs[0]=9,
user[email]=amy@example.com, services[web][port]=9090.
Shares resolve_step with resolve_path so
classification (bounds, shape) never drifts between read and write.
The walk itself diverges at the leaf: every intermediate hop requires
the child to already exist (descend_mut — no autovivification),
while the final hop may insert a new record key (apply_leaf_write) —
the ONLY thing a path-set may create. A list index write is in-bounds
update only (resolve_step’s classify_index already turns an
out-of-bounds index into a loud Absence); push is how lists grow.
A slice lvalue (xs[0:2]=…) is always a Shape error.
The root must already be defined (UndefinedRoot) and be a collection
(Shape for a scalar root) — same rule as a read. On success the
mutated root replaces the old value via set_global. A bracket-path
write updates the variable wherever it lives and ignores local,
because it mutates an existing binding instead of creating one. See
docs/LANGUAGE.md, “Assignment — bracket-path lvalues”.
Sourcepub fn walk_append(
&mut self,
path: &VarPath,
values: Vec<Value>,
) -> Result<(), String>
pub fn walk_append( &mut self, path: &VarPath, values: Vec<Value>, ) -> Result<(), String>
Append value(s) to a list variable, in place: a top-level bareword
target (push xs val) or a bracket-path target
(push services[web][tags] item).
The target must already exist and be a list — an undefined root, a
non-list leaf, or a missing intermediate hop is a loud error, never a
silent create or autoviv. See docs/LANGUAGE.md, “Assignment —
bracket-path lvalues + push”. Intermediate hops share walk_write’s
resolve_step/descend_mut, so a push path and an assignment path
classify identically. Only the final hop differs: it appends instead
of replacing.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Scope
impl RefUnwindSafe for Scope
impl Send for Scope
impl Sync for Scope
impl Unpin for Scope
impl UnsafeUnpin for Scope
impl UnwindSafe for Scope
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,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> OrderedSeq<'_, T> for Twhere
T: Clone,
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
impl<'p, T> Seq<'p, T> for Twhere
T: Clone,
Source§impl<T, S> SpanWrap<S> for Twhere
S: WrappingSpan<T>,
impl<T, S> SpanWrap<S> for Twhere
S: WrappingSpan<T>,
Source§fn with_span(self, span: S) -> <S as WrappingSpan<Self>>::Spanned
fn with_span(self, span: S) -> <S as WrappingSpan<Self>>::Spanned
WrappingSpan::make_wrapped to wrap an AST node in a span.