Implemented case statements

This commit is contained in:
2025-03-19 02:16:53 -04:00
parent 19dee4bcd6
commit aa2684546e
12 changed files with 2809 additions and 100 deletions

View File

@@ -3,7 +3,7 @@ use std::collections::VecDeque;
use crate::{builtin::{alias::alias, cd::cd, echo::echo, export::export, jobctl::{continue_job, jobs, JobBehavior}, pwd::pwd, shift::shift, source::source}, exec_input, jobs::{dispatch_job, ChildProc, Job, JobBldr, JobStack}, libsh::{error::{ShErr, ShErrKind, ShResult, ShResultExt}, utils::RedirVecUtils}, prelude::*, procio::{IoFrame, IoMode, IoStack}, state::{self, read_logic, read_vars, write_logic, write_vars, ShFunc, VarTab}};
use super::{lex::{LexFlags, LexStream, Span, Tk, TkFlags, KEYWORDS}, AssignKind, CondNode, ConjunctNode, ConjunctOp, LoopKind, NdFlags, NdRule, Node, ParseStream, ParsedSrc, Redir, RedirType};
use super::{lex::{LexFlags, LexStream, Span, Tk, TkFlags, KEYWORDS}, AssignKind, CaseNode, CondNode, ConjunctNode, ConjunctOp, LoopKind, NdFlags, NdRule, Node, ParseStream, ParsedSrc, Redir, RedirType};
pub enum AssignBehavior {
Export,
@@ -62,6 +62,7 @@ impl Dispatcher {
NdRule::Pipeline {..} => self.exec_pipeline(node)?,
NdRule::IfNode {..} => self.exec_if(node)?,
NdRule::LoopNode {..} => self.exec_loop(node)?,
NdRule::CaseNode {..} => self.exec_case(node)?,
NdRule::BraceGrp {..} => self.exec_brc_grp(node)?,
NdRule::FuncDef {..} => self.exec_func_def(node)?,
NdRule::Command {..} => self.dispatch_cmd(node)?,
@@ -181,6 +182,39 @@ impl Dispatcher {
Ok(())
}
pub fn exec_case(&mut self, case_stmt: Node) -> ShResult<()> {
let NdRule::CaseNode { pattern, case_blocks } = case_stmt.class else {
unreachable!()
};
self.io_stack.append_to_frame(case_stmt.redirs);
flog!(DEBUG,pattern.span.as_str());
let exp_pattern = pattern.clone().expand(pattern.span.clone(), pattern.flags.clone());
let pattern_raw = exp_pattern
.get_words()
.first()
.map(|s| s.to_string())
.unwrap_or_default();
flog!(DEBUG,exp_pattern);
for block in case_blocks {
let CaseNode { pattern, body } = block;
let block_pattern_raw = pattern.span.as_str().trim_end_matches(')').trim();
// Split at '|' to allow for multiple patterns like `foo|bar)`
let block_patterns = block_pattern_raw.split('|');
for pattern in block_patterns {
if pattern_raw == pattern || pattern == "*" {
for node in &body {
self.dispatch_node(node.clone())?;
}
}
}
}
Ok(())
}
pub fn exec_loop(&mut self, loop_stmt: Node) -> ShResult<()> {
let NdRule::LoopNode { kind, cond_node } = loop_stmt.class else {
unreachable!();