Add more argument types to view ir
This commit is contained in:
parent
801cfae279
commit
99873dda8c
|
@ -1,5 +1,4 @@
|
||||||
use nu_engine::command_prelude::*;
|
use nu_engine::command_prelude::*;
|
||||||
use nu_protocol::engine::Closure;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ViewIr;
|
pub struct ViewIr;
|
||||||
|
@ -12,15 +11,20 @@ impl Command for ViewIr {
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::new(self.name())
|
Signature::new(self.name())
|
||||||
.required(
|
.required(
|
||||||
"closure",
|
"target",
|
||||||
SyntaxShape::Closure(None),
|
SyntaxShape::Any,
|
||||||
"The closure to see compiled code for.",
|
"The name or block to view compiled code for.",
|
||||||
)
|
)
|
||||||
.switch(
|
.switch(
|
||||||
"json",
|
"json",
|
||||||
"Dump the raw block data as JSON (unstable).",
|
"Dump the raw block data as JSON (unstable).",
|
||||||
Some('j'),
|
Some('j'),
|
||||||
)
|
)
|
||||||
|
.switch(
|
||||||
|
"decl-id",
|
||||||
|
"Integer is a declaration ID rather than a block ID.",
|
||||||
|
Some('d'),
|
||||||
|
)
|
||||||
.input_output_type(Type::Nothing, Type::String)
|
.input_output_type(Type::Nothing, Type::String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +32,20 @@ impl Command for ViewIr {
|
||||||
"View the compiled IR code for a block of code."
|
"View the compiled IR code for a block of code."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extra_usage(&self) -> &str {
|
||||||
|
"
|
||||||
|
The target can be a closure, the name of a custom command, or an internal block
|
||||||
|
ID. Closure literals within IR dumps often reference the block by ID (e.g.
|
||||||
|
`closure(3231)`), so this provides an easy way to read the IR of any embedded
|
||||||
|
closures.
|
||||||
|
|
||||||
|
The --decl-id option is provided to use a declaration ID instead, which can be
|
||||||
|
found on `call` instructions. This is sometimes better than using the name, as
|
||||||
|
the declaration may not be in scope.
|
||||||
|
"
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
|
@ -35,10 +53,79 @@ impl Command for ViewIr {
|
||||||
call: &Call,
|
call: &Call,
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let closure: Closure = call.req(engine_state, stack, 0)?;
|
let target: Value = call.req(engine_state, stack, 0)?;
|
||||||
let json = call.has_flag(engine_state, stack, "json")?;
|
let json = call.has_flag(engine_state, stack, "json")?;
|
||||||
|
let is_decl_id = call.has_flag(engine_state, stack, "decl-id")?;
|
||||||
|
|
||||||
|
let block_id = match target {
|
||||||
|
Value::Closure { ref val, .. } => val.block_id,
|
||||||
|
// Decl by name
|
||||||
|
Value::String { ref val, .. } => {
|
||||||
|
if let Some(decl_id) = engine_state.find_decl(val.as_bytes(), &[]) {
|
||||||
|
let decl = engine_state.get_decl(decl_id);
|
||||||
|
decl.block_id().ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: format!("Can't view IR for `{val}`"),
|
||||||
|
msg: "not a custom command".into(),
|
||||||
|
span: Some(target.span()),
|
||||||
|
help: Some("internal commands don't have Nushell source code".into()),
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
} else {
|
||||||
|
return Err(ShellError::GenericError {
|
||||||
|
error: format!("Can't view IR for `{val}`"),
|
||||||
|
msg: "can't find a command with this name".into(),
|
||||||
|
span: Some(target.span()),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Decl by ID - IR dump always shows name of decl, but sometimes it isn't in scope
|
||||||
|
Value::Int { val, .. } if is_decl_id => {
|
||||||
|
let decl_id = val
|
||||||
|
.try_into()
|
||||||
|
.ok()
|
||||||
|
.filter(|id| *id < engine_state.num_decls())
|
||||||
|
.ok_or_else(|| ShellError::IncorrectValue {
|
||||||
|
msg: "not a valid decl id".into(),
|
||||||
|
val_span: target.span(),
|
||||||
|
call_span: call.head,
|
||||||
|
})?;
|
||||||
|
let decl = engine_state.get_decl(decl_id);
|
||||||
|
decl.block_id().ok_or_else(|| ShellError::GenericError {
|
||||||
|
error: format!("Can't view IR for `{}`", decl.name()),
|
||||||
|
msg: "not a custom command".into(),
|
||||||
|
span: Some(target.span()),
|
||||||
|
help: Some("internal commands don't have Nushell source code".into()),
|
||||||
|
inner: vec![],
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
// Block by ID - often shows up in IR
|
||||||
|
Value::Int { val, .. } => val.try_into().map_err(|_| ShellError::IncorrectValue {
|
||||||
|
msg: "not a valid block id".into(),
|
||||||
|
val_span: target.span(),
|
||||||
|
call_span: call.head,
|
||||||
|
})?,
|
||||||
|
// Pass through errors
|
||||||
|
Value::Error { error, .. } => return Err(*error),
|
||||||
|
_ => {
|
||||||
|
return Err(ShellError::TypeMismatch {
|
||||||
|
err_message: "expected closure, string, or int".into(),
|
||||||
|
span: call.head,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(block) = engine_state.try_get_block(block_id) else {
|
||||||
|
return Err(ShellError::GenericError {
|
||||||
|
error: format!("Unknown block ID: {block_id}"),
|
||||||
|
msg: "ensure the block ID is correct and try again".into(),
|
||||||
|
span: Some(target.span()),
|
||||||
|
help: None,
|
||||||
|
inner: vec![],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
let block = engine_state.get_block(closure.block_id);
|
|
||||||
let ir_block = block
|
let ir_block = block
|
||||||
.ir_block
|
.ir_block
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -62,7 +149,7 @@ impl Command for ViewIr {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
serde_json::to_string_pretty(&serde_json::json!({
|
serde_json::to_string_pretty(&serde_json::json!({
|
||||||
"block_id": closure.block_id,
|
"block_id": block_id,
|
||||||
"span": block.span,
|
"span": block.span,
|
||||||
"ir_block": ir_block,
|
"ir_block": ir_block,
|
||||||
"formatted_instructions": formatted_instructions,
|
"formatted_instructions": formatted_instructions,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user