mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
Retrieve external future locations during disassembling instead of in TYC
This commit is contained in:
parent
e99d7df699
commit
0ed5cd6924
@ -58,8 +58,6 @@ pub struct FunctionStub {
|
||||
pub variant: Variant,
|
||||
/// The function identifier, e.g., `foo` in `function foo(...) { ... }`.
|
||||
pub identifier: Identifier,
|
||||
/// Ordered list of futures inputted to finalize.
|
||||
pub future_locations: Vec<Location>,
|
||||
/// The function's input parameters.
|
||||
pub input: Vec<Input>,
|
||||
/// The function's output declarations.
|
||||
@ -109,7 +107,6 @@ impl FunctionStub {
|
||||
annotations,
|
||||
variant,
|
||||
identifier,
|
||||
future_locations: Vec::new(),
|
||||
input,
|
||||
output,
|
||||
output_type,
|
||||
@ -192,7 +189,7 @@ impl FunctionStub {
|
||||
}),
|
||||
ValueType::Future(_) => Output::Internal(FunctionOutput {
|
||||
mode: Mode::Public,
|
||||
type_: Type::Future(FutureType::new(Vec::new())),
|
||||
type_: Type::Future(FutureType::new(Vec::new(), Some(Location::new(Some(program), Identifier::from(function.name()).name)))),
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
}),
|
||||
@ -220,7 +217,6 @@ impl FunctionStub {
|
||||
false => Variant::Transition,
|
||||
},
|
||||
identifier: Identifier::from(function.name()),
|
||||
future_locations: Vec::new(),
|
||||
input: function
|
||||
.inputs()
|
||||
.iter()
|
||||
@ -276,25 +272,13 @@ impl FunctionStub {
|
||||
|
||||
pub fn from_finalize<N: Network, Instruction: InstructionTrait<N>, Command: CommandTrait<N>>(
|
||||
function: &FunctionCore<N, Instruction, Command>,
|
||||
name: Symbol,
|
||||
key_name: Symbol,
|
||||
program: Symbol,
|
||||
) -> Self {
|
||||
Self {
|
||||
annotations: Vec::new(),
|
||||
variant: Variant::AsyncFunction,
|
||||
identifier: Identifier::new(name, Default::default()),
|
||||
future_locations: function
|
||||
.finalize_logic()
|
||||
.unwrap()
|
||||
.inputs()
|
||||
.iter()
|
||||
.filter_map(|input| match input.finalize_type() {
|
||||
FinalizeType::Future(val) => Some(Location::new(
|
||||
Some(Identifier::from(val.program_id().name()).name),
|
||||
Symbol::intern(&format!("finalize/{}", val.resource())),
|
||||
)),
|
||||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
identifier: Identifier::new(key_name, Default::default()),
|
||||
input: function
|
||||
.finalize_logic()
|
||||
.unwrap()
|
||||
@ -306,21 +290,19 @@ impl FunctionStub {
|
||||
identifier: Identifier::new(Symbol::intern(&format!("arg{}", index + 1)), Default::default()),
|
||||
mode: Mode::None,
|
||||
type_: match input.finalize_type() {
|
||||
PlaintextFinalizeType(val) => Type::from_snarkvm(val, name),
|
||||
FutureFinalizeType(_) => Type::Future(Default::default()),
|
||||
PlaintextFinalizeType(val) => Type::from_snarkvm(val, key_name),
|
||||
FutureFinalizeType(val) => Type::Future(FutureType::new(Vec::new(), Some(Location::new(
|
||||
Some(Identifier::from(val.program_id().name()).name),
|
||||
Symbol::intern(&format!("finalize/{}", val.resource()))),
|
||||
))),
|
||||
},
|
||||
span: Default::default(),
|
||||
id: Default::default(),
|
||||
})
|
||||
})
|
||||
.collect_vec(),
|
||||
output: vec![Output::Internal(FunctionOutput {
|
||||
mode: Mode::None,
|
||||
type_: Type::Future(FutureType { inputs: Vec::new() }),
|
||||
span: Default::default(),
|
||||
id: 0,
|
||||
})],
|
||||
output_type: Type::Future(FutureType { inputs: Vec::new() }),
|
||||
output: Vec::new(),
|
||||
output_type: Type::Unit,
|
||||
span: Default::default(),
|
||||
id: 0,
|
||||
}
|
||||
@ -361,7 +343,6 @@ impl FunctionStub {
|
||||
annotations: Vec::new(),
|
||||
variant: Variant::Function,
|
||||
identifier: Identifier::from(closure.name()),
|
||||
future_locations: Vec::new(),
|
||||
input: closure
|
||||
.inputs()
|
||||
.iter()
|
||||
@ -396,7 +377,6 @@ impl From<Function> for FunctionStub {
|
||||
annotations: function.annotations,
|
||||
variant: function.variant,
|
||||
identifier: function.identifier,
|
||||
future_locations: Vec::new(),
|
||||
input: function.input,
|
||||
output: function.output,
|
||||
output_type: function.output_type,
|
||||
|
@ -86,7 +86,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
.map(|(_, function)| {
|
||||
if function.variant != Variant::AsyncFunction {
|
||||
// Set the `is_transition_function` flag.
|
||||
self.is_transition_function = matches!(function.variant, Variant::Transition);
|
||||
self.is_transition_function = function.variant.is_transition();
|
||||
|
||||
let mut function_string = self.visit_function(function);
|
||||
|
||||
|
@ -16,31 +16,7 @@
|
||||
|
||||
use crate::StaticSingleAssigner;
|
||||
|
||||
use leo_ast::{
|
||||
AccessExpression,
|
||||
ArrayAccess,
|
||||
ArrayExpression,
|
||||
AssociatedFunction,
|
||||
BinaryExpression,
|
||||
CallExpression,
|
||||
CastExpression,
|
||||
Composite,
|
||||
Expression,
|
||||
ExpressionConsumer,
|
||||
Identifier,
|
||||
Literal,
|
||||
Location,
|
||||
LocatorExpression,
|
||||
MemberAccess,
|
||||
Statement,
|
||||
StructExpression,
|
||||
StructVariableInitializer,
|
||||
TernaryExpression,
|
||||
TupleAccess,
|
||||
TupleExpression,
|
||||
UnaryExpression,
|
||||
UnitExpression,
|
||||
};
|
||||
use leo_ast::{AccessExpression, ArrayAccess, ArrayExpression, AssociatedFunction, BinaryExpression, CallExpression, CastExpression, Composite, Expression, ExpressionConsumer, Identifier, Literal, Location, LocatorExpression, MemberAccess, MethodCall, Statement, StructExpression, StructVariableInitializer, TernaryExpression, TupleAccess, TupleExpression, UnaryExpression, UnitExpression};
|
||||
use leo_span::{sym, Symbol};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
@ -751,6 +751,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
))
|
||||
.unwrap()
|
||||
.clone(),
|
||||
Some(Location::new(input.program, ident.name))
|
||||
));
|
||||
ret = match ret.clone() {
|
||||
Tuple(tup) => Tuple(TupleType::new(
|
||||
@ -797,7 +798,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
self.scope_state.has_called_finalize = true;
|
||||
|
||||
// Update ret to reflect fully inferred future type.
|
||||
ret = Type::Future(FutureType::new(inferred_finalize_inputs));
|
||||
ret = Type::Future(FutureType::new(inferred_finalize_inputs, Some(Location::new(input.program, ident.name))));
|
||||
}
|
||||
// Set call location so that definition statement knows where future comes from.
|
||||
self.scope_state.call_location = Some(Location::new(input.program, ident.name));
|
||||
|
@ -91,18 +91,16 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
// Create future stubs.
|
||||
if input.variant == Variant::AsyncFunction {
|
||||
let finalize_input_map = &mut self.finalize_input_types;
|
||||
let mut future_stubs = input.future_locations.clone();
|
||||
let resolved_inputs: Vec<Type> = input
|
||||
.input
|
||||
.iter()
|
||||
.map(|input_mode| {
|
||||
match input_mode {
|
||||
Internal(function_input) => match &function_input.type_ {
|
||||
Future(_) => {
|
||||
Future(f) => {
|
||||
// Since we traverse stubs in post-order, we can assume that the corresponding finalize stub has already been traversed.
|
||||
Future(FutureType::new(
|
||||
finalize_input_map.get(&future_stubs.remove(0)).unwrap().clone(),
|
||||
))
|
||||
finalize_input_map.get(&f.location.clone().unwrap()).unwrap().clone(), f.location.clone()))
|
||||
}
|
||||
_ => function_input.clone().type_,
|
||||
},
|
||||
@ -110,7 +108,6 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
assert!(future_stubs.is_empty(), "Disassembler produced malformed stub.");
|
||||
|
||||
finalize_input_map
|
||||
.insert(Location::new(self.scope_state.program_name, input.identifier.name), resolved_inputs);
|
||||
@ -164,7 +161,7 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
let mut transition_count = 0;
|
||||
for (_, function) in input.functions.iter() {
|
||||
self.visit_function(function);
|
||||
if matches!(function.variant, Variant::Transition) {
|
||||
if function.variant.is_transition() {
|
||||
transition_count += 1;
|
||||
}
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
// Fully type the expected return value.
|
||||
if self.scope_state.variant == Some(Variant::AsyncTransition) && self.scope_state.has_called_finalize {
|
||||
let inferred_future_type = match self.finalize_input_types.get(&func.unwrap().finalize.clone().unwrap()) {
|
||||
Some(types) => Future(FutureType::new(types.clone())),
|
||||
Some(types) => Future(FutureType::new(types.clone(), Some(Location::new(self.scope_state.program_name, parent)))),
|
||||
None => {
|
||||
return self.emit_err(TypeCheckerError::async_transition_missing_future_to_return(input.span()));
|
||||
}
|
||||
|
@ -1323,7 +1323,7 @@ impl<'a> TypeChecker<'a> {
|
||||
// Check that the input parameter is not a record.
|
||||
else if let Type::Composite(struct_) = input_var.type_() {
|
||||
// Note that this unwrap is safe, as the type is defined.
|
||||
if !matches!(function.variant, Variant::Transition)
|
||||
if !function.variant.is_transition()
|
||||
&& self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
@ -1378,7 +1378,7 @@ impl<'a> TypeChecker<'a> {
|
||||
Output::External(external) => {
|
||||
// If the function is not a transition function, then it cannot output a record.
|
||||
// Note that an external output must always be a record.
|
||||
if !matches!(function.variant, Variant::Transition) {
|
||||
if !function.variant.is_transition() {
|
||||
self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(external.span()));
|
||||
}
|
||||
}
|
||||
@ -1387,7 +1387,7 @@ impl<'a> TypeChecker<'a> {
|
||||
if self.assert_type_is_valid(&function_output.type_, function_output.span) {
|
||||
// If the function is not a transition function, then it cannot output a record.
|
||||
if let Type::Composite(struct_) = function_output.type_.clone() {
|
||||
if !matches!(function.variant, Variant::Transition)
|
||||
if !function.variant.is_transition()
|
||||
&& self
|
||||
.symbol_table
|
||||
.borrow()
|
||||
|
@ -52,7 +52,7 @@ impl ScopeState {
|
||||
has_return: false,
|
||||
is_return: false,
|
||||
program_name: None,
|
||||
is_stub: false,
|
||||
is_stub: true,
|
||||
futures: IndexMap::new(),
|
||||
has_called_finalize: false,
|
||||
is_conditional: false,
|
||||
|
@ -71,11 +71,11 @@ pub fn disassemble<N: Network, Instruction: InstructionTrait<N>, Command: Comman
|
||||
.iter()
|
||||
.filter_map(|(id, function)| match function.finalize_logic() {
|
||||
Some(_f) => {
|
||||
let name = Symbol::intern(&format!(
|
||||
let key_name = Symbol::intern(&format!(
|
||||
"finalize/{}",
|
||||
Symbol::intern(&Identifier::from(id).name.to_string())
|
||||
));
|
||||
Some((name, FunctionStub::from_finalize(function, name)))
|
||||
Some((key_name, FunctionStub::from_finalize(function, key_name, program_id.name.name)))
|
||||
}
|
||||
None => None,
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user