diff --git a/crates/aiken-lang/src/gen_uplc_old/air.rs b/crates/aiken-lang/src/gen_uplc_old/air.rs deleted file mode 100644 index 190432a4..00000000 --- a/crates/aiken-lang/src/gen_uplc_old/air.rs +++ /dev/null @@ -1,430 +0,0 @@ -use indexmap::IndexSet; -use std::sync::Arc; -use uplc::builtins::DefaultFunction; - -use crate::{ - ast::{BinOp, UnOp}, - tipo::{Type, ValueConstructor}, -}; - -use super::scope::Scope; - -#[derive(Debug, Clone, PartialEq)] -pub enum Air { - // Primitives - Int { - scope: Scope, - value: String, - }, - String { - scope: Scope, - value: String, - }, - ByteArray { - scope: Scope, - bytes: Vec, - }, - Bool { - scope: Scope, - value: bool, - }, - List { - scope: Scope, - count: usize, - tipo: Arc, - tail: bool, - }, - Tuple { - scope: Scope, - tipo: Arc, - count: usize, - }, - Void { - scope: Scope, - }, - Var { - scope: Scope, - constructor: ValueConstructor, - name: String, - variant_name: String, - }, - // Functions - Call { - scope: Scope, - count: usize, - tipo: Arc, - }, - DefineFunc { - scope: Scope, - func_name: String, - module_name: String, - params: Vec, - recursive: bool, - variant_name: String, - }, - Fn { - scope: Scope, - params: Vec, - }, - Builtin { - scope: Scope, - count: usize, - func: DefaultFunction, - tipo: Arc, - }, - // Operators - BinOp { - scope: Scope, - name: BinOp, - tipo: Arc, - }, - UnOp { - scope: Scope, - op: UnOp, - }, - // Assignment - Let { - scope: Scope, - name: String, - }, - UnWrapData { - scope: Scope, - tipo: Arc, - }, - WrapData { - scope: Scope, - tipo: Arc, - }, - AssertConstr { - scope: Scope, - constr_index: usize, - }, - AssertBool { - scope: Scope, - is_true: bool, - }, - // When - When { - scope: Scope, - tipo: Arc, - subject_name: String, - }, - Clause { - scope: Scope, - tipo: Arc, - subject_name: String, - complex_clause: bool, - }, - ListClause { - scope: Scope, - tipo: Arc, - tail_name: String, - next_tail_name: Option, - complex_clause: bool, - }, - WrapClause { - scope: Scope, - }, - TupleClause { - scope: Scope, - tipo: Arc, - indices: IndexSet<(usize, String)>, - predefined_indices: IndexSet<(usize, String)>, - subject_name: String, - count: usize, - complex_clause: bool, - }, - ClauseGuard { - scope: Scope, - subject_name: String, - tipo: Arc, - }, - ListClauseGuard { - scope: Scope, - tipo: Arc, - tail_name: String, - next_tail_name: Option, - inverse: bool, - }, - Finally { - scope: Scope, - }, - // If - If { - scope: Scope, - tipo: Arc, - }, - // Record Creation - Record { - scope: Scope, - tag: usize, - tipo: Arc, - count: usize, - }, - RecordUpdate { - scope: Scope, - highest_index: usize, - indices: Vec<(usize, Arc)>, - tipo: Arc, - }, - // Field Access - RecordAccess { - scope: Scope, - record_index: u64, - tipo: Arc, - }, - FieldsExpose { - scope: Scope, - indices: Vec<(usize, String, Arc)>, - check_last_item: bool, - }, - // ListAccess - ListAccessor { - scope: Scope, - tipo: Arc, - names: Vec, - tail: bool, - check_last_item: bool, - }, - ListExpose { - scope: Scope, - tipo: Arc, - tail_head_names: Vec<(String, String)>, - tail: Option<(String, String)>, - }, - // Tuple Access - TupleAccessor { - scope: Scope, - names: Vec, - tipo: Arc, - check_last_item: bool, - }, - TupleIndex { - scope: Scope, - tipo: Arc, - tuple_index: usize, - }, - // Misc. - ErrorTerm { - scope: Scope, - tipo: Arc, - }, - Trace { - scope: Scope, - tipo: Arc, - }, - NoOp { - scope: Scope, - }, - FieldsEmpty { - scope: Scope, - }, - ListEmpty { - scope: Scope, - }, -} - -impl Air { - pub fn scope(&self) -> Scope { - match self { - Air::Int { scope, .. } - | Air::String { scope, .. } - | Air::ByteArray { scope, .. } - | Air::Bool { scope, .. } - | Air::List { scope, .. } - | Air::Tuple { scope, .. } - | Air::Void { scope } - | Air::Var { scope, .. } - | Air::Call { scope, .. } - | Air::DefineFunc { scope, .. } - | Air::Fn { scope, .. } - | Air::Builtin { scope, .. } - | Air::BinOp { scope, .. } - | Air::UnOp { scope, .. } - | Air::Let { scope, .. } - | Air::UnWrapData { scope, .. } - | Air::WrapData { scope, .. } - | Air::AssertConstr { scope, .. } - | Air::AssertBool { scope, .. } - | Air::When { scope, .. } - | Air::Clause { scope, .. } - | Air::ListClause { scope, .. } - | Air::WrapClause { scope } - | Air::TupleClause { scope, .. } - | Air::ClauseGuard { scope, .. } - | Air::ListClauseGuard { scope, .. } - | Air::Finally { scope } - | Air::If { scope, .. } - | Air::Record { scope, .. } - | Air::RecordUpdate { scope, .. } - | Air::RecordAccess { scope, .. } - | Air::FieldsExpose { scope, .. } - | Air::FieldsEmpty { scope } - | Air::ListEmpty { scope } - | Air::ListAccessor { scope, .. } - | Air::ListExpose { scope, .. } - | Air::TupleAccessor { scope, .. } - | Air::TupleIndex { scope, .. } - | Air::ErrorTerm { scope, .. } - | Air::Trace { scope, .. } - | Air::NoOp { scope, .. } => scope.clone(), - } - } - pub fn scope_mut(&mut self) -> &mut Scope { - match self { - Air::Int { scope, .. } - | Air::String { scope, .. } - | Air::ByteArray { scope, .. } - | Air::Bool { scope, .. } - | Air::List { scope, .. } - | Air::Tuple { scope, .. } - | Air::Void { scope } - | Air::Var { scope, .. } - | Air::Call { scope, .. } - | Air::DefineFunc { scope, .. } - | Air::Fn { scope, .. } - | Air::Builtin { scope, .. } - | Air::BinOp { scope, .. } - | Air::UnOp { scope, .. } - | Air::Let { scope, .. } - | Air::UnWrapData { scope, .. } - | Air::WrapData { scope, .. } - | Air::AssertConstr { scope, .. } - | Air::AssertBool { scope, .. } - | Air::When { scope, .. } - | Air::Clause { scope, .. } - | Air::ListClause { scope, .. } - | Air::WrapClause { scope } - | Air::TupleClause { scope, .. } - | Air::ClauseGuard { scope, .. } - | Air::ListClauseGuard { scope, .. } - | Air::Finally { scope } - | Air::If { scope, .. } - | Air::Record { scope, .. } - | Air::RecordUpdate { scope, .. } - | Air::RecordAccess { scope, .. } - | Air::FieldsExpose { scope, .. } - | Air::FieldsEmpty { scope } - | Air::ListEmpty { scope } - | Air::ListAccessor { scope, .. } - | Air::ListExpose { scope, .. } - | Air::TupleAccessor { scope, .. } - | Air::TupleIndex { scope, .. } - | Air::ErrorTerm { scope, .. } - | Air::Trace { scope, .. } - | Air::NoOp { scope, .. } => scope, - } - } - pub fn tipo(&self) -> Option> { - match self { - Air::Int { .. } => Some( - Type::App { - public: true, - module: String::new(), - name: "Int".to_string(), - args: vec![], - } - .into(), - ), - Air::String { .. } => Some( - Type::App { - public: true, - module: String::new(), - name: "String".to_string(), - args: vec![], - } - .into(), - ), - Air::ByteArray { .. } => Some( - Type::App { - public: true, - module: String::new(), - name: "ByteArray".to_string(), - args: vec![], - } - .into(), - ), - Air::Bool { .. } => Some( - Type::App { - public: true, - module: String::new(), - name: "Bool".to_string(), - args: vec![], - } - .into(), - ), - Air::Void { .. } => Some( - Type::App { - public: true, - module: String::new(), - name: "Void".to_string(), - args: vec![], - } - .into(), - ), - Air::WrapData { .. } => Some( - Type::App { - public: true, - module: String::new(), - name: "Data".to_string(), - args: vec![], - } - .into(), - ), - Air::Var { constructor, .. } => Some(constructor.tipo.clone()), - Air::List { tipo, .. } - | Air::Tuple { tipo, .. } - | Air::Call { tipo, .. } - | Air::Builtin { tipo, .. } - | Air::BinOp { tipo, .. } - | Air::UnWrapData { tipo, .. } - | Air::When { tipo, .. } - | Air::Clause { tipo, .. } - | Air::ListClause { tipo, .. } - | Air::TupleClause { tipo, .. } - | Air::ClauseGuard { tipo, .. } - | Air::If { tipo, .. } - | Air::ListClauseGuard { tipo, .. } - | Air::Record { tipo, .. } - | Air::RecordUpdate { tipo, .. } - | Air::RecordAccess { tipo, .. } - | Air::ListAccessor { tipo, .. } - | Air::ListExpose { tipo, .. } - | Air::TupleAccessor { tipo, .. } - | Air::TupleIndex { tipo, .. } - | Air::ErrorTerm { tipo, .. } - | Air::Trace { tipo, .. } => Some(tipo.clone()), - Air::DefineFunc { .. } - | Air::Fn { .. } - | Air::Let { .. } - | Air::WrapClause { .. } - | Air::AssertConstr { .. } - | Air::AssertBool { .. } - | Air::Finally { .. } - | Air::FieldsExpose { .. } - | Air::FieldsEmpty { .. } - | Air::ListEmpty { .. } - | Air::NoOp { .. } => None, - Air::UnOp { op, .. } => match op { - UnOp::Not => Some( - Type::App { - public: true, - module: String::new(), - name: "Bool".to_string(), - args: vec![], - } - .into(), - ), - UnOp::Negate => Some( - Type::App { - public: true, - module: String::new(), - name: "Int".to_string(), - args: vec![], - } - .into(), - ), - }, - } - } -} diff --git a/crates/aiken-lang/src/gen_uplc_old/builder.rs b/crates/aiken-lang/src/gen_uplc_old/builder.rs deleted file mode 100644 index 8b137891..00000000 --- a/crates/aiken-lang/src/gen_uplc_old/builder.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/aiken-lang/src/gen_uplc_old/scope.rs b/crates/aiken-lang/src/gen_uplc_old/scope.rs deleted file mode 100644 index fe58855a..00000000 --- a/crates/aiken-lang/src/gen_uplc_old/scope.rs +++ /dev/null @@ -1,147 +0,0 @@ -#[derive(Debug, Clone, Default, Eq, PartialEq)] -pub struct Scope(pub(self) Vec); - -impl From> for Scope { - fn from(value: Vec) -> Self { - Self(value) - } -} - -impl Scope { - pub fn push(&mut self, value: u64) { - self.0.push(value); - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Find the common ancestor with the replacement, - /// remove it from `self`, and then prepend the - /// `replacement` to `self`. - pub fn replace(&mut self, mut replacement: Scope) { - let common = self.common_ancestor(&replacement); - - // we know that common will always be in the front of the - // scope Vec so we can always drain `0..common.len()`. - self.0.drain(0..common.0.len()); - - replacement.0.extend(self.0.iter()); - self.0 = replacement.0; - } - - 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() - } -} - -#[cfg(test)] -mod test { - use pretty_assertions::assert_eq; - - use super::Scope; - - #[test] - fn common_ancestor_equal_vecs() { - let ancestor = Scope(vec![1, 2, 3, 4, 5, 6]); - - let descendant = Scope(vec![1, 2, 3, 4, 5, 6]); - - let result = ancestor.common_ancestor(&descendant); - - assert_eq!(result, Scope(vec![1, 2, 3, 4, 5, 6])) - } - - #[test] - fn common_ancestor_equal_ancestor() { - let ancestor = Scope(vec![1, 2, 3, 4]); - - let descendant = Scope(vec![1, 2, 3, 4, 5, 6]); - - let result = ancestor.common_ancestor(&descendant); - - assert_eq!(result, Scope(vec![1, 2, 3, 4])); - } - - #[test] - fn common_ancestor_not_subset() { - let ancestor = Scope(vec![1, 2, 3, 4, 5]); - - let descendant = Scope(vec![1, 2, 3, 7, 8]); - - let result = ancestor.common_ancestor(&descendant); - - assert_eq!(result, Scope(vec![1, 2, 3])); - } - - #[test] - fn common_ancestor_not_found() { - let ancestor = Scope(vec![1, 2, 3, 4, 5, 6]); - - let descendant = Scope(vec![4, 5, 6]); - - let result = ancestor.common_ancestor(&descendant); - - assert_eq!(result, Scope::default()); - } - - #[test] - fn common_ancestor_no_shared_values() { - let ancestor = Scope(vec![1, 2, 3]); - - let descendant = Scope(vec![4, 5, 6]); - - let result = ancestor.common_ancestor(&descendant); - - assert_eq!(result, Scope::default()); - } - - #[test] - fn replace_same_value() { - let mut value = Scope(vec![1, 2, 3, 4, 5, 6]); - - let replacement = Scope(vec![1, 2, 3, 4, 5, 6]); - - value.replace(replacement); - - assert_eq!(value, Scope(vec![1, 2, 3, 4, 5, 6])); - } - - #[test] - fn replace_with_pattern() { - let mut value = Scope(vec![1, 2, 3, 4, 5]); - - let replacement = Scope(vec![1, 2, 8, 9]); - - value.replace(replacement); - - assert_eq!(value, Scope(vec![1, 2, 8, 9, 3, 4, 5])); - } - - #[test] - fn replace_with_no_pattern() { - let mut value = Scope(vec![1, 2, 3, 4, 5]); - - let replacement = Scope(vec![8, 9]); - - value.replace(replacement); - - assert_eq!(value, Scope(vec![8, 9, 1, 2, 3, 4, 5])); - } -} diff --git a/crates/aiken-lang/src/gen_uplc_old/stack.rs b/crates/aiken-lang/src/gen_uplc_old/stack.rs deleted file mode 100644 index e568480a..00000000 --- a/crates/aiken-lang/src/gen_uplc_old/stack.rs +++ /dev/null @@ -1,1043 +0,0 @@ -use std::{rc::Rc, sync::Arc}; - -use indexmap::IndexSet; - -use uplc::{builder::EXPECT_ON_LIST, builtins::DefaultFunction}; - -use crate::{ - ast::Span, - builtins::{data, list, void}, - tipo::{Type, ValueConstructor, ValueConstructorVariant}, - IdGenerator, -}; - -use super::{air::Air, scope::Scope}; - -/// A builder for [`Air`]. -#[derive(Debug)] -pub struct AirStack { - pub id_gen: Rc, - pub scope: Scope, - pub air: Vec, -} - -impl AirStack { - /// Create a new [`AirStack`] with an [`IdGenerator`] - pub fn new(id_gen: Rc) -> Self { - AirStack { - id_gen, - scope: Scope::default(), - air: vec![], - } - } - - /// Create a new [`AirStack`] with an [`IdGenerator`] and [`Scope`]. - pub fn with_scope(id_gen: Rc, scope: Scope) -> Self { - AirStack { - id_gen, - scope, - air: vec![], - } - } - - /// Create a new empty [`AirStack`] with the current stack's scope. - pub fn empty_with_scope(&mut self) -> Self { - AirStack::with_scope(self.id_gen.clone(), self.scope.clone()) - } - - /// Increment the [`Scope`] - fn new_scope(&mut self) { - 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) { - self.air.append(&mut other.air); - } - - pub fn merge_child(&mut self, mut other: AirStack) { - for ir in other.air.iter_mut() { - ir.scope_mut().replace(self.scope.clone()); - } - - self.merge(other); - } - - pub fn merge_children(&mut self, stacks: Vec) { - for stack in stacks { - self.merge_child(stack) - } - } - - pub fn complete(self) -> Vec { - self.air - } - - pub fn sequence(&mut self, stacks: Vec) { - for stack in stacks { - self.merge(stack) - } - } - - pub fn integer(&mut self, value: String) { - self.new_scope(); - - self.air.push(Air::Int { - scope: self.scope.clone(), - value, - }); - } - - pub fn string(&mut self, value: impl ToString) { - self.new_scope(); - - self.air.push(Air::String { - scope: self.scope.clone(), - value: value.to_string(), - }); - } - - pub fn byte_array(&mut self, bytes: Vec) { - self.new_scope(); - - self.air.push(Air::ByteArray { - scope: self.scope.clone(), - bytes, - }); - } - - pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc, args: Vec) { - self.new_scope(); - - self.air.push(Air::Builtin { - scope: self.scope.clone(), - count: args.len(), - func, - tipo, - }); - - self.merge_children(args); - } - - pub fn var( - &mut self, - constructor: ValueConstructor, - name: impl ToString, - variant_name: impl ToString, - ) { - self.new_scope(); - - self.air.push(Air::Var { - scope: self.scope.clone(), - constructor, - name: name.to_string(), - variant_name: variant_name.to_string(), - }); - } - - pub fn local_var(&mut self, tipo: Arc, 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, body: AirStack) { - self.new_scope(); - - self.air.push(Air::Fn { - scope: self.scope.clone(), - params, - }); - - self.merge_child(body); - } - - pub fn list(&mut self, tipo: Arc, elements: Vec, tail: Option) { - self.new_scope(); - - self.air.push(Air::List { - scope: self.scope.clone(), - count: elements.len(), - tipo, - tail: tail.is_some(), - }); - - self.merge_children(elements); - - if let Some(tail) = tail { - self.merge_child(tail); - } - } - - pub fn record(&mut self, tipo: Arc, tag: usize, fields: Vec) { - self.new_scope(); - - self.air.push(Air::Record { - scope: self.scope.clone(), - tag, - tipo, - count: fields.len(), - }); - - self.merge_children(fields); - } - - pub fn call(&mut self, tipo: Arc, fun: AirStack, args: Vec) { - self.new_scope(); - - self.air.push(Air::Call { - scope: self.scope.clone(), - count: args.len(), - tipo, - }); - - self.merge_child(fun); - - self.merge_children(args); - } - - pub fn binop( - &mut self, - name: crate::ast::BinOp, - tipo: Arc, - left: AirStack, - right: AirStack, - ) { - self.new_scope(); - - self.air.push(Air::BinOp { - scope: self.scope.clone(), - name, - tipo, - }); - - self.merge_child(left); - self.merge_child(right); - } - - pub fn unop(&mut self, op: crate::ast::UnOp, value: AirStack) { - self.new_scope(); - - self.air.push(Air::UnOp { - scope: self.scope.clone(), - op, - }); - - self.merge_child(value); - } - - pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) { - self.new_scope(); - - self.air.push(Air::Let { - scope: self.scope.clone(), - name: name.to_string(), - }); - - self.merge_child(value); - } - - pub fn expect_list_from_data( - &mut self, - tipo: Arc, - 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: tipo.clone(), - }); - - self.var( - ValueConstructor::public( - void(), - ValueConstructorVariant::ModuleFn { - name: EXPECT_ON_LIST.to_string(), - field_map: None, - module: "".to_string(), - arity: 2, - location: Span::empty(), - builtin: None, - }, - ), - EXPECT_ON_LIST, - "", - ); - - self.local_var(tipo, name); - - self.merge_child(unwrap_function); - } - - pub fn wrap_data(&mut self, tipo: Arc) { - self.new_scope(); - - self.air.push(Air::WrapData { - scope: self.scope.clone(), - tipo, - }) - } - - pub fn un_wrap_data(&mut self, tipo: Arc) { - self.new_scope(); - - self.air.push(Air::UnWrapData { - scope: self.scope.clone(), - 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, - names: Vec, - 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)>, - 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 fields_empty(&mut self, value: AirStack) { - self.new_scope(); - - self.air.push(Air::FieldsEmpty { - scope: self.scope.clone(), - }); - - self.merge_child(value); - } - - pub fn clause( - &mut self, - tipo: Arc, - subject_name: impl ToString, - 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.merge_child(body); - } - - pub fn list_clause( - &mut self, - tipo: Arc, - tail_name: impl ToString, - next_tail_name: Option, - complex_clause: bool, - body: AirStack, - ) { - self.new_scope(); - - self.air.push(Air::ListClause { - scope: self.scope.clone(), - tail_name: tail_name.to_string(), - next_tail_name, - complex_clause, - tipo, - }); - - self.merge_child(body); - } - - pub fn tuple_clause( - &mut self, - tipo: Arc, - subject_name: impl ToString, - indices: IndexSet<(usize, String)>, - predefined_indices: IndexSet<(usize, String)>, - complex_clause: bool, - body: AirStack, - ) { - self.new_scope(); - - let count = tipo.get_inner_types().len(); - - self.air.push(Air::TupleClause { - scope: self.scope.clone(), - subject_name: subject_name.to_string(), - indices, - predefined_indices, - complex_clause, - tipo, - count, - }); - - self.merge_child(body); - } - - pub fn wrap_clause(&mut self, body: AirStack) { - self.new_scope(); - - self.air.push(Air::WrapClause { - scope: self.scope.clone(), - }); - - self.merge_child(body); - } - - pub fn trace(&mut self, tipo: Arc) { - self.new_scope(); - - self.air.push(Air::Trace { - scope: self.scope.clone(), - tipo, - }) - } - - pub fn error(&mut self, tipo: Arc) { - self.new_scope(); - - self.air.push(Air::ErrorTerm { - scope: self.scope.clone(), - tipo, - }) - } - - pub fn expect_constr_from_data(&mut self, tipo: Arc, when_stack: AirStack) { - self.new_scope(); - - self.air.push(Air::Builtin { - scope: self.scope.clone(), - func: DefaultFunction::ChooseUnit, - tipo, - count: DefaultFunction::ChooseUnit.arity(), - }); - - self.merge_child(when_stack); - } - - pub fn when( - &mut self, - tipo: Arc, - 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, - names: Vec, - 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); - } - - pub fn expect_constr(&mut self, tag: usize, value: AirStack) { - self.new_scope(); - - self.air.push(Air::AssertConstr { - scope: self.scope.clone(), - constr_index: tag, - }); - - self.merge_child(value); - } - - pub fn expect_bool(&mut self, is_true: bool, value: AirStack) { - self.new_scope(); - - self.air.push(Air::AssertBool { - scope: self.scope.clone(), - is_true, - }); - - self.merge_child(value); - } - - pub fn if_branch(&mut self, tipo: Arc, condition: AirStack, branch_body: AirStack) { - self.new_scope(); - - self.air.push(Air::If { - scope: self.scope.clone(), - tipo, - }); - - self.merge_child(condition); - self.merge_child(branch_body); - } - - pub fn record_access(&mut self, tipo: Arc, record_index: u64, record: AirStack) { - self.new_scope(); - - self.air.push(Air::RecordAccess { - scope: self.scope.clone(), - record_index, - tipo, - }); - - self.merge_child(record); - } - - pub fn record_update( - &mut self, - tipo: Arc, - highest_index: usize, - indices: Vec<(usize, Arc)>, - update: AirStack, - ) { - self.new_scope(); - - self.air.push(Air::RecordUpdate { - scope: self.scope.clone(), - highest_index, - indices, - tipo, - }); - - self.merge_child(update); - } - - pub fn tuple(&mut self, tipo: Arc, elems: Vec) { - self.new_scope(); - - self.air.push(Air::Tuple { - scope: self.scope.clone(), - count: elems.len(), - tipo, - }); - - self.merge_children(elems); - } - - pub fn tuple_index(&mut self, tipo: Arc, tuple_index: usize, tuple: AirStack) { - self.new_scope(); - - self.air.push(Air::TupleIndex { - scope: self.scope.clone(), - tuple_index, - tipo, - }); - - self.merge_child(tuple); - } - - pub fn finally(&mut self, value: AirStack) { - self.new_scope(); - - self.air.push(Air::Finally { - scope: self.scope.clone(), - }); - - self.merge_child(value); - } - - pub fn bool(&mut self, value: bool) { - self.new_scope(); - - self.air.push(Air::Bool { - scope: self.scope.clone(), - value, - }); - } - - pub fn clause_guard( - &mut self, - subject_name: impl ToString, - tipo: Arc, - condition_stack: AirStack, - clause_then_stack: AirStack, - ) { - self.new_scope(); - - self.air.push(Air::ClauseGuard { - scope: self.scope.clone(), - subject_name: subject_name.to_string(), - tipo, - }); - - self.merge_child(condition_stack); - - self.merge_child(clause_then_stack); - } - - pub fn list_expose( - &mut self, - tipo: Arc, - tail_head_names: Vec<(String, String)>, - tail: Option<(String, String)>, - value: AirStack, - ) { - self.new_scope(); - - self.air.push(Air::ListExpose { - scope: self.scope.clone(), - tipo, - tail_head_names, - tail, - }); - - self.merge_child(value); - } - - pub fn list_clause_guard( - &mut self, - tipo: Arc, - tail_name: impl ToString, - next_tail_name: Option, - inverse: bool, - void_stack: AirStack, - ) { - self.new_scope(); - - self.air.push(Air::ListClauseGuard { - scope: self.scope.clone(), - tipo, - tail_name: tail_name.to_string(), - next_tail_name, - inverse, - }); - - self.merge_child(void_stack); - } - - pub fn define_func( - &mut self, - func_name: impl ToString, - module_name: impl ToString, - variant_name: impl ToString, - params: Vec, - recursive: bool, - body_stack: AirStack, - ) { - self.air.push(Air::DefineFunc { - scope: self.scope.clone(), - func_name: func_name.to_string(), - module_name: module_name.to_string(), - params, - recursive, - variant_name: variant_name.to_string(), - }); - - self.merge_child(body_stack); - } - - pub fn noop(&mut self) { - self.new_scope(); - - self.air.push(Air::NoOp { - scope: self.scope.clone(), - }); - } - - pub fn choose_unit(&mut self, value_stack: AirStack) { - self.new_scope(); - - self.air.push(Air::Builtin { - scope: self.scope.clone(), - func: DefaultFunction::ChooseUnit, - tipo: void(), - count: DefaultFunction::ChooseUnit.arity(), - }); - - self.merge_child(value_stack); - } - - pub fn expect_on_list(&mut self) { - let mut head_stack = self.empty_with_scope(); - let mut tail_stack = self.empty_with_scope(); - let mut check_with_stack = self.empty_with_scope(); - let mut expect_stack = self.empty_with_scope(); - let mut var_stack = self.empty_with_scope(); - let mut void_stack = self.empty_with_scope(); - let mut fun_stack = self.empty_with_scope(); - let mut arg_stack1 = self.empty_with_scope(); - let mut arg_stack2 = self.empty_with_scope(); - - self.air.push(Air::DefineFunc { - scope: self.scope.clone(), - func_name: EXPECT_ON_LIST.to_string(), - module_name: "".to_string(), - params: vec!["__list_to_check".to_string(), "__check_with".to_string()], - recursive: true, - variant_name: "".to_string(), - }); - - var_stack.local_var(list(data()), "__list_to_check"); - - head_stack.builtin(DefaultFunction::HeadList, data(), vec![var_stack]); - - fun_stack.local_var(void(), "__check_with".to_string()); - - check_with_stack.call(void(), fun_stack, vec![head_stack]); - - void_stack.void(); - void_stack.void(); - - self.list_clause(void(), "__list_to_check", None, false, void_stack); - - self.choose_unit(check_with_stack); - - expect_stack.var( - ValueConstructor::public( - void(), - ValueConstructorVariant::ModuleFn { - name: EXPECT_ON_LIST.to_string(), - field_map: None, - module: "".to_string(), - arity: 2, - location: Span::empty(), - builtin: None, - }, - ), - EXPECT_ON_LIST, - "", - ); - - arg_stack1.local_var(list(data()), "__list_to_check"); - - arg_stack2.local_var(void(), "__check_with"); - - tail_stack.builtin(DefaultFunction::TailList, list(data()), vec![arg_stack1]); - - self.call(void(), expect_stack, vec![tail_stack, arg_stack2]) - } - - pub fn list_empty(&mut self, value_stack: AirStack) { - self.new_scope(); - - self.air.push(Air::ListEmpty { - scope: self.scope.clone(), - }); - - self.merge_child(value_stack); - } -} - -#[cfg(test)] -mod test { - use std::rc::Rc; - - use uplc::builtins::DefaultFunction; - - use crate::{ - ast::Span, - builtins::{data, list, void}, - gen_uplc::air::Air, - tipo::{ValueConstructor, ValueConstructorVariant}, - IdGenerator, - }; - - use super::AirStack; - - #[test] - fn merge_different_scopes() { - let id_gen: Rc = IdGenerator::new().into(); - - let scope = vec![id_gen.next(), id_gen.next()]; - let scope2 = vec![id_gen.next(), id_gen.next()]; - - let air = vec![Air::Int { - scope: scope.clone().into(), - value: "1".to_string(), - }]; - - let air2 = vec![Air::Int { - scope: scope2.clone().into(), - value: "2".to_string(), - }]; - - let mut stack1 = AirStack { - id_gen: id_gen.clone(), - scope: scope.into(), - air, - }; - - let stack2 = AirStack { - id_gen, - scope: scope2.into(), - air: air2, - }; - - stack1.merge(stack2); - - assert_eq!(stack1.scope, vec![0, 1].into()); - - assert_eq!( - stack1.air, - vec![ - Air::Int { - scope: vec![0, 1].into(), - value: "1".to_string(), - }, - Air::Int { - scope: vec![2, 3].into(), - value: "2".to_string(), - }, - ], - ) - } - - #[test] - fn merge_child_common_ancestor() { - let id_gen: Rc = IdGenerator::new().into(); - - let scope = vec![id_gen.next(), id_gen.next()]; - let mut scope2 = scope.clone(); - scope2.push(id_gen.next()); - - let air = vec![Air::Int { - scope: scope.clone().into(), - value: "1".to_string(), - }]; - - let air2 = vec![Air::Int { - scope: scope2.clone().into(), - value: "2".to_string(), - }]; - - let mut stack1 = AirStack { - id_gen: id_gen.clone(), - scope: scope.into(), - air, - }; - - let stack2 = AirStack { - id_gen, - scope: scope2.into(), - air: air2, - }; - - stack1.merge_child(stack2); - - assert_eq!(stack1.scope, vec![0, 1].into()); - - assert_eq!( - stack1.air, - vec![ - Air::Int { - scope: vec![0, 1].into(), - value: "1".to_string(), - }, - Air::Int { - scope: vec![0, 1, 2].into(), - value: "2".to_string(), - }, - ], - ) - } - - #[test] - fn assert_on_list_matches_air() { - let id_gen: Rc = IdGenerator::new().into(); - - let scope = vec![id_gen.next()]; - - let mut stack1 = AirStack { - id_gen, - scope: scope.into(), - air: vec![], - }; - - stack1.expect_on_list(); - - println!("{:#?}", stack1); - - let air_vec = vec![ - Air::DefineFunc { - scope: vec![0].into(), - func_name: "__expect_on_list".to_string(), - module_name: "".to_string(), - params: vec!["__list_to_check".to_string(), "__check_with".to_string()], - recursive: true, - variant_name: "".to_string(), - }, - Air::ListClause { - scope: vec![0, 7].into(), - tipo: void(), - tail_name: "__list_to_check".to_string(), - next_tail_name: None, - complex_clause: false, - }, - Air::Void { - scope: vec![0, 7, 5].into(), - }, - Air::Void { - scope: vec![0, 7, 5, 6].into(), - }, - Air::Builtin { - scope: vec![0, 7, 8].into(), - count: 2, - func: DefaultFunction::ChooseUnit, - tipo: void(), - }, - Air::Call { - scope: vec![0, 7, 8, 4].into(), - count: 1, - tipo: void(), - }, - Air::Var { - scope: vec![0, 7, 8, 4, 3].into(), - constructor: ValueConstructor { - public: true, - variant: ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - tipo: void(), - }, - name: "__check_with".to_string(), - variant_name: "".to_string(), - }, - Air::Builtin { - scope: vec![0, 7, 8, 4, 2].into(), - count: 1, - func: DefaultFunction::HeadList, - tipo: data(), - }, - Air::Var { - scope: vec![0, 7, 8, 4, 2, 1].into(), - constructor: ValueConstructor { - public: true, - variant: ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - tipo: list(data()), - }, - name: "__list_to_check".to_string(), - variant_name: "".to_string(), - }, - Air::Call { - scope: vec![0, 7, 8, 13].into(), - count: 2, - tipo: void(), - }, - Air::Var { - scope: vec![0, 7, 8, 13, 9].into(), - constructor: ValueConstructor::public( - void(), - ValueConstructorVariant::ModuleFn { - name: "__expect_on_list".to_string(), - field_map: None, - module: "".to_string(), - arity: 2, - location: Span::empty(), - builtin: None, - }, - ), - name: "__expect_on_list".to_string(), - variant_name: "".to_string(), - }, - Air::Builtin { - scope: vec![0, 7, 8, 13, 12].into(), - count: 1, - func: DefaultFunction::TailList, - tipo: list(data()), - }, - Air::Var { - scope: vec![0, 7, 8, 13, 12, 10].into(), - constructor: ValueConstructor { - public: true, - variant: ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - tipo: list(data()), - }, - name: "__list_to_check".to_string(), - variant_name: "".to_string(), - }, - Air::Var { - scope: vec![0, 7, 8, 13, 11].into(), - constructor: ValueConstructor { - public: true, - variant: ValueConstructorVariant::LocalVariable { - location: Span::empty(), - }, - tipo: void(), - }, - name: "__check_with".to_string(), - variant_name: "".to_string(), - }, - ]; - - assert_eq!(stack1.air, air_vec) - } -}