Remove the Value::Block case (#12582)

# Description
`Value` describes the types of first-class values that users and scripts
can create, manipulate, pass around, and store. However, `Block`s are
not first-class values in the language, so this PR removes it from
`Value`. This removes some unnecessary code, and this change should be
invisible to the user except for the change to `scope modules` described
below.

# User-Facing Changes
Breaking change: the output of `scope modules` was changed so that
`env_block` is now `has_env_block` which is a boolean value instead of a
`Block`.

# After Submitting
Update the language guide possibly.
This commit is contained in:
Ian Manske
2024-04-21 05:03:33 +00:00
committed by GitHub
parent 5fd34320e9
commit 3b1d405b96
32 changed files with 171 additions and 352 deletions

View File

@ -276,8 +276,7 @@ pub fn debug_string_without_formatting(value: &Value) -> String {
Ok(val) => debug_string_without_formatting(&val),
Err(error) => format!("{error:?}"),
},
//TODO: It would be good to drill in deeper to blocks and closures.
Value::Block { val, .. } => format!("<Block {val}>"),
//TODO: It would be good to drill deeper into closures.
Value::Closure { val, .. } => format!("<Closure {}>", val.block_id),
Value::Nothing { .. } => String::new(),
Value::Error { error, .. } => format!("{error:?}"),

View File

@ -173,8 +173,8 @@ impl Command for ViewSource {
}
}
value => {
if let Ok(block_id) = value.coerce_block() {
let block = engine_state.get_block(block_id);
if let Ok(closure) = value.as_closure() {
let block = engine_state.get_block(closure.block_id);
if let Some(span) = block.span {
let contents = engine_state.get_span_contents(span);

View File

@ -1,5 +1,4 @@
use nu_engine::{command_prelude::*, get_eval_block, redirect_env};
use nu_protocol::engine::Closure;
#[derive(Clone)]
pub struct ExportEnv;
@ -31,10 +30,15 @@ impl Command for ExportEnv {
call: &Call,
input: PipelineData,
) -> Result<PipelineData, ShellError> {
let capture_block: Closure = call.req(engine_state, caller_stack, 0)?;
let block = engine_state.get_block(capture_block.block_id);
let block_id = call
.positional_nth(0)
.expect("checked through parser")
.as_block()
.expect("internal error: missing block");
let block = engine_state.get_block(block_id);
let mut callee_stack = caller_stack
.captures_to_stack(capture_block.captures)
.gather_captures(engine_state, &block.captures)
.reset_pipes();
let eval_block = get_eval_block(engine_state);

View File

@ -522,7 +522,6 @@ fn value_should_be_printed(
| Value::Date { .. }
| Value::Range { .. }
| Value::Float { .. }
| Value::Block { .. }
| Value::Closure { .. }
| Value::Nothing { .. }
| Value::Error { .. } => term_equals_value(term, &lower_value, span),

View File

@ -2,7 +2,6 @@ use nu_engine::{command_prelude::*, get_eval_block, EvalBlockFn};
use nu_protocol::{
ast::{Block, PathMember},
engine::Closure,
FromValue,
};
#[derive(Clone)]
@ -132,25 +131,23 @@ fn insert(
let cell_path: CellPath = call.req(engine_state, stack, 0)?;
let replacement: Value = call.req(engine_state, stack, 1)?;
let replacement_span = replacement.span();
let ctrlc = engine_state.ctrlc.clone();
let eval_block = get_eval_block(engine_state);
match input {
PipelineData::Value(mut value, metadata) => {
if replacement.coerce_block().is_ok() {
if let Value::Closure { val: closure, .. } = replacement {
match (cell_path.members.first(), &mut value) {
(Some(PathMember::String { .. }), Value::List { vals, .. }) => {
let span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let stack = stack.captures_to_stack(capture_block.captures.clone());
let block = engine_state.get_block(closure.block_id);
let stack = stack.captures_to_stack(closure.captures);
for val in vals {
let mut stack = stack.clone();
insert_value_by_closure(
val,
span,
replacement_span,
engine_state,
&mut stack,
block,
@ -163,7 +160,8 @@ fn insert(
(first, _) => {
insert_single_value_by_closure(
&mut value,
replacement,
closure,
replacement_span,
engine_state,
stack,
&cell_path.members,
@ -201,14 +199,12 @@ fn insert(
}
if path.is_empty() {
if replacement.coerce_block().is_ok() {
let span = replacement.span();
if let Value::Closure { val: closure, .. } = replacement {
let value = stream.next();
let end_of_stream = value.is_none();
let value = value.unwrap_or(Value::nothing(span));
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let mut stack = stack.captures_to_stack(capture_block.captures);
let value = value.unwrap_or(Value::nothing(replacement_span));
let block = engine_state.get_block(closure.block_id);
let mut stack = stack.captures_to_stack(closure.captures);
if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
@ -223,7 +219,7 @@ fn insert(
value.clone().into_pipeline_data(),
)?;
pre_elems.push(output.into_value(span));
pre_elems.push(output.into_value(replacement_span));
if !end_of_stream {
pre_elems.push(value);
}
@ -231,10 +227,11 @@ fn insert(
pre_elems.push(replacement);
}
} else if let Some(mut value) = stream.next() {
if replacement.coerce_block().is_ok() {
if let Value::Closure { val: closure, .. } = replacement {
insert_single_value_by_closure(
&mut value,
replacement,
closure,
replacement_span,
engine_state,
stack,
path,
@ -256,12 +253,10 @@ fn insert(
.into_iter()
.chain(stream)
.into_pipeline_data_with_metadata(metadata, ctrlc))
} else if replacement.coerce_block().is_ok() {
} else if let Value::Closure { val: closure, .. } = replacement {
let engine_state = engine_state.clone();
let replacement_span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id).clone();
let stack = stack.captures_to_stack(capture_block.captures.clone());
let block = engine_state.get_block(closure.block_id).clone();
let stack = stack.captures_to_stack(closure.captures);
Ok(stream
.map(move |mut input| {
@ -348,17 +343,16 @@ fn insert_value_by_closure(
#[allow(clippy::too_many_arguments)]
fn insert_single_value_by_closure(
value: &mut Value,
replacement: Value,
closure: Closure,
span: Span,
engine_state: &EngineState,
stack: &mut Stack,
cell_path: &[PathMember],
first_path_member_int: bool,
eval_block_fn: EvalBlockFn,
) -> Result<(), ShellError> {
let span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let mut stack = stack.captures_to_stack(capture_block.captures);
let block = engine_state.get_block(closure.block_id);
let mut stack = stack.captures_to_stack(closure.captures);
insert_value_by_closure(
value,

View File

@ -2,7 +2,6 @@ use nu_engine::{command_prelude::*, get_eval_block, EvalBlockFn};
use nu_protocol::{
ast::{Block, PathMember},
engine::Closure,
FromValue,
};
#[derive(Clone)]
@ -116,25 +115,23 @@ fn update(
let cell_path: CellPath = call.req(engine_state, stack, 0)?;
let replacement: Value = call.req(engine_state, stack, 1)?;
let replacement_span = replacement.span();
let ctrlc = engine_state.ctrlc.clone();
let eval_block = get_eval_block(engine_state);
match input {
PipelineData::Value(mut value, metadata) => {
if replacement.coerce_block().is_ok() {
if let Value::Closure { val: closure, .. } = replacement {
match (cell_path.members.first(), &mut value) {
(Some(PathMember::String { .. }), Value::List { vals, .. }) => {
let span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let stack = stack.captures_to_stack(capture_block.captures.clone());
let block = engine_state.get_block(closure.block_id);
let stack = stack.captures_to_stack(closure.captures);
for val in vals {
let mut stack = stack.clone();
update_value_by_closure(
val,
span,
replacement_span,
engine_state,
&mut stack,
block,
@ -147,7 +144,8 @@ fn update(
(first, _) => {
update_single_value_by_closure(
&mut value,
replacement,
closure,
replacement_span,
engine_state,
stack,
&cell_path.members,
@ -189,10 +187,11 @@ fn update(
// cannot fail since loop above does at least one iteration or returns an error
let value = pre_elems.last_mut().expect("one element");
if replacement.coerce_block().is_ok() {
if let Value::Closure { val: closure, .. } = replacement {
update_single_value_by_closure(
value,
replacement,
closure,
replacement_span,
engine_state,
stack,
path,
@ -207,12 +206,10 @@ fn update(
.into_iter()
.chain(stream)
.into_pipeline_data_with_metadata(metadata, ctrlc))
} else if replacement.coerce_block().is_ok() {
let replacement_span = replacement.span();
} else if let Value::Closure { val: closure, .. } = replacement {
let engine_state = engine_state.clone();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id).clone();
let stack = stack.captures_to_stack(capture_block.captures.clone());
let block = engine_state.get_block(closure.block_id).clone();
let stack = stack.captures_to_stack(closure.captures);
Ok(stream
.map(move |mut input| {
@ -302,17 +299,16 @@ fn update_value_by_closure(
#[allow(clippy::too_many_arguments)]
fn update_single_value_by_closure(
value: &mut Value,
replacement: Value,
closure: Closure,
span: Span,
engine_state: &EngineState,
stack: &mut Stack,
cell_path: &[PathMember],
first_path_member_int: bool,
eval_block_fn: EvalBlockFn,
) -> Result<(), ShellError> {
let span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let mut stack = stack.captures_to_stack(capture_block.captures);
let block = engine_state.get_block(closure.block_id);
let mut stack = stack.captures_to_stack(closure.captures);
update_value_by_closure(
value,

View File

@ -2,7 +2,6 @@ use nu_engine::{command_prelude::*, get_eval_block, EvalBlockFn};
use nu_protocol::{
ast::{Block, PathMember},
engine::Closure,
FromValue,
};
#[derive(Clone)]
@ -162,24 +161,23 @@ fn upsert(
let cell_path: CellPath = call.req(engine_state, stack, 0)?;
let replacement: Value = call.req(engine_state, stack, 1)?;
let replacement_span = replacement.span();
let eval_block = get_eval_block(engine_state);
let ctrlc = engine_state.ctrlc.clone();
match input {
PipelineData::Value(mut value, metadata) => {
if replacement.coerce_block().is_ok() {
if let Value::Closure { val: closure, .. } = replacement {
match (cell_path.members.first(), &mut value) {
(Some(PathMember::String { .. }), Value::List { vals, .. }) => {
let span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let stack = stack.captures_to_stack(capture_block.captures.clone());
let block = engine_state.get_block(closure.block_id);
let stack = stack.captures_to_stack(closure.captures);
for val in vals {
let mut stack = stack.clone();
upsert_value_by_closure(
val,
span,
replacement_span,
engine_state,
&mut stack,
block,
@ -192,7 +190,8 @@ fn upsert(
(first, _) => {
upsert_single_value_by_closure(
&mut value,
replacement,
closure,
replacement_span,
engine_state,
stack,
&cell_path.members,
@ -230,12 +229,10 @@ fn upsert(
}
if path.is_empty() {
let span = replacement.span();
let value = stream.next().unwrap_or(Value::nothing(span));
if replacement.coerce_block().is_ok() {
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let mut stack = stack.captures_to_stack(capture_block.captures);
if let Value::Closure { val: closure, .. } = replacement {
let block = engine_state.get_block(closure.block_id);
let mut stack = stack.captures_to_stack(closure.captures);
if let Some(var) = block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
@ -250,15 +247,16 @@ fn upsert(
value.clone().into_pipeline_data(),
)?;
pre_elems.push(output.into_value(span));
pre_elems.push(output.into_value(replacement_span));
} else {
pre_elems.push(replacement);
}
} else if let Some(mut value) = stream.next() {
if replacement.coerce_block().is_ok() {
if let Value::Closure { val: closure, .. } = replacement {
upsert_single_value_by_closure(
&mut value,
replacement,
closure,
replacement_span,
engine_state,
stack,
path,
@ -280,12 +278,10 @@ fn upsert(
.into_iter()
.chain(stream)
.into_pipeline_data_with_metadata(metadata, ctrlc))
} else if replacement.coerce_block().is_ok() {
} else if let Value::Closure { val: closure, .. } = replacement {
let engine_state = engine_state.clone();
let replacement_span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id).clone();
let stack = stack.captures_to_stack(capture_block.captures.clone());
let block = engine_state.get_block(closure.block_id).clone();
let stack = stack.captures_to_stack(closure.captures);
Ok(stream
.map(move |mut input| {
@ -374,17 +370,16 @@ fn upsert_value_by_closure(
#[allow(clippy::too_many_arguments)]
fn upsert_single_value_by_closure(
value: &mut Value,
replacement: Value,
closure: Closure,
span: Span,
engine_state: &EngineState,
stack: &mut Stack,
cell_path: &[PathMember],
first_path_member_int: bool,
eval_block_fn: EvalBlockFn,
) -> Result<(), ShellError> {
let span = replacement.span();
let capture_block = Closure::from_value(replacement)?;
let block = engine_state.get_block(capture_block.block_id);
let mut stack = stack.captures_to_stack(capture_block.captures);
let block = engine_state.get_block(closure.block_id);
let mut stack = stack.captures_to_stack(closure.captures);
upsert_value_by_closure(
value,

View File

@ -124,7 +124,7 @@ pub fn value_to_json_value(v: &Value) -> Result<nu_json::Value, ShellError> {
Value::List { vals, .. } => nu_json::Value::Array(json_list(vals)?),
Value::Error { error, .. } => return Err(*error.clone()),
Value::Closure { .. } | Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null,
Value::Closure { .. } | Value::Range { .. } => nu_json::Value::Null,
Value::Binary { val, .. } => {
nu_json::Value::Array(val.iter().map(|x| nu_json::Value::U64(*x as u64)).collect())
}

View File

@ -134,7 +134,6 @@ fn local_into_string(value: Value, separator: &str, config: &Config) -> String {
Ok(val) => local_into_string(val, separator, config),
Err(error) => format!("{error:?}"),
},
Value::Block { val, .. } => format!("<Block {val}>"),
Value::Closure { val, .. } => format!("<Closure {}>", val.block_id),
Value::Nothing { .. } => String::new(),
Value::Error { error, .. } => format!("{error:?}"),

View File

@ -67,11 +67,6 @@ fn helper(engine_state: &EngineState, v: &Value) -> Result<toml::Value, ShellErr
helper(engine_state, &collected)?
}
Value::List { vals, .. } => toml::Value::Array(toml_list(engine_state, vals)?),
Value::Block { .. } => {
let code = engine_state.get_span_contents(span);
let code = String::from_utf8_lossy(code).to_string();
toml::Value::String(code)
}
Value::Closure { .. } => {
let code = engine_state.get_span_contents(span);
let code = String::from_utf8_lossy(code).to_string();

View File

@ -75,7 +75,6 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
serde_yaml::Value::Sequence(out)
}
Value::Block { .. } => serde_yaml::Value::Null,
Value::Closure { .. } => serde_yaml::Value::Null,
Value::Nothing { .. } => serde_yaml::Value::Null,
Value::Error { error, .. } => return Err(*error.clone()),