it does calls!!!
This commit is contained in:
parent
b0d24ea434
commit
3c4877b059
|
@ -1,9 +1,9 @@
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Bits, Block, Boolean, CellPath, Comparison, Math, Operator},
|
ast::{Bits, Block, Boolean, CellPath, Comparison, Math, Operator},
|
||||||
debugger::DebugContext,
|
debugger::DebugContext,
|
||||||
engine::{Closure, EngineState, Stack},
|
engine::{Argument, Closure, EngineState, Stack},
|
||||||
ir::{Instruction, IrBlock, Literal},
|
ir::{Call, Instruction, IrBlock, Literal},
|
||||||
PipelineData, RegId, ShellError, Span, Value,
|
DeclId, PipelineData, RegId, ShellError, Span, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Evaluate the compiled representation of a [`Block`].
|
/// Evaluate the compiled representation of a [`Block`].
|
||||||
|
@ -18,12 +18,14 @@ pub fn eval_ir_block<D: DebugContext>(
|
||||||
|
|
||||||
let block_span = block.span;
|
let block_span = block.span;
|
||||||
|
|
||||||
|
let args_base = stack.argument_stack.get_base();
|
||||||
let mut registers = stack.register_buf_cache.acquire(ir_block.register_count);
|
let mut registers = stack.register_buf_cache.acquire(ir_block.register_count);
|
||||||
|
|
||||||
let result = eval_ir_block_impl::<D>(
|
let result = eval_ir_block_impl::<D>(
|
||||||
&mut EvalContext {
|
&mut EvalContext {
|
||||||
engine_state,
|
engine_state,
|
||||||
stack,
|
stack,
|
||||||
|
args_base,
|
||||||
registers: &mut registers[..],
|
registers: &mut registers[..],
|
||||||
},
|
},
|
||||||
&block_span,
|
&block_span,
|
||||||
|
@ -52,6 +54,8 @@ pub fn eval_ir_block<D: DebugContext>(
|
||||||
struct EvalContext<'a> {
|
struct EvalContext<'a> {
|
||||||
engine_state: &'a EngineState,
|
engine_state: &'a EngineState,
|
||||||
stack: &'a mut Stack,
|
stack: &'a mut Stack,
|
||||||
|
/// Base index on the argument stack to reset to after a call
|
||||||
|
args_base: usize,
|
||||||
registers: &'a mut [PipelineData],
|
registers: &'a mut [PipelineData],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,6 +70,13 @@ impl<'a> EvalContext<'a> {
|
||||||
fn take_reg(&mut self, reg_id: RegId) -> PipelineData {
|
fn take_reg(&mut self, reg_id: RegId) -> PipelineData {
|
||||||
self.put_reg(reg_id, PipelineData::Empty)
|
self.put_reg(reg_id, PipelineData::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Take and implicitly collect a register to a value
|
||||||
|
fn collect_reg(&mut self, reg_id: RegId) -> Result<Value, ShellError> {
|
||||||
|
let pipeline_data = self.take_reg(reg_id);
|
||||||
|
let span = pipeline_data.span().unwrap_or(Span::unknown());
|
||||||
|
pipeline_data.into_value(span)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Eval an IR block on the provided slice of registers.
|
/// Eval an IR block on the provided slice of registers.
|
||||||
|
@ -86,7 +97,7 @@ fn eval_ir_block_impl<D: DebugContext>(
|
||||||
let instruction = &ir_block.instructions[pc];
|
let instruction = &ir_block.instructions[pc];
|
||||||
let span = &ir_block.spans[pc];
|
let span = &ir_block.spans[pc];
|
||||||
log::trace!("{pc:-4}: {}", instruction.display(ctx.engine_state));
|
log::trace!("{pc:-4}: {}", instruction.display(ctx.engine_state));
|
||||||
match do_instruction(ctx, instruction, span)? {
|
match eval_instruction(ctx, instruction, span)? {
|
||||||
InstructionResult::Continue => {
|
InstructionResult::Continue => {
|
||||||
pc += 1;
|
pc += 1;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +132,7 @@ enum InstructionResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform an instruction
|
/// Perform an instruction
|
||||||
fn do_instruction(
|
fn eval_instruction(
|
||||||
ctx: &mut EvalContext<'_>,
|
ctx: &mut EvalContext<'_>,
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
|
@ -159,13 +170,50 @@ fn do_instruction(
|
||||||
Instruction::LoadEnv { dst, key } => todo!(),
|
Instruction::LoadEnv { dst, key } => todo!(),
|
||||||
Instruction::LoadEnvOpt { dst, key } => todo!(),
|
Instruction::LoadEnvOpt { dst, key } => todo!(),
|
||||||
Instruction::StoreEnv { key, src } => todo!(),
|
Instruction::StoreEnv { key, src } => todo!(),
|
||||||
Instruction::PushPositional { src } => todo!(),
|
Instruction::PushPositional { src } => {
|
||||||
Instruction::AppendRest { src } => todo!(),
|
let val = ctx.collect_reg(*src)?;
|
||||||
Instruction::PushFlag { name } => todo!(),
|
ctx.stack
|
||||||
Instruction::PushNamed { name, src } => todo!(),
|
.argument_stack
|
||||||
Instruction::RedirectOut { mode } => todo!(),
|
.push(Argument::Positional { span: *span, val });
|
||||||
Instruction::RedirectErr { mode } => todo!(),
|
Ok(InstructionResult::Continue)
|
||||||
Instruction::Call { decl_id, src_dst } => todo!(),
|
}
|
||||||
|
Instruction::AppendRest { src } => {
|
||||||
|
let vals = ctx.collect_reg(*src)?;
|
||||||
|
ctx.stack
|
||||||
|
.argument_stack
|
||||||
|
.push(Argument::Spread { span: *span, vals });
|
||||||
|
Ok(InstructionResult::Continue)
|
||||||
|
}
|
||||||
|
Instruction::PushFlag { name } => {
|
||||||
|
ctx.stack.argument_stack.push(Argument::Flag {
|
||||||
|
name: name.clone(),
|
||||||
|
span: *span,
|
||||||
|
});
|
||||||
|
Ok(InstructionResult::Continue)
|
||||||
|
}
|
||||||
|
Instruction::PushNamed { name, src } => {
|
||||||
|
let val = ctx.collect_reg(*src)?;
|
||||||
|
ctx.stack.argument_stack.push(Argument::Named {
|
||||||
|
name: name.clone(),
|
||||||
|
span: *span,
|
||||||
|
val,
|
||||||
|
});
|
||||||
|
Ok(InstructionResult::Continue)
|
||||||
|
}
|
||||||
|
Instruction::RedirectOut { mode } => {
|
||||||
|
log::warn!("TODO: RedirectOut");
|
||||||
|
Ok(InstructionResult::Continue)
|
||||||
|
}
|
||||||
|
Instruction::RedirectErr { mode } => {
|
||||||
|
log::warn!("TODO: RedirectErr");
|
||||||
|
Ok(InstructionResult::Continue)
|
||||||
|
}
|
||||||
|
Instruction::Call { decl_id, src_dst } => {
|
||||||
|
let input = ctx.take_reg(*src_dst);
|
||||||
|
let result = eval_call(ctx, *decl_id, *span, input)?;
|
||||||
|
ctx.put_reg(*src_dst, result);
|
||||||
|
Ok(InstructionResult::Continue)
|
||||||
|
}
|
||||||
Instruction::BinaryOp { lhs_dst, op, rhs } => binary_op(ctx, *lhs_dst, op, *rhs, *span),
|
Instruction::BinaryOp { lhs_dst, op, rhs } => binary_op(ctx, *lhs_dst, op, *rhs, *span),
|
||||||
Instruction::FollowCellPath { src_dst, path } => todo!(),
|
Instruction::FollowCellPath { src_dst, path } => todo!(),
|
||||||
Instruction::CloneCellPath { dst, src, path } => todo!(),
|
Instruction::CloneCellPath { dst, src, path } => todo!(),
|
||||||
|
@ -309,3 +357,33 @@ fn binary_op(
|
||||||
|
|
||||||
Ok(InstructionResult::Continue)
|
Ok(InstructionResult::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a call
|
||||||
|
fn eval_call(
|
||||||
|
ctx: &mut EvalContext<'_>,
|
||||||
|
decl_id: DeclId,
|
||||||
|
head: Span,
|
||||||
|
input: PipelineData,
|
||||||
|
) -> Result<PipelineData, ShellError> {
|
||||||
|
// TODO: handle block eval
|
||||||
|
let args_len = ctx.stack.argument_stack.get_len(ctx.args_base);
|
||||||
|
let decl = ctx.engine_state.get_decl(decl_id);
|
||||||
|
// should this be precalculated? ideally we just use the call builder...
|
||||||
|
let span = ctx
|
||||||
|
.stack
|
||||||
|
.argument_stack
|
||||||
|
.get_args(ctx.args_base, args_len)
|
||||||
|
.into_iter()
|
||||||
|
.fold(head, |span, arg| span.append(arg.span()));
|
||||||
|
let call = Call {
|
||||||
|
decl_id,
|
||||||
|
head,
|
||||||
|
span,
|
||||||
|
args_base: ctx.args_base,
|
||||||
|
args_len,
|
||||||
|
};
|
||||||
|
let result = decl.run(ctx.engine_state, ctx.stack, &(&call).into(), input);
|
||||||
|
// Important that this runs:
|
||||||
|
ctx.stack.argument_stack.leave_frame(ctx.args_base);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
engine::{self, Argument, Stack},
|
engine::{self, Argument, Stack},
|
||||||
ShellError, Span, Spanned, Value,
|
DeclId, ShellError, Span, Spanned, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains the information for a call being made to a declared command.
|
/// Contains the information for a call being made to a declared command.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
/// The declaration ID of the command to be invoked.
|
/// The declaration ID of the command to be invoked.
|
||||||
pub decl_id: usize,
|
pub decl_id: DeclId,
|
||||||
/// The span encompassing the command name, before the arguments.
|
/// The span encompassing the command name, before the arguments.
|
||||||
pub head: Span,
|
pub head: Span,
|
||||||
/// The span encompassing the command name and all arguments.
|
/// The span encompassing the command name and all arguments.
|
||||||
|
@ -23,7 +23,7 @@ pub struct Call {
|
||||||
|
|
||||||
impl Call {
|
impl Call {
|
||||||
/// Build a new call with arguments.
|
/// Build a new call with arguments.
|
||||||
pub fn build(decl_id: usize, head: Span) -> CallBuilder {
|
pub fn build(decl_id: DeclId, head: Span) -> CallBuilder {
|
||||||
CallBuilder {
|
CallBuilder {
|
||||||
inner: Call {
|
inner: Call {
|
||||||
decl_id,
|
decl_id,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user