feat: code gen support for if/is
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
parent
1b8805825b
commit
5024bd3f9c
|
@ -5,7 +5,7 @@ pub mod tree;
|
||||||
use self::{
|
use self::{
|
||||||
air::Air,
|
air::Air,
|
||||||
builder::{
|
builder::{
|
||||||
air_holds_msg, cast_validator_args, constants_ir, convert_type_to_data, extract_constant,
|
cast_validator_args, constants_ir, convert_type_to_data, extract_constant,
|
||||||
modify_cyclic_calls, modify_self_calls, rearrange_list_clauses, AssignmentProperties,
|
modify_cyclic_calls, modify_self_calls, rearrange_list_clauses, AssignmentProperties,
|
||||||
ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames, HoistableFunction, Variant,
|
ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames, HoistableFunction, Variant,
|
||||||
},
|
},
|
||||||
|
@ -42,6 +42,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use petgraph::{algo, Graph};
|
use petgraph::{algo, Graph};
|
||||||
use std::{collections::HashMap, rc::Rc};
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType},
|
ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType},
|
||||||
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST},
|
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST},
|
||||||
|
@ -258,18 +259,23 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let air_value = self.build(value, module_build_name, &[]);
|
let air_value = self.build(value, module_build_name, &[]);
|
||||||
|
|
||||||
let msg_func = match self.tracing {
|
let otherwise = match (self.tracing, kind) {
|
||||||
TraceLevel::Silent => None,
|
(
|
||||||
TraceLevel::Verbose | TraceLevel::Compact => {
|
TraceLevel::Silent,
|
||||||
if kind.is_expect() {
|
AssignmentKind::Let { .. } | AssignmentKind::Expect { .. },
|
||||||
|
) => AirTree::error(void(), false),
|
||||||
|
|
||||||
|
(TraceLevel::Compact | TraceLevel::Verbose, AssignmentKind::Let { .. }) => {
|
||||||
|
AirTree::error(void(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
(TraceLevel::Verbose | TraceLevel::Compact, AssignmentKind::Expect { .. }) => {
|
||||||
let msg = match self.tracing {
|
let msg = match self.tracing {
|
||||||
TraceLevel::Silent => unreachable!("excluded from pattern guards"),
|
TraceLevel::Silent => unreachable!("excluded from pattern guards"),
|
||||||
TraceLevel::Compact => get_line_columns_by_span(
|
TraceLevel::Compact => {
|
||||||
module_build_name,
|
get_line_columns_by_span(module_build_name, location, &self.module_src)
|
||||||
location,
|
.to_string()
|
||||||
&self.module_src,
|
}
|
||||||
)
|
|
||||||
.to_string(),
|
|
||||||
TraceLevel::Verbose => {
|
TraceLevel::Verbose => {
|
||||||
get_src_code_by_span(module_build_name, location, &self.module_src)
|
get_src_code_by_span(module_build_name, location, &self.module_src)
|
||||||
}
|
}
|
||||||
|
@ -283,10 +289,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
string(),
|
string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(self.special_functions.use_function_msg(msg_func_name))
|
let msg_string =
|
||||||
} else {
|
AirTree::string(self.special_functions.use_function_string(msg_func_name));
|
||||||
None
|
|
||||||
}
|
AirTree::trace(msg_string, void(), AirTree::error(void(), false))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -304,7 +310,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: *kind,
|
kind: *kind,
|
||||||
remove_unused: kind.is_let(),
|
remove_unused: kind.is_let(),
|
||||||
full_check: !tipo.is_data() && value.tipo().is_data() && kind.is_expect(),
|
full_check: !tipo.is_data() && value.tipo().is_data() && kind.is_expect(),
|
||||||
msg_func,
|
otherwise,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -574,7 +580,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: AssignmentKind::let_(),
|
kind: AssignmentKind::let_(),
|
||||||
remove_unused: false,
|
remove_unused: false,
|
||||||
full_check: false,
|
full_check: false,
|
||||||
msg_func: None,
|
otherwise: AirTree::error(void(), false),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -625,24 +631,39 @@ impl<'a> CodeGenerator<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// let pattern = branch.condition
|
||||||
|
// branch.body
|
||||||
|
//
|
||||||
|
// if <expr:condition> is <pattern>: <annotation> { <expr:body> }
|
||||||
|
// [(builtin ifThenElse) (condition is pattern) (body) (else) ]
|
||||||
TypedExpr::If {
|
TypedExpr::If {
|
||||||
branches,
|
branches,
|
||||||
final_else,
|
final_else,
|
||||||
tipo,
|
tipo,
|
||||||
..
|
..
|
||||||
} => AirTree::if_branches(
|
} => branches.iter().rfold(
|
||||||
branches
|
|
||||||
.iter()
|
|
||||||
.map(|branch| {
|
|
||||||
(
|
|
||||||
self.build(&branch.condition, module_build_name, &[]),
|
|
||||||
self.build(&branch.body, module_build_name, &[]),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect_vec(),
|
|
||||||
tipo.clone(),
|
|
||||||
self.build(final_else, module_build_name, &[]),
|
self.build(final_else, module_build_name, &[]),
|
||||||
|
|acc, branch| {
|
||||||
|
let condition = self.build(&branch.condition, module_build_name, &[]);
|
||||||
|
let body = self.build(&branch.body, module_build_name, &[]);
|
||||||
|
|
||||||
|
match &branch.is {
|
||||||
|
Some(pattern) => self.assignment(
|
||||||
|
pattern,
|
||||||
|
condition,
|
||||||
|
body,
|
||||||
|
&pattern.tipo(&branch.condition).unwrap(),
|
||||||
|
AssignmentProperties {
|
||||||
|
value_type: branch.condition.tipo(),
|
||||||
|
kind: AssignmentKind::Expect { backpassing: () },
|
||||||
|
remove_unused: false,
|
||||||
|
full_check: true,
|
||||||
|
otherwise: acc,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
None => AirTree::if_branch(tipo.clone(), condition, body, acc),
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
TypedExpr::RecordAccess {
|
TypedExpr::RecordAccess {
|
||||||
|
@ -878,7 +899,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
// Cast value to or from data so we don't have to worry from this point onward
|
// Cast value to or from data so we don't have to worry from this point onward
|
||||||
if props.value_type.is_data() && props.kind.is_expect() && !tipo.is_data() {
|
if props.value_type.is_data() && props.kind.is_expect() && !tipo.is_data() {
|
||||||
value = AirTree::cast_from_data(value, tipo.clone(), props.msg_func.clone());
|
value = AirTree::cast_from_data(value, tipo.clone(), props.otherwise.clone());
|
||||||
} else if !props.value_type.is_data() && tipo.is_data() {
|
} else if !props.value_type.is_data() && tipo.is_data() {
|
||||||
value = AirTree::cast_to_data(value, props.value_type.clone());
|
value = AirTree::cast_to_data(value, props.value_type.clone());
|
||||||
}
|
}
|
||||||
|
@ -906,7 +927,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let expr = AirTree::let_assignment(name, value, expect);
|
let expr = AirTree::let_assignment(name, value, expect);
|
||||||
|
|
||||||
AirTree::assert_bool(true, expr, props.msg_func.clone(), then)
|
AirTree::assert_bool(true, expr, then, props.otherwise.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
|
@ -925,7 +946,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
val,
|
val,
|
||||||
&mut index_map,
|
&mut index_map,
|
||||||
pattern.location(),
|
pattern.location(),
|
||||||
props.msg_func,
|
props.otherwise,
|
||||||
);
|
);
|
||||||
|
|
||||||
let assign_expect = AirTree::let_assignment("_", expect, then);
|
let assign_expect = AirTree::let_assignment("_", expect, then);
|
||||||
|
@ -965,7 +986,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
val,
|
val,
|
||||||
&mut index_map,
|
&mut index_map,
|
||||||
pattern.location(),
|
pattern.location(),
|
||||||
props.msg_func,
|
props.otherwise,
|
||||||
);
|
);
|
||||||
|
|
||||||
let assignment = AirTree::let_assignment("_", expect, then);
|
let assignment = AirTree::let_assignment("_", expect, then);
|
||||||
|
@ -975,7 +996,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} else if !props.remove_unused {
|
} else if !props.remove_unused {
|
||||||
AirTree::let_assignment(name, value, then)
|
AirTree::let_assignment(name, value, then)
|
||||||
} else {
|
} else {
|
||||||
AirTree::no_op(then)
|
then
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,7 +1046,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: props.kind,
|
kind: props.kind,
|
||||||
remove_unused: true,
|
remove_unused: true,
|
||||||
full_check: props.full_check,
|
full_check: props.full_check,
|
||||||
msg_func: props.msg_func.clone(),
|
otherwise: props.otherwise.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1073,7 +1094,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: props.kind,
|
kind: props.kind,
|
||||||
remove_unused: true,
|
remove_unused: true,
|
||||||
full_check: props.full_check,
|
full_check: props.full_check,
|
||||||
msg_func: props.msg_func.clone(),
|
otherwise: props.otherwise.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1088,20 +1109,20 @@ impl<'a> CodeGenerator<'a> {
|
||||||
elems.reverse();
|
elems.reverse();
|
||||||
|
|
||||||
if elements.is_empty() {
|
if elements.is_empty() {
|
||||||
AirTree::list_empty(value, props.msg_func, then)
|
AirTree::list_empty(value, then, props.otherwise.clone())
|
||||||
} else {
|
} else {
|
||||||
AirTree::list_access(
|
AirTree::list_access(
|
||||||
elems,
|
elems,
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
tail.is_some(),
|
tail.is_some(),
|
||||||
value,
|
value,
|
||||||
props.msg_func,
|
|
||||||
if props.full_check {
|
if props.full_check {
|
||||||
ExpectLevel::Full
|
ExpectLevel::Full
|
||||||
} else {
|
} else {
|
||||||
ExpectLevel::Items
|
ExpectLevel::Items
|
||||||
},
|
},
|
||||||
then,
|
then,
|
||||||
|
props.otherwise.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1164,7 +1185,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: props.kind,
|
kind: props.kind,
|
||||||
remove_unused: true,
|
remove_unused: true,
|
||||||
full_check: props.full_check,
|
full_check: props.full_check,
|
||||||
msg_func: props.msg_func.clone(),
|
otherwise: props.otherwise.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1190,11 +1211,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let local_value = AirTree::local_var(&constructor_name, tipo.clone());
|
let local_value = AirTree::local_var(&constructor_name, tipo.clone());
|
||||||
|
|
||||||
let then = {
|
let then = {
|
||||||
let (is_expect, msg) = if props.full_check {
|
|
||||||
(true, props.msg_func.clone())
|
|
||||||
} else {
|
|
||||||
(false, None)
|
|
||||||
};
|
|
||||||
assert!(fields.len() == 2);
|
assert!(fields.len() == 2);
|
||||||
|
|
||||||
AirTree::pair_access(
|
AirTree::pair_access(
|
||||||
|
@ -1208,9 +1224,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
local_value,
|
local_value,
|
||||||
msg,
|
props.full_check,
|
||||||
is_expect,
|
|
||||||
then,
|
then,
|
||||||
|
props.otherwise.clone(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1223,7 +1239,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} if tipo.is_bool() => {
|
} if tipo.is_bool() => {
|
||||||
assert!(props.kind.is_expect());
|
assert!(props.kind.is_expect());
|
||||||
|
|
||||||
AirTree::assert_bool(name == "True", value, props.msg_func, then)
|
AirTree::assert_bool(name == "True", value, then, props.otherwise.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::Constructor { .. } if tipo.is_void() => {
|
Pattern::Constructor { .. } if tipo.is_void() => {
|
||||||
|
@ -1308,7 +1324,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: props.kind,
|
kind: props.kind,
|
||||||
remove_unused: true,
|
remove_unused: true,
|
||||||
full_check: props.full_check,
|
full_check: props.full_check,
|
||||||
msg_func: props.msg_func.clone(),
|
otherwise: props.otherwise.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1336,12 +1352,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let then = if check_replaceable_opaque_type(tipo, &self.data_types) {
|
let then = if check_replaceable_opaque_type(tipo, &self.data_types) {
|
||||||
AirTree::let_assignment(&fields[0].1, local_value, then)
|
AirTree::let_assignment(&fields[0].1, local_value, then)
|
||||||
} else {
|
} else {
|
||||||
let (is_expect, msg) = if props.full_check {
|
AirTree::fields_expose(
|
||||||
(true, props.msg_func.clone())
|
fields,
|
||||||
} else {
|
local_value,
|
||||||
(false, None)
|
props.full_check,
|
||||||
};
|
then,
|
||||||
AirTree::fields_expose(fields, local_value, msg, is_expect, then)
|
props.otherwise.clone(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo)
|
let data_type = lookup_data_type_by_tipo(&self.data_types, tipo)
|
||||||
|
@ -1362,10 +1379,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::assert_constr_index(
|
AirTree::assert_constr_index(
|
||||||
index,
|
index,
|
||||||
AirTree::local_var(&constructor_name, tipo.clone()),
|
AirTree::local_var(&constructor_name, tipo.clone()),
|
||||||
props.msg_func,
|
|
||||||
then,
|
then,
|
||||||
|
props.otherwise.clone(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
assert!(data_type.constructors.len() == 1);
|
||||||
then
|
then
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1425,7 +1443,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: props.kind,
|
kind: props.kind,
|
||||||
remove_unused: true,
|
remove_unused: true,
|
||||||
full_check: props.full_check,
|
full_check: props.full_check,
|
||||||
msg_func: props.msg_func.clone(),
|
otherwise: props.otherwise.clone(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1439,15 +1457,16 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
fields.reverse();
|
fields.reverse();
|
||||||
|
|
||||||
let (is_expect, msg) = if props.full_check {
|
|
||||||
(true, props.msg_func)
|
|
||||||
} else {
|
|
||||||
(false, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// This `value` is either value param that was passed in or local var
|
// This `value` is either value param that was passed in or local var
|
||||||
|
|
||||||
AirTree::tuple_access(fields, tipo.clone(), value, msg, is_expect, then)
|
AirTree::tuple_access(
|
||||||
|
fields,
|
||||||
|
tipo.clone(),
|
||||||
|
value,
|
||||||
|
props.full_check,
|
||||||
|
then,
|
||||||
|
props.otherwise.clone(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1458,7 +1477,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
value: AirTree,
|
value: AirTree,
|
||||||
defined_data_types: &mut IndexMap<String, u64>,
|
defined_data_types: &mut IndexMap<String, u64>,
|
||||||
location: Span,
|
location: Span,
|
||||||
msg_func: Option<AirMsg>,
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
assert!(tipo.get_generic().is_none());
|
assert!(tipo.get_generic().is_none());
|
||||||
// Shouldn't be needed but still here just in case
|
// Shouldn't be needed but still here just in case
|
||||||
|
@ -1468,6 +1487,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
match uplc_type {
|
match uplc_type {
|
||||||
// primitives
|
// primitives
|
||||||
|
// Untyped Data
|
||||||
Some(
|
Some(
|
||||||
UplcType::Integer
|
UplcType::Integer
|
||||||
| UplcType::String
|
| UplcType::String
|
||||||
|
@ -1476,10 +1496,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
| UplcType::Unit
|
| UplcType::Unit
|
||||||
| UplcType::Bls12_381G1Element
|
| UplcType::Bls12_381G1Element
|
||||||
| UplcType::Bls12_381G2Element
|
| UplcType::Bls12_381G2Element
|
||||||
| UplcType::Bls12_381MlResult,
|
| UplcType::Bls12_381MlResult
|
||||||
|
| UplcType::Data,
|
||||||
) => value,
|
) => value,
|
||||||
// Untyped Data
|
|
||||||
Some(UplcType::Data) => value,
|
|
||||||
|
|
||||||
// Map type
|
// Map type
|
||||||
Some(UplcType::List(_)) if tipo.is_map() => {
|
Some(UplcType::List(_)) if tipo.is_map() => {
|
||||||
|
@ -1500,7 +1519,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::local_var(fst_name.clone(), inner_pair_types[0].clone()),
|
AirTree::local_var(fst_name.clone(), inner_pair_types[0].clone()),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_func.clone(),
|
otherwise.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let expect_snd = self.expect_type_assign(
|
let expect_snd = self.expect_type_assign(
|
||||||
|
@ -1508,7 +1527,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::local_var(snd_name.clone(), inner_pair_types[1].clone()),
|
AirTree::local_var(snd_name.clone(), inner_pair_types[1].clone()),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_func.clone(),
|
otherwise.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let anon_func_body = AirTree::pair_access(
|
let anon_func_body = AirTree::pair_access(
|
||||||
|
@ -1516,9 +1535,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Some(snd_name),
|
Some(snd_name),
|
||||||
inner_list_type.clone(),
|
inner_list_type.clone(),
|
||||||
AirTree::local_var(&pair_name, inner_list_type.clone()),
|
AirTree::local_var(&pair_name, inner_list_type.clone()),
|
||||||
msg_func.clone(),
|
|
||||||
true,
|
true,
|
||||||
AirTree::let_assignment("_", expect_fst, expect_snd),
|
AirTree::let_assignment("_", expect_fst, expect_snd),
|
||||||
|
otherwise.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body);
|
let unwrap_function = AirTree::anon_func(vec![pair_name], anon_func_body);
|
||||||
|
@ -1587,7 +1606,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::local_var(&tuple_index_name, arg.clone()),
|
AirTree::local_var(&tuple_index_name, arg.clone()),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_func.clone(),
|
otherwise.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
tuple_expect_items.push(tuple_index_name);
|
tuple_expect_items.push(tuple_index_name);
|
||||||
|
@ -1602,9 +1621,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
tuple_expect_items,
|
tuple_expect_items,
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
AirTree::local_var(&tuple_name, tipo.clone()),
|
AirTree::local_var(&tuple_name, tipo.clone()),
|
||||||
msg_func,
|
|
||||||
true,
|
true,
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
);
|
);
|
||||||
|
|
||||||
AirTree::let_assignment(&tuple_name, value, tuple_access)
|
AirTree::let_assignment(&tuple_name, value, tuple_access)
|
||||||
|
@ -1626,11 +1645,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::cast_from_data(
|
AirTree::cast_from_data(
|
||||||
AirTree::local_var(&item_name, data()),
|
AirTree::local_var(&item_name, data()),
|
||||||
inner_list_type.clone(),
|
inner_list_type.clone(),
|
||||||
msg_func.clone(),
|
otherwise.clone(),
|
||||||
),
|
),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_func,
|
otherwise,
|
||||||
);
|
);
|
||||||
|
|
||||||
let anon_func_body = expect_item;
|
let anon_func_body = expect_item;
|
||||||
|
@ -1701,7 +1720,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::local_var(fst_name.clone(), tuple_inner_types[0].clone()),
|
AirTree::local_var(fst_name.clone(), tuple_inner_types[0].clone()),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_func.clone(),
|
otherwise.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let expect_snd = self.expect_type_assign(
|
let expect_snd = self.expect_type_assign(
|
||||||
|
@ -1709,7 +1728,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::local_var(snd_name.clone(), tuple_inner_types[1].clone()),
|
AirTree::local_var(snd_name.clone(), tuple_inner_types[1].clone()),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_func.clone(),
|
otherwise.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let pair_access = AirTree::pair_access(
|
let pair_access = AirTree::pair_access(
|
||||||
|
@ -1717,9 +1736,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Some(snd_name.clone()),
|
Some(snd_name.clone()),
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
AirTree::local_var(&pair_name, tipo.clone()),
|
AirTree::local_var(&pair_name, tipo.clone()),
|
||||||
msg_func.clone(),
|
|
||||||
true,
|
true,
|
||||||
AirTree::let_assignment("_", expect_fst, expect_snd),
|
AirTree::let_assignment("_", expect_fst, expect_snd),
|
||||||
|
otherwise,
|
||||||
);
|
);
|
||||||
|
|
||||||
AirTree::let_assignment(&pair_name, value, pair_access)
|
AirTree::let_assignment(&pair_name, value, pair_access)
|
||||||
|
@ -1800,7 +1819,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::local_var(arg_name, arg_tipo),
|
AirTree::local_var(arg_name, arg_tipo),
|
||||||
defined_data_types,
|
defined_data_types,
|
||||||
location,
|
location,
|
||||||
msg_term.clone(),
|
otherwise.clone(),
|
||||||
),
|
),
|
||||||
then,
|
then,
|
||||||
)
|
)
|
||||||
|
@ -1830,9 +1849,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
),
|
),
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
),
|
),
|
||||||
msg_term.clone(),
|
|
||||||
true,
|
true,
|
||||||
constr_then,
|
constr_then,
|
||||||
|
otherwise.clone(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1895,12 +1914,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let args = match self.tracing {
|
let args = match self.tracing {
|
||||||
TraceLevel::Silent => vec![value],
|
TraceLevel::Silent => vec![value],
|
||||||
TraceLevel::Compact | TraceLevel::Verbose => vec![
|
TraceLevel::Compact | TraceLevel::Verbose => vec![value, otherwise],
|
||||||
value,
|
|
||||||
msg_func
|
|
||||||
.expect("should be unreachable: no msg func with tracing enabled.")
|
|
||||||
.to_air_tree(),
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let module_fn = ValueConstructorVariant::ModuleFn {
|
let module_fn = ValueConstructorVariant::ModuleFn {
|
||||||
|
@ -2459,9 +2473,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
// One special usage of list access here
|
// One special usage of list access here
|
||||||
// So for the msg we pass in empty string if tracing is on
|
// So for the msg we pass in empty string if tracing is on
|
||||||
// Since check_last_item is false this will never get added to the final uplc anyway
|
// Since check_last_item is false this will never get added to the final uplc anyway
|
||||||
None,
|
|
||||||
ExpectLevel::None,
|
ExpectLevel::None,
|
||||||
elems_then,
|
elems_then,
|
||||||
|
AirTree::error(void(), false),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
assert!(defined_tails.len() >= elems.len());
|
assert!(defined_tails.len() >= elems.len());
|
||||||
|
@ -2540,9 +2554,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
name_index_assigns[1].0.clone(),
|
name_index_assigns[1].0.clone(),
|
||||||
subject_tipo.clone(),
|
subject_tipo.clone(),
|
||||||
AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
|
AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
|
||||||
None,
|
|
||||||
false,
|
false,
|
||||||
next_then,
|
next_then,
|
||||||
|
AirTree::error(void(), false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2667,9 +2681,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AirTree::fields_expose(
|
AirTree::fields_expose(
|
||||||
fields,
|
fields,
|
||||||
AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
|
AirTree::local_var(props.clause_var_name.clone(), subject_tipo.clone()),
|
||||||
None,
|
|
||||||
false,
|
false,
|
||||||
next_then,
|
next_then,
|
||||||
|
AirTree::error(void(), false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2796,9 +2810,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
names,
|
names,
|
||||||
subject_tipo.clone(),
|
subject_tipo.clone(),
|
||||||
AirTree::local_var(&props.clause_var_name, subject_tipo.clone()),
|
AirTree::local_var(&props.clause_var_name, subject_tipo.clone()),
|
||||||
None,
|
|
||||||
false,
|
false,
|
||||||
tuple_name_assigns,
|
tuple_name_assigns,
|
||||||
|
AirTree::error(void(), false),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -3034,8 +3048,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let actual_type = convert_opaque_type(&arg.tipo, &self.data_types, true);
|
let actual_type = convert_opaque_type(&arg.tipo, &self.data_types, true);
|
||||||
|
|
||||||
let msg_func = match self.tracing {
|
let otherwise = match self.tracing {
|
||||||
TraceLevel::Silent => None,
|
TraceLevel::Silent => AirTree::error(void(), false),
|
||||||
TraceLevel::Compact | TraceLevel::Verbose => {
|
TraceLevel::Compact | TraceLevel::Verbose => {
|
||||||
let msg = match self.tracing {
|
let msg = match self.tracing {
|
||||||
TraceLevel::Silent => {
|
TraceLevel::Silent => {
|
||||||
|
@ -3059,7 +3073,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
string(),
|
string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Some(self.special_functions.use_function_msg(msg_func_name))
|
let msg_string = AirTree::string(
|
||||||
|
self.special_functions.use_function_string(msg_func_name),
|
||||||
|
);
|
||||||
|
|
||||||
|
AirTree::trace(msg_string, void(), AirTree::error(void(), false))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3076,7 +3094,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
kind: AssignmentKind::expect(),
|
kind: AssignmentKind::expect(),
|
||||||
remove_unused: false,
|
remove_unused: false,
|
||||||
full_check: true,
|
full_check: true,
|
||||||
msg_func,
|
otherwise,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4017,24 +4035,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_uplc(&mut self, ir: Air, arg_stack: &mut Vec<Term<Name>>) -> Option<Term<Name>> {
|
fn gen_uplc(&mut self, ir: Air, arg_stack: &mut Vec<Term<Name>>) -> Option<Term<Name>> {
|
||||||
// Going to mark the changes made to code gen after air tree implementation
|
let convert_data_to_type = |term, tipo, otherwise| {
|
||||||
let error_term = match self.tracing {
|
if otherwise == Term::Error {
|
||||||
TraceLevel::Silent => Term::Error,
|
|
||||||
TraceLevel::Compact | TraceLevel::Verbose => {
|
|
||||||
if air_holds_msg(&ir) {
|
|
||||||
let msg = arg_stack.pop().unwrap();
|
|
||||||
Term::Error.delayed_trace(msg)
|
|
||||||
} else {
|
|
||||||
Term::Error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let convert_data_to_type = |term, tipo| {
|
|
||||||
if error_term == Term::Error {
|
|
||||||
builder::unknown_data_to_type(term, tipo)
|
builder::unknown_data_to_type(term, tipo)
|
||||||
} else {
|
} else {
|
||||||
builder::unknown_data_to_type_debug(term, tipo, error_term.clone())
|
builder::unknown_data_to_type_otherwise(term, tipo, otherwise)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4337,6 +4342,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
let otherwise = if matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) {
|
||||||
|
arg_stack.pop().unwrap()
|
||||||
|
} else {
|
||||||
|
Term::Error
|
||||||
|
};
|
||||||
|
|
||||||
let list_id = self.id_gen.next();
|
let list_id = self.id_gen.next();
|
||||||
|
|
||||||
let mut id_list = vec![];
|
let mut id_list = vec![];
|
||||||
|
@ -4362,7 +4373,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
term,
|
term,
|
||||||
true,
|
true,
|
||||||
expect_level,
|
expect_level,
|
||||||
error_term,
|
otherwise,
|
||||||
)
|
)
|
||||||
.apply(value);
|
.apply(value);
|
||||||
|
|
||||||
|
@ -4774,8 +4785,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
Air::CastFromData { tipo, .. } => {
|
Air::CastFromData { tipo, .. } => {
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
term = convert_data_to_type(term, &tipo);
|
term = convert_data_to_type(term, &tipo, otherwise);
|
||||||
|
|
||||||
if extract_constant(&term).is_some() {
|
if extract_constant(&term).is_some() {
|
||||||
let mut program: Program<Name> = Program {
|
let mut program: Program<Name> = Program {
|
||||||
|
@ -4834,6 +4846,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let constr = arg_stack.pop().unwrap();
|
let constr = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
term = Term::equals_integer()
|
term = Term::equals_integer()
|
||||||
.apply(Term::integer(constr_index.into()))
|
.apply(Term::integer(constr_index.into()))
|
||||||
|
@ -4844,7 +4857,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
)
|
)
|
||||||
.apply(constr),
|
.apply(constr),
|
||||||
)
|
)
|
||||||
.delayed_if_then_else(term, error_term);
|
.delayed_if_then_else(term, otherwise);
|
||||||
|
|
||||||
Some(term)
|
Some(term)
|
||||||
}
|
}
|
||||||
|
@ -4852,11 +4865,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let value = arg_stack.pop().unwrap();
|
let value = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
if is_true {
|
if is_true {
|
||||||
term = value.delayed_if_then_else(term, error_term)
|
term = value.delayed_if_then_else(term, otherwise)
|
||||||
} else {
|
} else {
|
||||||
term = value.delayed_if_then_else(error_term, term)
|
term = value.delayed_if_then_else(otherwise, term)
|
||||||
}
|
}
|
||||||
Some(term)
|
Some(term)
|
||||||
}
|
}
|
||||||
|
@ -5286,6 +5300,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let value = arg_stack.pop().unwrap();
|
let value = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
let otherwise = if is_expect {
|
||||||
|
arg_stack.pop().unwrap()
|
||||||
|
} else {
|
||||||
|
Term::Error
|
||||||
|
};
|
||||||
|
|
||||||
let list_id = self.id_gen.next();
|
let list_id = self.id_gen.next();
|
||||||
|
|
||||||
id_list.push(list_id);
|
id_list.push(list_id);
|
||||||
|
@ -5313,7 +5334,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
term,
|
term,
|
||||||
false,
|
false,
|
||||||
is_expect.into(),
|
is_expect.into(),
|
||||||
error_term,
|
otherwise,
|
||||||
);
|
);
|
||||||
|
|
||||||
term = term.apply(
|
term = term.apply(
|
||||||
|
@ -5333,13 +5354,14 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let value = arg_stack.pop().unwrap();
|
let value = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
term = Term::var(
|
term = Term::var(
|
||||||
self.special_functions
|
self.special_functions
|
||||||
.use_function_uplc(CONSTR_FIELDS_EXPOSER.to_string()),
|
.use_function_uplc(CONSTR_FIELDS_EXPOSER.to_string()),
|
||||||
)
|
)
|
||||||
.apply(value)
|
.apply(value)
|
||||||
.delayed_choose_list(term, error_term);
|
.delayed_choose_list(term, otherwise);
|
||||||
|
|
||||||
Some(term)
|
Some(term)
|
||||||
}
|
}
|
||||||
|
@ -5347,8 +5369,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let value = arg_stack.pop().unwrap();
|
let value = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
term = value.delayed_choose_list(term, error_term);
|
term = value.delayed_choose_list(term, otherwise);
|
||||||
|
|
||||||
Some(term)
|
Some(term)
|
||||||
}
|
}
|
||||||
|
@ -5545,6 +5568,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let value = arg_stack.pop().unwrap();
|
let value = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = if is_expect {
|
||||||
|
arg_stack.pop().unwrap()
|
||||||
|
} else {
|
||||||
|
Term::Error
|
||||||
|
};
|
||||||
let list_id = self.id_gen.next();
|
let list_id = self.id_gen.next();
|
||||||
|
|
||||||
let mut id_list = vec![];
|
let mut id_list = vec![];
|
||||||
|
@ -5567,7 +5595,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
term,
|
term,
|
||||||
false,
|
false,
|
||||||
is_expect.into(),
|
is_expect.into(),
|
||||||
error_term,
|
otherwise,
|
||||||
)
|
)
|
||||||
.apply(value);
|
.apply(value);
|
||||||
|
|
||||||
|
@ -5583,6 +5611,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let value = arg_stack.pop().unwrap();
|
let value = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
let mut term = arg_stack.pop().unwrap();
|
||||||
|
let otherwise = if is_expect {
|
||||||
|
arg_stack.pop().unwrap()
|
||||||
|
} else {
|
||||||
|
Term::Error
|
||||||
|
};
|
||||||
|
|
||||||
let list_id = self.id_gen.next();
|
let list_id = self.id_gen.next();
|
||||||
|
|
||||||
if let Some(name) = snd {
|
if let Some(name) = snd {
|
||||||
|
@ -5590,6 +5624,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
convert_data_to_type(
|
convert_data_to_type(
|
||||||
Term::snd_pair().apply(Term::var(format!("__pair_{list_id}"))),
|
Term::snd_pair().apply(Term::var(format!("__pair_{list_id}"))),
|
||||||
&inner_types[1],
|
&inner_types[1],
|
||||||
|
otherwise.clone(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
known_data_to_type(
|
known_data_to_type(
|
||||||
|
@ -5604,6 +5639,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
convert_data_to_type(
|
convert_data_to_type(
|
||||||
Term::fst_pair().apply(Term::var(format!("__pair_{list_id}"))),
|
Term::fst_pair().apply(Term::var(format!("__pair_{list_id}"))),
|
||||||
&inner_types[0],
|
&inner_types[0],
|
||||||
|
otherwise,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
known_data_to_type(
|
known_data_to_type(
|
||||||
|
|
|
@ -102,7 +102,6 @@ pub enum Air {
|
||||||
},
|
},
|
||||||
CastFromData {
|
CastFromData {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
is_expect: bool,
|
|
||||||
},
|
},
|
||||||
CastToData {
|
CastToData {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{
|
use super::{
|
||||||
air::{Air, ExpectLevel},
|
air::ExpectLevel,
|
||||||
tree::{AirMsg, AirTree, TreePath},
|
tree::{AirMsg, AirTree, TreePath},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -71,7 +71,7 @@ pub struct AssignmentProperties {
|
||||||
pub kind: TypedAssignmentKind,
|
pub kind: TypedAssignmentKind,
|
||||||
pub remove_unused: bool,
|
pub remove_unused: bool,
|
||||||
pub full_check: bool,
|
pub full_check: bool,
|
||||||
pub msg_func: Option<AirMsg>,
|
pub otherwise: AirTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -233,6 +233,14 @@ impl CodeGenSpecialFuncs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn use_function_string(&mut self, func_name: String) -> String {
|
||||||
|
if !self.used_funcs.contains(&func_name) {
|
||||||
|
self.used_funcs.push(func_name.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
func_name
|
||||||
|
}
|
||||||
|
|
||||||
pub fn use_function_tree(&mut self, func_name: String) -> AirTree {
|
pub fn use_function_tree(&mut self, func_name: String) -> AirTree {
|
||||||
if !self.used_funcs.contains(&func_name) {
|
if !self.used_funcs.contains(&func_name) {
|
||||||
self.used_funcs.push(func_name.to_string());
|
self.used_funcs.push(func_name.to_string());
|
||||||
|
@ -1035,7 +1043,7 @@ pub fn unknown_data_to_type(term: Term<Name>, field_type: &Type) -> Term<Name> {
|
||||||
/// Due to the nature of the types BLS12_381_G1Element and BLS12_381_G2Element and String coming from bytearray
|
/// Due to the nature of the types BLS12_381_G1Element and BLS12_381_G2Element and String coming from bytearray
|
||||||
/// We don't have error handling if the bytearray is not properly aligned to the type. Oh well lol
|
/// We don't have error handling if the bytearray is not properly aligned to the type. Oh well lol
|
||||||
/// For BLS12_381_G1Element and BLS12_381_G2Element, hash to group exists so just adopt that.
|
/// For BLS12_381_G1Element and BLS12_381_G2Element, hash to group exists so just adopt that.
|
||||||
pub fn unknown_data_to_type_debug(
|
pub fn unknown_data_to_type_otherwise(
|
||||||
term: Term<Name>,
|
term: Term<Name>,
|
||||||
field_type: &Type,
|
field_type: &Type,
|
||||||
error_term: Term<Name>,
|
error_term: Term<Name>,
|
||||||
|
@ -1362,7 +1370,7 @@ pub fn list_access_to_uplc(
|
||||||
term: Term<Name>,
|
term: Term<Name>,
|
||||||
is_list_accessor: bool,
|
is_list_accessor: bool,
|
||||||
expect_level: ExpectLevel,
|
expect_level: ExpectLevel,
|
||||||
error_term: Term<Name>,
|
otherwise: Term<Name>,
|
||||||
) -> Term<Name> {
|
) -> Term<Name> {
|
||||||
let names_len = names_types_ids.len();
|
let names_len = names_types_ids.len();
|
||||||
|
|
||||||
|
@ -1393,7 +1401,7 @@ pub fn list_access_to_uplc(
|
||||||
}
|
}
|
||||||
|
|
||||||
return Term::var("empty_list")
|
return Term::var("empty_list")
|
||||||
.delayed_choose_list(term, error_term)
|
.delayed_choose_list(term, otherwise)
|
||||||
.lambda("empty_list");
|
.lambda("empty_list");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1412,16 +1420,16 @@ pub fn list_access_to_uplc(
|
||||||
Term::head_list().apply(Term::var(tail_name.to_string()))
|
Term::head_list().apply(Term::var(tail_name.to_string()))
|
||||||
} else if matches!(expect_level, ExpectLevel::Full) {
|
} else if matches!(expect_level, ExpectLevel::Full) {
|
||||||
// Expect level is full so we have an unknown piece of data to cast
|
// Expect level is full so we have an unknown piece of data to cast
|
||||||
if error_term == Term::Error {
|
if otherwise == Term::Error {
|
||||||
unknown_data_to_type(
|
unknown_data_to_type(
|
||||||
Term::head_list().apply(Term::var(tail_name.to_string())),
|
Term::head_list().apply(Term::var(tail_name.to_string())),
|
||||||
&tipo.to_owned(),
|
&tipo.to_owned(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
unknown_data_to_type_debug(
|
unknown_data_to_type_otherwise(
|
||||||
Term::head_list().apply(Term::var(tail_name.to_string())),
|
Term::head_list().apply(Term::var(tail_name.to_string())),
|
||||||
&tipo.to_owned(),
|
&tipo.to_owned(),
|
||||||
error_term.clone(),
|
otherwise.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1456,22 +1464,22 @@ pub fn list_access_to_uplc(
|
||||||
ExpectLevel::None => acc.lambda(name).apply(head_item).lambda(tail_name),
|
ExpectLevel::None => acc.lambda(name).apply(head_item).lambda(tail_name),
|
||||||
|
|
||||||
ExpectLevel::Full | ExpectLevel::Items => {
|
ExpectLevel::Full | ExpectLevel::Items => {
|
||||||
if error_term == Term::Error && tail_present {
|
if otherwise == Term::Error && tail_present {
|
||||||
// No need to check last item if tail was present
|
// No need to check last item if tail was present
|
||||||
acc.lambda(name).apply(head_item).lambda(tail_name)
|
acc.lambda(name).apply(head_item).lambda(tail_name)
|
||||||
} else if tail_present {
|
} else if tail_present {
|
||||||
// Custom error instead of trying to do head_item on a possibly empty list.
|
// Custom error instead of trying to do head_item on a possibly empty list.
|
||||||
Term::var(tail_name.to_string())
|
Term::var(tail_name.to_string())
|
||||||
.delayed_choose_list(
|
.delayed_choose_list(
|
||||||
error_term.clone(),
|
otherwise.clone(),
|
||||||
acc.lambda(name).apply(head_item),
|
acc.lambda(name).apply(head_item),
|
||||||
)
|
)
|
||||||
.lambda(tail_name)
|
.lambda(tail_name)
|
||||||
} else if error_term == Term::Error {
|
} else if otherwise == Term::Error {
|
||||||
// Check head is last item in this list
|
// Check head is last item in this list
|
||||||
Term::tail_list()
|
Term::tail_list()
|
||||||
.apply(Term::var(tail_name.to_string()))
|
.apply(Term::var(tail_name.to_string()))
|
||||||
.delayed_choose_list(acc, error_term.clone())
|
.delayed_choose_list(acc, otherwise.clone())
|
||||||
.lambda(name)
|
.lambda(name)
|
||||||
.apply(head_item)
|
.apply(head_item)
|
||||||
.lambda(tail_name)
|
.lambda(tail_name)
|
||||||
|
@ -1479,10 +1487,10 @@ pub fn list_access_to_uplc(
|
||||||
// Custom error if list is not empty after this head
|
// Custom error if list is not empty after this head
|
||||||
Term::var(tail_name.to_string())
|
Term::var(tail_name.to_string())
|
||||||
.delayed_choose_list(
|
.delayed_choose_list(
|
||||||
error_term.clone(),
|
otherwise.clone(),
|
||||||
Term::tail_list()
|
Term::tail_list()
|
||||||
.apply(Term::var(tail_name.to_string()))
|
.apply(Term::var(tail_name.to_string()))
|
||||||
.delayed_choose_list(acc, error_term.clone())
|
.delayed_choose_list(acc, otherwise.clone())
|
||||||
.lambda(name)
|
.lambda(name)
|
||||||
.apply(head_item),
|
.apply(head_item),
|
||||||
)
|
)
|
||||||
|
@ -1498,7 +1506,7 @@ pub fn list_access_to_uplc(
|
||||||
|
|
||||||
let head_item = head_item(name, tipo, &tail_name);
|
let head_item = head_item(name, tipo, &tail_name);
|
||||||
|
|
||||||
if matches!(expect_level, ExpectLevel::None) || error_term == Term::Error {
|
if matches!(expect_level, ExpectLevel::None) || otherwise == Term::Error {
|
||||||
acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string())))
|
acc.apply(Term::tail_list().apply(Term::var(tail_name.to_string())))
|
||||||
.lambda(name)
|
.lambda(name)
|
||||||
.apply(head_item)
|
.apply(head_item)
|
||||||
|
@ -1507,7 +1515,7 @@ pub fn list_access_to_uplc(
|
||||||
// case for a custom error if the list is empty at this point
|
// case for a custom error if the list is empty at this point
|
||||||
Term::var(tail_name.to_string())
|
Term::var(tail_name.to_string())
|
||||||
.delayed_choose_list(
|
.delayed_choose_list(
|
||||||
error_term.clone(),
|
otherwise.clone(),
|
||||||
acc.apply(
|
acc.apply(
|
||||||
Term::tail_list().apply(Term::var(tail_name.to_string())),
|
Term::tail_list().apply(Term::var(tail_name.to_string())),
|
||||||
)
|
)
|
||||||
|
@ -1778,7 +1786,6 @@ pub fn cast_validator_args(term: Term<Name>, arguments: &[TypedArg]) -> Term<Nam
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree {
|
pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree {
|
||||||
let success_branch = vec![(air_tree, AirTree::void())];
|
|
||||||
let otherwise = match trace {
|
let otherwise = match trace {
|
||||||
TraceLevel::Silent | TraceLevel::Compact => AirTree::error(void(), true),
|
TraceLevel::Silent | TraceLevel::Compact => AirTree::error(void(), true),
|
||||||
TraceLevel::Verbose => AirTree::trace(
|
TraceLevel::Verbose => AirTree::trace(
|
||||||
|
@ -1788,7 +1795,7 @@ pub fn wrap_validator_condition(air_tree: AirTree, trace: TraceLevel) -> AirTree
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
AirTree::if_branches(success_branch, void(), otherwise)
|
AirTree::if_branch(void(), air_tree, AirTree::void(), otherwise)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_constant(term: &Term<Name>) -> Option<Rc<UplcConstant>> {
|
pub fn extract_constant(term: &Term<Name>) -> Option<Rc<UplcConstant>> {
|
||||||
|
@ -1841,22 +1848,3 @@ pub fn get_line_columns_by_span(
|
||||||
.line_and_column_number(span.start)
|
.line_and_column_number(span.start)
|
||||||
.expect("Out of bounds span")
|
.expect("Out of bounds span")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn air_holds_msg(air: &Air) -> bool {
|
|
||||||
match air {
|
|
||||||
Air::AssertConstr { .. } | Air::AssertBool { .. } | Air::FieldsEmpty | Air::ListEmpty => {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
Air::FieldsExpose { is_expect, .. }
|
|
||||||
| Air::TupleAccessor { is_expect, .. }
|
|
||||||
| Air::PairAccessor { is_expect, .. }
|
|
||||||
| Air::CastFromData { is_expect, .. } => *is_expect,
|
|
||||||
|
|
||||||
Air::ListAccessor { expect_level, .. } => {
|
|
||||||
matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -133,14 +133,14 @@ pub enum AirTree {
|
||||||
AssertConstr {
|
AssertConstr {
|
||||||
constr_index: usize,
|
constr_index: usize,
|
||||||
constr: Box<AirTree>,
|
constr: Box<AirTree>,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
AssertBool {
|
AssertBool {
|
||||||
is_true: bool,
|
is_true: bool,
|
||||||
value: Box<AirTree>,
|
value: Box<AirTree>,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
// Clause Guards
|
// Clause Guards
|
||||||
ClauseGuard {
|
ClauseGuard {
|
||||||
|
@ -174,8 +174,8 @@ pub enum AirTree {
|
||||||
indices: Vec<(usize, String, Rc<Type>)>,
|
indices: Vec<(usize, String, Rc<Type>)>,
|
||||||
record: Box<AirTree>,
|
record: Box<AirTree>,
|
||||||
is_expect: bool,
|
is_expect: bool,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
// List Access
|
// List Access
|
||||||
ListAccessor {
|
ListAccessor {
|
||||||
|
@ -184,8 +184,8 @@ pub enum AirTree {
|
||||||
tail: bool,
|
tail: bool,
|
||||||
list: Box<AirTree>,
|
list: Box<AirTree>,
|
||||||
expect_level: ExpectLevel,
|
expect_level: ExpectLevel,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
ListExpose {
|
ListExpose {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
|
@ -199,8 +199,8 @@ pub enum AirTree {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
tuple: Box<AirTree>,
|
tuple: Box<AirTree>,
|
||||||
is_expect: bool,
|
is_expect: bool,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
// Pair Access
|
// Pair Access
|
||||||
PairAccessor {
|
PairAccessor {
|
||||||
|
@ -208,9 +208,9 @@ pub enum AirTree {
|
||||||
snd: Option<String>,
|
snd: Option<String>,
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
is_expect: bool,
|
is_expect: bool,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
pair: Box<AirTree>,
|
pair: Box<AirTree>,
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
// Misc.
|
// Misc.
|
||||||
FieldsEmpty {
|
FieldsEmpty {
|
||||||
|
@ -220,8 +220,8 @@ pub enum AirTree {
|
||||||
},
|
},
|
||||||
ListEmpty {
|
ListEmpty {
|
||||||
list: Box<AirTree>,
|
list: Box<AirTree>,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
NoOp {
|
NoOp {
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
|
@ -297,7 +297,7 @@ pub enum AirTree {
|
||||||
CastFromData {
|
CastFromData {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
value: Box<AirTree>,
|
value: Box<AirTree>,
|
||||||
msg: Option<AirMsg>,
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
CastToData {
|
CastToData {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
|
@ -359,7 +359,7 @@ pub enum AirTree {
|
||||||
// If
|
// If
|
||||||
If {
|
If {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
pattern: Box<AirTree>,
|
condition: Box<AirTree>,
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
otherwise: Box<AirTree>,
|
otherwise: Box<AirTree>,
|
||||||
},
|
},
|
||||||
|
@ -390,6 +390,10 @@ pub enum AirTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AirTree {
|
impl AirTree {
|
||||||
|
pub fn is_error(&self) -> bool {
|
||||||
|
matches!(self, AirTree::ErrorTerm { .. })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn int(value: impl ToString) -> AirTree {
|
pub fn int(value: impl ToString) -> AirTree {
|
||||||
AirTree::Int {
|
AirTree::Int {
|
||||||
value: value.to_string(),
|
value: value.to_string(),
|
||||||
|
@ -562,11 +566,11 @@ impl AirTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cast_from_data(value: AirTree, tipo: Rc<Type>, msg: Option<AirMsg>) -> AirTree {
|
pub fn cast_from_data(value: AirTree, tipo: Rc<Type>, otherwise: AirTree) -> AirTree {
|
||||||
AirTree::CastFromData {
|
AirTree::CastFromData {
|
||||||
tipo,
|
tipo,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
msg,
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,28 +584,28 @@ impl AirTree {
|
||||||
pub fn assert_constr_index(
|
pub fn assert_constr_index(
|
||||||
constr_index: usize,
|
constr_index: usize,
|
||||||
constr: AirTree,
|
constr: AirTree,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::AssertConstr {
|
AirTree::AssertConstr {
|
||||||
constr_index,
|
constr_index,
|
||||||
constr: constr.into(),
|
constr: constr.into(),
|
||||||
msg,
|
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_bool(
|
pub fn assert_bool(
|
||||||
is_true: bool,
|
is_true: bool,
|
||||||
value: AirTree,
|
value: AirTree,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::AssertBool {
|
AirTree::AssertBool {
|
||||||
is_true,
|
is_true,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
msg,
|
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,31 +775,18 @@ impl AirTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn if_branches(
|
pub fn if_branch(
|
||||||
mut branches: Vec<(AirTree, AirTree)>,
|
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
|
condition: AirTree,
|
||||||
|
branch: AirTree,
|
||||||
otherwise: AirTree,
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
assert!(!branches.is_empty());
|
AirTree::If {
|
||||||
let last_if = branches.pop().unwrap();
|
tipo,
|
||||||
|
condition: condition.into(),
|
||||||
let mut final_if = AirTree::If {
|
then: branch.into(),
|
||||||
tipo: tipo.clone(),
|
|
||||||
pattern: Box::new(last_if.0),
|
|
||||||
then: Box::new(last_if.1),
|
|
||||||
otherwise: otherwise.into(),
|
otherwise: otherwise.into(),
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(branch) = branches.pop() {
|
|
||||||
final_if = AirTree::If {
|
|
||||||
tipo: tipo.clone(),
|
|
||||||
pattern: Box::new(branch.0),
|
|
||||||
then: Box::new(branch.1),
|
|
||||||
otherwise: final_if.into(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final_if
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_constr(tag: usize, tipo: Rc<Type>, args: Vec<AirTree>) -> AirTree {
|
pub fn create_constr(tag: usize, tipo: Rc<Type>, args: Vec<AirTree>) -> AirTree {
|
||||||
|
@ -845,23 +836,23 @@ impl AirTree {
|
||||||
vec![list_of_fields],
|
vec![list_of_fields],
|
||||||
),
|
),
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
None,
|
AirTree::error(void(), false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields_expose(
|
pub fn fields_expose(
|
||||||
indices: Vec<(usize, String, Rc<Type>)>,
|
indices: Vec<(usize, String, Rc<Type>)>,
|
||||||
record: AirTree,
|
record: AirTree,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
is_expect: bool,
|
is_expect: bool,
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::FieldsExpose {
|
AirTree::FieldsExpose {
|
||||||
indices,
|
indices,
|
||||||
record: record.into(),
|
record: record.into(),
|
||||||
msg,
|
|
||||||
is_expect,
|
is_expect,
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,9 +861,10 @@ impl AirTree {
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
tail: bool,
|
tail: bool,
|
||||||
list: AirTree,
|
list: AirTree,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
expect_level: ExpectLevel,
|
expect_level: ExpectLevel,
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::ListAccessor {
|
AirTree::ListAccessor {
|
||||||
tipo,
|
tipo,
|
||||||
|
@ -880,8 +872,8 @@ impl AirTree {
|
||||||
tail,
|
tail,
|
||||||
list: list.into(),
|
list: list.into(),
|
||||||
expect_level,
|
expect_level,
|
||||||
msg,
|
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -903,17 +895,17 @@ impl AirTree {
|
||||||
names: Vec<String>,
|
names: Vec<String>,
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
tuple: AirTree,
|
tuple: AirTree,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
is_expect: bool,
|
is_expect: bool,
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::TupleAccessor {
|
AirTree::TupleAccessor {
|
||||||
names,
|
names,
|
||||||
tipo,
|
tipo,
|
||||||
tuple: tuple.into(),
|
tuple: tuple.into(),
|
||||||
msg,
|
|
||||||
is_expect,
|
is_expect,
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,18 +914,18 @@ impl AirTree {
|
||||||
snd: Option<String>,
|
snd: Option<String>,
|
||||||
tipo: Rc<Type>,
|
tipo: Rc<Type>,
|
||||||
pair: AirTree,
|
pair: AirTree,
|
||||||
msg: Option<AirMsg>,
|
|
||||||
is_expect: bool,
|
is_expect: bool,
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
|
otherwise: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::PairAccessor {
|
AirTree::PairAccessor {
|
||||||
fst,
|
fst,
|
||||||
snd,
|
snd,
|
||||||
tipo,
|
tipo,
|
||||||
is_expect,
|
is_expect,
|
||||||
msg,
|
|
||||||
pair: pair.into(),
|
pair: pair.into(),
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,7 +941,7 @@ impl AirTree {
|
||||||
vec![tuple],
|
vec![tuple],
|
||||||
),
|
),
|
||||||
tipo.clone(),
|
tipo.clone(),
|
||||||
None,
|
AirTree::error(void(), false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,11 +968,12 @@ impl AirTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_empty(list: AirTree, msg: Option<AirMsg>, then: AirTree) -> AirTree {
|
pub fn list_empty(list: AirTree, then: AirTree, otherwise: AirTree) -> AirTree {
|
||||||
AirTree::ListEmpty {
|
AirTree::ListEmpty {
|
||||||
list: list.into(),
|
list: list.into(),
|
||||||
msg,
|
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
|
otherwise: otherwise.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1114,8 +1107,8 @@ impl AirTree {
|
||||||
AirTree::AssertConstr {
|
AirTree::AssertConstr {
|
||||||
constr,
|
constr,
|
||||||
constr_index,
|
constr_index,
|
||||||
msg,
|
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
air_vec.push(Air::AssertConstr {
|
air_vec.push(Air::AssertConstr {
|
||||||
constr_index: *constr_index,
|
constr_index: *constr_index,
|
||||||
|
@ -1123,27 +1116,21 @@ impl AirTree {
|
||||||
// msg is first so we can pop it off first in uplc_gen
|
// msg is first so we can pop it off first in uplc_gen
|
||||||
// if traces are on
|
// if traces are on
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
constr.create_air_vec(air_vec);
|
constr.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirTree::AssertBool {
|
AirTree::AssertBool {
|
||||||
is_true,
|
is_true,
|
||||||
value,
|
value,
|
||||||
msg,
|
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
air_vec.push(Air::AssertBool { is_true: *is_true });
|
air_vec.push(Air::AssertBool { is_true: *is_true });
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
value.create_air_vec(air_vec);
|
value.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirTree::ClauseGuard {
|
AirTree::ClauseGuard {
|
||||||
subject_name,
|
subject_name,
|
||||||
|
@ -1205,30 +1192,29 @@ impl AirTree {
|
||||||
AirTree::FieldsExpose {
|
AirTree::FieldsExpose {
|
||||||
indices,
|
indices,
|
||||||
record,
|
record,
|
||||||
msg,
|
|
||||||
is_expect,
|
is_expect,
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
air_vec.push(Air::FieldsExpose {
|
air_vec.push(Air::FieldsExpose {
|
||||||
indices: indices.clone(),
|
indices: indices.clone(),
|
||||||
is_expect: *is_expect,
|
is_expect: *is_expect,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
record.create_air_vec(air_vec);
|
record.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
if *is_expect {
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AirTree::ListAccessor {
|
AirTree::ListAccessor {
|
||||||
tipo,
|
tipo,
|
||||||
names,
|
names,
|
||||||
tail,
|
tail,
|
||||||
list,
|
list,
|
||||||
msg,
|
|
||||||
expect_level,
|
expect_level,
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
air_vec.push(Air::ListAccessor {
|
air_vec.push(Air::ListAccessor {
|
||||||
tipo: tipo.clone(),
|
tipo: tipo.clone(),
|
||||||
|
@ -1237,12 +1223,11 @@ impl AirTree {
|
||||||
expect_level: *expect_level,
|
expect_level: *expect_level,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.create_air_vec(air_vec);
|
list.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
if matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) {
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AirTree::ListExpose {
|
AirTree::ListExpose {
|
||||||
tipo,
|
tipo,
|
||||||
|
@ -1261,9 +1246,9 @@ impl AirTree {
|
||||||
names,
|
names,
|
||||||
tipo,
|
tipo,
|
||||||
tuple,
|
tuple,
|
||||||
msg,
|
|
||||||
is_expect,
|
is_expect,
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
air_vec.push(Air::TupleAccessor {
|
air_vec.push(Air::TupleAccessor {
|
||||||
names: names.clone(),
|
names: names.clone(),
|
||||||
|
@ -1271,21 +1256,20 @@ impl AirTree {
|
||||||
is_expect: *is_expect,
|
is_expect: *is_expect,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
tuple.create_air_vec(air_vec);
|
tuple.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
if *is_expect {
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AirTree::PairAccessor {
|
AirTree::PairAccessor {
|
||||||
fst,
|
fst,
|
||||||
snd,
|
snd,
|
||||||
tipo,
|
tipo,
|
||||||
is_expect,
|
is_expect,
|
||||||
msg,
|
|
||||||
pair,
|
pair,
|
||||||
then,
|
then,
|
||||||
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
air_vec.push(Air::PairAccessor {
|
air_vec.push(Air::PairAccessor {
|
||||||
fst: fst.clone(),
|
fst: fst.clone(),
|
||||||
|
@ -1294,12 +1278,11 @@ impl AirTree {
|
||||||
is_expect: *is_expect,
|
is_expect: *is_expect,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
pair.create_air_vec(air_vec);
|
pair.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
if *is_expect {
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AirTree::FieldsEmpty { constr, msg, then } => {
|
AirTree::FieldsEmpty { constr, msg, then } => {
|
||||||
air_vec.push(Air::FieldsEmpty);
|
air_vec.push(Air::FieldsEmpty);
|
||||||
|
@ -1311,15 +1294,16 @@ impl AirTree {
|
||||||
constr.create_air_vec(air_vec);
|
constr.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirTree::ListEmpty { list, msg, then } => {
|
AirTree::ListEmpty {
|
||||||
|
list,
|
||||||
|
then,
|
||||||
|
otherwise,
|
||||||
|
} => {
|
||||||
air_vec.push(Air::ListEmpty);
|
air_vec.push(Air::ListEmpty);
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.create_air_vec(air_vec);
|
list.create_air_vec(air_vec);
|
||||||
then.create_air_vec(air_vec);
|
then.create_air_vec(air_vec);
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirTree::NoOp { then } => {
|
AirTree::NoOp { then } => {
|
||||||
air_vec.push(Air::NoOp);
|
air_vec.push(Air::NoOp);
|
||||||
|
@ -1417,17 +1401,15 @@ impl AirTree {
|
||||||
air_vec.push(Air::UnOp { op: *op });
|
air_vec.push(Air::UnOp { op: *op });
|
||||||
arg.create_air_vec(air_vec);
|
arg.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirTree::CastFromData { tipo, value, msg } => {
|
AirTree::CastFromData {
|
||||||
air_vec.push(Air::CastFromData {
|
tipo,
|
||||||
tipo: tipo.clone(),
|
value,
|
||||||
is_expect: msg.is_some(),
|
otherwise,
|
||||||
});
|
} => {
|
||||||
|
air_vec.push(Air::CastFromData { tipo: tipo.clone() });
|
||||||
if let Some(msg) = msg {
|
|
||||||
msg.to_air_tree().create_air_vec(air_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
value.create_air_vec(air_vec);
|
value.create_air_vec(air_vec);
|
||||||
|
otherwise.create_air_vec(air_vec);
|
||||||
}
|
}
|
||||||
AirTree::CastToData { tipo, value } => {
|
AirTree::CastToData { tipo, value } => {
|
||||||
air_vec.push(Air::CastToData { tipo: tipo.clone() });
|
air_vec.push(Air::CastToData { tipo: tipo.clone() });
|
||||||
|
@ -1532,7 +1514,7 @@ impl AirTree {
|
||||||
}
|
}
|
||||||
AirTree::If {
|
AirTree::If {
|
||||||
tipo,
|
tipo,
|
||||||
pattern,
|
condition: pattern,
|
||||||
then,
|
then,
|
||||||
otherwise,
|
otherwise,
|
||||||
} => {
|
} => {
|
||||||
|
@ -2174,7 +2156,7 @@ impl AirTree {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AirTree::If {
|
AirTree::If {
|
||||||
pattern,
|
condition: pattern,
|
||||||
then,
|
then,
|
||||||
otherwise,
|
otherwise,
|
||||||
..
|
..
|
||||||
|
@ -2590,7 +2572,7 @@ impl AirTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AirTree::If {
|
AirTree::If {
|
||||||
pattern,
|
condition: pattern,
|
||||||
then,
|
then,
|
||||||
otherwise,
|
otherwise,
|
||||||
..
|
..
|
||||||
|
|
Loading…
Reference in New Issue