From 96959011e9a4cfbd2fd3958e7aaee2030078f325 Mon Sep 17 00:00:00 2001 From: microproofs Date: Thu, 29 Jun 2023 16:54:36 -0400 Subject: [PATCH] feat: finish up build. just have helper methods feat: Create an air and AirTree iterator. This allows us to iterate forwards or backwards over the tree as a vec. chore: moved around some functions --- crates/aiken-lang/src/gen_uplc2.rs | 71 ++++++- crates/aiken-lang/src/gen_uplc2/air.rs | 10 +- crates/aiken-lang/src/gen_uplc2/builder.rs | 13 +- crates/aiken-lang/src/gen_uplc2/tree.rs | 203 +++++++++++++-------- 4 files changed, 200 insertions(+), 97 deletions(-) diff --git a/crates/aiken-lang/src/gen_uplc2.rs b/crates/aiken-lang/src/gen_uplc2.rs index fd28ed9e..ebd5466b 100644 --- a/crates/aiken-lang/src/gen_uplc2.rs +++ b/crates/aiken-lang/src/gen_uplc2.rs @@ -12,12 +12,17 @@ use uplc::{ }; use crate::{ - ast::{AssignmentKind, BinOp, Pattern, Span, TypedDataType, TypedFunction, TypedValidator}, + ast::{ + AssignmentKind, BinOp, Pattern, Span, TypedClause, TypedDataType, TypedFunction, + TypedValidator, + }, builtins::{int, void}, expr::TypedExpr, gen_uplc::{ air::Air, - builder::{self as build, AssignmentProperties, DataTypeKey, FunctionAccessKey}, + builder::{ + self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey, + }, }, tipo::{ ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, @@ -234,7 +239,7 @@ impl<'a> CodeGenerator<'a> { AirTree::call(self.build(fun.as_ref()), tipo.clone(), func_args) } } - _ => todo!("IS THIS REACHABLE?"), + _ => unreachable!("IS THIS REACHABLE? Well you reached it with {:#?}", body), }, TypedExpr::BinOp { name, @@ -303,14 +308,40 @@ impl<'a> CodeGenerator<'a> { AirTree::hoist_over(assignment, clause_then) } else { clauses = if subject.tipo().is_list() { - build::rearrange_clauses(clauses.clone()) + build::rearrange_clauses(clauses) } else { clauses }; let last_clause = clauses.pop().unwrap(); - todo!() + let constr_var = format!( + "__when_var_span_{}_{}", + subject.location().start, + subject.location().end + ); + + let subject_name = format!( + "__subject_var_span_{}_{}", + subject.location().start, + subject.location().end + ); + + let clauses = self.handle_each_clause( + &clauses, + last_clause, + &subject.tipo(), + &mut ClauseProperties::init( + &subject.tipo(), + constr_var.clone(), + subject_name.clone(), + ), + ); + + let constr_assign = AirTree::let_assignment(&constr_var, self.build(subject)); + let when_assign = AirTree::when(subject_name, subject.tipo(), clauses); + + AirTree::hoist_over(constr_assign, when_assign) } } @@ -952,4 +983,34 @@ impl<'a> CodeGenerator<'a> { todo!() } } + + pub fn handle_each_clause( + &mut self, + clauses: &[TypedClause], + final_clause: TypedClause, + subject_tipo: &Arc, + props: &mut ClauseProperties, + ) -> AirTree { + assert!(!clauses.is_empty()); + *props.is_complex_clause() = false; + + if let Some((clause, rest_clauses)) = clauses.split_first() { + todo!() + } else { + // handle final_clause + + *props.is_final_clause() = true; + assert!(final_clause.guard.is_none()); + let clause_then = self.build(&final_clause.then); + self.clause_pattern(&final_clause.pattern, clause_then) + } + } + + pub fn clause_pattern( + &mut self, + pattern: &Pattern>, + clause_then: AirTree, + ) -> AirTree { + todo!() + } } diff --git a/crates/aiken-lang/src/gen_uplc2/air.rs b/crates/aiken-lang/src/gen_uplc2/air.rs index 0782e004..e278791e 100644 --- a/crates/aiken-lang/src/gen_uplc2/air.rs +++ b/crates/aiken-lang/src/gen_uplc2/air.rs @@ -31,7 +31,7 @@ pub enum Air { tipo: Arc, count: usize, }, - Void {}, + Void, Var { constructor: ValueConstructor, name: String, @@ -116,7 +116,7 @@ pub enum Air { next_tail_name: Option, inverse: bool, }, - Finally {}, + Finally, // If If { tipo: Arc, @@ -170,9 +170,9 @@ pub enum Air { Trace { tipo: Arc, }, - NoOp {}, - FieldsEmpty {}, - ListEmpty {}, + NoOp, + FieldsEmpty, + ListEmpty, } impl Air { diff --git a/crates/aiken-lang/src/gen_uplc2/builder.rs b/crates/aiken-lang/src/gen_uplc2/builder.rs index 5889faae..666d3e4f 100644 --- a/crates/aiken-lang/src/gen_uplc2/builder.rs +++ b/crates/aiken-lang/src/gen_uplc2/builder.rs @@ -1,8 +1,8 @@ use std::sync::Arc; use crate::{ - ast::{Constant, Pattern}, - gen_uplc::builder::AssignmentProperties, + ast::{Constant, Pattern, TypedClause}, + gen_uplc::builder::{AssignmentProperties, ClauseProperties}, tipo::{PatternConstructor, Type}, }; @@ -12,15 +12,6 @@ pub fn convert_opaque_type() -> Arc { todo!() } -pub fn handle_each_clause( - pattern: &Pattern>, - value: AirTree, - tipo: &Arc, - props: AssignmentProperties, -) -> AirTree { - todo!() -} - pub fn constants_ir(literal: &Constant) -> AirTree { match literal { Constant::Int { value, .. } => AirTree::int(value), diff --git a/crates/aiken-lang/src/gen_uplc2/tree.rs b/crates/aiken-lang/src/gen_uplc2/tree.rs index bcee4e68..4d60a740 100644 --- a/crates/aiken-lang/src/gen_uplc2/tree.rs +++ b/crates/aiken-lang/src/gen_uplc2/tree.rs @@ -1,5 +1,5 @@ use indexmap::IndexSet; -use std::sync::Arc; +use std::{collections::VecDeque, sync::Arc}; use uplc::builtins::DefaultFunction; use crate::{ @@ -17,6 +17,42 @@ pub enum AirTree { UnhoistedSequence(Vec), } +pub struct AirIterator<'a> { + deque_pointer: VecDeque<&'a AirTree>, +} + +impl Iterator for AirIterator<'_> { + type Item = Air; + + fn next(&mut self) -> Option { + todo!() + } +} + +impl DoubleEndedIterator for AirIterator<'_> { + fn next_back(&mut self) -> Option { + todo!() + } +} + +pub struct AirTreeIterator<'a> { + deque_pointer: VecDeque<&'a AirTree>, +} + +impl<'a> Iterator for AirTreeIterator<'a> { + fn next(&mut self) -> Option { + self.deque_pointer.pop_front() + } + + type Item = &'a AirTree; +} + +impl DoubleEndedIterator for AirTreeIterator<'_> { + fn next_back(&mut self) -> Option { + self.deque_pointer.pop_back() + } +} + #[derive(Debug, Clone, PartialEq)] pub enum AirStatement { // Assignment @@ -153,8 +189,7 @@ pub enum AirExpression { When { tipo: Arc, subject_name: String, - clauses: Vec, - final_clause: Box, + clauses: Box, }, Clause { tipo: Arc, @@ -397,17 +432,11 @@ impl AirTree { hoisted_over: None, }) } - pub fn when( - subject_name: impl ToString, - tipo: Arc, - clauses: Vec, - final_clause: AirTree, - ) -> AirTree { + pub fn when(subject_name: impl ToString, tipo: Arc, clauses: AirTree) -> AirTree { AirTree::Expression(AirExpression::When { tipo, subject_name: subject_name.to_string(), - clauses, - final_clause: final_clause.into(), + clauses: clauses.into(), }) } pub fn clause( @@ -725,52 +754,89 @@ impl AirTree { // self.call(void(), expect_stack, vec![tail_stack, arg_stack2]) } - pub fn to_air_vec(&self, air_vec: &mut Vec) { + pub fn iter(&self) -> AirTreeIterator { + let mut new_vec = vec![]; + self.create_iter(&mut new_vec); + AirTreeIterator { + deque_pointer: new_vec.into(), + } + } + + pub fn air_iter(&self) -> AirIterator { + let mut new_vec = vec![]; + self.create_iter(&mut new_vec); + AirIterator { + deque_pointer: new_vec.into(), + } + } + + fn create_iter<'a>(&'a self, pointer_vec: &mut Vec<&'a AirTree>) { + match self { + AirTree::Statement(st) => match st { + AirStatement::Let { + value, + hoisted_over: Some(exp), + .. + } => { + pointer_vec.push(self); + value.create_iter(pointer_vec); + exp.create_iter(pointer_vec); + } + AirStatement::DefineFunc { .. } => todo!(), + AirStatement::AssertConstr { + constr, + hoisted_over: Some(exp), + .. + } => { + pointer_vec.push(self); + constr.create_iter(pointer_vec); + exp.create_iter(pointer_vec); + } + AirStatement::AssertBool { .. } => todo!(), + AirStatement::FieldsExpose { .. } => todo!(), + AirStatement::ListAccessor { .. } => todo!(), + AirStatement::ListExpose { .. } => todo!(), + AirStatement::TupleAccessor { .. } => todo!(), + AirStatement::NoOp { .. } => todo!(), + _ => unreachable!("FOUND UNHOISTED STATEMENT"), + }, + AirTree::Expression(_) => todo!(), + AirTree::UnhoistedSequence(_) => { + unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES") + } + } + } + + pub fn convert_to_air(&self) -> Air { 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); - } + } => Air::Let { name: name.clone() }, 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); - } + } => Air::AssertConstr { + constr_index: *constr_index, + }, 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); - } + } => Air::AssertBool { is_true: *is_true }, 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); - } + } => Air::FieldsExpose { + indices: indices.clone(), + check_last_item: *check_last_item, + }, AirStatement::ListAccessor { tipo, names, @@ -778,65 +844,50 @@ impl AirTree { 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); - } + } => Air::ListAccessor { + tipo: tipo.clone(), + names: names.clone(), + tail: *tail, + check_last_item: *check_last_item, + }, 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); - } + } => Air::ListExpose { + tipo: tipo.clone(), + tail_head_names: tail_head_names.clone(), + tail: tail.clone(), + }, 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); - } + } => Air::TupleAccessor { + names: names.clone(), + tipo: tipo.clone(), + check_last_item: *check_last_item, + }, AirStatement::NoOp { hoisted_over: Some(exp), - } => { - // No need to push NoOp. It does nothing. - exp.to_air_vec(air_vec); - } + } => Air::NoOp, _ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"), }, AirTree::Expression(exp) => match exp { - AirExpression::Int { value } => air_vec.push(Air::Int { + AirExpression::Int { value } => Air::Int { value: value.clone(), - }), - AirExpression::String { value } => air_vec.push(Air::String { + }, + AirExpression::String { value } => Air::String { value: value.clone(), - }), - AirExpression::ByteArray { bytes } => air_vec.push(Air::ByteArray { + }, + AirExpression::ByteArray { bytes } => Air::ByteArray { bytes: bytes.clone(), - }), - AirExpression::Bool { value } => air_vec.push(Air::Bool { value: *value }), + }, + AirExpression::Bool { value } => Air::Bool { value: *value }, AirExpression::List { .. } => todo!(), AirExpression::Tuple { .. } => todo!(), AirExpression::Void => todo!(),