add specific error for match guard bool
This commit is contained in:
parent
f026a07fe3
commit
6a8169e8ba
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user