add specific error for match guard bool

This commit is contained in:
Devyn Cairns 2024-07-08 20:13:50 -07:00
parent f026a07fe3
commit 6a8169e8ba
5 changed files with 40 additions and 20 deletions

View File

@ -227,6 +227,7 @@ impl BlockBuilder {
src, src,
index: _, index: _,
} => allocate(&[*src], &[*src]), } => allocate(&[*src], &[*src]),
Instruction::CheckMatchGuard { src } => allocate(&[*src], &[*src]),
Instruction::Iterate { Instruction::Iterate {
dst, dst,
stream, stream,

View File

@ -149,6 +149,7 @@ pub(crate) fn compile_match(
// drop %match_reg // drop %match_reg
// jump END // jump END
// PAT1: %guard_reg <- <guard_expr> // PAT1: %guard_reg <- <guard_expr>
// check-match-guard %guard_reg
// not %guard_reg // not %guard_reg
// branch-if %guard_reg, MATCH2 // branch-if %guard_reg, MATCH2
// drop %match_reg // drop %match_reg
@ -224,6 +225,8 @@ pub(crate) fn compile_match(
None, None,
guard_reg, guard_reg,
)?; )?;
builder
.push(Instruction::CheckMatchGuard { src: guard_reg }.into_spanned(guard.span))?;
builder.push(Instruction::Not { src_dst: guard_reg }.into_spanned(guard.span))?; builder.push(Instruction::Not { src_dst: guard_reg }.into_spanned(guard.span))?;
// Branch to the next match instruction if the branch fails to match // Branch to the next match instruction if the branch fails to match
builder.push( builder.push(

View File

@ -116,6 +116,12 @@ impl<'a> EvalContext<'a> {
self.registers[reg_id.0 as usize] = new_value; self.registers[reg_id.0 as usize] = new_value;
} }
/// Borrow the contents of a register.
#[inline]
fn borrow_reg(&self, reg_id: RegId) -> &PipelineData {
&self.registers[reg_id.0 as usize]
}
/// Replace the contents of a register with `Empty` and then return the value that it contained /// Replace the contents of a register with `Empty` and then return the value that it contained
#[inline] #[inline]
fn take_reg(&mut self, reg_id: RegId) -> PipelineData { fn take_reg(&mut self, reg_id: RegId) -> PipelineData {
@ -422,13 +428,10 @@ fn eval_instruction<D: DebugContext>(
ctx.redirect_err = eval_redirection(ctx, mode, *span, RedirectionStream::Err)?; ctx.redirect_err = eval_redirection(ctx, mode, *span, RedirectionStream::Err)?;
Ok(Continue) Ok(Continue)
} }
Instruction::CheckErrRedirected { src } => { Instruction::CheckErrRedirected { src } => match ctx.borrow_reg(*src) {
let data = ctx.take_reg(*src);
match &data {
PipelineData::ByteStream(stream, _) PipelineData::ByteStream(stream, _)
if matches!(stream.source(), ByteStreamSource::Child(_)) => if matches!(stream.source(), ByteStreamSource::Child(_)) =>
{ {
ctx.put_reg(*src, data);
Ok(Continue) Ok(Continue)
} }
_ => Err(ShellError::GenericError { _ => Err(ShellError::GenericError {
@ -438,8 +441,7 @@ fn eval_instruction<D: DebugContext>(
help: None, help: None,
inner: vec![], inner: vec![],
}), }),
} },
}
Instruction::OpenFile { Instruction::OpenFile {
file_num, file_num,
path, path,
@ -656,12 +658,10 @@ fn eval_instruction<D: DebugContext>(
} }
} }
Instruction::BranchIfEmpty { src, index } => { Instruction::BranchIfEmpty { src, index } => {
let data = ctx.take_reg(*src);
let is_empty = matches!( let is_empty = matches!(
data, ctx.borrow_reg(*src),
PipelineData::Empty | PipelineData::Value(Value::Nothing { .. }, _) PipelineData::Empty | PipelineData::Value(Value::Nothing { .. }, _)
); );
ctx.put_reg(*src, data);
if is_empty { if is_empty {
Ok(Branch(*index)) Ok(Branch(*index))
@ -688,6 +688,16 @@ fn eval_instruction<D: DebugContext>(
Ok(Continue) Ok(Continue)
} }
} }
Instruction::CheckMatchGuard { src } => {
if matches!(
ctx.borrow_reg(*src),
PipelineData::Value(Value::Bool { .. }, _)
) {
Ok(Continue)
} else {
Err(ShellError::MatchGuardNotBool { span: *span })
}
}
Instruction::Iterate { Instruction::Iterate {
dst, dst,
stream, stream,

View File

@ -216,6 +216,9 @@ impl<'a> fmt::Display for FmtInstruction<'a> {
}; };
write!(f, "{:WIDTH$} ({pattern}), {src}, {index}", "match") write!(f, "{:WIDTH$} ({pattern}), {src}, {index}", "match")
} }
Instruction::CheckMatchGuard { src } => {
write!(f, "{:WIDTH$} {src}", "check-match-guard")
}
Instruction::Iterate { Instruction::Iterate {
dst, dst,
stream, stream,

View File

@ -223,6 +223,9 @@ pub enum Instruction {
src: RegId, src: RegId,
index: usize, index: usize,
}, },
/// Check that a match guard is a boolean, throwing
/// [`MatchGuardNotBool`](crate::ShellError::MatchGuardNotBool) if it isn't. Preserves `src`.
CheckMatchGuard { src: RegId },
/// Iterate on register `stream`, putting the next value in `dst` if present, or jumping to /// Iterate on register `stream`, putting the next value in `dst` if present, or jumping to
/// `end_index` if the iterator is finished /// `end_index` if the iterator is finished
Iterate { Iterate {