From ba3265054cfbf0f1576db4331ac25a46caca79aa Mon Sep 17 00:00:00 2001 From: microproofs Date: Thu, 29 Jun 2023 13:30:24 -0400 Subject: [PATCH] chore: move tree to gen_uplc2 and create a duplicate air file without scope --- crates/aiken-lang/src/gen_uplc.rs | 1 - crates/aiken-lang/src/gen_uplc2.rs | 10 +- crates/aiken-lang/src/gen_uplc2/air.rs | 291 ++++++++++++++++++ crates/aiken-lang/src/gen_uplc2/builder.rs | 4 +- .../src/{gen_uplc => gen_uplc2}/tree.rs | 187 +++++++++-- 5 files changed, 461 insertions(+), 32 deletions(-) create mode 100644 crates/aiken-lang/src/gen_uplc2/air.rs rename crates/aiken-lang/src/{gen_uplc => gen_uplc2}/tree.rs (73%) diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index f830c848..ab6be1bf 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -33,7 +33,6 @@ pub mod air; pub mod builder; pub mod scope; pub mod stack; -pub mod tree; use air::Air; use builder::{ diff --git a/crates/aiken-lang/src/gen_uplc2.rs b/crates/aiken-lang/src/gen_uplc2.rs index f7e6081f..fd28ed9e 100644 --- a/crates/aiken-lang/src/gen_uplc2.rs +++ b/crates/aiken-lang/src/gen_uplc2.rs @@ -1,4 +1,6 @@ +pub mod air; mod builder; +pub mod tree; use std::sync::Arc; @@ -10,16 +12,12 @@ use uplc::{ }; use crate::{ - ast::{ - AssignmentKind, BinOp, DataType, Pattern, Span, TypedDataType, TypedFunction, - TypedValidator, - }, + ast::{AssignmentKind, BinOp, Pattern, Span, TypedDataType, TypedFunction, TypedValidator}, builtins::{int, void}, expr::TypedExpr, gen_uplc::{ air::Air, builder::{self as build, AssignmentProperties, DataTypeKey, FunctionAccessKey}, - tree::AirTree, }, tipo::{ ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, @@ -27,6 +25,8 @@ use crate::{ }, }; +use self::tree::AirTree; + #[derive(Clone, Debug)] pub enum CodeGenFunction { Function(AirTree, Vec), diff --git a/crates/aiken-lang/src/gen_uplc2/air.rs b/crates/aiken-lang/src/gen_uplc2/air.rs new file mode 100644 index 00000000..0782e004 --- /dev/null +++ b/crates/aiken-lang/src/gen_uplc2/air.rs @@ -0,0 +1,291 @@ +use indexmap::IndexSet; +use std::sync::Arc; +use uplc::builtins::DefaultFunction; + +use crate::{ + ast::{BinOp, UnOp}, + tipo::{Type, ValueConstructor}, +}; + +#[derive(Debug, Clone, PartialEq)] +pub enum Air { + // Primitives + Int { + value: String, + }, + String { + value: String, + }, + ByteArray { + bytes: Vec, + }, + Bool { + value: bool, + }, + List { + count: usize, + tipo: Arc, + tail: bool, + }, + Tuple { + tipo: Arc, + count: usize, + }, + Void {}, + Var { + constructor: ValueConstructor, + name: String, + variant_name: String, + }, + // Functions + Call { + count: usize, + tipo: Arc, + }, + DefineFunc { + func_name: String, + module_name: String, + params: Vec, + recursive: bool, + variant_name: String, + }, + Fn { + params: Vec, + }, + Builtin { + count: usize, + func: DefaultFunction, + tipo: Arc, + }, + // Operators + BinOp { + name: BinOp, + tipo: Arc, + }, + UnOp { + op: UnOp, + }, + // Assignment + Let { + name: String, + }, + UnWrapData { + tipo: Arc, + }, + WrapData { + tipo: Arc, + }, + AssertConstr { + constr_index: usize, + }, + AssertBool { + is_true: bool, + }, + // When + When { + tipo: Arc, + subject_name: String, + }, + Clause { + tipo: Arc, + subject_name: String, + complex_clause: bool, + }, + ListClause { + tipo: Arc, + tail_name: String, + next_tail_name: Option, + complex_clause: bool, + }, + WrapClause {}, + TupleClause { + tipo: Arc, + indices: IndexSet<(usize, String)>, + predefined_indices: IndexSet<(usize, String)>, + subject_name: String, + count: usize, + complex_clause: bool, + }, + ClauseGuard { + subject_name: String, + tipo: Arc, + }, + ListClauseGuard { + tipo: Arc, + tail_name: String, + next_tail_name: Option, + inverse: bool, + }, + Finally {}, + // If + If { + tipo: Arc, + }, + // Record Creation + Record { + tag: usize, + tipo: Arc, + count: usize, + }, + RecordUpdate { + highest_index: usize, + indices: Vec<(usize, Arc)>, + tipo: Arc, + }, + // Field Access + RecordAccess { + record_index: u64, + tipo: Arc, + }, + FieldsExpose { + indices: Vec<(usize, String, Arc)>, + check_last_item: bool, + }, + // ListAccess + ListAccessor { + tipo: Arc, + names: Vec, + tail: bool, + check_last_item: bool, + }, + ListExpose { + tipo: Arc, + tail_head_names: Vec<(String, String)>, + tail: Option<(String, String)>, + }, + // Tuple Access + TupleAccessor { + names: Vec, + tipo: Arc, + check_last_item: bool, + }, + TupleIndex { + tipo: Arc, + tuple_index: usize, + }, + // Misc. + ErrorTerm { + tipo: Arc, + }, + Trace { + tipo: Arc, + }, + NoOp {}, + FieldsEmpty {}, + ListEmpty {}, +} + +impl Air { + 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_uplc2/builder.rs b/crates/aiken-lang/src/gen_uplc2/builder.rs index 3bedc89e..5889faae 100644 --- a/crates/aiken-lang/src/gen_uplc2/builder.rs +++ b/crates/aiken-lang/src/gen_uplc2/builder.rs @@ -2,10 +2,12 @@ use std::sync::Arc; use crate::{ ast::{Constant, Pattern}, - gen_uplc::{builder::AssignmentProperties, tree::AirTree}, + gen_uplc::builder::AssignmentProperties, tipo::{PatternConstructor, Type}, }; +use super::tree::AirTree; + pub fn convert_opaque_type() -> Arc { todo!() } diff --git a/crates/aiken-lang/src/gen_uplc/tree.rs b/crates/aiken-lang/src/gen_uplc2/tree.rs similarity index 73% rename from crates/aiken-lang/src/gen_uplc/tree.rs rename to crates/aiken-lang/src/gen_uplc2/tree.rs index 317f704e..bcee4e68 100644 --- a/crates/aiken-lang/src/gen_uplc/tree.rs +++ b/crates/aiken-lang/src/gen_uplc2/tree.rs @@ -23,7 +23,7 @@ pub enum AirStatement { Let { name: String, value: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, DefineFunc { func_name: String, @@ -38,19 +38,19 @@ pub enum AirStatement { AssertConstr { constr_index: usize, constr: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, AssertBool { is_true: bool, value: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, // Field Access FieldsExpose { indices: Vec<(usize, String, Arc)>, check_last_item: bool, record: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, // List Access ListAccessor { @@ -59,14 +59,14 @@ pub enum AirStatement { tail: bool, check_last_item: bool, list: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, ListExpose { tipo: Arc, tail_head_names: Vec<(String, String)>, tail: Option<(String, String)>, list: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, // Tuple Access TupleAccessor { @@ -74,11 +74,11 @@ pub enum AirStatement { tipo: Arc, check_last_item: bool, tuple: Box, - hoisted_over: Box>, + hoisted_over: Option>, }, // Misc. NoOp { - hoisted_over: Box>, + hoisted_over: Option>, }, } @@ -368,7 +368,7 @@ impl AirTree { AirTree::Statement(AirStatement::Let { name: name.to_string(), value: value.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn unwrap_data(value: AirTree, tipo: Arc) -> AirTree { @@ -387,14 +387,14 @@ impl AirTree { AirTree::Statement(AirStatement::AssertConstr { constr_index, constr: constr.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree { AirTree::Statement(AirStatement::AssertBool { is_true, value: value.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn when( @@ -568,7 +568,7 @@ impl AirTree { indices, check_last_item, record: record.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn list_access( @@ -584,7 +584,7 @@ impl AirTree { tail, check_last_item, list: list.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn list_expose( @@ -598,7 +598,7 @@ impl AirTree { tail_head_names, tail, list: list.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn tuple_access( @@ -612,7 +612,7 @@ impl AirTree { tipo, check_last_item, tuple: tuple.into(), - hoisted_over: None.into(), + hoisted_over: None, }) } pub fn tuple_index(tuple_index: usize, tipo: Arc, tuple: AirTree) -> AirTree { @@ -633,9 +633,7 @@ impl AirTree { }) } pub fn no_op() -> AirTree { - AirTree::Statement(AirStatement::NoOp { - hoisted_over: None.into(), - }) + AirTree::Statement(AirStatement::NoOp { hoisted_over: None }) } pub fn fields_empty(constr: AirTree) -> AirTree { AirTree::Expression(AirExpression::FieldsEmpty { @@ -657,7 +655,7 @@ impl AirTree { | AirStatement::ListExpose { hoisted_over, .. } | AirStatement::TupleAccessor { hoisted_over, .. } => { assert!(hoisted_over.is_none()); - *hoisted_over = Some(next_exp).into(); + *hoisted_over = Some(next_exp.into()); assignment } AirStatement::DefineFunc { .. } => { @@ -691,7 +689,7 @@ impl AirTree { let head_list = AirTree::builtin(DefaultFunction::HeadList, data(), vec![list_var]); - let expect_on_head = AirTree::call( + let _expect_on_head = AirTree::call( AirTree::local_var("__check_with", void()), void(), vec![head_list], @@ -727,11 +725,150 @@ impl AirTree { // self.call(void(), expect_stack, vec![tail_stack, arg_stack2]) } - pub fn to_air_vec(_air_vec: &mut Vec, tree: AirTree) { - match tree { - AirTree::Statement(_) => todo!(), - AirTree::Expression(_) => todo!(), - AirTree::UnhoistedSequence(_) => todo!(), + pub fn to_air_vec(&self, air_vec: &mut Vec) { + match self { + AirTree::Statement(st) => match st { + AirStatement::Let { + name, + value, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::Let { name: name.clone() }); + value.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::DefineFunc { .. } => todo!(), + AirStatement::AssertConstr { + constr_index, + constr, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::AssertConstr { + constr_index: *constr_index, + }); + constr.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::AssertBool { + is_true, + value, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::AssertBool { is_true: *is_true }); + value.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::FieldsExpose { + indices, + check_last_item, + record, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::FieldsExpose { + indices: indices.clone(), + check_last_item: *check_last_item, + }); + record.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::ListAccessor { + tipo, + names, + tail, + check_last_item, + list, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::ListAccessor { + tipo: tipo.clone(), + names: names.clone(), + tail: *tail, + check_last_item: *check_last_item, + }); + list.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::ListExpose { + tipo, + tail_head_names, + tail, + list, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::ListExpose { + tipo: tipo.clone(), + tail_head_names: tail_head_names.clone(), + tail: tail.clone(), + }); + list.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::TupleAccessor { + names, + tipo, + check_last_item, + tuple, + hoisted_over: Some(exp), + } => { + air_vec.push(Air::TupleAccessor { + names: names.clone(), + tipo: tipo.clone(), + check_last_item: *check_last_item, + }); + tuple.to_air_vec(air_vec); + exp.to_air_vec(air_vec); + } + AirStatement::NoOp { + hoisted_over: Some(exp), + } => { + // No need to push NoOp. It does nothing. + exp.to_air_vec(air_vec); + } + _ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"), + }, + AirTree::Expression(exp) => match exp { + AirExpression::Int { value } => air_vec.push(Air::Int { + value: value.clone(), + }), + AirExpression::String { value } => air_vec.push(Air::String { + value: value.clone(), + }), + AirExpression::ByteArray { bytes } => air_vec.push(Air::ByteArray { + bytes: bytes.clone(), + }), + AirExpression::Bool { value } => air_vec.push(Air::Bool { value: *value }), + AirExpression::List { .. } => todo!(), + AirExpression::Tuple { .. } => todo!(), + AirExpression::Void => todo!(), + AirExpression::Var { .. } => todo!(), + AirExpression::Call { .. } => todo!(), + AirExpression::Fn { .. } => todo!(), + AirExpression::Builtin { .. } => todo!(), + AirExpression::BinOp { .. } => todo!(), + AirExpression::UnOp { .. } => todo!(), + AirExpression::UnWrapData { .. } => todo!(), + AirExpression::WrapData { .. } => todo!(), + AirExpression::When { .. } => todo!(), + AirExpression::Clause { .. } => todo!(), + AirExpression::ListClause { .. } => todo!(), + AirExpression::WrapClause { .. } => todo!(), + AirExpression::TupleClause { .. } => todo!(), + AirExpression::ClauseGuard { .. } => todo!(), + AirExpression::ListClauseGuard { .. } => todo!(), + AirExpression::Finally { .. } => todo!(), + AirExpression::If { .. } => todo!(), + AirExpression::Constr { .. } => todo!(), + AirExpression::RecordUpdate { .. } => todo!(), + AirExpression::RecordAccess { .. } => todo!(), + AirExpression::TupleIndex { .. } => todo!(), + AirExpression::ErrorTerm { .. } => todo!(), + AirExpression::Trace { .. } => todo!(), + AirExpression::FieldsEmpty { .. } => todo!(), + AirExpression::ListEmpty { .. } => todo!(), + }, + AirTree::UnhoistedSequence(_) => { + unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES") + } } } }