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

View File

@ -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<Type> {
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 {
match literal {
Constant::Int { value, .. } => AirTree::int(value),

View File

@ -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<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)]
pub enum AirStatement {
// Assignment
@ -153,8 +189,7 @@ pub enum AirExpression {
When {
tipo: Arc<Type>,
subject_name: String,
clauses: Vec<AirTree>,
final_clause: Box<AirTree>,
clauses: Box<AirTree>,
},
Clause {
tipo: Arc<Type>,
@ -397,17 +432,11 @@ impl AirTree {
hoisted_over: None,
})
}
pub fn when(
subject_name: impl ToString,
tipo: Arc<Type>,
clauses: Vec<AirTree>,
final_clause: AirTree,
) -> AirTree {
pub fn when(subject_name: impl ToString, tipo: Arc<Type>, 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<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 {
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 {
} => 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);
}
} => Air::AssertBool { is_true: *is_true },
AirStatement::FieldsExpose {
indices,
check_last_item,
record,
hoisted_over: Some(exp),
} => {
air_vec.push(Air::FieldsExpose {
} => 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,
@ -778,65 +844,50 @@ impl AirTree {
check_last_item,
list,
hoisted_over: Some(exp),
} => {
air_vec.push(Air::ListAccessor {
} => 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 {
} => 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 {
} => 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);
}
} => 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!(),