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
This commit is contained in:
microproofs 2023-06-29 16:54:36 -04:00 committed by Kasey
parent ba3265054c
commit 96959011e9
4 changed files with 200 additions and 97 deletions

View File

@ -12,12 +12,17 @@ use uplc::{
}; };
use crate::{ use crate::{
ast::{AssignmentKind, BinOp, Pattern, Span, TypedDataType, TypedFunction, TypedValidator}, ast::{
AssignmentKind, BinOp, Pattern, Span, TypedClause, TypedDataType, TypedFunction,
TypedValidator,
},
builtins::{int, void}, builtins::{int, void},
expr::TypedExpr, expr::TypedExpr,
gen_uplc::{ gen_uplc::{
air::Air, air::Air,
builder::{self as build, AssignmentProperties, DataTypeKey, FunctionAccessKey}, builder::{
self as build, AssignmentProperties, ClauseProperties, DataTypeKey, FunctionAccessKey,
},
}, },
tipo::{ tipo::{
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
@ -234,7 +239,7 @@ impl<'a> CodeGenerator<'a> {
AirTree::call(self.build(fun.as_ref()), tipo.clone(), func_args) 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 { TypedExpr::BinOp {
name, name,
@ -303,14 +308,40 @@ impl<'a> CodeGenerator<'a> {
AirTree::hoist_over(assignment, clause_then) AirTree::hoist_over(assignment, clause_then)
} else { } else {
clauses = if subject.tipo().is_list() { clauses = if subject.tipo().is_list() {
build::rearrange_clauses(clauses.clone()) build::rearrange_clauses(clauses)
} else { } else {
clauses clauses
}; };
let last_clause = clauses.pop().unwrap(); 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!() todo!()
} }
} }
pub fn handle_each_clause(
&mut self,
clauses: &[TypedClause],
final_clause: TypedClause,
subject_tipo: &Arc<Type>,
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<PatternConstructor, Arc<Type>>,
clause_then: AirTree,
) -> AirTree {
todo!()
}
} }

View File

@ -31,7 +31,7 @@ pub enum Air {
tipo: Arc<Type>, tipo: Arc<Type>,
count: usize, count: usize,
}, },
Void {}, Void,
Var { Var {
constructor: ValueConstructor, constructor: ValueConstructor,
name: String, name: String,
@ -116,7 +116,7 @@ pub enum Air {
next_tail_name: Option<String>, next_tail_name: Option<String>,
inverse: bool, inverse: bool,
}, },
Finally {}, Finally,
// If // If
If { If {
tipo: Arc<Type>, tipo: Arc<Type>,
@ -170,9 +170,9 @@ pub enum Air {
Trace { Trace {
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
NoOp {}, NoOp,
FieldsEmpty {}, FieldsEmpty,
ListEmpty {}, ListEmpty,
} }
impl Air { impl Air {

View File

@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
ast::{Constant, Pattern}, ast::{Constant, Pattern, TypedClause},
gen_uplc::builder::AssignmentProperties, gen_uplc::builder::{AssignmentProperties, ClauseProperties},
tipo::{PatternConstructor, Type}, tipo::{PatternConstructor, Type},
}; };
@ -12,15 +12,6 @@ pub fn convert_opaque_type() -> Arc<Type> {
todo!() todo!()
} }
pub fn handle_each_clause(
pattern: &Pattern<PatternConstructor, Arc<Type>>,
value: AirTree,
tipo: &Arc<Type>,
props: AssignmentProperties,
) -> AirTree {
todo!()
}
pub fn constants_ir(literal: &Constant) -> AirTree { pub fn constants_ir(literal: &Constant) -> AirTree {
match literal { match literal {
Constant::Int { value, .. } => AirTree::int(value), Constant::Int { value, .. } => AirTree::int(value),

View File

@ -1,5 +1,5 @@
use indexmap::IndexSet; use indexmap::IndexSet;
use std::sync::Arc; use std::{collections::VecDeque, sync::Arc};
use uplc::builtins::DefaultFunction; use uplc::builtins::DefaultFunction;
use crate::{ use crate::{
@ -17,6 +17,42 @@ pub enum AirTree {
UnhoistedSequence(Vec<AirTree>), UnhoistedSequence(Vec<AirTree>),
} }
pub struct AirIterator<'a> {
deque_pointer: VecDeque<&'a AirTree>,
}
impl Iterator for AirIterator<'_> {
type Item = Air;
fn next(&mut self) -> Option<Self::Item> {
todo!()
}
}
impl DoubleEndedIterator for AirIterator<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
todo!()
}
}
pub struct AirTreeIterator<'a> {
deque_pointer: VecDeque<&'a AirTree>,
}
impl<'a> Iterator for AirTreeIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
self.deque_pointer.pop_front()
}
type Item = &'a AirTree;
}
impl DoubleEndedIterator for AirTreeIterator<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.deque_pointer.pop_back()
}
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum AirStatement { pub enum AirStatement {
// Assignment // Assignment
@ -153,8 +189,7 @@ pub enum AirExpression {
When { When {
tipo: Arc<Type>, tipo: Arc<Type>,
subject_name: String, subject_name: String,
clauses: Vec<AirTree>, clauses: Box<AirTree>,
final_clause: Box<AirTree>,
}, },
Clause { Clause {
tipo: Arc<Type>, tipo: Arc<Type>,
@ -397,17 +432,11 @@ impl AirTree {
hoisted_over: None, hoisted_over: None,
}) })
} }
pub fn when( pub fn when(subject_name: impl ToString, tipo: Arc<Type>, clauses: AirTree) -> AirTree {
subject_name: impl ToString,
tipo: Arc<Type>,
clauses: Vec<AirTree>,
final_clause: AirTree,
) -> AirTree {
AirTree::Expression(AirExpression::When { AirTree::Expression(AirExpression::When {
tipo, tipo,
subject_name: subject_name.to_string(), subject_name: subject_name.to_string(),
clauses, clauses: clauses.into(),
final_clause: final_clause.into(),
}) })
} }
pub fn clause( pub fn clause(
@ -725,52 +754,89 @@ impl AirTree {
// self.call(void(), expect_stack, vec![tail_stack, arg_stack2]) // self.call(void(), expect_stack, vec![tail_stack, arg_stack2])
} }
pub fn to_air_vec(&self, air_vec: &mut Vec<Air>) { 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 { match self {
AirTree::Statement(st) => match st { AirTree::Statement(st) => match st {
AirStatement::Let { AirStatement::Let {
name, name,
value, value,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::Let { name: name.clone() },
air_vec.push(Air::Let { name: name.clone() });
value.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::DefineFunc { .. } => todo!(), AirStatement::DefineFunc { .. } => todo!(),
AirStatement::AssertConstr { AirStatement::AssertConstr {
constr_index, constr_index,
constr, constr,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::AssertConstr {
air_vec.push(Air::AssertConstr { constr_index: *constr_index,
constr_index: *constr_index, },
});
constr.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::AssertBool { AirStatement::AssertBool {
is_true, is_true,
value, value,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::AssertBool { is_true: *is_true },
air_vec.push(Air::AssertBool { is_true: *is_true });
value.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::FieldsExpose { AirStatement::FieldsExpose {
indices, indices,
check_last_item, check_last_item,
record, record,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::FieldsExpose {
air_vec.push(Air::FieldsExpose { indices: indices.clone(),
indices: indices.clone(), check_last_item: *check_last_item,
check_last_item: *check_last_item, },
});
record.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::ListAccessor { AirStatement::ListAccessor {
tipo, tipo,
names, names,
@ -778,65 +844,50 @@ impl AirTree {
check_last_item, check_last_item,
list, list,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::ListAccessor {
air_vec.push(Air::ListAccessor { tipo: tipo.clone(),
tipo: tipo.clone(), names: names.clone(),
names: names.clone(), tail: *tail,
tail: *tail, check_last_item: *check_last_item,
check_last_item: *check_last_item, },
});
list.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::ListExpose { AirStatement::ListExpose {
tipo, tipo,
tail_head_names, tail_head_names,
tail, tail,
list, list,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::ListExpose {
air_vec.push(Air::ListExpose { tipo: tipo.clone(),
tipo: tipo.clone(), tail_head_names: tail_head_names.clone(),
tail_head_names: tail_head_names.clone(), tail: tail.clone(),
tail: tail.clone(), },
});
list.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::TupleAccessor { AirStatement::TupleAccessor {
names, names,
tipo, tipo,
check_last_item, check_last_item,
tuple, tuple,
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::TupleAccessor {
air_vec.push(Air::TupleAccessor { names: names.clone(),
names: names.clone(), tipo: tipo.clone(),
tipo: tipo.clone(), check_last_item: *check_last_item,
check_last_item: *check_last_item, },
});
tuple.to_air_vec(air_vec);
exp.to_air_vec(air_vec);
}
AirStatement::NoOp { AirStatement::NoOp {
hoisted_over: Some(exp), hoisted_over: Some(exp),
} => { } => Air::NoOp,
// No need to push NoOp. It does nothing.
exp.to_air_vec(air_vec);
}
_ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"), _ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"),
}, },
AirTree::Expression(exp) => match exp { AirTree::Expression(exp) => match exp {
AirExpression::Int { value } => air_vec.push(Air::Int { AirExpression::Int { value } => Air::Int {
value: value.clone(), value: value.clone(),
}), },
AirExpression::String { value } => air_vec.push(Air::String { AirExpression::String { value } => Air::String {
value: value.clone(), value: value.clone(),
}), },
AirExpression::ByteArray { bytes } => air_vec.push(Air::ByteArray { AirExpression::ByteArray { bytes } => Air::ByteArray {
bytes: bytes.clone(), bytes: bytes.clone(),
}), },
AirExpression::Bool { value } => air_vec.push(Air::Bool { value: *value }), AirExpression::Bool { value } => Air::Bool { value: *value },
AirExpression::List { .. } => todo!(), AirExpression::List { .. } => todo!(),
AirExpression::Tuple { .. } => todo!(), AirExpression::Tuple { .. } => todo!(),
AirExpression::Void => todo!(), AirExpression::Void => todo!(),