Implemented arrays and array indexing

This commit is contained in:
2026-02-26 00:32:54 -05:00
parent b55e6e2dfd
commit f9312885bd
10 changed files with 570 additions and 309 deletions

View File

@@ -9,7 +9,7 @@ use crate::{
libsh::{error::{ShErr, ShErrKind, ShResult, ShResultExt}, utils::RedirVecUtils},
prelude::*,
procio::{IoMode, IoStack},
state::{self, ShFunc, VarFlags, read_logic, read_shopts, write_jobs, write_logic, write_vars},
state::{self, ShFunc, VarFlags, VarKind, read_logic, read_shopts, write_jobs, write_logic, write_vars},
};
use super::{
@@ -569,7 +569,7 @@ impl Dispatcher {
.zip(chunk.iter().chain(std::iter::repeat(&empty)));
for (var, val) in chunk_iter {
write_vars(|v| v.set_var(&var.to_string(), &val.to_string(), VarFlags::NONE))?;
write_vars(|v| v.set_var(&var.to_string(), VarKind::Str(val.to_string()), VarFlags::NONE))?;
for_guard.vars.insert(var.to_string());
}
@@ -899,13 +899,18 @@ impl Dispatcher {
match behavior {
AssignBehavior::Export => {
for assign in assigns {
let is_arr = assign.flags.contains(NdFlags::ARR_ASSIGN);
let NdRule::Assignment { kind, var, val } = assign.class else {
unreachable!()
};
let var = var.span.as_str();
let val = val.expand()?.get_words().join(" ");
let val = if is_arr {
VarKind::arr_from_tk(val)?
} else {
VarKind::Str(val.expand()?.get_words().join(" "))
};
match kind {
AssignKind::Eq => write_vars(|v| v.set_var(var, &val, VarFlags::EXPORT))?,
AssignKind::Eq => write_vars(|v| v.set_var(var, val, VarFlags::EXPORT))?,
AssignKind::PlusEq => todo!(),
AssignKind::MinusEq => todo!(),
AssignKind::MultEq => todo!(),
@@ -916,13 +921,18 @@ impl Dispatcher {
}
AssignBehavior::Set => {
for assign in assigns {
let is_arr = assign.flags.contains(NdFlags::ARR_ASSIGN);
let NdRule::Assignment { kind, var, val } = assign.class else {
unreachable!()
};
let var = var.span.as_str();
let val = val.expand()?.get_words().join(" ");
let val = if is_arr {
VarKind::arr_from_tk(val)?
} else {
VarKind::Str(val.expand()?.get_words().join(" "))
};
match kind {
AssignKind::Eq => write_vars(|v| v.set_var(var, &val, VarFlags::NONE))?,
AssignKind::Eq => write_vars(|v| v.set_var(var, val, VarFlags::NONE))?,
AssignKind::PlusEq => todo!(),
AssignKind::MinusEq => todo!(),
AssignKind::MultEq => todo!(),

View File

@@ -357,7 +357,7 @@ impl LexStream {
'$' if chars.peek() == Some(&'{') => {
pos += 2;
chars.next();
let mut brace_count = 0;
let mut brace_count = 1;
while let Some(brc_ch) = chars.next() {
match brc_ch {
'\\' => {
@@ -624,6 +624,35 @@ impl LexStream {
}
}
}
'=' if chars.peek() == Some(&'(') => {
pos += 1; // '='
let mut depth = 1;
chars.next();
pos += 1; // '('
// looks like an array
while let Some(arr_ch) = chars.next() {
match arr_ch {
'\\' => {
pos += 1;
if let Some(next_ch) = chars.next() {
pos += next_ch.len_utf8();
}
}
'(' => {
depth += 1;
pos += 1;
}
')' => {
depth -= 1;
pos += 1;
if depth == 0 {
break;
}
}
_ => pos += arr_ch.len_utf8(),
}
}
}
_ if !self.in_quote && is_op(ch) => break,
_ if is_hard_sep(ch) => break,
_ => pos += ch.len_utf8(),

View File

@@ -144,6 +144,7 @@ bitflags! {
const BACKGROUND = 0b000001;
const FORK_BUILTINS = 0b000010;
const NO_FORK = 0b000100;
const ARR_ASSIGN = 0b001000;
}
}
@@ -1472,22 +1473,28 @@ impl ParseStream {
}
}
}
if assign_kind.is_none() || var_name.is_empty() {
None
} else {
if let Some(assign_kind) = assign_kind && !var_name.is_empty() {
let var = Tk::new(TkRule::Str, Span::new(name_range, token.source()));
let val = Tk::new(TkRule::Str, Span::new(val_range, token.source()));
let flags = if var_val.starts_with('(') && var_val.ends_with(')') {
NdFlags::ARR_ASSIGN
} else {
NdFlags::empty()
};
Some(Node {
class: NdRule::Assignment {
kind: assign_kind.unwrap(),
kind: assign_kind,
var,
val,
},
tokens: vec![token.clone()],
flags: NdFlags::empty(),
flags,
redirs: vec![],
})
}
} else {
None
}
}
}