use std::sync::Arc; use indexmap::IndexSet; use uplc::builtins::DefaultFunction; use crate::{ ast::{BinOp, UnOp}, tipo::{Type, ValueConstructor}, }; #[derive(Debug, Clone)] pub enum Air { // Primitives Int { scope: Vec, value: String, }, String { scope: Vec, value: String, }, ByteArray { scope: Vec, bytes: Vec, }, Bool { scope: Vec, value: bool, }, List { scope: Vec, count: usize, tipo: Arc, tail: bool, }, Tuple { scope: Vec, tipo: Arc, count: usize, }, Void { scope: Vec, }, Var { scope: Vec, constructor: ValueConstructor, name: String, variant_name: String, }, // Functions Call { scope: Vec, count: usize, tipo: Arc, }, DefineFunc { scope: Vec, func_name: String, module_name: String, params: Vec, recursive: bool, variant_name: String, }, Fn { scope: Vec, params: Vec, }, Builtin { scope: Vec, func: DefaultFunction, tipo: Arc, }, // Operators BinOp { scope: Vec, name: BinOp, count: usize, tipo: Arc, }, UnOp { scope: Vec, op: UnOp, }, // Assignment Let { scope: Vec, name: String, }, UnWrapData { scope: Vec, tipo: Arc, }, AssertConstr { scope: Vec, constr_index: usize, }, // When When { scope: Vec, tipo: Arc, subject_name: String, }, Clause { scope: Vec, tipo: Arc, subject_name: String, complex_clause: bool, }, ListClause { scope: Vec, tipo: Arc, tail_name: String, next_tail_name: Option, complex_clause: bool, }, WrapClause { scope: Vec, }, TupleClause { scope: Vec, tipo: Arc, indices: IndexSet<(usize, String)>, predefined_indices: IndexSet<(usize, String)>, subject_name: String, count: usize, complex_clause: bool, }, ClauseGuard { scope: Vec, subject_name: String, tipo: Arc, }, ListClauseGuard { scope: Vec, tipo: Arc, tail_name: String, next_tail_name: Option, inverse: bool, }, Finally { scope: Vec, }, // If If { scope: Vec, tipo: Arc, }, // Record Creation Record { scope: Vec, constr_index: usize, tipo: Arc, count: usize, }, RecordUpdate { scope: Vec, highest_index: usize, indices: Vec<(usize, Arc)>, tipo: Arc, }, // Field Access RecordAccess { scope: Vec, record_index: u64, tipo: Arc, }, FieldsExpose { scope: Vec, indices: Vec<(usize, String, Arc)>, check_last_item: bool, }, // ListAccess ListAccessor { scope: Vec, tipo: Arc, names: Vec, tail: bool, check_last_item: bool, }, ListExpose { scope: Vec, tipo: Arc, tail_head_names: Vec<(String, String)>, tail: Option<(String, String)>, }, // Tuple Access TupleAccessor { scope: Vec, names: Vec, tipo: Arc, check_last_item: bool, }, TupleIndex { scope: Vec, tipo: Arc, tuple_index: usize, }, // Misc. Todo { scope: Vec, label: Option, tipo: Arc, }, ErrorTerm { scope: Vec, tipo: Arc, label: Option, }, Trace { scope: Vec, text: Option, tipo: Arc, }, } impl Air { pub fn scope(&self) -> Vec { 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::AssertConstr { 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::ListAccessor { scope, .. } | Air::ListExpose { scope, .. } | Air::TupleAccessor { scope, .. } | Air::TupleIndex { scope, .. } | Air::Todo { scope, .. } | Air::ErrorTerm { scope, .. } | Air::Trace { scope, .. } => scope.clone(), } } 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::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::Todo { tipo, .. } | Air::ErrorTerm { tipo, .. } | Air::Trace { tipo, .. } => Some(tipo.clone()), Air::DefineFunc { .. } | Air::Fn { .. } | Air::Let { .. } | Air::WrapClause { .. } | Air::AssertConstr { .. } | Air::Finally { .. } | Air::FieldsExpose { .. } => 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(), ), }, } } }