separate handling of input/output regs for expression
This commit is contained in:
parent
e45ff3dd1d
commit
554ba494c6
|
@ -97,7 +97,7 @@ fn compile_pipeline(
|
||||||
&element.expr,
|
&element.expr,
|
||||||
out_mode,
|
out_mode,
|
||||||
err_mode,
|
err_mode,
|
||||||
io_reg,
|
Some(io_reg),
|
||||||
io_reg,
|
io_reg,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -116,14 +116,14 @@ fn redirection_target_to_mode(
|
||||||
append,
|
append,
|
||||||
span: redir_span,
|
span: redir_span,
|
||||||
} => {
|
} => {
|
||||||
let path_reg = builder.nothing()?;
|
let path_reg = builder.next_register()?;
|
||||||
compile_expression(
|
compile_expression(
|
||||||
engine_state,
|
engine_state,
|
||||||
builder,
|
builder,
|
||||||
expr,
|
expr,
|
||||||
Some(RedirectMode::Capture.into_spanned(*redir_span)),
|
Some(RedirectMode::Capture.into_spanned(*redir_span)),
|
||||||
None,
|
None,
|
||||||
path_reg,
|
None,
|
||||||
path_reg,
|
path_reg,
|
||||||
)?;
|
)?;
|
||||||
RedirectMode::File {
|
RedirectMode::File {
|
||||||
|
@ -168,7 +168,7 @@ fn compile_expression(
|
||||||
expr: &Expression,
|
expr: &Expression,
|
||||||
out_mode: Option<Spanned<RedirectMode>>,
|
out_mode: Option<Spanned<RedirectMode>>,
|
||||||
err_mode: Option<Spanned<RedirectMode>>,
|
err_mode: Option<Spanned<RedirectMode>>,
|
||||||
in_reg: RegId,
|
in_reg: Option<RegId>,
|
||||||
out_reg: RegId,
|
out_reg: RegId,
|
||||||
) -> Result<(), CompileError> {
|
) -> Result<(), CompileError> {
|
||||||
let lit = |builder: &mut BlockBuilder, literal: Literal| {
|
let lit = |builder: &mut BlockBuilder, literal: Literal| {
|
||||||
|
@ -190,17 +190,24 @@ fn compile_expression(
|
||||||
Expr::Var(_) => todo!(),
|
Expr::Var(_) => todo!(),
|
||||||
Expr::VarDecl(_) => todo!(),
|
Expr::VarDecl(_) => todo!(),
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
compile_call(engine_state, builder, &call, out_mode, err_mode, in_reg)?;
|
// Ensure that out_reg contains the input value, because a call only uses one register
|
||||||
if in_reg != out_reg {
|
if let Some(in_reg) = in_reg {
|
||||||
builder.push(
|
if in_reg != out_reg {
|
||||||
Instruction::Move {
|
// Have to move in_reg to out_reg so it can be used
|
||||||
dst: out_reg,
|
builder.push(
|
||||||
src: in_reg,
|
Instruction::Move {
|
||||||
}
|
dst: out_reg,
|
||||||
.into_spanned(expr.span),
|
src: in_reg,
|
||||||
)?;
|
}
|
||||||
|
.into_spanned(call.head),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Will have to initialize out_reg with Nothing first
|
||||||
|
builder.load_nothing(out_reg)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
|
compile_call(engine_state, builder, &call, out_mode, err_mode, out_reg)
|
||||||
}
|
}
|
||||||
Expr::ExternalCall(_, _) => todo!(),
|
Expr::ExternalCall(_, _) => todo!(),
|
||||||
Expr::Operator(_) => todo!(),
|
Expr::Operator(_) => todo!(),
|
||||||
|
@ -273,7 +280,7 @@ fn compile_call(
|
||||||
let arg_reg = arg
|
let arg_reg = arg
|
||||||
.expr()
|
.expr()
|
||||||
.map(|expr| {
|
.map(|expr| {
|
||||||
let arg_reg = builder.nothing()?;
|
let arg_reg = builder.next_register()?;
|
||||||
|
|
||||||
compile_expression(
|
compile_expression(
|
||||||
engine_state,
|
engine_state,
|
||||||
|
@ -281,7 +288,7 @@ fn compile_call(
|
||||||
expr,
|
expr,
|
||||||
Some(RedirectMode::Capture.into_spanned(arg.span())),
|
Some(RedirectMode::Capture.into_spanned(arg.span())),
|
||||||
None,
|
None,
|
||||||
arg_reg,
|
None,
|
||||||
arg_reg,
|
arg_reg,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -345,16 +352,16 @@ fn compile_binary_op(
|
||||||
lhs: &Expression,
|
lhs: &Expression,
|
||||||
op: Spanned<Operator>,
|
op: Spanned<Operator>,
|
||||||
rhs: &Expression,
|
rhs: &Expression,
|
||||||
in_reg: RegId, // only for $in (TODO)
|
in_reg: Option<RegId>, // only for $in (TODO)
|
||||||
out_reg: RegId,
|
out_reg: RegId,
|
||||||
) -> Result<(), CompileError> {
|
) -> Result<(), CompileError> {
|
||||||
// If we aren't worried about clobbering in_reg, we can write straight to out_reg
|
// If we aren't worried about clobbering in_reg, we can write straight to out_reg
|
||||||
let lhs_reg = if in_reg != out_reg {
|
let lhs_reg = if in_reg != Some(out_reg) {
|
||||||
out_reg
|
out_reg
|
||||||
} else {
|
} else {
|
||||||
builder.nothing()?
|
builder.next_register()?
|
||||||
};
|
};
|
||||||
let rhs_reg = builder.nothing()?;
|
let rhs_reg = builder.next_register()?;
|
||||||
|
|
||||||
compile_expression(
|
compile_expression(
|
||||||
engine_state,
|
engine_state,
|
||||||
|
@ -539,22 +546,15 @@ impl BlockBuilder {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a register for and then load a literal.
|
/// Initialize a register with [`Nothing`](Literal::Nothing).
|
||||||
fn literal(&mut self, literal: Spanned<Literal>) -> Result<RegId, CompileError> {
|
fn load_nothing(&mut self, reg_id: RegId) -> Result<(), CompileError> {
|
||||||
let reg_id = self.next_register()?;
|
|
||||||
self.push(
|
self.push(
|
||||||
Instruction::LoadLiteral {
|
Instruction::LoadLiteral {
|
||||||
dst: reg_id,
|
dst: reg_id,
|
||||||
lit: literal.item,
|
lit: Literal::Nothing,
|
||||||
}
|
}
|
||||||
.into_spanned(literal.span),
|
.into_spanned(Span::unknown()),
|
||||||
)?;
|
)
|
||||||
Ok(reg_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allocate a register with [`Nothing`](Literal::Nothing).
|
|
||||||
fn nothing(&mut self) -> Result<RegId, CompileError> {
|
|
||||||
self.literal(Literal::Nothing.into_spanned(Span::unknown()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume the builder and produce the final [`IrBlock`].
|
/// Consume the builder and produce the final [`IrBlock`].
|
||||||
|
|
|
@ -24,6 +24,10 @@ pub struct RegId(pub u32);
|
||||||
|
|
||||||
impl std::fmt::Display for RegId {
|
impl std::fmt::Display for RegId {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "%{}", self.0)
|
if self.0 != 0 {
|
||||||
|
write!(f, "%{}", self.0)
|
||||||
|
} else {
|
||||||
|
write!(f, "%none")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user