feat(gen_uplc): introduce scope new type
* new module scope which holds some ancestor logic * rework some things to truly hide scope increments Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
parent
ca0d896b8d
commit
33a3c5dc13
|
@ -4,7 +4,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
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::{ASSERT_ON_LIST, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER},
|
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST},
|
||||||
builtins::DefaultFunction,
|
builtins::DefaultFunction,
|
||||||
machine::cost_model::ExBudget,
|
machine::cost_model::ExBudget,
|
||||||
optimize::aiken_optimize_and_intern,
|
optimize::aiken_optimize_and_intern,
|
||||||
|
@ -27,6 +27,7 @@ use crate::{
|
||||||
|
|
||||||
pub mod air;
|
pub mod air;
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
|
pub mod scope;
|
||||||
pub mod stack;
|
pub mod stack;
|
||||||
|
|
||||||
use air::Air;
|
use air::Air;
|
||||||
|
@ -185,14 +186,15 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::String { value, .. } => ir_stack.string(value.to_string()),
|
TypedExpr::String { value, .. } => ir_stack.string(value.to_string()),
|
||||||
TypedExpr::ByteArray { bytes, .. } => ir_stack.byte_array(bytes.to_vec()),
|
TypedExpr::ByteArray { bytes, .. } => ir_stack.byte_array(bytes.to_vec()),
|
||||||
TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => {
|
TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => {
|
||||||
let stacks = Vec::new();
|
let mut stacks = Vec::new();
|
||||||
|
|
||||||
for (index, expr) in expressions.iter().enumerate() {
|
for (index, expr) in expressions.iter().enumerate() {
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
self.build_ir(expr, ir_stack);
|
self.build_ir(expr, ir_stack);
|
||||||
} else {
|
} else {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
self.build_ir(expr, &mut stack);
|
self.build_ir(expr, &mut stack);
|
||||||
|
stacks.push(stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +217,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TypedExpr::Fn { args, body, .. } => {
|
TypedExpr::Fn { args, body, .. } => {
|
||||||
let mut body_stack = ir_stack.in_new_scope();
|
let mut body_stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
self.build_ir(body, &mut body_stack);
|
self.build_ir(body, &mut body_stack);
|
||||||
|
|
||||||
|
@ -234,7 +236,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} => {
|
} => {
|
||||||
let stacks = Vec::new();
|
let stacks = Vec::new();
|
||||||
for element in elements {
|
for element in elements {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
self.build_ir(element, &mut stack);
|
self.build_ir(element, &mut stack);
|
||||||
|
|
||||||
|
@ -242,7 +244,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let tail = tail.as_ref().map(|tail| {
|
let tail = tail.as_ref().map(|tail| {
|
||||||
let mut tail_stack = ir_stack.in_new_scope();
|
let mut tail_stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
self.build_ir(tail, &mut tail_stack);
|
self.build_ir(tail, &mut tail_stack);
|
||||||
|
|
||||||
|
@ -276,7 +278,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let stacks = Vec::new();
|
let stacks = Vec::new();
|
||||||
|
|
||||||
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
if func_type.is_data() && !arg.value.tipo().is_data() {
|
if func_type.is_data() && !arg.value.tipo().is_data() {
|
||||||
stack.wrap_data(arg.value.tipo());
|
stack.wrap_data(arg.value.tipo());
|
||||||
|
@ -301,7 +303,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let stacks = Vec::new();
|
let stacks = Vec::new();
|
||||||
|
|
||||||
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
if func_type.is_data() && !arg.value.tipo().is_data() {
|
if func_type.is_data() && !arg.value.tipo().is_data() {
|
||||||
stack.wrap_data(arg.value.tipo());
|
stack.wrap_data(arg.value.tipo());
|
||||||
|
@ -341,7 +343,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let mut stacks = Vec::new();
|
let mut stacks = Vec::new();
|
||||||
|
|
||||||
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
if func_type.is_data() && !arg.value.tipo().is_data() {
|
if func_type.is_data() && !arg.value.tipo().is_data() {
|
||||||
stack.wrap_data(arg.value.tipo());
|
stack.wrap_data(arg.value.tipo());
|
||||||
|
@ -366,7 +368,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let mut stacks = Vec::new();
|
let mut stacks = Vec::new();
|
||||||
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
if func_type.is_data() && !arg.value.tipo().is_data() {
|
if func_type.is_data() && !arg.value.tipo().is_data() {
|
||||||
stack.wrap_data(arg.value.tipo());
|
stack.wrap_data(arg.value.tipo());
|
||||||
|
@ -385,7 +387,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut fun_stack = ir_stack.in_new_scope();
|
let mut fun_stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
self.build_ir(fun, &mut fun_stack);
|
self.build_ir(fun, &mut fun_stack);
|
||||||
|
|
||||||
|
@ -393,7 +395,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let mut stacks = Vec::new();
|
let mut stacks = Vec::new();
|
||||||
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
for (arg, func_type) in args.iter().zip(fun_arg_types) {
|
||||||
let mut stack = ir_stack.in_new_scope();
|
let mut stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
if func_type.is_data() && !arg.value.tipo().is_data() {
|
if func_type.is_data() && !arg.value.tipo().is_data() {
|
||||||
stack.wrap_data(arg.value.tipo());
|
stack.wrap_data(arg.value.tipo());
|
||||||
|
@ -407,8 +409,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::BinOp {
|
TypedExpr::BinOp {
|
||||||
name, left, right, ..
|
name, left, right, ..
|
||||||
} => {
|
} => {
|
||||||
let mut left_stack = ir_stack.in_new_scope();
|
let mut left_stack = ir_stack.empty_with_scope();
|
||||||
let mut right_stack = ir_stack.in_new_scope();
|
let mut right_stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
self.build_ir(left, &mut left_stack);
|
self.build_ir(left, &mut left_stack);
|
||||||
self.build_ir(right, &mut right_stack);
|
self.build_ir(right, &mut right_stack);
|
||||||
|
@ -422,8 +424,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
tipo,
|
tipo,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let mut value_stack = ir_stack.in_new_scope();
|
let mut value_stack = ir_stack.empty_with_scope();
|
||||||
let mut pattern_stack = ir_stack.in_new_scope();
|
let mut pattern_stack = ir_stack.empty_with_scope();
|
||||||
|
|
||||||
let mut replaced_type = tipo.clone();
|
let mut replaced_type = tipo.clone();
|
||||||
builder::replace_opaque_type(&mut replaced_type, self.data_types.clone());
|
builder::replace_opaque_type(&mut replaced_type, self.data_types.clone());
|
||||||
|
@ -1756,17 +1758,17 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
&& !pattern.is_discard()
|
&& !pattern.is_discard()
|
||||||
{
|
{
|
||||||
let mut wrap_stack = pattern_stack.in_new_scope();
|
let mut wrap_stack = pattern_stack.empty_with_scope();
|
||||||
wrap_stack.un_wrap_data(tipo.clone().into());
|
wrap_stack.un_wrap_data(tipo.clone().into());
|
||||||
wrap_stack.merge(value_stack);
|
wrap_stack.merge_child(value_stack);
|
||||||
wrap_stack
|
wrap_stack
|
||||||
} else if !assignment_properties.value_type.is_data()
|
} else if !assignment_properties.value_type.is_data()
|
||||||
&& tipo.is_data()
|
&& tipo.is_data()
|
||||||
&& !pattern.is_discard()
|
&& !pattern.is_discard()
|
||||||
{
|
{
|
||||||
let mut wrap_stack = pattern_stack.in_new_scope();
|
let mut wrap_stack = pattern_stack.empty_with_scope();
|
||||||
wrap_stack.wrap_data(assignment_properties.value_type.clone());
|
wrap_stack.wrap_data(assignment_properties.value_type.clone());
|
||||||
wrap_stack.merge(value_stack);
|
wrap_stack.merge_child(value_stack);
|
||||||
wrap_stack
|
wrap_stack
|
||||||
} else {
|
} else {
|
||||||
value_stack
|
value_stack
|
||||||
|
@ -1775,24 +1777,24 @@ impl<'a> CodeGenerator<'a> {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::Int { .. } => todo!(),
|
Pattern::Int { .. } => todo!(),
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
let assert_value_stack = value_stack.in_new_scope();
|
let expect_value_stack = value_stack.empty_with_scope();
|
||||||
pattern_stack.let_assignment(name, value_stack);
|
pattern_stack.let_assignment(name, value_stack);
|
||||||
|
|
||||||
if matches!(assignment_properties.kind, AssignmentKind::Expect)
|
if matches!(assignment_properties.kind, AssignmentKind::Expect)
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
let mut assert_stack = pattern_stack.in_new_scope();
|
let mut expect_stack = pattern_stack.empty_with_scope();
|
||||||
|
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
pattern,
|
pattern,
|
||||||
&mut assert_stack,
|
&mut expect_stack,
|
||||||
assert_value_stack,
|
expect_value_stack,
|
||||||
tipo,
|
tipo,
|
||||||
assignment_properties,
|
assignment_properties,
|
||||||
);
|
);
|
||||||
|
|
||||||
pattern_stack.merge(assert_stack);
|
pattern_stack.merge(expect_stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pattern::Assign { .. } => todo!("Assign not yet implemented"),
|
Pattern::Assign { .. } => todo!("Assign not yet implemented"),
|
||||||
|
@ -1804,7 +1806,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
list,
|
list,
|
||||||
pattern_vec,
|
pattern_vec,
|
||||||
value_vec,
|
value_vec,
|
||||||
|
@ -1828,7 +1830,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
constr,
|
constr,
|
||||||
pattern_vec,
|
pattern_vec,
|
||||||
value_vec,
|
value_vec,
|
||||||
|
@ -1852,7 +1854,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
tuple,
|
tuple,
|
||||||
pattern_vec,
|
pattern_vec,
|
||||||
value_vec,
|
value_vec,
|
||||||
|
@ -2165,10 +2167,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recursive_assert_pattern(
|
pub fn expect_pattern(
|
||||||
&mut self,
|
&mut self,
|
||||||
pattern: &Pattern<PatternConstructor, Arc<Type>>,
|
pattern: &Pattern<PatternConstructor, Arc<Type>>,
|
||||||
assert_stack: &mut AirStack,
|
expect_stack: &mut AirStack,
|
||||||
value_stack: AirStack,
|
value_stack: AirStack,
|
||||||
tipo: &Type,
|
tipo: &Type,
|
||||||
assignment_properties: AssignmentProperties,
|
assignment_properties: AssignmentProperties,
|
||||||
|
@ -2176,51 +2178,52 @@ impl<'a> CodeGenerator<'a> {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::Int { .. } => unreachable!(),
|
Pattern::Int { .. } => unreachable!(),
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
assert_stack.merge(value_stack);
|
expect_stack.merge(value_stack);
|
||||||
|
|
||||||
self.recursive_assert_tipo(tipo, assert_stack, name);
|
self.expect_type(tipo, expect_stack, name);
|
||||||
}
|
}
|
||||||
Pattern::Assign { .. } => todo!(),
|
Pattern::Assign { .. } => todo!(),
|
||||||
Pattern::Discard { .. } => unreachable!(),
|
Pattern::Discard { .. } => unreachable!(),
|
||||||
Pattern::List { elements, tail, .. } => {
|
Pattern::List { elements, tail, .. } => {
|
||||||
let mut assert_list_vec = vec![];
|
|
||||||
let inner_list_type = &tipo.get_inner_types()[0];
|
let inner_list_type = &tipo.get_inner_types()[0];
|
||||||
let mut names = vec![];
|
let mut names = vec![];
|
||||||
|
|
||||||
|
let mut expect_list_stacks = vec![];
|
||||||
|
|
||||||
for element in elements {
|
for element in elements {
|
||||||
match element {
|
match element {
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
names.push(name.clone());
|
names.push(name.clone());
|
||||||
}
|
}
|
||||||
Pattern::Assign { .. } => todo!(),
|
Pattern::Assign { .. } => todo!(),
|
||||||
l @ (Pattern::List { .. }
|
element_pattern @ (Pattern::List { .. }
|
||||||
| Pattern::Constructor { .. }
|
| Pattern::Constructor { .. }
|
||||||
| Pattern::Tuple { .. }) => {
|
| Pattern::Tuple { .. }) => {
|
||||||
let name = format!("list_item_id_{}", self.id_gen.next());
|
let name = format!("list_item_id_{}", self.id_gen.next());
|
||||||
|
|
||||||
names.push(name.clone());
|
names.push(name.clone());
|
||||||
|
|
||||||
self.recursive_assert_pattern(
|
let mut element_stack = expect_stack.empty_with_scope();
|
||||||
l,
|
let mut value_stack = element_stack.empty_with_scope();
|
||||||
&mut assert_list_vec,
|
|
||||||
&mut vec![Air::Var {
|
value_stack.local_var(tipo.clone().into(), name);
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
self.expect_pattern(
|
||||||
tipo.clone().into(),
|
element_pattern,
|
||||||
ValueConstructorVariant::LocalVariable {
|
&mut element_stack,
|
||||||
location: Span::empty(),
|
value_stack,
|
||||||
},
|
|
||||||
),
|
|
||||||
name,
|
|
||||||
variant_name: String::new(),
|
|
||||||
}],
|
|
||||||
inner_list_type,
|
inner_list_type,
|
||||||
assignment_properties.clone(),
|
assignment_properties.clone(),
|
||||||
scope.clone(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
expect_list_stacks.push(element_stack);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut tail_stack = expect_stack.empty_with_scope();
|
||||||
|
|
||||||
let name = if let Some(tail) = tail {
|
let name = if let Some(tail) = tail {
|
||||||
match &**tail {
|
match &**tail {
|
||||||
Pattern::Var { name, .. } => name.clone(),
|
Pattern::Var { name, .. } => name.clone(),
|
||||||
|
@ -2230,21 +2233,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
format!("__tail_{}", self.id_gen.next())
|
format!("__tail_{}", self.id_gen.next())
|
||||||
};
|
};
|
||||||
|
|
||||||
self.recursive_assert_tipo(tipo, &mut assert_list_vec, &name, scope.clone());
|
self.expect_type(tipo, &mut tail_stack, &name);
|
||||||
|
|
||||||
names.push(name);
|
names.push(name);
|
||||||
|
|
||||||
pattern_vec.push(Air::ListAccessor {
|
expect_stack.list_accessor(tipo.clone().into(), names, true, false, value_stack);
|
||||||
scope,
|
|
||||||
tipo: tipo.clone().into(),
|
|
||||||
names,
|
|
||||||
tail: true,
|
|
||||||
check_last_item: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
pattern_vec.append(value_vec);
|
expect_stack.merge_children(expect_list_stacks);
|
||||||
|
|
||||||
pattern_vec.append(&mut assert_list_vec);
|
|
||||||
}
|
}
|
||||||
Pattern::Constructor {
|
Pattern::Constructor {
|
||||||
arguments,
|
arguments,
|
||||||
|
@ -2306,17 +2301,19 @@ impl<'a> CodeGenerator<'a> {
|
||||||
current_index += 1;
|
current_index += 1;
|
||||||
} else {
|
} else {
|
||||||
let id_next = self.id_gen.next();
|
let id_next = self.id_gen.next();
|
||||||
|
|
||||||
final_args.push((format!("__field_{index}_{id_next}"), index));
|
final_args.push((format!("__field_{index}_{id_next}"), index));
|
||||||
self.recursive_assert_tipo(
|
|
||||||
|
self.expect_type(
|
||||||
type_map.get(&index).unwrap(),
|
type_map.get(&index).unwrap(),
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
&format!("__field_{index}_{id_next}"),
|
&format!("__field_{index}_{id_next}"),
|
||||||
scope.clone(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let constr_var = format!("__constr_{}", self.id_gen.next());
|
let constr_var = format!("__constr_{}", self.id_gen.next());
|
||||||
|
|
||||||
pattern_vec.push(Air::Let {
|
pattern_vec.push(Air::Let {
|
||||||
scope: scope.clone(),
|
scope: scope.clone(),
|
||||||
name: constr_var.clone(),
|
name: constr_var.clone(),
|
||||||
|
@ -2411,11 +2408,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
} else {
|
} else {
|
||||||
let id_next = self.id_gen.next();
|
let id_next = self.id_gen.next();
|
||||||
final_args.push((format!("__tuple_{index}_{id_next}"), index));
|
final_args.push((format!("__tuple_{index}_{id_next}"), index));
|
||||||
self.recursive_assert_tipo(
|
self.expect_type(
|
||||||
type_map.get(&index).unwrap(),
|
type_map.get(&index).unwrap(),
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
&format!("__tuple_{index}_{id_next}"),
|
&format!("__tuple_{index}_{id_next}"),
|
||||||
scope.clone(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2436,7 +2432,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recursive_assert_tipo(&mut self, tipo: &Type, assert_vec: &mut AirStack, name: &str) {
|
fn expect_type(&mut self, tipo: &Type, expect_stack: &mut AirStack, name: &str) {
|
||||||
let mut tipo = tipo.clone().into();
|
let mut tipo = tipo.clone().into();
|
||||||
builder::replace_opaque_type(&mut tipo, self.data_types.clone());
|
builder::replace_opaque_type(&mut tipo, self.data_types.clone());
|
||||||
|
|
||||||
|
@ -2455,231 +2451,103 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let inner_list_type = &tipo.get_inner_types()[0];
|
let inner_list_type = &tipo.get_inner_types()[0];
|
||||||
let inner_pair_types = inner_list_type.get_inner_types();
|
let inner_pair_types = inner_list_type.get_inner_types();
|
||||||
|
|
||||||
assert_vec.push(Air::Builtin {
|
let mut unwrap_function_stack = expect_stack.empty_with_scope();
|
||||||
scope: scope.clone(),
|
let mut pair_access_stack = unwrap_function_stack.empty_with_scope();
|
||||||
func: DefaultFunction::ChooseUnit,
|
let mut local_var_stack = pair_access_stack.empty_with_scope();
|
||||||
tipo: tipo.clone(),
|
|
||||||
count: DefaultFunction::ChooseUnit.arity(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Call {
|
local_var_stack.local_var(inner_list_type.clone(), format!("__pair_{new_id}"));
|
||||||
scope: scope.clone(),
|
|
||||||
count: 2,
|
|
||||||
tipo: tipo.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
pair_access_stack.tuple_accessor(
|
||||||
scope: scope.clone(),
|
inner_list_type.clone(),
|
||||||
constructor: ValueConstructor::public(
|
vec![
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: ASSERT_ON_LIST.to_string(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: name.to_owned(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Fn {
|
|
||||||
scope: scope.clone(),
|
|
||||||
params: vec![format!("__pair_{new_id}")],
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::TupleAccessor {
|
|
||||||
scope: scope.clone(),
|
|
||||||
names: vec![
|
|
||||||
format!("__pair_fst_{}", id_pair.0),
|
format!("__pair_fst_{}", id_pair.0),
|
||||||
format!("__pair_snd_{}", id_pair.1),
|
format!("__pair_snd_{}", id_pair.1),
|
||||||
],
|
],
|
||||||
tipo: inner_list_type.clone(),
|
false,
|
||||||
check_last_item: false,
|
local_var_stack,
|
||||||
});
|
);
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
self.expect_type(
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: format!("__pair_{new_id}"),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.recursive_assert_tipo(
|
|
||||||
&inner_pair_types[0],
|
&inner_pair_types[0],
|
||||||
assert_vec,
|
&mut pair_access_stack,
|
||||||
&format!("__pair_fst_{}", id_pair.0),
|
&format!("__pair_fst_{}", id_pair.0),
|
||||||
scope.clone(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
self.recursive_assert_tipo(
|
self.expect_type(
|
||||||
&inner_pair_types[1],
|
&inner_pair_types[1],
|
||||||
assert_vec,
|
&mut pair_access_stack,
|
||||||
&format!("__pair_snd_{}", id_pair.1),
|
&format!("__pair_snd_{}", id_pair.1),
|
||||||
scope.clone(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_vec.push(Air::Void { scope });
|
unwrap_function_stack
|
||||||
|
.anonymous_function(vec![format!("__pair_{new_id}")], pair_access_stack);
|
||||||
|
|
||||||
|
expect_stack.expect_list_from_data(tipo.clone(), name, unwrap_function_stack);
|
||||||
|
|
||||||
|
expect_stack.void();
|
||||||
} else if tipo.is_list() {
|
} else if tipo.is_list() {
|
||||||
self.used_data_assert_on_list = true;
|
self.used_data_assert_on_list = true;
|
||||||
let new_id = self.id_gen.next();
|
let new_id = self.id_gen.next();
|
||||||
let inner_list_type = &tipo.get_inner_types()[0];
|
let inner_list_type = &tipo.get_inner_types()[0];
|
||||||
|
|
||||||
assert_vec.push(Air::Builtin {
|
let mut unwrap_function_stack = expect_stack.empty_with_scope();
|
||||||
scope: scope.clone(),
|
let mut list_access_stack = unwrap_function_stack.empty_with_scope();
|
||||||
func: DefaultFunction::ChooseUnit,
|
let mut local_var_stack = list_access_stack.empty_with_scope();
|
||||||
tipo: tipo.clone(),
|
|
||||||
count: DefaultFunction::ChooseUnit.arity(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Call {
|
local_var_stack.un_wrap_data(inner_list_type.clone());
|
||||||
scope: scope.clone(),
|
local_var_stack.local_var(inner_list_type.clone(), format!("__list_item_{new_id}"));
|
||||||
count: 2,
|
|
||||||
tipo: tipo.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
list_access_stack.let_assignment(format!("__list_item_{new_id}"), local_var_stack);
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: ASSERT_ON_LIST.to_string(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
self.expect_type(
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: name.to_owned(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Fn {
|
|
||||||
scope: scope.clone(),
|
|
||||||
params: vec![format!("__list_item_{new_id}")],
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Let {
|
|
||||||
scope: scope.clone(),
|
|
||||||
name: format!("__list_item_{new_id}"),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::UnWrapData {
|
|
||||||
scope: scope.clone(),
|
|
||||||
tipo: inner_list_type.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: format!("__list_item_{new_id}"),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.recursive_assert_tipo(
|
|
||||||
inner_list_type,
|
inner_list_type,
|
||||||
assert_vec,
|
&mut list_access_stack,
|
||||||
&format!("__list_item_{new_id}"),
|
&format!("__list_item_{new_id}"),
|
||||||
scope.clone(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_vec.push(Air::Void { scope });
|
unwrap_function_stack
|
||||||
|
.anonymous_function(vec![format!("__list_item_{new_id}")], list_access_stack);
|
||||||
|
|
||||||
|
expect_stack.expect_list_from_data(tipo.clone(), name, unwrap_function_stack);
|
||||||
|
|
||||||
|
expect_stack.void();
|
||||||
} else if tipo.is_tuple() {
|
} else if tipo.is_tuple() {
|
||||||
let tuple_inner_types = tipo.get_inner_types();
|
let tuple_inner_types = tipo.get_inner_types();
|
||||||
let mut new_id_list = vec![];
|
let mut new_id_list = vec![];
|
||||||
|
|
||||||
for (index, _) in tuple_inner_types.iter().enumerate() {
|
for (index, _) in tuple_inner_types.iter().enumerate() {
|
||||||
new_id_list.push((index, self.id_gen.next()));
|
new_id_list.push((index, self.id_gen.next()));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_vec.push(Air::TupleAccessor {
|
let mut local_var_stack = expect_stack.empty_with_scope();
|
||||||
scope: scope.clone(),
|
|
||||||
names: new_id_list
|
local_var_stack.local_var(tipo, name);
|
||||||
|
|
||||||
|
let names = new_id_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(index, id)| format!("__tuple_index_{index}_{id}"))
|
.map(|(index, id)| format!("__tuple_index_{index}_{id}"))
|
||||||
.collect_vec(),
|
.collect();
|
||||||
tipo: tipo.clone(),
|
|
||||||
check_last_item: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
expect_stack.tuple_accessor(tipo, names, true, local_var_stack);
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: name.to_owned(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
for (index, name) in new_id_list
|
for (index, name) in new_id_list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(index, id)| (index, format!("__tuple_index_{index}_{id}")))
|
.map(|(index, id)| (index, format!("__tuple_index_{index}_{id}")))
|
||||||
{
|
{
|
||||||
self.recursive_assert_tipo(
|
self.expect_type(&tuple_inner_types[index], expect_stack, &name);
|
||||||
&tuple_inner_types[index],
|
|
||||||
assert_vec,
|
|
||||||
&name,
|
|
||||||
scope.clone(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let data_type =
|
let data_type =
|
||||||
builder::lookup_data_type_by_tipo(self.data_types.clone(), &tipo).unwrap();
|
builder::lookup_data_type_by_tipo(self.data_types.clone(), &tipo).unwrap();
|
||||||
|
|
||||||
let new_id = self.id_gen.next();
|
let new_id = self.id_gen.next();
|
||||||
|
|
||||||
assert_vec.push(Air::Builtin {
|
// START HERE
|
||||||
scope: scope.clone(),
|
let mut arg_stack = expect_stack.empty_with_scope();
|
||||||
func: DefaultFunction::ChooseUnit,
|
let mut clause_stack = expect_stack.empty_with_scope();
|
||||||
tipo: tipo.clone(),
|
let mut when_stack = expect_stack.empty_with_scope();
|
||||||
count: DefaultFunction::ChooseUnit.arity(),
|
let mut trace_stack = expect_stack.empty_with_scope();
|
||||||
});
|
let mut subject_stack = expect_stack.empty_with_scope();
|
||||||
|
|
||||||
assert_vec.push(Air::When {
|
|
||||||
scope: scope.clone(),
|
|
||||||
tipo: tipo.clone(),
|
|
||||||
subject_name: format!("__subject_{new_id}"),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: name.to_owned(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
|
|
||||||
for (index, constr) in data_type.constructors.iter().enumerate() {
|
for (index, constr) in data_type.constructors.iter().enumerate() {
|
||||||
let arg_indices = constr
|
let arg_indices = constr
|
||||||
|
@ -2691,65 +2559,50 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.label
|
.label
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or(format!("__field_{index}_{new_id}"));
|
.unwrap_or(format!("__field_{index}_{new_id}"));
|
||||||
|
|
||||||
(index, arg_name, arg.tipo.clone())
|
(index, arg_name, arg.tipo.clone())
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
assert_vec.push(Air::Clause {
|
for (index, name, tipo) in arg_indices {
|
||||||
scope: scope.clone(),
|
self.expect_type(&tipo, &mut arg_stack, &name);
|
||||||
tipo: tipo.clone(),
|
|
||||||
subject_name: format!("__subject_{new_id}"),
|
|
||||||
complex_clause: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Int {
|
|
||||||
scope: scope.clone(),
|
|
||||||
value: index.to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if !arg_indices.is_empty() {
|
|
||||||
assert_vec.push(Air::FieldsExpose {
|
|
||||||
scope: scope.clone(),
|
|
||||||
indices: arg_indices.clone(),
|
|
||||||
check_last_item: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::Var {
|
|
||||||
scope: scope.clone(),
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
tipo.clone(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: name.to_owned(),
|
|
||||||
variant_name: String::new(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (_, name, tipo) in arg_indices {
|
arg_stack = if !arg_indices.is_empty() {
|
||||||
self.recursive_assert_tipo(&tipo, assert_vec, &name, scope.clone());
|
arg_stack.local_var(tipo, name);
|
||||||
|
|
||||||
|
let field_expose_stack = expect_stack.empty_with_scope();
|
||||||
|
|
||||||
|
field_expose_stack.fields_expose(arg_indices.clone(), true, arg_stack);
|
||||||
|
|
||||||
|
field_expose_stack
|
||||||
|
} else {
|
||||||
|
arg_stack
|
||||||
|
};
|
||||||
|
|
||||||
|
arg_stack.void();
|
||||||
|
|
||||||
|
clause_stack.clause(tipo, format!("__subject_{new_id}"), index, false, arg_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_vec.push(Air::Void {
|
trace_stack.trace(tipo.clone());
|
||||||
scope: scope.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_vec.push(Air::Trace {
|
trace_stack.string("Constr index did not match any type variant");
|
||||||
scope: scope.clone(),
|
|
||||||
tipo: tipo.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::String {
|
trace_stack.error(tipo.clone());
|
||||||
scope: scope.clone(),
|
|
||||||
value: "Constr index did not match any type variant".to_string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_vec.push(Air::ErrorTerm {
|
subject_stack.local_var(tipo, name);
|
||||||
scope,
|
|
||||||
tipo: tipo.clone(),
|
when_stack.when(
|
||||||
});
|
tipo,
|
||||||
|
format!("__subject_{new_id}"),
|
||||||
|
subject_stack,
|
||||||
|
clause_stack,
|
||||||
|
trace_stack,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Only used here
|
||||||
|
expect_stack.expect_constr_from_data(tipo.clone(), when_stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2774,7 +2627,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
a,
|
a,
|
||||||
nested_pattern,
|
nested_pattern,
|
||||||
&mut vec![Air::Var {
|
&mut vec![Air::Var {
|
||||||
|
@ -2827,7 +2680,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
a,
|
a,
|
||||||
nested_pattern,
|
nested_pattern,
|
||||||
&mut vec![Air::Var {
|
&mut vec![Air::Var {
|
||||||
|
@ -2876,7 +2729,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&& assignment_properties.value_type.is_data()
|
&& assignment_properties.value_type.is_data()
|
||||||
&& !tipo.is_data()
|
&& !tipo.is_data()
|
||||||
{
|
{
|
||||||
self.recursive_assert_pattern(
|
self.expect_pattern(
|
||||||
a,
|
a,
|
||||||
nested_pattern,
|
nested_pattern,
|
||||||
&mut vec![Air::Var {
|
&mut vec![Air::Var {
|
||||||
|
|
|
@ -7,53 +7,55 @@ use crate::{
|
||||||
tipo::{Type, ValueConstructor},
|
tipo::{Type, ValueConstructor},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::scope::Scope;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Air {
|
pub enum Air {
|
||||||
// Primitives
|
// Primitives
|
||||||
Int {
|
Int {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
value: String,
|
value: String,
|
||||||
},
|
},
|
||||||
String {
|
String {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
value: String,
|
value: String,
|
||||||
},
|
},
|
||||||
ByteArray {
|
ByteArray {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
bytes: Vec<u8>,
|
bytes: Vec<u8>,
|
||||||
},
|
},
|
||||||
Bool {
|
Bool {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
value: bool,
|
value: bool,
|
||||||
},
|
},
|
||||||
List {
|
List {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
count: usize,
|
count: usize,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
tail: bool,
|
tail: bool,
|
||||||
},
|
},
|
||||||
Tuple {
|
Tuple {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
count: usize,
|
count: usize,
|
||||||
},
|
},
|
||||||
Void {
|
Void {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
},
|
},
|
||||||
Var {
|
Var {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
constructor: ValueConstructor,
|
constructor: ValueConstructor,
|
||||||
name: String,
|
name: String,
|
||||||
variant_name: String,
|
variant_name: String,
|
||||||
},
|
},
|
||||||
// Functions
|
// Functions
|
||||||
Call {
|
Call {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
count: usize,
|
count: usize,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
DefineFunc {
|
DefineFunc {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
func_name: String,
|
func_name: String,
|
||||||
module_name: String,
|
module_name: String,
|
||||||
params: Vec<String>,
|
params: Vec<String>,
|
||||||
|
@ -61,70 +63,70 @@ pub enum Air {
|
||||||
variant_name: String,
|
variant_name: String,
|
||||||
},
|
},
|
||||||
Fn {
|
Fn {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
params: Vec<String>,
|
params: Vec<String>,
|
||||||
},
|
},
|
||||||
Builtin {
|
Builtin {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
count: usize,
|
count: usize,
|
||||||
func: DefaultFunction,
|
func: DefaultFunction,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
// Operators
|
// Operators
|
||||||
BinOp {
|
BinOp {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
name: BinOp,
|
name: BinOp,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
UnOp {
|
UnOp {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
op: UnOp,
|
op: UnOp,
|
||||||
},
|
},
|
||||||
// Assignment
|
// Assignment
|
||||||
Let {
|
Let {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
UnWrapData {
|
UnWrapData {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
WrapData {
|
WrapData {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
AssertConstr {
|
AssertConstr {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
constr_index: usize,
|
constr_index: usize,
|
||||||
},
|
},
|
||||||
AssertBool {
|
AssertBool {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
is_true: bool,
|
is_true: bool,
|
||||||
},
|
},
|
||||||
// When
|
// When
|
||||||
When {
|
When {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
subject_name: String,
|
subject_name: String,
|
||||||
},
|
},
|
||||||
Clause {
|
Clause {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
subject_name: String,
|
subject_name: String,
|
||||||
complex_clause: bool,
|
complex_clause: bool,
|
||||||
},
|
},
|
||||||
ListClause {
|
ListClause {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
tail_name: String,
|
tail_name: String,
|
||||||
next_tail_name: Option<String>,
|
next_tail_name: Option<String>,
|
||||||
complex_clause: bool,
|
complex_clause: bool,
|
||||||
},
|
},
|
||||||
WrapClause {
|
WrapClause {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
},
|
},
|
||||||
TupleClause {
|
TupleClause {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
indices: IndexSet<(usize, String)>,
|
indices: IndexSet<(usize, String)>,
|
||||||
predefined_indices: IndexSet<(usize, String)>,
|
predefined_indices: IndexSet<(usize, String)>,
|
||||||
|
@ -133,88 +135,88 @@ pub enum Air {
|
||||||
complex_clause: bool,
|
complex_clause: bool,
|
||||||
},
|
},
|
||||||
ClauseGuard {
|
ClauseGuard {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
subject_name: String,
|
subject_name: String,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
ListClauseGuard {
|
ListClauseGuard {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
tail_name: String,
|
tail_name: String,
|
||||||
next_tail_name: Option<String>,
|
next_tail_name: Option<String>,
|
||||||
inverse: bool,
|
inverse: bool,
|
||||||
},
|
},
|
||||||
Finally {
|
Finally {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
},
|
},
|
||||||
// If
|
// If
|
||||||
If {
|
If {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
// Record Creation
|
// Record Creation
|
||||||
Record {
|
Record {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tag: usize,
|
tag: usize,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
count: usize,
|
count: usize,
|
||||||
},
|
},
|
||||||
RecordUpdate {
|
RecordUpdate {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
highest_index: usize,
|
highest_index: usize,
|
||||||
indices: Vec<(usize, Arc<Type>)>,
|
indices: Vec<(usize, Arc<Type>)>,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
// Field Access
|
// Field Access
|
||||||
RecordAccess {
|
RecordAccess {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
record_index: u64,
|
record_index: u64,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
FieldsExpose {
|
FieldsExpose {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
indices: Vec<(usize, String, Arc<Type>)>,
|
indices: Vec<(usize, String, Arc<Type>)>,
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
},
|
},
|
||||||
// ListAccess
|
// ListAccess
|
||||||
ListAccessor {
|
ListAccessor {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
names: Vec<String>,
|
names: Vec<String>,
|
||||||
tail: bool,
|
tail: bool,
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
},
|
},
|
||||||
ListExpose {
|
ListExpose {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
tail_head_names: Vec<(String, String)>,
|
tail_head_names: Vec<(String, String)>,
|
||||||
tail: Option<(String, String)>,
|
tail: Option<(String, String)>,
|
||||||
},
|
},
|
||||||
// Tuple Access
|
// Tuple Access
|
||||||
TupleAccessor {
|
TupleAccessor {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
names: Vec<String>,
|
names: Vec<String>,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
},
|
},
|
||||||
TupleIndex {
|
TupleIndex {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
tuple_index: usize,
|
tuple_index: usize,
|
||||||
},
|
},
|
||||||
// Misc.
|
// Misc.
|
||||||
ErrorTerm {
|
ErrorTerm {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
Trace {
|
Trace {
|
||||||
scope: Vec<u64>,
|
scope: Scope,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Air {
|
impl Air {
|
||||||
pub fn scope(&self) -> Vec<u64> {
|
pub fn scope(&self) -> Scope {
|
||||||
match self {
|
match self {
|
||||||
Air::Int { scope, .. }
|
Air::Int { scope, .. }
|
||||||
| Air::String { scope, .. }
|
| Air::String { scope, .. }
|
||||||
|
@ -256,7 +258,7 @@ impl Air {
|
||||||
| Air::Trace { scope, .. } => scope.clone(),
|
| Air::Trace { scope, .. } => scope.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn scope_mut(&mut self) -> &mut Vec<u64> {
|
pub fn scope_mut(&mut self) -> &mut Scope {
|
||||||
match self {
|
match self {
|
||||||
Air::Int { scope, .. }
|
Air::Int { scope, .. }
|
||||||
| Air::String { scope, .. }
|
| Air::String { scope, .. }
|
||||||
|
|
|
@ -636,29 +636,6 @@ pub fn list_access_to_uplc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_common_ancestor(scope: &[u64], scope_prev: &[u64]) -> Vec<u64> {
|
|
||||||
let longest_length = if scope.len() >= scope_prev.len() {
|
|
||||||
scope.len()
|
|
||||||
} else {
|
|
||||||
scope_prev.len()
|
|
||||||
};
|
|
||||||
|
|
||||||
if *scope == *scope_prev {
|
|
||||||
return scope.to_vec();
|
|
||||||
}
|
|
||||||
|
|
||||||
for index in 0..longest_length {
|
|
||||||
if scope.get(index).is_none() {
|
|
||||||
return scope.to_vec();
|
|
||||||
} else if scope_prev.get(index).is_none() {
|
|
||||||
return scope_prev.to_vec();
|
|
||||||
} else if scope[index] != scope_prev[index] {
|
|
||||||
return scope[0..index].to_vec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_when_pattern_needs(
|
pub fn check_when_pattern_needs(
|
||||||
pattern: &Pattern<PatternConstructor, Arc<Type>>,
|
pattern: &Pattern<PatternConstructor, Arc<Type>>,
|
||||||
clause_properties: &mut ClauseProperties,
|
clause_properties: &mut ClauseProperties,
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct Scope(Vec<u64>);
|
||||||
|
|
||||||
|
impl Scope {
|
||||||
|
pub fn push(&mut self, value: u64) {
|
||||||
|
self.0.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace(&mut self, pattern: &Scope, replacement: Scope) {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
let mut index = 0;
|
||||||
|
let mut pattern_index = 0;
|
||||||
|
|
||||||
|
let mut no_matches = true;
|
||||||
|
|
||||||
|
while index < self.0.len() {
|
||||||
|
if self.0[index] == pattern.0[pattern_index] {
|
||||||
|
if pattern_index == pattern.0.len() - 1 {
|
||||||
|
no_matches = false;
|
||||||
|
result.extend(replacement.0.clone());
|
||||||
|
pattern_index = 0;
|
||||||
|
} else {
|
||||||
|
pattern_index += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(self.0[index]);
|
||||||
|
pattern_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if no_matches {
|
||||||
|
replacement.0.extend(self.0);
|
||||||
|
self.0 = replacement.0;
|
||||||
|
} else {
|
||||||
|
self.0 = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn common_ancestor(&self, other: &Self) -> Scope {
|
||||||
|
let longest_length = self.0.len().max(other.0.len());
|
||||||
|
|
||||||
|
if *self.0 == *other.0 {
|
||||||
|
return self.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
for index in 0..longest_length {
|
||||||
|
if self.0.get(index).is_none() {
|
||||||
|
return self.clone();
|
||||||
|
} else if other.0.get(index).is_none() {
|
||||||
|
return other.clone();
|
||||||
|
} else if self.0[index] != other.0[index] {
|
||||||
|
return Scope(self.0[0..index].to_vec());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope::default()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,30 +1,34 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use uplc::builtins::DefaultFunction;
|
use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
tipo::{Type, ValueConstructor},
|
ast::Span,
|
||||||
|
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::air::Air;
|
use super::{air::Air, scope::Scope};
|
||||||
|
|
||||||
|
/// A builder for [`Air`].
|
||||||
pub struct AirStack<'a> {
|
pub struct AirStack<'a> {
|
||||||
pub id_gen: &'a mut IdGenerator,
|
pub id_gen: &'a mut IdGenerator,
|
||||||
pub scope: Vec<u64>,
|
pub scope: Scope,
|
||||||
pub air: Vec<Air>,
|
pub air: Vec<Air>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AirStack<'a> {
|
impl<'a> AirStack<'a> {
|
||||||
|
/// Create a new [`AirStack`] with an [`IdGenerator`]
|
||||||
pub fn new(id_gen: &'a mut IdGenerator) -> Self {
|
pub fn new(id_gen: &'a mut IdGenerator) -> Self {
|
||||||
AirStack {
|
AirStack {
|
||||||
id_gen,
|
id_gen,
|
||||||
scope: vec![id_gen.next()],
|
scope: Scope::default(),
|
||||||
air: vec![],
|
air: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_scope(id_gen: &'a mut IdGenerator, scope: Vec<u64>) -> Self {
|
/// Create a new [`AirStack`] with an [`IdGenerator`] and [`Scope`].
|
||||||
|
pub fn with_scope(id_gen: &'a mut IdGenerator, scope: Scope) -> Self {
|
||||||
AirStack {
|
AirStack {
|
||||||
id_gen,
|
id_gen,
|
||||||
scope,
|
scope,
|
||||||
|
@ -32,22 +36,37 @@ impl<'a> AirStack<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn in_new_scope(&mut self) -> Self {
|
/// Create a new empty [`AirStack`] with the current stack's scope.
|
||||||
let mut new_stack = AirStack::with_scope(&mut self.id_gen, self.scope.clone());
|
pub fn empty_with_scope(&mut self) -> Self {
|
||||||
|
AirStack::with_scope(&mut self.id_gen, self.scope.clone())
|
||||||
new_stack.new_scope();
|
|
||||||
|
|
||||||
new_stack
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_scope(&mut self) {
|
/// Increment the [`Scope`]
|
||||||
|
fn new_scope(&mut self) {
|
||||||
self.scope.push(self.id_gen.next());
|
self.scope.push(self.id_gen.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Merge two [`AirStack`]'s together while maintaining the current stack's [`Scope`]
|
||||||
pub fn merge(&mut self, mut other: AirStack) {
|
pub fn merge(&mut self, mut other: AirStack) {
|
||||||
self.air.append(&mut other.air);
|
self.air.append(&mut other.air);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn merge_child(&mut self, mut other: AirStack) {
|
||||||
|
let pattern = self.scope.common_ancestor(&other.scope);
|
||||||
|
|
||||||
|
for ir in other.air.iter_mut() {
|
||||||
|
ir.scope_mut().replace(&pattern, self.scope.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.merge(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn merge_children(&mut self, stacks: Vec<AirStack>) {
|
||||||
|
for stack in stacks {
|
||||||
|
self.merge_child(stack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sequence(&mut self, stacks: Vec<AirStack>) {
|
pub fn sequence(&mut self, stacks: Vec<AirStack>) {
|
||||||
for stack in stacks {
|
for stack in stacks {
|
||||||
self.merge(stack)
|
self.merge(stack)
|
||||||
|
@ -55,20 +74,26 @@ impl<'a> AirStack<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn integer(&mut self, value: String) {
|
pub fn integer(&mut self, value: String) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Int {
|
self.air.push(Air::Int {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string(&mut self, value: String) {
|
pub fn string(&mut self, value: impl ToString) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::String {
|
self.air.push(Air::String {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
value,
|
value: value.to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn byte_array(&mut self, bytes: Vec<u8>) {
|
pub fn byte_array(&mut self, bytes: Vec<u8>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::ByteArray {
|
self.air.push(Air::ByteArray {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
bytes,
|
bytes,
|
||||||
|
@ -76,6 +101,8 @@ impl<'a> AirStack<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirStack>) {
|
pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirStack>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Builtin {
|
self.air.push(Air::Builtin {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
count: args.len(),
|
count: args.len(),
|
||||||
|
@ -83,7 +110,7 @@ impl<'a> AirStack<'a> {
|
||||||
tipo,
|
tipo,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.sequence(args);
|
self.merge_children(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn var(
|
pub fn var(
|
||||||
|
@ -92,6 +119,8 @@ impl<'a> AirStack<'a> {
|
||||||
name: impl ToString,
|
name: impl ToString,
|
||||||
variant_name: impl ToString,
|
variant_name: impl ToString,
|
||||||
) {
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Var {
|
self.air.push(Air::Var {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
constructor,
|
constructor,
|
||||||
|
@ -100,16 +129,36 @@ impl<'a> AirStack<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn local_var(&mut self, tipo: Arc<Type>, name: impl ToString) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Var {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo,
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: name.to_string(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn anonymous_function(&mut self, params: Vec<String>, body: AirStack) {
|
pub fn anonymous_function(&mut self, params: Vec<String>, body: AirStack) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Fn {
|
self.air.push(Air::Fn {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.merge(body);
|
self.merge_child(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(&mut self, tipo: Arc<Type>, elements: Vec<AirStack>, tail: Option<AirStack>) {
|
pub fn list(&mut self, tipo: Arc<Type>, elements: Vec<AirStack>, tail: Option<AirStack>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::List {
|
self.air.push(Air::List {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
count: elements.len(),
|
count: elements.len(),
|
||||||
|
@ -117,14 +166,16 @@ impl<'a> AirStack<'a> {
|
||||||
tail: tail.is_some(),
|
tail: tail.is_some(),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.sequence(elements);
|
self.merge_children(elements);
|
||||||
|
|
||||||
if let Some(tail) = tail {
|
if let Some(tail) = tail {
|
||||||
self.merge(tail);
|
self.merge_child(tail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record(&mut self, tipo: Arc<Type>, tag: usize, fields: Vec<AirStack>) {
|
pub fn record(&mut self, tipo: Arc<Type>, tag: usize, fields: Vec<AirStack>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Record {
|
self.air.push(Air::Record {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
tag,
|
tag,
|
||||||
|
@ -132,19 +183,21 @@ impl<'a> AirStack<'a> {
|
||||||
count: fields.len(),
|
count: fields.len(),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.sequence(fields);
|
self.merge_children(fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&mut self, tipo: Arc<Type>, fun: AirStack, args: Vec<AirStack>) {
|
pub fn call(&mut self, tipo: Arc<Type>, fun: AirStack, args: Vec<AirStack>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Call {
|
self.air.push(Air::Call {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
count: args.len(),
|
count: args.len(),
|
||||||
tipo,
|
tipo,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.merge(fun);
|
self.merge_child(fun);
|
||||||
|
|
||||||
self.sequence(args);
|
self.merge_children(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binop(
|
pub fn binop(
|
||||||
|
@ -154,26 +207,62 @@ impl<'a> AirStack<'a> {
|
||||||
left: AirStack,
|
left: AirStack,
|
||||||
right: AirStack,
|
right: AirStack,
|
||||||
) {
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::BinOp {
|
self.air.push(Air::BinOp {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
name,
|
name,
|
||||||
tipo,
|
tipo,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.merge(left);
|
self.merge_child(left);
|
||||||
self.merge(right);
|
self.merge_child(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) {
|
pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::Let {
|
self.air.push(Air::Let {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.merge(value);
|
self.merge_child(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_list_from_data(
|
||||||
|
&mut self,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
name: impl ToString,
|
||||||
|
unwrap_function: AirStack,
|
||||||
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Builtin {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
func: DefaultFunction::ChooseUnit,
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
count: DefaultFunction::ChooseUnit.arity(),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Call {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
count: 2,
|
||||||
|
tipo,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.local_var(tipo.clone(), EXPECT_ON_LIST);
|
||||||
|
|
||||||
|
self.local_var(tipo, name);
|
||||||
|
|
||||||
|
self.merge_child(unwrap_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wrap_data(&mut self, tipo: Arc<Type>) {
|
pub fn wrap_data(&mut self, tipo: Arc<Type>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::WrapData {
|
self.air.push(Air::WrapData {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
tipo,
|
tipo,
|
||||||
|
@ -181,9 +270,150 @@ impl<'a> AirStack<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn un_wrap_data(&mut self, tipo: Arc<Type>) {
|
pub fn un_wrap_data(&mut self, tipo: Arc<Type>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
self.air.push(Air::UnWrapData {
|
self.air.push(Air::UnWrapData {
|
||||||
scope: self.scope.clone(),
|
scope: self.scope.clone(),
|
||||||
tipo,
|
tipo,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn void(&mut self) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Void {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tuple_accessor(
|
||||||
|
&mut self,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
names: Vec<String>,
|
||||||
|
check_last_item: bool,
|
||||||
|
value: AirStack,
|
||||||
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::TupleAccessor {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
names,
|
||||||
|
tipo,
|
||||||
|
check_last_item,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.merge_child(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fields_expose(
|
||||||
|
&mut self,
|
||||||
|
indices: Vec<(usize, String, Arc<Type>)>,
|
||||||
|
check_last_item: bool,
|
||||||
|
value: AirStack,
|
||||||
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::FieldsExpose {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
indices,
|
||||||
|
check_last_item,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.merge_child(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clause(
|
||||||
|
&mut self,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
subject_name: impl ToString,
|
||||||
|
tag: usize,
|
||||||
|
complex_clause: bool,
|
||||||
|
body: AirStack,
|
||||||
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Clause {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
subject_name: subject_name.to_string(),
|
||||||
|
complex_clause,
|
||||||
|
tipo,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.integer(tag.to_string());
|
||||||
|
|
||||||
|
self.merge_child(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trace(&mut self, tipo: Arc<Type>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Trace {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
tipo,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(&mut self, tipo: Arc<Type>) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::ErrorTerm {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
tipo,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_constr_from_data(&mut self, tipo: Arc<Type>, when_stack: AirStack) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::Builtin {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
func: DefaultFunction::ChooseUnit,
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
count: DefaultFunction::ChooseUnit.arity(),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.merge_child(when_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn when(
|
||||||
|
&mut self,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
subject_name: impl ToString,
|
||||||
|
subject_stack: AirStack,
|
||||||
|
clauses_stack: AirStack,
|
||||||
|
else_stack: AirStack,
|
||||||
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::When {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
subject_name: subject_name.to_string(),
|
||||||
|
tipo,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.merge_child(subject_stack);
|
||||||
|
self.merge_child(clauses_stack);
|
||||||
|
self.merge_child(else_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_accessor(
|
||||||
|
&mut self,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
names: Vec<String>,
|
||||||
|
tail: bool,
|
||||||
|
check_last_item: bool,
|
||||||
|
value: AirStack,
|
||||||
|
) {
|
||||||
|
self.new_scope();
|
||||||
|
|
||||||
|
self.air.push(Air::ListAccessor {
|
||||||
|
scope: self.scope.clone(),
|
||||||
|
names,
|
||||||
|
tail,
|
||||||
|
check_last_item,
|
||||||
|
tipo,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.merge_child(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer";
|
pub const CONSTR_FIELDS_EXPOSER: &str = "__constr_fields_exposer";
|
||||||
pub const CONSTR_INDEX_EXPOSER: &str = "__constr_index_exposer";
|
pub const CONSTR_INDEX_EXPOSER: &str = "__constr_index_exposer";
|
||||||
pub const CONSTR_GET_FIELD: &str = "__constr_get_field";
|
pub const CONSTR_GET_FIELD: &str = "__constr_get_field";
|
||||||
pub const ASSERT_ON_LIST: &str = "__assert_on_list";
|
pub const EXPECT_ON_LIST: &str = "__expect_on_list";
|
||||||
|
|
||||||
impl Term<Name> {
|
impl Term<Name> {
|
||||||
pub fn apply(self, arg: Self) -> Self {
|
pub fn apply(self, arg: Self) -> Self {
|
||||||
|
@ -213,11 +213,11 @@ impl Term<Name> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_on_list(self) -> Term<Name> {
|
pub fn assert_on_list(self) -> Term<Name> {
|
||||||
self.lambda(ASSERT_ON_LIST.to_string())
|
self.lambda(EXPECT_ON_LIST.to_string())
|
||||||
.apply(
|
.apply(
|
||||||
Term::var(ASSERT_ON_LIST.to_string()).apply(Term::var(ASSERT_ON_LIST.to_string())),
|
Term::var(EXPECT_ON_LIST.to_string()).apply(Term::var(EXPECT_ON_LIST.to_string())),
|
||||||
)
|
)
|
||||||
.lambda(ASSERT_ON_LIST.to_string())
|
.lambda(EXPECT_ON_LIST.to_string())
|
||||||
.apply(
|
.apply(
|
||||||
Term::var("__list_to_check".to_string())
|
Term::var("__list_to_check".to_string())
|
||||||
.delayed_choose_list(
|
.delayed_choose_list(
|
||||||
|
@ -227,8 +227,8 @@ impl Term<Name> {
|
||||||
Term::head_list().apply(Term::var("__list_to_check".to_string())),
|
Term::head_list().apply(Term::var("__list_to_check".to_string())),
|
||||||
)
|
)
|
||||||
.choose_unit(
|
.choose_unit(
|
||||||
Term::var(ASSERT_ON_LIST.to_string())
|
Term::var(EXPECT_ON_LIST.to_string())
|
||||||
.apply(Term::var(ASSERT_ON_LIST.to_string()))
|
.apply(Term::var(EXPECT_ON_LIST.to_string()))
|
||||||
.apply(
|
.apply(
|
||||||
Term::tail_list()
|
Term::tail_list()
|
||||||
.apply(Term::var("__list_to_check".to_string())),
|
.apply(Term::var("__list_to_check".to_string())),
|
||||||
|
@ -238,7 +238,7 @@ impl Term<Name> {
|
||||||
)
|
)
|
||||||
.lambda("__check_with".to_string())
|
.lambda("__check_with".to_string())
|
||||||
.lambda("__list_to_check".to_string())
|
.lambda("__list_to_check".to_string())
|
||||||
.lambda(ASSERT_ON_LIST),
|
.lambda(EXPECT_ON_LIST),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue