add compiled IR to blocks
This commit is contained in:
parent
a836711a22
commit
20a214a4b9
|
@ -37,7 +37,7 @@ impl Command for ViewIr {
|
|||
})?;
|
||||
|
||||
let block = engine_state.get_block(block_id);
|
||||
let ir_block = compile(engine_state, &block)?;
|
||||
let ir_block = compile(&StateWorkingSet::new(engine_state), &block)?;
|
||||
|
||||
let formatted = format!("{}", ir_block.display(engine_state));
|
||||
Ok(Value::string(formatted, call.head).into_pipeline_data())
|
||||
|
|
|
@ -3,7 +3,7 @@ use nu_protocol::{
|
|||
Argument, Block, Call, CellPath, Expr, Expression, Operator, Pipeline, PipelineRedirection,
|
||||
RedirectionSource, RedirectionTarget,
|
||||
},
|
||||
engine::EngineState,
|
||||
engine::StateWorkingSet,
|
||||
ir::{Instruction, IrBlock, Literal, RedirectMode},
|
||||
IntoSpanned, OutDest, RegId, ShellError, Span, Spanned,
|
||||
};
|
||||
|
@ -12,11 +12,11 @@ const BLOCK_INPUT: RegId = RegId(0);
|
|||
|
||||
/// Compile Nushell pipeline abstract syntax tree (AST) to internal representation (IR) instructions
|
||||
/// for evaluation.
|
||||
pub fn compile(engine_state: &EngineState, block: &Block) -> Result<IrBlock, ShellError> {
|
||||
pub fn compile(working_set: &StateWorkingSet, block: &Block) -> Result<IrBlock, ShellError> {
|
||||
let mut builder = BlockBuilder::new();
|
||||
|
||||
compile_block(
|
||||
engine_state,
|
||||
working_set,
|
||||
&mut builder,
|
||||
block,
|
||||
RedirectModes::default(),
|
||||
|
@ -52,7 +52,7 @@ impl RedirectModes {
|
|||
}
|
||||
|
||||
fn compile_block(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
builder: &mut BlockBuilder,
|
||||
block: &Block,
|
||||
redirect_modes: RedirectModes,
|
||||
|
@ -65,7 +65,7 @@ fn compile_block(
|
|||
let last_index = block.pipelines.len() - 1;
|
||||
for (index, pipeline) in block.pipelines.iter().enumerate() {
|
||||
compile_pipeline(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
pipeline,
|
||||
span,
|
||||
|
@ -97,7 +97,7 @@ fn compile_block(
|
|||
}
|
||||
|
||||
fn compile_pipeline(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
builder: &mut BlockBuilder,
|
||||
pipeline: &Pipeline,
|
||||
fallback_span: Span,
|
||||
|
@ -116,7 +116,7 @@ fn compile_pipeline(
|
|||
// element, then it's from whatever is passed in as the mode to use.
|
||||
|
||||
let next_redirect_modes = if let Some(next_element) = iter.peek() {
|
||||
redirect_modes_of_expression(engine_state, &next_element.expr, span)?
|
||||
redirect_modes_of_expression(working_set, &next_element.expr, span)?
|
||||
} else {
|
||||
redirect_modes
|
||||
.take()
|
||||
|
@ -125,7 +125,7 @@ fn compile_pipeline(
|
|||
|
||||
let spec_redirect_modes = match &element.redirection {
|
||||
Some(PipelineRedirection::Single { source, target }) => {
|
||||
let mode = redirection_target_to_mode(engine_state, builder, target, false)?;
|
||||
let mode = redirection_target_to_mode(working_set, builder, target, false)?;
|
||||
match source {
|
||||
RedirectionSource::Stdout => RedirectModes {
|
||||
out: Some(mode),
|
||||
|
@ -142,8 +142,8 @@ fn compile_pipeline(
|
|||
}
|
||||
}
|
||||
Some(PipelineRedirection::Separate { out, err }) => {
|
||||
let out = redirection_target_to_mode(engine_state, builder, out, true)?;
|
||||
let err = redirection_target_to_mode(engine_state, builder, err, true)?;
|
||||
let out = redirection_target_to_mode(working_set, builder, out, true)?;
|
||||
let err = redirection_target_to_mode(working_set, builder, err, true)?;
|
||||
RedirectModes {
|
||||
out: Some(out),
|
||||
err: Some(err),
|
||||
|
@ -159,7 +159,7 @@ fn compile_pipeline(
|
|||
let err_mode = spec_redirect_modes.err.or(next_redirect_modes.err);
|
||||
|
||||
compile_expression(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
&element.expr,
|
||||
RedirectModes {
|
||||
|
@ -177,7 +177,7 @@ fn compile_pipeline(
|
|||
}
|
||||
|
||||
fn redirection_target_to_mode(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
builder: &mut BlockBuilder,
|
||||
target: &RedirectionTarget,
|
||||
separate: bool,
|
||||
|
@ -190,7 +190,7 @@ fn redirection_target_to_mode(
|
|||
} => {
|
||||
let path_reg = builder.next_register()?;
|
||||
compile_expression(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
expr,
|
||||
RedirectModes::capture_out(*redir_span),
|
||||
|
@ -213,11 +213,11 @@ fn redirection_target_to_mode(
|
|||
}
|
||||
|
||||
fn redirect_modes_of_expression(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
expression: &Expression,
|
||||
redir_span: Span,
|
||||
) -> Result<RedirectModes, CompileError> {
|
||||
let (out, err) = expression.expr.pipe_redirection(&engine_state);
|
||||
let (out, err) = expression.expr.pipe_redirection(&working_set);
|
||||
Ok(RedirectModes {
|
||||
out: out
|
||||
.map(|out| out_dest_to_redirect_mode(out))
|
||||
|
@ -241,7 +241,7 @@ fn out_dest_to_redirect_mode(out_dest: OutDest) -> Result<RedirectMode, CompileE
|
|||
}
|
||||
|
||||
fn compile_expression(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
builder: &mut BlockBuilder,
|
||||
expr: &Expression,
|
||||
redirect_modes: RedirectModes,
|
||||
|
@ -284,7 +284,7 @@ fn compile_expression(
|
|||
builder.load_nothing(out_reg)?;
|
||||
}
|
||||
|
||||
compile_call(engine_state, builder, &call, redirect_modes, out_reg)
|
||||
compile_call(working_set, builder, &call, redirect_modes, out_reg)
|
||||
}
|
||||
Expr::ExternalCall(_, _) => Err(CompileError::Todo("ExternalCall")),
|
||||
Expr::Operator(_) => Err(CompileError::Todo("Operator")),
|
||||
|
@ -293,7 +293,7 @@ fn compile_expression(
|
|||
Expr::BinaryOp(lhs, op, rhs) => {
|
||||
if let Expr::Operator(ref operator) = op.expr {
|
||||
compile_binary_op(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
&lhs,
|
||||
operator.clone().into_spanned(op.span),
|
||||
|
@ -306,9 +306,9 @@ fn compile_expression(
|
|||
}
|
||||
}
|
||||
Expr::Subexpression(block_id) => {
|
||||
let block = engine_state.get_block(*block_id);
|
||||
let block = working_set.get_block(*block_id);
|
||||
compile_block(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
&block,
|
||||
redirect_modes,
|
||||
|
@ -333,7 +333,7 @@ fn compile_expression(
|
|||
Expr::CellPath(path) => lit(builder, Literal::CellPath(Box::new(path.clone()))),
|
||||
Expr::FullCellPath(full_cell_path) => {
|
||||
compile_expression(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
&full_cell_path.head,
|
||||
RedirectModes::capture_out(expr.span),
|
||||
|
@ -368,7 +368,7 @@ fn compile_expression(
|
|||
}
|
||||
|
||||
fn compile_call(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
builder: &mut BlockBuilder,
|
||||
call: &Call,
|
||||
redirect_modes: RedirectModes,
|
||||
|
@ -395,7 +395,7 @@ fn compile_call(
|
|||
let arg_reg = builder.next_register()?;
|
||||
|
||||
compile_expression(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
expr,
|
||||
RedirectModes::capture_out(arg.span()),
|
||||
|
@ -464,7 +464,7 @@ fn compile_call(
|
|||
}
|
||||
|
||||
fn compile_binary_op(
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
builder: &mut BlockBuilder,
|
||||
lhs: &Expression,
|
||||
op: Spanned<Operator>,
|
||||
|
@ -481,7 +481,7 @@ fn compile_binary_op(
|
|||
let rhs_reg = builder.next_register()?;
|
||||
|
||||
compile_expression(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
lhs,
|
||||
RedirectModes::capture_out(op.span),
|
||||
|
@ -489,7 +489,7 @@ fn compile_binary_op(
|
|||
lhs_reg,
|
||||
)?;
|
||||
compile_expression(
|
||||
engine_state,
|
||||
working_set,
|
||||
builder,
|
||||
rhs,
|
||||
RedirectModes::capture_out(op.span),
|
||||
|
|
|
@ -7,7 +7,7 @@ use nu_protocol::{
|
|||
PipelineRedirection, RedirectionSource, RedirectionTarget,
|
||||
},
|
||||
debugger::DebugContext,
|
||||
engine::{Closure, EngineState, Redirection, Stack},
|
||||
engine::{Closure, EngineState, Redirection, Stack, StateWorkingSet},
|
||||
eval_base::Eval,
|
||||
ByteStreamSource, Config, FromValue, IntoPipelineData, OutDest, PipelineData, ShellError, Span,
|
||||
Spanned, Type, Value, VarId, ENV_VARIABLE_ID,
|
||||
|
@ -521,7 +521,7 @@ pub fn eval_block<D: DebugContext>(
|
|||
|
||||
for (i, element) in elements.iter().enumerate() {
|
||||
let next = elements.get(i + 1).unwrap_or(last);
|
||||
let (next_out, next_err) = next.pipe_redirection(engine_state);
|
||||
let (next_out, next_err) = next.pipe_redirection(&StateWorkingSet::new(engine_state));
|
||||
let (stdout, stderr) = eval_element_redirection::<D>(
|
||||
engine_state,
|
||||
stack,
|
||||
|
|
|
@ -11,9 +11,9 @@ use itertools::Itertools;
|
|||
use log::trace;
|
||||
use nu_engine::DIR_VAR_PARSER_INFO;
|
||||
use nu_protocol::{
|
||||
ast::*, engine::StateWorkingSet, eval_const::eval_constant, BlockId, DidYouMean, Flag,
|
||||
ParseError, PositionalArg, Signature, Span, Spanned, SyntaxShape, Type, VarId, ENV_VARIABLE_ID,
|
||||
IN_VARIABLE_ID,
|
||||
ast::*, engine::StateWorkingSet, eval_const::eval_constant, report_error, BlockId, DidYouMean,
|
||||
Flag, ParseError, PositionalArg, Signature, Span, Spanned, SyntaxShape, Type, VarId,
|
||||
ENV_VARIABLE_ID, IN_VARIABLE_ID,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
|
@ -5676,6 +5676,15 @@ pub fn parse_block(
|
|||
working_set.parse_errors.extend_from_slice(&errors);
|
||||
}
|
||||
|
||||
if !is_subexpression {
|
||||
match nu_engine::compile(working_set, &block) {
|
||||
Ok(ir_block) => {
|
||||
block.ir_block = Some(ir_block);
|
||||
}
|
||||
Err(err) => report_error(working_set, &err),
|
||||
}
|
||||
}
|
||||
|
||||
block
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::Pipeline;
|
||||
use crate::{engine::EngineState, OutDest, Signature, Span, Type, VarId};
|
||||
use crate::{engine::StateWorkingSet, ir::IrBlock, OutDest, Signature, Span, Type, VarId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -8,6 +8,8 @@ pub struct Block {
|
|||
pub pipelines: Vec<Pipeline>,
|
||||
pub captures: Vec<VarId>,
|
||||
pub redirect_env: bool,
|
||||
/// The block compiled to IR instructions. Not available for subexpressions.
|
||||
pub ir_block: Option<IrBlock>,
|
||||
pub span: Option<Span>, // None option encodes no span to avoid using test_span()
|
||||
}
|
||||
|
||||
|
@ -22,10 +24,10 @@ impl Block {
|
|||
|
||||
pub fn pipe_redirection(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
) -> (Option<OutDest>, Option<OutDest>) {
|
||||
if let Some(first) = self.pipelines.first() {
|
||||
first.pipe_redirection(engine_state)
|
||||
first.pipe_redirection(working_set)
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
|
@ -45,6 +47,7 @@ impl Block {
|
|||
pipelines: vec![],
|
||||
captures: vec![],
|
||||
redirect_env: false,
|
||||
ir_block: None,
|
||||
span: None,
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +58,7 @@ impl Block {
|
|||
pipelines: Vec::with_capacity(capacity),
|
||||
captures: vec![],
|
||||
redirect_env: false,
|
||||
ir_block: None,
|
||||
span: None,
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +90,7 @@ where
|
|||
pipelines: pipelines.collect(),
|
||||
captures: vec![],
|
||||
redirect_env: false,
|
||||
ir_block: None,
|
||||
span: None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ use super::{
|
|||
Call, CellPath, Expression, ExternalArgument, FullCellPath, Keyword, MatchPattern, Operator,
|
||||
Range, Table, ValueWithUnit,
|
||||
};
|
||||
use crate::{ast::ImportPattern, engine::EngineState, BlockId, OutDest, Signature, Span, VarId};
|
||||
use crate::{
|
||||
ast::ImportPattern, engine::StateWorkingSet, BlockId, OutDest, Signature, Span, VarId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Expr {
|
||||
|
@ -55,17 +57,17 @@ const _: () = assert!(std::mem::size_of::<Expr>() <= 40);
|
|||
impl Expr {
|
||||
pub fn pipe_redirection(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
) -> (Option<OutDest>, Option<OutDest>) {
|
||||
// Usages of `$in` will be wrapped by a `collect` call by the parser,
|
||||
// so we do not have to worry about that when considering
|
||||
// which of the expressions below may consume pipeline output.
|
||||
match self {
|
||||
Expr::Call(call) => engine_state.get_decl(call.decl_id).pipe_redirection(),
|
||||
Expr::Subexpression(block_id) | Expr::Block(block_id) => engine_state
|
||||
Expr::Call(call) => working_set.get_decl(call.decl_id).pipe_redirection(),
|
||||
Expr::Subexpression(block_id) | Expr::Block(block_id) => working_set
|
||||
.get_block(*block_id)
|
||||
.pipe_redirection(engine_state),
|
||||
Expr::FullCellPath(cell_path) => cell_path.head.expr.pipe_redirection(engine_state),
|
||||
.pipe_redirection(working_set),
|
||||
Expr::FullCellPath(cell_path) => cell_path.head.expr.pipe_redirection(working_set),
|
||||
Expr::Bool(_)
|
||||
| Expr::Int(_)
|
||||
| Expr::Float(_)
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
use crate::{
|
||||
ast::Expression,
|
||||
engine::{EngineState, StateWorkingSet},
|
||||
OutDest, Span,
|
||||
};
|
||||
use crate::{ast::Expression, engine::StateWorkingSet, OutDest, Span};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
|
||||
|
@ -120,9 +116,9 @@ impl PipelineElement {
|
|||
|
||||
pub fn pipe_redirection(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
) -> (Option<OutDest>, Option<OutDest>) {
|
||||
self.expr.expr.pipe_redirection(engine_state)
|
||||
self.expr.expr.pipe_redirection(working_set)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,10 +162,10 @@ impl Pipeline {
|
|||
|
||||
pub fn pipe_redirection(
|
||||
&self,
|
||||
engine_state: &EngineState,
|
||||
working_set: &StateWorkingSet,
|
||||
) -> (Option<OutDest>, Option<OutDest>) {
|
||||
if let Some(first) = self.elements.first() {
|
||||
first.pipe_redirection(engine_state)
|
||||
first.pipe_redirection(working_set)
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ use crate::{
|
|||
BlockId, DeclId, RegId, Span,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod display;
|
||||
pub use display::FmtIrBlock;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct IrBlock {
|
||||
pub instructions: Vec<Instruction>,
|
||||
pub spans: Vec<Span>,
|
||||
|
@ -25,7 +27,7 @@ impl IrBlock {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Instruction {
|
||||
/// Load a literal value into the `dst` register
|
||||
LoadLiteral { dst: RegId, lit: Literal },
|
||||
|
@ -76,7 +78,7 @@ pub enum Instruction {
|
|||
const _: () = assert!(std::mem::size_of::<Instruction>() <= 32);
|
||||
|
||||
/// A literal value that can be embedded in an instruction.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Literal {
|
||||
Bool(bool),
|
||||
Int(i64),
|
||||
|
@ -103,7 +105,7 @@ pub enum Literal {
|
|||
/// piped into.
|
||||
///
|
||||
/// Not setting it uses the default, determined by [`Stack`](crate::engine::Stack).
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub enum RedirectMode {
|
||||
Pipe,
|
||||
Capture,
|
||||
|
|
Loading…
Reference in New Issue
Block a user