fixes: tuple clauses, zero args funcs, list clause named pattern

List Clauses patterns handle var cases

Fixed Tuple Clauses issue with last clause not being a tuple

Redid how zero arg functions and dependencies are handled. Tough one lol
This commit is contained in:
Kasey White 2023-02-14 20:49:40 -05:00 committed by Kasey
parent 23bf101e08
commit 32b0200966
5 changed files with 131 additions and 137 deletions

View File

@ -31,6 +31,7 @@ pub struct FuncComponents {
pub dependencies: Vec<FunctionAccessKey>, pub dependencies: Vec<FunctionAccessKey>,
pub args: Vec<String>, pub args: Vec<String>,
pub recursive: bool, pub recursive: bool,
pub defined_by_zero_arg: bool,
} }
#[derive(Clone, Eq, Debug, PartialEq, Hash)] #[derive(Clone, Eq, Debug, PartialEq, Hash)]
@ -1862,8 +1863,7 @@ pub fn handle_func_dependencies_ir(
dependency_vec.reverse(); dependency_vec.reverse();
while let Some(dependency) = dependency_vec.pop() { while let Some(dependency) = dependency_vec.pop() {
if (defined_functions.contains_key(&dependency) && !funt_comp.args.is_empty()) if defined_functions.contains_key(&dependency) || func_components.get(&dependency).is_none()
|| func_components.get(&dependency).is_none()
{ {
continue; continue;
} }
@ -1874,8 +1874,6 @@ pub fn handle_func_dependencies_ir(
if get_common_ancestor(dep_scope, func_scope) == func_scope.to_vec() if get_common_ancestor(dep_scope, func_scope) == func_scope.to_vec()
|| funt_comp.args.is_empty() || funt_comp.args.is_empty()
{ {
// we handle zero arg functions and their dependencies in a unique way
if !depend_comp.args.is_empty() {
let mut recursion_ir = vec![]; let mut recursion_ir = vec![];
handle_recursion_ir(&dependency, depend_comp, &mut recursion_ir); handle_recursion_ir(&dependency, depend_comp, &mut recursion_ir);
@ -1896,9 +1894,7 @@ pub fn handle_func_dependencies_ir(
if get_common_ancestor(dep_scope, func_scope) == func_scope.to_vec() { if get_common_ancestor(dep_scope, func_scope) == func_scope.to_vec() {
defined_functions.insert(dependency, ()); defined_functions.insert(dependency, ());
} }
} } else if depend_comp.args.is_empty() {
} else {
// Dependency will need to be defined somewhere in the main body
to_be_defined.insert(dependency, ()); to_be_defined.insert(dependency, ());
} }
} }

View File

@ -411,7 +411,7 @@ impl<'a> CodeGenerator<'a> {
final_scope.push(self.id_gen.next()); final_scope.push(self.id_gen.next());
if !matches!(clause_properties, ClauseProperties::TupleClause { .. }) { if !matches!(last_pattern, Pattern::Tuple { .. }) {
pattern_vec.push(Air::Finally { pattern_vec.push(Air::Finally {
scope: final_scope.clone(), scope: final_scope.clone(),
}); });
@ -773,8 +773,14 @@ impl<'a> CodeGenerator<'a> {
let current_clause_index = let current_clause_index =
if let Pattern::List { elements, .. } = &clause.pattern[0] { if let Pattern::List { elements, .. } = &clause.pattern[0] {
elements.len() elements.len()
} else if let Pattern::Assign { pattern, .. } = &clause.pattern[0] {
if let Pattern::List { elements, .. } = pattern.as_ref() {
elements.len()
} else { } else {
unreachable!() unreachable!("{:#?}", pattern)
}
} else {
unreachable!("{:#?}", &clause.pattern[0])
}; };
let prev_index = *current_index; let prev_index = *current_index;
@ -801,6 +807,14 @@ impl<'a> CodeGenerator<'a> {
&clauses[index + 1].pattern[0] &clauses[index + 1].pattern[0]
{ {
elements.len() elements.len()
} else if let Pattern::Assign { pattern, .. } =
&clauses[index + 1].pattern[0]
{
if let Pattern::List { elements, .. } = pattern.as_ref() {
elements.len()
} else {
unreachable!("{:#?}", pattern)
}
} else { } else {
unreachable!() unreachable!()
}; };
@ -2755,33 +2769,55 @@ impl<'a> CodeGenerator<'a> {
let recursion_func_map = IndexMap::new(); let recursion_func_map = IndexMap::new();
self.define_recurse_ir( self.define_ir_recurse(
ir_stack, ir_stack,
&mut func_components, &mut func_components,
&mut func_index_map, &mut func_index_map,
recursion_func_map, recursion_func_map,
false,
); );
let mut final_func_dep_ir = IndexMap::new(); let mut final_func_dep_ir = IndexMap::new();
let mut zero_arg_defined_functions = IndexMap::new();
let mut to_be_defined = IndexMap::new(); let mut to_be_defined = IndexMap::new();
let mut dependency_map = IndexMap::new(); let mut dependency_map = IndexMap::new();
let mut dependency_vec = vec![]; let mut dependency_vec = vec![];
let mut func_keys = func_components.keys().cloned().collect_vec(); let mut func_keys = func_components
.clone()
.into_iter()
.filter(|(_, val)| !val.defined_by_zero_arg)
.map(|(key, val)| (key, val.defined_by_zero_arg))
.collect_vec();
// deal with function dependencies by sorting order in which we iter over them. // deal with function dependencies by sorting order in which we iter over them.
while let Some(function) = func_keys.pop() { while let Some(function) = func_keys.pop() {
let funct_comp = func_components.get(&function).unwrap(); let funct_comp = func_components.get(&function.0).unwrap();
if dependency_map.contains_key(&function) { if dependency_map.contains_key(&function.0) {
dependency_map.shift_remove(&function); dependency_map.shift_remove(&function.0);
} }
dependency_map.insert(function, ()); dependency_map.insert(function.0, function.1);
func_keys.extend(funct_comp.dependencies.clone().into_iter()); func_keys.extend(
funct_comp
.dependencies
.iter()
.map(|key| {
(
key.clone(),
func_components.get(key).unwrap().defined_by_zero_arg,
)
})
.collect_vec(),
);
} }
dependency_vec.extend(dependency_map.keys().cloned()); dependency_vec.extend(
dependency_map
.iter()
.filter(|(_, defined_in_zero_arg)| !**defined_in_zero_arg)
.map(|(key, _)| key.clone())
.collect_vec(),
);
for func in dependency_vec { for func in dependency_vec {
if self.defined_functions.contains_key(&func) { if self.defined_functions.contains_key(&func) {
@ -2808,6 +2844,7 @@ impl<'a> CodeGenerator<'a> {
// since zero arg functions are run at compile time we need to pull all deps // since zero arg functions are run at compile time we need to pull all deps
// note anon functions are not included in the above. They exist in a function anyway // note anon functions are not included in the above. They exist in a function anyway
let mut defined_functions = IndexMap::new(); let mut defined_functions = IndexMap::new();
// deal with function dependencies in zero arg functions // deal with function dependencies in zero arg functions
handle_func_dependencies_ir( handle_func_dependencies_ir(
&mut dep_ir, &mut dep_ir,
@ -2816,7 +2853,7 @@ impl<'a> CodeGenerator<'a> {
&mut defined_functions, &mut defined_functions,
&func_index_map, &func_index_map,
func_scope, func_scope,
&mut IndexMap::new(), &mut to_be_defined,
); );
let mut final_zero_arg_ir = dep_ir; let mut final_zero_arg_ir = dep_ir;
@ -2827,18 +2864,33 @@ impl<'a> CodeGenerator<'a> {
self.zero_arg_functions.insert(func, final_zero_arg_ir); self.zero_arg_functions.insert(func, final_zero_arg_ir);
// zero arg functions don't contain the dependencies since they are pre-evaluated // zero arg functions don't contain the dependencies since they are pre-evaluated
// As such we add functions to defined only after dependencies for all other functions are calculated // As such we add functions to defined only after dependencies for all other functions are calculated
for (key, val) in defined_functions.into_iter() {
zero_arg_defined_functions.insert(key, val);
}
} }
} }
// handle functions that are used in zero arg funcs but also used by the validator while let Some(func) = to_be_defined.pop() {
// or a func used by the validator let mut dep_ir = vec![];
for (key, val) in zero_arg_defined_functions.into_iter() { let mut defined_functions = IndexMap::new();
if !to_be_defined.contains_key(&key) { // deal with function dependencies in zero arg functions
self.defined_functions.insert(key, val);
} let funt_comp = func_components.get(&func.0).unwrap();
let func_scope = func_index_map.get(&func.0).unwrap();
handle_func_dependencies_ir(
&mut dep_ir,
funt_comp,
&func_components,
&mut defined_functions,
&func_index_map,
func_scope,
&mut to_be_defined,
);
let mut final_zero_arg_ir = dep_ir;
final_zero_arg_ir.extend(funt_comp.ir.clone());
self.convert_opaque_type_to_inner_ir(&mut final_zero_arg_ir);
self.zero_arg_functions.insert(func.0, final_zero_arg_ir);
} }
for (index, ir) in ir_stack.clone().into_iter().enumerate().rev() { for (index, ir) in ir_stack.clone().into_iter().enumerate().rev() {
@ -2850,6 +2902,7 @@ impl<'a> CodeGenerator<'a> {
get_common_ancestor(&func.1, &ir.scope()) == ir.scope() get_common_ancestor(&func.1, &ir.scope()) == ir.scope()
&& !self.defined_functions.contains_key(&func.0) && !self.defined_functions.contains_key(&func.0)
&& !self.zero_arg_functions.contains_key(&func.0) && !self.zero_arg_functions.contains_key(&func.0)
&& !(*dependency_map.get(&func.0).unwrap())
}) })
.collect_vec(); .collect_vec();
@ -2894,14 +2947,15 @@ impl<'a> CodeGenerator<'a> {
} }
} }
fn define_recurse_ir( fn define_ir_recurse(
&mut self, &mut self,
ir_stack: &mut [Air], ir_stack: &mut [Air],
func_components: &mut IndexMap<FunctionAccessKey, FuncComponents>, func_components: &mut IndexMap<FunctionAccessKey, FuncComponents>,
func_index_map: &mut IndexMap<FunctionAccessKey, Vec<u64>>, func_index_map: &mut IndexMap<FunctionAccessKey, Vec<u64>>,
mut recursion_func_map: IndexMap<FunctionAccessKey, ()>, mut recursion_func_map: IndexMap<FunctionAccessKey, ()>,
in_zero_arg_func: bool,
) { ) {
self.process_define_ir(ir_stack, func_components, func_index_map); self.define_ir_processor(ir_stack, func_components, func_index_map, in_zero_arg_func);
let mut recursion_func_map_to_add = recursion_func_map.clone(); let mut recursion_func_map_to_add = recursion_func_map.clone();
@ -2910,6 +2964,7 @@ impl<'a> CodeGenerator<'a> {
let function_components = func_components.get_mut(func).unwrap(); let function_components = func_components.get_mut(func).unwrap();
let mut function_ir = function_components.ir.clone(); let mut function_ir = function_components.ir.clone();
let in_zero_arg = function_components.args.is_empty() || in_zero_arg_func;
let mut skip = false; let mut skip = false;
for ir in function_ir.clone() { for ir in function_ir.clone() {
@ -2965,18 +3020,22 @@ impl<'a> CodeGenerator<'a> {
let mut inner_func_index_map = IndexMap::new(); let mut inner_func_index_map = IndexMap::new();
self.define_recurse_ir( self.define_ir_recurse(
&mut function_ir, &mut function_ir,
&mut inner_func_components, &mut inner_func_components,
&mut inner_func_index_map, &mut inner_func_index_map,
recursion_func_map.clone(), recursion_func_map.clone(),
in_zero_arg,
); );
function_components.ir = function_ir; function_components.ir = function_ir;
//now unify //now unify
for item in inner_func_components { for item in inner_func_components {
if !func_components.contains_key(&item.0) { if let Some(entry) = func_components.get_mut(&item.0) {
entry.defined_by_zero_arg =
entry.defined_by_zero_arg && item.1.defined_by_zero_arg
} else {
func_components.insert(item.0, item.1); func_components.insert(item.0, item.1);
} }
} }
@ -2992,11 +3051,12 @@ impl<'a> CodeGenerator<'a> {
} }
} }
fn process_define_ir( fn define_ir_processor(
&mut self, &mut self,
ir_stack: &mut [Air], ir_stack: &mut [Air],
func_components: &mut IndexMap<FunctionAccessKey, FuncComponents>, func_components: &mut IndexMap<FunctionAccessKey, FuncComponents>,
func_index_map: &mut IndexMap<FunctionAccessKey, Vec<u64>>, func_index_map: &mut IndexMap<FunctionAccessKey, Vec<u64>>,
in_zero_arg_func: bool,
) { ) {
let mut to_be_defined_map: IndexMap<FunctionAccessKey, Vec<u64>> = IndexMap::new(); let mut to_be_defined_map: IndexMap<FunctionAccessKey, Vec<u64>> = IndexMap::new();
for (index, ir) in ir_stack.to_vec().iter().enumerate().rev() { for (index, ir) in ir_stack.to_vec().iter().enumerate().rev() {
@ -3172,6 +3232,7 @@ impl<'a> CodeGenerator<'a> {
dependencies: func_calls.keys().cloned().collect_vec(), dependencies: func_calls.keys().cloned().collect_vec(),
recursive, recursive,
args, args,
defined_by_zero_arg: in_zero_arg_func,
}, },
); );
} }

View File

@ -3,11 +3,11 @@
[[requirements]] [[requirements]]
name = "aiken-lang/stdlib" name = "aiken-lang/stdlib"
version = "cf89161cbcd5e2c9519e7ea5d61986473b708179" version = "3b47c89006e7580c2213370d7426ed2a38d2836e"
source = "github" source = "github"
[[packages]] [[packages]]
name = "aiken-lang/stdlib" name = "aiken-lang/stdlib"
version = "cf89161cbcd5e2c9519e7ea5d61986473b708179" version = "3b47c89006e7580c2213370d7426ed2a38d2836e"
requirements = [] requirements = []
source = "github" source = "github"

View File

@ -2,5 +2,5 @@ name = "aiken-lang/acceptance_test_055"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
{ name = "aiken-lang/stdlib", version="cf89161cbcd5e2c9519e7ea5d61986473b708179", source = "github" }, { name = "aiken-lang/stdlib", version="3b47c89006e7580c2213370d7426ed2a38d2836e", source = "github" },
] ]

View File

@ -1,16 +1,9 @@
use aiken/bytearray use aiken/bytearray
use aiken/dict use aiken/dict
use aiken/hash.{Hash, Sha2_256, sha2_256} use aiken/hash.{Hash, Sha2_256, sha2_256}
use aiken/interval.{Interval, IntervalBound, PositiveInfinity} use aiken/interval.{between, intersection, is_empty, strictly_between}
use aiken/list use aiken/list
use aiken/string use aiken/transaction.{InlineDatum}
use aiken/transaction.{
InlineDatum, Input, Output, OutputReference, Transaction, TransactionId,
}
use aiken/transaction/credential.{
Address, PublicKeyCredential, ScriptCredential, StakeCredential,
}
use aiken/transaction/value
// MerkleTree in Aiken (ported from: https://github.com/input-output-hk/hydra/blob/master/plutus-merkle-tree/src/Plutus/MerkleTree.hs) // MerkleTree in Aiken (ported from: https://github.com/input-output-hk/hydra/blob/master/plutus-merkle-tree/src/Plutus/MerkleTree.hs)
@ -74,83 +67,27 @@ test foo() {
size(mt) == 3 size(mt) == 3
} }
// const keyhash = #"010203040506"
// const scripthash = #"060504030201"
// pub fn keyhash_address(with_stake_credential: Option<StakeCredential>) {
// Address {
// payment_credential: PublicKeyCredential(keyhash),
// stake_credential: with_stake_credential,
// }
// }
// pub fn scripthash_address(with_stake_credential: Option<StakeCredential>) {
// Address {
// payment_credential: ScriptCredential(scripthash),
// stake_credential: with_stake_credential,
// }
// }
// type SampleData {
// a: Int,
// b: ByteArray,
// }
// pub fn tx_1() -> Transaction {
// let sample_datum = SampleData { a: 1, b: #"01" }
// // let sample_data: Data = sample_datum
// let tx =
// Transaction {
// inputs: [
// Input {
// output_reference: OutputReference {
// transaction_id: TransactionId { hash: #"" },
// output_index: 0,
// },
// output: Output {
// address: scripthash_address(None),
// value: value.zero(),
// datum: InlineDatum(sample_datum),
// reference_script: None,
// },
// },
// ],
// reference_inputs: [],
// outputs: [
// Output {
// address: keyhash_address(None),
// value: value.from_lovelace(10000),
// datum: InlineDatum(sample_datum),
// reference_script: None,
// },
// ],
// fee: value.zero(),
// mint: value.from_asset(#"000000", #"00", -1),
// certificates: [],
// withdrawals: dict.new(),
// validity_range: Interval {
// lower_bound: IntervalBound {
// bound_type: PositiveInfinity,
// is_inclusive: True,
// },
// upper_bound: IntervalBound {
// bound_type: PositiveInfinity,
// is_inclusive: True,
// },
// },
// extra_signatories: [keyhash],
// redeemers: dict.new(),
// datums: dict.new(),
// id: TransactionId { hash: #"" },
// }
// tx
// }
// test some_test2() {
// tx_1() == tx_1()
// }
test some_test1() { test some_test1() {
InlineDatum(Void) == InlineDatum(Void) InlineDatum(Void) == InlineDatum(Void)
} }
test intersection_3() {
let iv1 = between(0, 1)
let iv2 = strictly_between(1, 2)
intersection(iv1, iv2)
|> is_empty
}
const fooz = #"666f6f"
const bar = #"626172"
fn fixture_1() {
dict.new()
|> dict.insert(fooz, 42, bytearray.compare)
|> dict.insert(bar, 14, bytearray.compare)
}
test union_1() {
dict.union(fixture_1(), dict.new(), bytearray.compare) == fixture_1()
}