Update disassembling

This commit is contained in:
evan-schott 2024-02-12 22:37:18 -08:00
parent a2e31558c1
commit acdb2b5c9b
4 changed files with 66 additions and 151 deletions

View File

@ -26,9 +26,6 @@ pub use variant::*;
pub mod external;
pub use external::*;
pub mod finalize;
pub use finalize::*;
pub mod input;
pub use input::*;
@ -49,6 +46,8 @@ use std::fmt;
pub struct Function {
/// Annotations on the function.
pub annotations: Vec<Annotation>,
/// Is this function asynchronous or synchronous?
pub is_async: bool,
/// Is this function a transition, inlined, or a regular function?.
pub variant: Variant,
/// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
@ -61,8 +60,6 @@ pub struct Function {
pub output_type: Type,
/// The body of the function.
pub block: Block,
/// An optional finalize block
pub finalize: Option<Finalize>,
/// The entire span of the function definition.
pub span: Span,
/// The ID of the node.
@ -82,12 +79,12 @@ impl Function {
#[allow(clippy::too_many_arguments)]
pub fn new(
annotations: Vec<Annotation>,
is_async: bool,
variant: Variant,
identifier: Identifier,
input: Vec<Input>,
output: Vec<Output>,
block: Block,
finalize: Option<Finalize>,
span: Span,
id: NodeID,
) -> Self {
@ -103,7 +100,7 @@ impl Function {
_ => Type::Tuple(TupleType::new(output.iter().map(get_output_type).collect())),
};
Function { annotations, variant, identifier, input, output, output_type, block, finalize, span, id }
Function { annotations, is_async, variant, identifier, input, output, output_type, block, span, id }
}
/// Returns function name.
@ -129,28 +126,22 @@ impl Function {
_ => self.output.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(","),
};
write!(f, "({parameters}) -> {returns} {}", self.block)?;
if let Some(finalize) = &self.finalize {
let parameters = finalize.input.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
write!(f, " finalize ({parameters}) {}", finalize.block)
} else {
Ok(())
}
Ok(())
}
}
impl From<FunctionStub> for Function {
fn from(function: FunctionStub) -> Self {
let finalize = function.finalize_stub.map(Finalize::from);
Self {
annotations: function.annotations,
is_async: false,
variant: function.variant,
identifier: function.identifier,
input: function.input,
output: function.output,
output_type: function.output_type,
block: Block::default(),
finalize,
span: function.span,
id: function.id,
}

View File

@ -1,102 +0,0 @@
// Copyright (C) 2019-2023 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Finalize, FunctionInput, Identifier, Input, Mode, Node, NodeID, Output, TupleType, Type};
use leo_span::{Span, Symbol};
use core::fmt;
use serde::{Deserialize, Serialize};
use snarkvm::{
prelude::{
FinalizeType::{Future, Plaintext},
Network,
},
synthesizer::program::{CommandTrait, FinalizeCore},
};
/// A finalize stub.
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
pub struct FinalizeStub {
/// The finalize identifier.
pub identifier: Identifier,
/// The finalize block's input parameters.
pub input: Vec<Input>,
/// The finalize blocks's output declaration.
pub output: Vec<Output>,
/// The finalize block's output type.
pub output_type: Type,
/// The entire span of the finalize stub.
pub span: Span,
/// The ID of the node.
pub id: NodeID,
}
impl FinalizeStub {
/// Create a new finalize stub.
pub fn new(identifier: Identifier, input: Vec<Input>, output: Vec<Output>, span: Span, id: NodeID) -> Self {
let output_type = match output.len() {
0 => Type::Unit,
1 => output[0].type_(),
_ => Type::Tuple(TupleType::new(output.iter().map(|output| output.type_()).collect())),
};
Self { identifier, input, output, output_type, span, id }
}
pub fn from_snarkvm<N: Network, Command: CommandTrait<N>>(
finalize: &FinalizeCore<N, Command>,
program: Symbol,
) -> Self {
let mut inputs = Vec::new();
finalize.inputs().iter().enumerate().for_each(|(index, input)| {
let arg_name = Identifier::new(Symbol::intern(&format!("a{}", index + 1)), Default::default());
match input.finalize_type() {
Plaintext(val) => inputs.push(Input::Internal(FunctionInput {
identifier: arg_name,
mode: Mode::None,
type_: Type::from_snarkvm(val, program),
span: Default::default(),
id: Default::default(),
})),
Future(_) => {} // Don't need to worry about nested futures
}
});
Self::new(Identifier::from(finalize.name()), inputs, Vec::new(), Default::default(), Default::default())
}
}
impl From<Finalize> for FinalizeStub {
fn from(finalize: Finalize) -> Self {
Self::new(finalize.identifier, finalize.input, finalize.output, Default::default(), Default::default())
}
}
impl fmt::Display for FinalizeStub {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let parameters = self.input.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
let returns = match self.output.len() {
0 => "()".to_string(),
1 => self.output[0].to_string(),
_ => format!("({})", self.output.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",")),
};
write!(f, " finalize {}({parameters}) -> {returns}", self.identifier)
}
}
crate::simple_node_impl!(FinalizeStub);

View File

@ -14,32 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
finalize_stub::*,
Annotation,
CompositeType,
External,
Function,
FunctionInput,
FunctionOutput,
Identifier,
Input,
Mode,
Node,
NodeID,
Output,
ProgramId,
TupleType,
Type,
Variant,
};
use crate::{Annotation, CompositeType, External, Function, FunctionInput, FunctionOutput, Identifier, Input, Mode, Node, NodeID, Output, ProgramId, TupleType, Type, Variant, FutureType};
use leo_span::{sym, Span, Symbol};
use crate::Type::Composite;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use snarkvm::{
console::program::RegisterType::{ExternalRecord, Future, Plaintext, Record},
console::program::{RegisterType::{ExternalRecord, Future, Plaintext, Record}, FinalizeType::{Future as FutureFinalizeType, Plaintext as PlaintextFinalizeType}},
prelude::{Network, ValueType},
synthesizer::program::{ClosureCore, CommandTrait, FunctionCore, InstructionTrait},
};
@ -50,6 +32,8 @@ use std::fmt;
pub struct FunctionStub {
/// Annotations on the function.
pub annotations: Vec<Annotation>,
/// Is this function asynchronous or synchronous?
pub is_async: bool,
/// Is this function a transition, inlined, or a regular function?.
pub variant: Variant,
/// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
@ -60,8 +44,6 @@ pub struct FunctionStub {
pub output: Vec<Output>,
/// The function's output type.
pub output_type: Type,
/// An optional finalize stub
pub finalize_stub: Option<FinalizeStub>,
/// The entire span of the function definition.
pub span: Span,
/// The ID of the node.
@ -81,11 +63,11 @@ impl FunctionStub {
#[allow(clippy::too_many_arguments)]
pub fn new(
annotations: Vec<Annotation>,
is_async: bool,
variant: Variant,
identifier: Identifier,
input: Vec<Input>,
output: Vec<Output>,
finalize_stub: Option<FinalizeStub>,
span: Span,
id: NodeID,
) -> Self {
@ -101,7 +83,7 @@ impl FunctionStub {
_ => Type::Tuple(TupleType::new(output.iter().map(get_output_type).collect())),
};
FunctionStub { annotations, variant, identifier, input, output, output_type, finalize_stub, span, id }
FunctionStub { annotations, is_async, variant, identifier, input, output, output_type, span, id }
}
/// Returns function name.
@ -133,12 +115,7 @@ impl FunctionStub {
};
write!(f, "({parameters}) -> {returns}")?;
if let Some(finalize) = &self.finalize_stub {
let parameters = finalize.input.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
write!(f, " finalize ({parameters})")
} else {
Ok(())
}
Ok(())
}
/// Converts from snarkvm function type to leo FunctionStub, while also carrying the parent program name.
@ -204,6 +181,7 @@ impl FunctionStub {
Self {
annotations: Vec::new(),
is_async: function.finalize_logic().is_some(),
variant: Variant::Transition,
identifier: Identifier::from(function.name()),
input: function
@ -254,12 +232,45 @@ impl FunctionStub {
.collect_vec(),
output: outputs,
output_type,
finalize_stub: function.finalize_logic().map(|f| FinalizeStub::from_snarkvm(f, program)),
span: Default::default(),
id: Default::default(),
}
}
pub fn from_finalize<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
function: &FunctionCore<N, Instruction, Command>,
name: Symbol,
) -> Self {
Self {
annotations: Vec::new(),
is_async: true,
variant: Variant::Transition,
identifier: Identifier::new(name, Default::default()),
input: function.finalize_logic().unwrap().inputs().iter().enumerate().map(|(index, input)| {
Input::Internal(FunctionInput {
identifier: Identifier::new(Symbol::intern(&format!("a{}", index + 1)), Default::default()),
mode: Mode::Public,
type_: match input.finalize_type() {
PlaintextFinalizeType(val) => Type::from_snarkvm(&val, name),
FutureFinalizeType(_) => Type::Future(Default::default()),
},
span: Default::default(),
id: Default::default(),
})
}).collect_vec(),
output: vec![Output::Internal(FunctionOutput {
mode: Mode::Public,
type_: Type::Future(FutureType { inputs: None} ),
span: Default::default(),
id: 0,
})
],
output_type: Type::Future(FutureType { inputs: None}),
span: Default::default(),
id: 0,
}
}
pub fn from_closure<N: Network, Instruction: InstructionTrait<N>>(
closure: &ClosureCore<N, Instruction>,
program: Symbol,
@ -293,6 +304,7 @@ impl FunctionStub {
};
Self {
annotations: Vec::new(),
is_async: false,
variant: Variant::Standard,
identifier: Identifier::from(closure.name()),
input: closure
@ -319,7 +331,6 @@ impl FunctionStub {
output_type,
span: Default::default(),
id: Default::default(),
finalize_stub: None,
}
}
}
@ -328,12 +339,12 @@ impl From<Function> for FunctionStub {
fn from(function: Function) -> Self {
Self {
annotations: function.annotations,
is_async: function.is_async,
variant: function.variant,
identifier: function.identifier,
input: function.input,
output: function.output,
output_type: function.output_type,
finalize_stub: function.finalize.map(FinalizeStub::from),
span: function.span,
id: function.id,
}

View File

@ -23,6 +23,7 @@ type CurrentNetwork = Testnet3;
use leo_ast::{Composite, FunctionStub, Identifier, Mapping, ProgramId, Stub};
use leo_errors::UtilError;
use leo_span::Symbol;
pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
program: ProgramCore<N, Instruction, Command>,
@ -65,6 +66,20 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
(Identifier::from(id).name, FunctionStub::from_function_core(function, program_id.name.name))
})
.collect_vec(),
program
.functions()
.iter()
.filter_map(|(id, function)| match function.finalize_logic() {
Some(f) => {
let name = Symbol::intern(&format!(
"finalize/{}",
Symbol::intern(&Identifier::from(id).name.to_string())
));
Some((name, FunctionStub::from_finalize(f, name)))
}
None => None,
})
.collect_vec(),
]
.concat(),
span: Default::default(),