Cargo fmt
This commit is contained in:
parent
90c7753201
commit
0d99afe5e2
|
@ -1,4 +1,4 @@
|
||||||
use std::{rc::Rc, sync::Arc, collections::HashMap};
|
use std::{collections::HashMap, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -586,18 +586,33 @@ pub fn erase_opaque_type_operations(
|
||||||
/// Determine whether this air_tree node introduces any shadowing over `potential_matches`
|
/// Determine whether this air_tree node introduces any shadowing over `potential_matches`
|
||||||
pub fn find_introduced_variables(air_tree: &AirTree) -> Vec<String> {
|
pub fn find_introduced_variables(air_tree: &AirTree) -> Vec<String> {
|
||||||
match air_tree {
|
match air_tree {
|
||||||
AirTree::Statement { statement: AirStatement::Let { name, .. }, .. } => vec![name.clone()],
|
AirTree::Statement {
|
||||||
AirTree::Statement { statement: AirStatement::TupleGuard { indices, .. }, .. } |
|
statement: AirStatement::Let { name, .. },
|
||||||
AirTree::Expression(AirExpression::TupleClause { indices, .. }) => {
|
..
|
||||||
|
} => vec![name.clone()],
|
||||||
|
AirTree::Statement {
|
||||||
|
statement: AirStatement::TupleGuard { indices, .. },
|
||||||
|
..
|
||||||
|
}
|
||||||
|
| AirTree::Expression(AirExpression::TupleClause { indices, .. }) => {
|
||||||
indices.iter().map(|(_, name)| name).cloned().collect()
|
indices.iter().map(|(_, name)| name).cloned().collect()
|
||||||
},
|
}
|
||||||
AirTree::Expression(AirExpression::Fn { params, .. }) => {
|
AirTree::Expression(AirExpression::Fn { params, .. }) => {
|
||||||
params.iter().map(|name| name).cloned().collect()
|
params.iter().map(|name| name).cloned().collect()
|
||||||
},
|
|
||||||
AirTree::Statement { statement: AirStatement::ListAccessor { names, .. }, ..} => {
|
|
||||||
names.clone()
|
|
||||||
}
|
}
|
||||||
AirTree::Statement { statement: AirStatement::ListExpose { tail, tail_head_names, .. }, .. } => {
|
AirTree::Statement {
|
||||||
|
statement: AirStatement::ListAccessor { names, .. },
|
||||||
|
..
|
||||||
|
} => names.clone(),
|
||||||
|
AirTree::Statement {
|
||||||
|
statement:
|
||||||
|
AirStatement::ListExpose {
|
||||||
|
tail,
|
||||||
|
tail_head_names,
|
||||||
|
..
|
||||||
|
},
|
||||||
|
..
|
||||||
|
} => {
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
if let Some((_, head)) = tail {
|
if let Some((_, head)) = tail {
|
||||||
ret.push(head.clone())
|
ret.push(head.clone())
|
||||||
|
@ -607,19 +622,25 @@ pub fn find_introduced_variables(air_tree: &AirTree) -> Vec<String> {
|
||||||
ret.push(name.clone());
|
ret.push(name.clone());
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
},
|
|
||||||
AirTree::Statement { statement: AirStatement::TupleAccessor { names, .. }, .. } => {
|
|
||||||
names.clone()
|
|
||||||
},
|
|
||||||
AirTree::Statement { statement: AirStatement::FieldsExpose { indices, .. }, ..} => {
|
|
||||||
indices.iter().map(|(_, name, _)| name).cloned().collect()
|
|
||||||
}
|
}
|
||||||
_ => vec![]
|
AirTree::Statement {
|
||||||
|
statement: AirStatement::TupleAccessor { names, .. },
|
||||||
|
..
|
||||||
|
} => names.clone(),
|
||||||
|
AirTree::Statement {
|
||||||
|
statement: AirStatement::FieldsExpose { indices, .. },
|
||||||
|
..
|
||||||
|
} => indices.iter().map(|(_, name, _)| name).cloned().collect(),
|
||||||
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether a function is recursive, and if so, get the arguments
|
/// Determine whether a function is recursive, and if so, get the arguments
|
||||||
pub fn is_recursive_function_call<'a>(air_tree: &'a AirTree, func_key: &FunctionAccessKey, variant: &String) -> (bool, Option<&'a Vec<AirTree>>) {
|
pub fn is_recursive_function_call<'a>(
|
||||||
|
air_tree: &'a AirTree,
|
||||||
|
func_key: &FunctionAccessKey,
|
||||||
|
variant: &String,
|
||||||
|
) -> (bool, Option<&'a Vec<AirTree>>) {
|
||||||
if let AirTree::Expression(AirExpression::Call { func, args, .. }) = air_tree {
|
if let AirTree::Expression(AirExpression::Call { func, args, .. }) = air_tree {
|
||||||
if let AirTree::Expression(AirExpression::Var {
|
if let AirTree::Expression(AirExpression::Var {
|
||||||
constructor:
|
constructor:
|
||||||
|
@ -629,15 +650,17 @@ pub fn is_recursive_function_call<'a>(air_tree: &'a AirTree, func_key: &Function
|
||||||
},
|
},
|
||||||
variant_name,
|
variant_name,
|
||||||
..
|
..
|
||||||
}) = func.as_ref() {
|
}) = func.as_ref()
|
||||||
|
{
|
||||||
if name == &func_key.function_name
|
if name == &func_key.function_name
|
||||||
&& module == &func_key.module_name
|
&& module == &func_key.module_name
|
||||||
&& variant == variant_name {
|
&& variant == variant_name
|
||||||
return (true, Some(args))
|
{
|
||||||
|
return (true, Some(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (false, None)
|
return (false, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn identify_recursive_static_params(
|
pub fn identify_recursive_static_params(
|
||||||
|
@ -647,7 +670,7 @@ pub fn identify_recursive_static_params(
|
||||||
func_key: &FunctionAccessKey,
|
func_key: &FunctionAccessKey,
|
||||||
variant: &String,
|
variant: &String,
|
||||||
shadowed_parameters: &mut HashMap<String, TreePath>,
|
shadowed_parameters: &mut HashMap<String, TreePath>,
|
||||||
potential_recursive_statics: &mut Vec<String>
|
potential_recursive_statics: &mut Vec<String>,
|
||||||
) {
|
) {
|
||||||
// Find whether any of the potential recursive statics get shadowed (because even if we pass in the same referenced name, it might not be static)
|
// Find whether any of the potential recursive statics get shadowed (because even if we pass in the same referenced name, it might not be static)
|
||||||
for introduced_variable in find_introduced_variables(air_tree) {
|
for introduced_variable in find_introduced_variables(air_tree) {
|
||||||
|
@ -658,7 +681,10 @@ pub fn identify_recursive_static_params(
|
||||||
// Otherwise, if this is a recursive call site, disqualify anything that is different (or the same, but shadowed)
|
// Otherwise, if this is a recursive call site, disqualify anything that is different (or the same, but shadowed)
|
||||||
if let (true, Some(args)) = is_recursive_function_call(air_tree, func_key, variant) {
|
if let (true, Some(args)) = is_recursive_function_call(air_tree, func_key, variant) {
|
||||||
for (param, arg) in func_params.iter().zip(args) {
|
for (param, arg) in func_params.iter().zip(args) {
|
||||||
if let Some((idx, _)) = potential_recursive_statics.iter().find_position(|&p| p == param) {
|
if let Some((idx, _)) = potential_recursive_statics
|
||||||
|
.iter()
|
||||||
|
.find_position(|&p| p == param)
|
||||||
|
{
|
||||||
// Check if we pass something different in this recursive call site
|
// Check if we pass something different in this recursive call site
|
||||||
// by different, we mean
|
// by different, we mean
|
||||||
// - a variable that is bound to a different name
|
// - a variable that is bound to a different name
|
||||||
|
@ -667,13 +693,14 @@ pub fn identify_recursive_static_params(
|
||||||
let param_is_different = match arg {
|
let param_is_different = match arg {
|
||||||
AirTree::Expression(AirExpression::Var { name, .. }) => {
|
AirTree::Expression(AirExpression::Var { name, .. }) => {
|
||||||
// "shadowed in an ancestor scope" means "the definition scope is a prefix of our scope"
|
// "shadowed in an ancestor scope" means "the definition scope is a prefix of our scope"
|
||||||
name != param || if let Some(p) = shadowed_parameters.get(param) {
|
name != param
|
||||||
|
|| if let Some(p) = shadowed_parameters.get(param) {
|
||||||
p.common_ancestor(tree_path) == *p
|
p.common_ancestor(tree_path) == *p
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => true
|
_ => true,
|
||||||
};
|
};
|
||||||
// If so, then we disqualify this parameter from being a recursive static parameter
|
// If so, then we disqualify this parameter from being a recursive static parameter
|
||||||
if param_is_different {
|
if param_is_different {
|
||||||
|
@ -684,14 +711,27 @@ pub fn identify_recursive_static_params(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn modify_self_calls(body: &mut AirTree, func_key: &FunctionAccessKey, variant: &String, func_params: &Vec<String>) -> Vec<String> {
|
pub fn modify_self_calls(
|
||||||
|
body: &mut AirTree,
|
||||||
|
func_key: &FunctionAccessKey,
|
||||||
|
variant: &String,
|
||||||
|
func_params: &Vec<String>,
|
||||||
|
) -> Vec<String> {
|
||||||
let mut potential_recursive_statics = func_params.clone();
|
let mut potential_recursive_statics = func_params.clone();
|
||||||
// identify which parameters are recursively nonstatic (i.e. get modified before the self-call)
|
// identify which parameters are recursively nonstatic (i.e. get modified before the self-call)
|
||||||
// TODO: this would be a lot simpler if each `Var`, `Let`, function argument, etc. had a unique identifier
|
// TODO: this would be a lot simpler if each `Var`, `Let`, function argument, etc. had a unique identifier
|
||||||
// rather than just a name; this would let us track if the Var passed to itself was the same value as the method argument
|
// rather than just a name; this would let us track if the Var passed to itself was the same value as the method argument
|
||||||
let mut shadowed_parameters: HashMap<String, TreePath> = HashMap::new();
|
let mut shadowed_parameters: HashMap<String, TreePath> = HashMap::new();
|
||||||
body.traverse_tree_with(&mut |air_tree: &mut AirTree, tree_path| {
|
body.traverse_tree_with(&mut |air_tree: &mut AirTree, tree_path| {
|
||||||
identify_recursive_static_params(air_tree, tree_path, &func_params, func_key, variant, &mut shadowed_parameters, &mut potential_recursive_statics);
|
identify_recursive_static_params(
|
||||||
|
air_tree,
|
||||||
|
tree_path,
|
||||||
|
&func_params,
|
||||||
|
func_key,
|
||||||
|
variant,
|
||||||
|
&mut shadowed_parameters,
|
||||||
|
&mut potential_recursive_statics,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Find the index of any recursively static parameters,
|
// Find the index of any recursively static parameters,
|
||||||
|
@ -733,7 +773,11 @@ pub fn modify_self_calls(body: &mut AirTree, func_key: &FunctionAccessKey, varia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let recursive_nonstatics = func_params.iter().filter(|p| !potential_recursive_statics.contains(p)).cloned().collect();
|
let recursive_nonstatics = func_params
|
||||||
|
.iter()
|
||||||
|
.filter(|p| !potential_recursive_statics.contains(p))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
recursive_nonstatics
|
recursive_nonstatics
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,32 +21,3 @@ validator {
|
||||||
must_say_hello && must_be_signed
|
must_say_hello && must_be_signed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ABC {
|
|
||||||
a: ByteArray,
|
|
||||||
b: Int,
|
|
||||||
c: ByteArray,
|
|
||||||
}
|
|
||||||
|
|
||||||
type XYZ {
|
|
||||||
a: ByteArray,
|
|
||||||
b: ByteArray,
|
|
||||||
c: ByteArray,
|
|
||||||
d: Int,
|
|
||||||
e: ABC,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recursive(a: ByteArray, b: Int, c: XYZ, d: Int, e: Int) -> ByteArray {
|
|
||||||
if c.e.a == "a" {
|
|
||||||
"d"
|
|
||||||
} else if b == 0 {
|
|
||||||
a
|
|
||||||
} else {
|
|
||||||
recursive(a, b - 1, c, d, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test hah() {
|
|
||||||
expect "a" == recursive("a", 30, XYZ("", "", "", 1, ABC("", 1, "")), 2, 5)
|
|
||||||
True
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue