Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make if blocks work like a def-env #4656

Merged
merged 5 commits into from
Mar 8, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Make if work like a def-env
  • Loading branch information
sophiajt committed Feb 26, 2022
commit 1de9e1df6348a7b1b2208c659b66758cc61c0b96
66 changes: 52 additions & 14 deletions crates/nu-command/src/core_commands/if_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,50 +37,88 @@ impl Command for If {
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
caller_stack: &mut Stack,
call: &Call,
input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let cond = &call.positional[0];
let then_block: CaptureBlock = call.req(engine_state, stack, 1)?;
let then_block: CaptureBlock = call.req(engine_state, caller_stack, 1)?;
let else_case = call.positional.get(2);

let result = eval_expression(engine_state, stack, cond)?;
let result = eval_expression(engine_state, caller_stack, cond)?;
match &result {
Value::Bool { val, .. } => {
if *val {
let block = engine_state.get_block(then_block.block_id);
let mut stack = stack.captures_to_stack(&then_block.captures);
eval_block(
let mut callee_stack = caller_stack.captures_to_stack(&then_block.captures);
let result = eval_block(
engine_state,
&mut stack,
&mut callee_stack,
block,
input,
call.redirect_stdout,
call.redirect_stderr,
)
);
let caller_env_vars = caller_stack.get_env_var_names(engine_state);

// remove env vars that are present in the caller but not in the callee
// (the callee hid them)
for var in caller_env_vars.iter() {
if !callee_stack.has_env_var(engine_state, var) {
caller_stack.remove_env_var(engine_state, var);
}
}

// add new env vars from callee to caller
for env_vars in callee_stack.env_vars {
for (var, value) in env_vars {
caller_stack.add_env_var(var, value);
}
}

result
} else if let Some(else_case) = else_case {
if let Some(else_expr) = else_case.as_keyword() {
if let Some(block_id) = else_expr.as_block() {
let result = eval_expression(engine_state, stack, else_expr)?;
let result = eval_expression(engine_state, caller_stack, else_expr)?;
let else_block: CaptureBlock = FromValue::from_value(&result)?;

let mut stack = stack.captures_to_stack(&else_block.captures);
let mut callee_stack =
caller_stack.captures_to_stack(&else_block.captures);
let block = engine_state.get_block(block_id);
eval_block(
let result = eval_block(
engine_state,
&mut stack,
&mut callee_stack,
block,
input,
call.redirect_stdout,
call.redirect_stderr,
)
);

let caller_env_vars = caller_stack.get_env_var_names(engine_state);

// remove env vars that are present in the caller but not in the callee
// (the callee hid them)
for var in caller_env_vars.iter() {
if !callee_stack.has_env_var(engine_state, var) {
caller_stack.remove_env_var(engine_state, var);
}
}

// add new env vars from callee to caller
for env_vars in callee_stack.env_vars {
for (var, value) in env_vars {
caller_stack.add_env_var(var, value);
}
}

result
} else {
eval_expression(engine_state, stack, else_expr)
eval_expression(engine_state, caller_stack, else_expr)
.map(|x| x.into_pipeline_data())
}
} else {
eval_expression(engine_state, stack, else_case)
eval_expression(engine_state, caller_stack, else_case)
.map(|x| x.into_pipeline_data())
}
} else {
Expand Down