feat: start on build assignment
feat: implement assignment hoisting
This commit is contained in:
parent
c359bd35d7
commit
65bb7e48e2
|
@ -3,8 +3,8 @@ use std::sync::Arc;
|
|||
use uplc::builtins::DefaultFunction;
|
||||
|
||||
use crate::{
|
||||
ast::{BinOp, UnOp},
|
||||
tipo::{Type, ValueConstructor},
|
||||
ast::{BinOp, Span, UnOp},
|
||||
tipo::{Type, ValueConstructor, ValueConstructorVariant},
|
||||
};
|
||||
|
||||
use super::air::Air;
|
||||
|
@ -91,10 +91,12 @@ pub enum AirTree {
|
|||
AssertConstr {
|
||||
constr_index: usize,
|
||||
constr: Box<AirTree>,
|
||||
hoisted_over: Box<Option<AirTree>>,
|
||||
},
|
||||
AssertBool {
|
||||
is_true: bool,
|
||||
value: Box<AirTree>,
|
||||
hoisted_over: Box<Option<AirTree>>,
|
||||
},
|
||||
// When
|
||||
When {
|
||||
|
@ -216,7 +218,9 @@ pub enum AirTree {
|
|||
msg: Box<AirTree>,
|
||||
then: Box<AirTree>,
|
||||
},
|
||||
NoOp,
|
||||
NoOp {
|
||||
hoisted_over: Box<Option<AirTree>>,
|
||||
},
|
||||
FieldsEmpty {
|
||||
constr: Box<AirTree>,
|
||||
},
|
||||
|
@ -276,6 +280,18 @@ impl AirTree {
|
|||
variant_name: variant_name.to_string(),
|
||||
}
|
||||
}
|
||||
pub fn local_var(name: impl ToString, tipo: Arc<Type>) -> AirTree {
|
||||
AirTree::Var {
|
||||
constructor: ValueConstructor::public(
|
||||
tipo,
|
||||
ValueConstructorVariant::LocalVariable {
|
||||
location: Span::empty(),
|
||||
},
|
||||
),
|
||||
name: name.to_string(),
|
||||
variant_name: "".to_string(),
|
||||
}
|
||||
}
|
||||
pub fn call(func: AirTree, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
||||
AirTree::Call {
|
||||
tipo,
|
||||
|
@ -348,12 +364,14 @@ impl AirTree {
|
|||
AirTree::AssertConstr {
|
||||
constr_index,
|
||||
constr: constr.into(),
|
||||
hoisted_over: None.into(),
|
||||
}
|
||||
}
|
||||
pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree {
|
||||
AirTree::AssertBool {
|
||||
is_true,
|
||||
value: value.into(),
|
||||
hoisted_over: None.into(),
|
||||
}
|
||||
}
|
||||
pub fn when(
|
||||
|
@ -588,7 +606,9 @@ impl AirTree {
|
|||
}
|
||||
}
|
||||
pub fn no_op() -> AirTree {
|
||||
AirTree::NoOp
|
||||
AirTree::NoOp {
|
||||
hoisted_over: None.into(),
|
||||
}
|
||||
}
|
||||
pub fn fields_empty(constr: AirTree) -> AirTree {
|
||||
AirTree::FieldsEmpty {
|
||||
|
@ -605,13 +625,30 @@ impl AirTree {
|
|||
value,
|
||||
hoisted_over: Some(next_exp).into(),
|
||||
},
|
||||
AirTree::AssertBool { is_true, value, .. } => AirTree::AssertBool {
|
||||
is_true,
|
||||
value,
|
||||
hoisted_over: Some(next_exp).into(),
|
||||
},
|
||||
AirTree::AssertConstr {
|
||||
constr_index,
|
||||
constr,
|
||||
..
|
||||
} => AirTree::AssertConstr {
|
||||
constr_index,
|
||||
constr,
|
||||
hoisted_over: Some(next_exp).into(),
|
||||
},
|
||||
AirTree::NoOp { .. } => AirTree::NoOp {
|
||||
hoisted_over: Some(next_exp).into(),
|
||||
},
|
||||
_ => unimplemented!("IS THIS REACHABLE?"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_air_vec(tree: AirTree) -> Vec<Air> {
|
||||
pub fn to_air_vec(air_vec: &mut Vec<Air>, tree: AirTree) {
|
||||
match tree {
|
||||
AirTree::Int { value } => todo!(),
|
||||
AirTree::Int { value } => air_vec.push(todo!()),
|
||||
AirTree::String { value } => todo!(),
|
||||
AirTree::ByteArray { bytes } => todo!(),
|
||||
AirTree::Bool { value } => todo!(),
|
||||
|
@ -649,11 +686,8 @@ impl AirTree {
|
|||
} => todo!(),
|
||||
AirTree::UnWrapData { tipo, value } => todo!(),
|
||||
AirTree::WrapData { tipo, value } => todo!(),
|
||||
AirTree::AssertConstr {
|
||||
constr_index,
|
||||
constr,
|
||||
} => todo!(),
|
||||
AirTree::AssertBool { is_true, value } => todo!(),
|
||||
AirTree::AssertConstr { .. } => todo!(),
|
||||
AirTree::AssertBool { .. } => todo!(),
|
||||
AirTree::When {
|
||||
tipo,
|
||||
subject_name,
|
||||
|
@ -751,7 +785,7 @@ impl AirTree {
|
|||
} => todo!(),
|
||||
AirTree::ErrorTerm { tipo } => todo!(),
|
||||
AirTree::Trace { tipo, msg, then } => todo!(),
|
||||
AirTree::NoOp => todo!(),
|
||||
AirTree::NoOp { .. } => todo!(),
|
||||
AirTree::FieldsEmpty { constr } => todo!(),
|
||||
AirTree::ListEmpty { list } => todo!(),
|
||||
}
|
||||
|
|
|
@ -389,7 +389,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
let mut update_args = vec![];
|
||||
|
||||
let mut highest_index = 0;
|
||||
let record = self.build(spread);
|
||||
|
||||
for arg in args
|
||||
.iter()
|
||||
|
@ -409,7 +408,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
index_types,
|
||||
highest_index,
|
||||
tipo.clone(),
|
||||
record,
|
||||
self.build(spread),
|
||||
update_args,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,90 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
ast::{Constant, Pattern},
|
||||
gen_uplc::{builder::AssignmentProperties, tree::AirTree},
|
||||
ast::{AssignmentKind, BinOp, Constant, Pattern},
|
||||
builtins::int,
|
||||
gen_uplc::{
|
||||
air::{self, Air},
|
||||
builder::AssignmentProperties,
|
||||
tree::AirTree,
|
||||
},
|
||||
tipo::{PatternConstructor, Type},
|
||||
};
|
||||
|
||||
pub fn assignment_air_tree(
|
||||
pattern: &Pattern<PatternConstructor, Arc<Type>>,
|
||||
value: AirTree,
|
||||
mut value: AirTree,
|
||||
tipo: &Arc<Type>,
|
||||
props: AssignmentProperties,
|
||||
) -> AirTree {
|
||||
todo!()
|
||||
if props.value_type.is_data() && props.kind.is_expect() && !tipo.is_data() {
|
||||
value = AirTree::unwrap_data(value, tipo.clone());
|
||||
} else if !props.value_type.is_data() && tipo.is_data() {
|
||||
value = AirTree::wrap_data(value, tipo.clone());
|
||||
}
|
||||
|
||||
match pattern {
|
||||
Pattern::Int {
|
||||
value: expected_int,
|
||||
..
|
||||
} => {
|
||||
if props.kind.is_expect() {
|
||||
let name = format!("__expected_by_{}", expected_int);
|
||||
let assignment = AirTree::let_assignment(&name, value);
|
||||
|
||||
let expect = AirTree::binop(
|
||||
BinOp::Eq,
|
||||
int(),
|
||||
AirTree::int(expected_int),
|
||||
AirTree::local_var(name, int()),
|
||||
);
|
||||
|
||||
AirTree::assert_bool(true, AirTree::hoist_let(assignment, expect))
|
||||
} else {
|
||||
unreachable!("Code Gen should never reach here")
|
||||
}
|
||||
}
|
||||
Pattern::Var { name, .. } => {
|
||||
if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() {
|
||||
let assignment = AirTree::let_assignment(name, value);
|
||||
let expect = todo!();
|
||||
let assign = AirTree::let_assignment("_", AirTree::hoist_let(assignment, expect));
|
||||
let val = AirTree::local_var(name, tipo.clone());
|
||||
AirTree::let_assignment(name, AirTree::hoist_let(assign, val))
|
||||
} else {
|
||||
AirTree::let_assignment(name, value)
|
||||
}
|
||||
}
|
||||
Pattern::Assign { name, pattern, .. } => {
|
||||
let inner_pattern =
|
||||
assignment_air_tree(pattern, AirTree::local_var(name, tipo.clone()), tipo, props);
|
||||
|
||||
AirTree::let_assignment(name, inner_pattern)
|
||||
}
|
||||
Pattern::Discard { name, .. } => {
|
||||
if props.kind.is_expect() {
|
||||
AirTree::let_assignment(name, value)
|
||||
} else {
|
||||
AirTree::no_op()
|
||||
}
|
||||
}
|
||||
Pattern::List {
|
||||
location,
|
||||
elements,
|
||||
tail,
|
||||
} => todo!(),
|
||||
Pattern::Constructor {
|
||||
is_record,
|
||||
location,
|
||||
name,
|
||||
arguments,
|
||||
module,
|
||||
constructor,
|
||||
with_spread,
|
||||
tipo,
|
||||
} => todo!(),
|
||||
Pattern::Tuple { location, elems } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_each_clause(
|
||||
|
@ -31,5 +103,3 @@ pub fn constants_ir(literal: &Constant) -> AirTree {
|
|||
Constant::ByteArray { bytes, .. } => AirTree::byte_array(bytes.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue