range support
This commit is contained in:
parent
69b2d00756
commit
2202118efb
|
@ -252,7 +252,18 @@ fn compile_expression(
|
||||||
in_reg: Option<RegId>,
|
in_reg: Option<RegId>,
|
||||||
out_reg: RegId,
|
out_reg: RegId,
|
||||||
) -> Result<(), CompileError> {
|
) -> Result<(), CompileError> {
|
||||||
|
let drop_input = |builder: &mut BlockBuilder| {
|
||||||
|
if let Some(in_reg) = in_reg {
|
||||||
|
if in_reg != out_reg {
|
||||||
|
builder.drop_reg(in_reg)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
let lit = |builder: &mut BlockBuilder, literal: Literal| {
|
let lit = |builder: &mut BlockBuilder, literal: Literal| {
|
||||||
|
drop_input(builder)?;
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.push(
|
.push(
|
||||||
Instruction::LoadLiteral {
|
Instruction::LoadLiteral {
|
||||||
|
@ -265,11 +276,7 @@ fn compile_expression(
|
||||||
};
|
};
|
||||||
|
|
||||||
let ignore = |builder: &mut BlockBuilder| {
|
let ignore = |builder: &mut BlockBuilder| {
|
||||||
if let Some(in_reg) = in_reg {
|
drop_input(builder)?;
|
||||||
if in_reg != out_reg {
|
|
||||||
builder.drop_reg(in_reg)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.load_empty(out_reg)
|
builder.load_empty(out_reg)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -281,16 +288,56 @@ fn compile_expression(
|
||||||
let data_slice = builder.data(bin)?;
|
let data_slice = builder.data(bin)?;
|
||||||
lit(builder, Literal::Binary(data_slice))
|
lit(builder, Literal::Binary(data_slice))
|
||||||
}
|
}
|
||||||
Expr::Range(_) => Err(CompileError::Todo("Range")),
|
Expr::Range(range) => {
|
||||||
Expr::Var(var_id) => builder
|
// Compile the subexpressions of the range
|
||||||
.push(
|
let compile_part = |builder: &mut BlockBuilder,
|
||||||
|
part_expr: Option<&Expression>|
|
||||||
|
-> Result<RegId, CompileError> {
|
||||||
|
let reg = builder.next_register()?;
|
||||||
|
if let Some(part_expr) = part_expr {
|
||||||
|
compile_expression(
|
||||||
|
working_set,
|
||||||
|
builder,
|
||||||
|
part_expr,
|
||||||
|
redirect_modes.with_capture_out(part_expr.span),
|
||||||
|
None,
|
||||||
|
reg,
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
builder.load_literal(reg, Literal::Nothing.into_spanned(expr.span))?;
|
||||||
|
}
|
||||||
|
Ok(reg)
|
||||||
|
};
|
||||||
|
|
||||||
|
drop_input(builder)?;
|
||||||
|
|
||||||
|
let start = compile_part(builder, range.from.as_ref())?;
|
||||||
|
let step = compile_part(builder, range.next.as_ref())?;
|
||||||
|
let end = compile_part(builder, range.to.as_ref())?;
|
||||||
|
|
||||||
|
// Assemble the range
|
||||||
|
builder.load_literal(
|
||||||
|
out_reg,
|
||||||
|
Literal::Range {
|
||||||
|
start,
|
||||||
|
step,
|
||||||
|
end,
|
||||||
|
inclusion: range.operator.inclusion,
|
||||||
|
}
|
||||||
|
.into_spanned(expr.span),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Expr::Var(var_id) => {
|
||||||
|
drop_input(builder)?;
|
||||||
|
builder.push(
|
||||||
Instruction::LoadVariable {
|
Instruction::LoadVariable {
|
||||||
dst: out_reg,
|
dst: out_reg,
|
||||||
var_id: *var_id,
|
var_id: *var_id,
|
||||||
}
|
}
|
||||||
.into_spanned(expr.span),
|
.into_spanned(expr.span),
|
||||||
)
|
)?;
|
||||||
.map(|_| ()),
|
Ok(())
|
||||||
|
}
|
||||||
Expr::VarDecl(_) => Err(CompileError::Todo("VarDecl")),
|
Expr::VarDecl(_) => Err(CompileError::Todo("VarDecl")),
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
// Ensure that out_reg contains the input value, because a call only uses one register
|
// Ensure that out_reg contains the input value, because a call only uses one register
|
||||||
|
@ -316,10 +363,7 @@ fn compile_expression(
|
||||||
Expr::Operator(_) => Err(CompileError::Todo("Operator")),
|
Expr::Operator(_) => Err(CompileError::Todo("Operator")),
|
||||||
Expr::RowCondition(_) => Err(CompileError::Todo("RowCondition")),
|
Expr::RowCondition(_) => Err(CompileError::Todo("RowCondition")),
|
||||||
Expr::UnaryNot(subexpr) => {
|
Expr::UnaryNot(subexpr) => {
|
||||||
if let Some(in_reg) = in_reg {
|
drop_input(builder)?;
|
||||||
// Discard the input
|
|
||||||
builder.drop_reg(in_reg)?;
|
|
||||||
}
|
|
||||||
compile_expression(
|
compile_expression(
|
||||||
working_set,
|
working_set,
|
||||||
builder,
|
builder,
|
||||||
|
@ -333,10 +377,7 @@ fn compile_expression(
|
||||||
}
|
}
|
||||||
Expr::BinaryOp(lhs, op, rhs) => {
|
Expr::BinaryOp(lhs, op, rhs) => {
|
||||||
if let Expr::Operator(ref operator) = op.expr {
|
if let Expr::Operator(ref operator) = op.expr {
|
||||||
if let Some(in_reg) = in_reg {
|
drop_input(builder)?;
|
||||||
// Discard the input
|
|
||||||
builder.drop_reg(in_reg)?;
|
|
||||||
}
|
|
||||||
compile_binary_op(
|
compile_binary_op(
|
||||||
working_set,
|
working_set,
|
||||||
builder,
|
builder,
|
||||||
|
@ -1081,7 +1122,46 @@ impl BlockBuilder {
|
||||||
/// Returns the offset of the inserted instruction.
|
/// Returns the offset of the inserted instruction.
|
||||||
fn push(&mut self, instruction: Spanned<Instruction>) -> Result<usize, CompileError> {
|
fn push(&mut self, instruction: Spanned<Instruction>) -> Result<usize, CompileError> {
|
||||||
match &instruction.item {
|
match &instruction.item {
|
||||||
Instruction::LoadLiteral { dst, lit: _ } => self.mark_register(*dst)?,
|
Instruction::LoadLiteral { dst, lit } => {
|
||||||
|
self.mark_register(*dst)?;
|
||||||
|
// Free any registers on the literal
|
||||||
|
match lit {
|
||||||
|
Literal::Range {
|
||||||
|
start,
|
||||||
|
step,
|
||||||
|
end,
|
||||||
|
inclusion: _,
|
||||||
|
} => {
|
||||||
|
self.free_register(*start)?;
|
||||||
|
self.free_register(*step)?;
|
||||||
|
self.free_register(*end)?;
|
||||||
|
}
|
||||||
|
Literal::Bool(_)
|
||||||
|
| Literal::Int(_)
|
||||||
|
| Literal::Float(_)
|
||||||
|
| Literal::Binary(_)
|
||||||
|
| Literal::Block(_)
|
||||||
|
| Literal::Closure(_)
|
||||||
|
| Literal::List { capacity: _ }
|
||||||
|
| Literal::Record { capacity: _ }
|
||||||
|
| Literal::Filepath {
|
||||||
|
val: _,
|
||||||
|
no_expand: _,
|
||||||
|
}
|
||||||
|
| Literal::Directory {
|
||||||
|
val: _,
|
||||||
|
no_expand: _,
|
||||||
|
}
|
||||||
|
| Literal::GlobPattern {
|
||||||
|
val: _,
|
||||||
|
no_expand: _,
|
||||||
|
}
|
||||||
|
| Literal::String(_)
|
||||||
|
| Literal::RawString(_)
|
||||||
|
| Literal::CellPath(_)
|
||||||
|
| Literal::Nothing => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
Instruction::Move { dst, src } => {
|
Instruction::Move { dst, src } => {
|
||||||
self.free_register(*src)?;
|
self.free_register(*src)?;
|
||||||
self.mark_register(*dst)?;
|
self.mark_register(*dst)?;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user