feat: almost done assignment have tuple and constr left
feat: modified the AirTree structure to have statements, sequences, and expressions feat: changed the hoist_over function to be universal
This commit is contained in:
parent
65bb7e48e2
commit
59362e3d8c
|
@ -501,6 +501,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AssignmentProperties {
|
AssignmentProperties {
|
||||||
value_type: value.tipo(),
|
value_type: value.tipo(),
|
||||||
kind: *kind,
|
kind: *kind,
|
||||||
|
remove_unused: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -531,6 +532,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AssignmentProperties {
|
AssignmentProperties {
|
||||||
value_type: clauses[0].then.tipo(),
|
value_type: clauses[0].then.tipo(),
|
||||||
kind: AssignmentKind::Let,
|
kind: AssignmentKind::Let,
|
||||||
|
remove_unused: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -5182,6 +5184,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AssignmentProperties {
|
AssignmentProperties {
|
||||||
value_type: data(),
|
value_type: data(),
|
||||||
kind: AssignmentKind::Expect,
|
kind: AssignmentKind::Expect,
|
||||||
|
remove_unused: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
value_stack.local_var(actual_type, &arg_name);
|
value_stack.local_var(actual_type, &arg_name);
|
||||||
|
|
|
@ -60,6 +60,7 @@ pub struct FunctionAccessKey {
|
||||||
pub struct AssignmentProperties {
|
pub struct AssignmentProperties {
|
||||||
pub value_type: Arc<Type>,
|
pub value_type: Arc<Type>,
|
||||||
pub kind: AssignmentKind,
|
pub kind: AssignmentKind,
|
||||||
|
pub remove_unused: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -11,6 +11,78 @@ use super::air::Air;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum AirTree {
|
pub enum AirTree {
|
||||||
|
Statement(AirStatement),
|
||||||
|
Expression(AirExpression),
|
||||||
|
IncompleteSequence(Vec<AirTree>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum AirStatement {
|
||||||
|
// Assignment
|
||||||
|
Let {
|
||||||
|
name: String,
|
||||||
|
value: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
DefineFunc {
|
||||||
|
func_name: String,
|
||||||
|
module_name: String,
|
||||||
|
params: Vec<String>,
|
||||||
|
recursive: bool,
|
||||||
|
variant_name: String,
|
||||||
|
func_body: Box<AirTree>,
|
||||||
|
hoisted_over: Box<AirTree>,
|
||||||
|
},
|
||||||
|
// Assertions
|
||||||
|
AssertConstr {
|
||||||
|
constr_index: usize,
|
||||||
|
constr: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
AssertBool {
|
||||||
|
is_true: bool,
|
||||||
|
value: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
// Field Access
|
||||||
|
FieldsExpose {
|
||||||
|
indices: Vec<(usize, String, Arc<Type>)>,
|
||||||
|
check_last_item: bool,
|
||||||
|
record: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
// List Access
|
||||||
|
ListAccessor {
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
names: Vec<String>,
|
||||||
|
tail: bool,
|
||||||
|
check_last_item: bool,
|
||||||
|
list: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
ListExpose {
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
tail_head_names: Vec<(String, String)>,
|
||||||
|
tail: Option<(String, String)>,
|
||||||
|
list: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
// Tuple Access
|
||||||
|
TupleAccessor {
|
||||||
|
names: Vec<String>,
|
||||||
|
tipo: Arc<Type>,
|
||||||
|
check_last_item: bool,
|
||||||
|
tuple: Box<AirTree>,
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
// Misc.
|
||||||
|
NoOp {
|
||||||
|
hoisted_over: Box<Option<AirTree>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum AirExpression {
|
||||||
// Primitives
|
// Primitives
|
||||||
Int {
|
Int {
|
||||||
value: String,
|
value: String,
|
||||||
|
@ -45,15 +117,7 @@ pub enum AirTree {
|
||||||
func: Box<AirTree>,
|
func: Box<AirTree>,
|
||||||
args: Vec<AirTree>,
|
args: Vec<AirTree>,
|
||||||
},
|
},
|
||||||
DefineFunc {
|
|
||||||
func_name: String,
|
|
||||||
module_name: String,
|
|
||||||
params: Vec<String>,
|
|
||||||
recursive: bool,
|
|
||||||
variant_name: String,
|
|
||||||
func_body: Box<AirTree>,
|
|
||||||
hoisted_over: Box<AirTree>,
|
|
||||||
},
|
|
||||||
Fn {
|
Fn {
|
||||||
params: Vec<String>,
|
params: Vec<String>,
|
||||||
func_body: Box<AirTree>,
|
func_body: Box<AirTree>,
|
||||||
|
@ -74,12 +138,7 @@ pub enum AirTree {
|
||||||
op: UnOp,
|
op: UnOp,
|
||||||
arg: Box<AirTree>,
|
arg: Box<AirTree>,
|
||||||
},
|
},
|
||||||
// Assignment
|
|
||||||
Let {
|
|
||||||
name: String,
|
|
||||||
value: Box<AirTree>,
|
|
||||||
hoisted_over: Box<Option<AirTree>>,
|
|
||||||
},
|
|
||||||
UnWrapData {
|
UnWrapData {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
value: Box<AirTree>,
|
value: Box<AirTree>,
|
||||||
|
@ -88,16 +147,7 @@ pub enum AirTree {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
value: Box<AirTree>,
|
value: Box<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
|
||||||
When {
|
When {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
|
@ -178,32 +228,7 @@ pub enum AirTree {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
record: Box<AirTree>,
|
record: Box<AirTree>,
|
||||||
},
|
},
|
||||||
FieldsExpose {
|
|
||||||
indices: Vec<(usize, String, Arc<Type>)>,
|
|
||||||
check_last_item: bool,
|
|
||||||
record: Box<AirTree>,
|
|
||||||
},
|
|
||||||
// ListAccess
|
|
||||||
ListAccessor {
|
|
||||||
tipo: Arc<Type>,
|
|
||||||
names: Vec<String>,
|
|
||||||
tail: bool,
|
|
||||||
check_last_item: bool,
|
|
||||||
list: Box<AirTree>,
|
|
||||||
},
|
|
||||||
ListExpose {
|
|
||||||
tipo: Arc<Type>,
|
|
||||||
tail_head_names: Vec<(String, String)>,
|
|
||||||
tail: Option<(String, String)>,
|
|
||||||
list: Box<AirTree>,
|
|
||||||
},
|
|
||||||
// Tuple Access
|
// Tuple Access
|
||||||
TupleAccessor {
|
|
||||||
names: Vec<String>,
|
|
||||||
tipo: Arc<Type>,
|
|
||||||
check_last_item: bool,
|
|
||||||
tuple: Box<AirTree>,
|
|
||||||
},
|
|
||||||
TupleIndex {
|
TupleIndex {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
tuple_index: usize,
|
tuple_index: usize,
|
||||||
|
@ -218,9 +243,6 @@ pub enum AirTree {
|
||||||
msg: Box<AirTree>,
|
msg: Box<AirTree>,
|
||||||
then: Box<AirTree>,
|
then: Box<AirTree>,
|
||||||
},
|
},
|
||||||
NoOp {
|
|
||||||
hoisted_over: Box<Option<AirTree>>,
|
|
||||||
},
|
|
||||||
FieldsEmpty {
|
FieldsEmpty {
|
||||||
constr: Box<AirTree>,
|
constr: Box<AirTree>,
|
||||||
},
|
},
|
||||||
|
@ -231,57 +253,57 @@ pub enum AirTree {
|
||||||
|
|
||||||
impl AirTree {
|
impl AirTree {
|
||||||
pub fn int(value: impl ToString) -> AirTree {
|
pub fn int(value: impl ToString) -> AirTree {
|
||||||
AirTree::Int {
|
AirTree::Expression(AirExpression::Int {
|
||||||
value: value.to_string(),
|
value: value.to_string(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn string(value: impl ToString) -> AirTree {
|
pub fn string(value: impl ToString) -> AirTree {
|
||||||
AirTree::String {
|
AirTree::Expression(AirExpression::String {
|
||||||
value: value.to_string(),
|
value: value.to_string(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn byte_array(bytes: Vec<u8>) -> AirTree {
|
pub fn byte_array(bytes: Vec<u8>) -> AirTree {
|
||||||
AirTree::ByteArray { bytes }
|
AirTree::Expression(AirExpression::ByteArray { bytes })
|
||||||
}
|
}
|
||||||
pub fn bool(value: bool) -> AirTree {
|
pub fn bool(value: bool) -> AirTree {
|
||||||
AirTree::Bool { value }
|
AirTree::Expression(AirExpression::Bool { value })
|
||||||
}
|
}
|
||||||
pub fn list(mut items: Vec<AirTree>, tipo: Arc<Type>, tail: Option<AirTree>) -> AirTree {
|
pub fn list(mut items: Vec<AirTree>, tipo: Arc<Type>, tail: Option<AirTree>) -> AirTree {
|
||||||
if let Some(tail) = tail {
|
if let Some(tail) = tail {
|
||||||
items.push(tail);
|
items.push(tail);
|
||||||
|
|
||||||
AirTree::List {
|
AirTree::Expression(AirExpression::List {
|
||||||
tipo,
|
tipo,
|
||||||
tail: true,
|
tail: true,
|
||||||
items,
|
items,
|
||||||
}
|
})
|
||||||
} else {
|
} else {
|
||||||
AirTree::List {
|
AirTree::Expression(AirExpression::List {
|
||||||
tipo,
|
tipo,
|
||||||
tail: false,
|
tail: false,
|
||||||
items,
|
items,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn tuple(items: Vec<AirTree>, tipo: Arc<Type>) -> AirTree {
|
pub fn tuple(items: Vec<AirTree>, tipo: Arc<Type>) -> AirTree {
|
||||||
AirTree::Tuple { tipo, items }
|
AirTree::Expression(AirExpression::Tuple { tipo, items })
|
||||||
}
|
}
|
||||||
pub fn void() -> AirTree {
|
pub fn void() -> AirTree {
|
||||||
AirTree::Void
|
AirTree::Expression(AirExpression::Void)
|
||||||
}
|
}
|
||||||
pub fn var(
|
pub fn var(
|
||||||
constructor: ValueConstructor,
|
constructor: ValueConstructor,
|
||||||
name: impl ToString,
|
name: impl ToString,
|
||||||
variant_name: impl ToString,
|
variant_name: impl ToString,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::Var {
|
AirTree::Expression(AirExpression::Var {
|
||||||
constructor,
|
constructor,
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
variant_name: variant_name.to_string(),
|
variant_name: variant_name.to_string(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn local_var(name: impl ToString, tipo: Arc<Type>) -> AirTree {
|
pub fn local_var(name: impl ToString, tipo: Arc<Type>) -> AirTree {
|
||||||
AirTree::Var {
|
AirTree::Expression(AirExpression::Var {
|
||||||
constructor: ValueConstructor::public(
|
constructor: ValueConstructor::public(
|
||||||
tipo,
|
tipo,
|
||||||
ValueConstructorVariant::LocalVariable {
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
@ -290,14 +312,14 @@ impl AirTree {
|
||||||
),
|
),
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
variant_name: "".to_string(),
|
variant_name: "".to_string(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn call(func: AirTree, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
pub fn call(func: AirTree, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
||||||
AirTree::Call {
|
AirTree::Expression(AirExpression::Call {
|
||||||
tipo,
|
tipo,
|
||||||
func: func.into(),
|
func: func.into(),
|
||||||
args,
|
args,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn define_func(
|
pub fn define_func(
|
||||||
func_name: impl ToString,
|
func_name: impl ToString,
|
||||||
|
@ -308,7 +330,7 @@ impl AirTree {
|
||||||
func_body: AirTree,
|
func_body: AirTree,
|
||||||
hoisting_over: AirTree,
|
hoisting_over: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::DefineFunc {
|
AirTree::Statement(AirStatement::DefineFunc {
|
||||||
func_name: func_name.to_string(),
|
func_name: func_name.to_string(),
|
||||||
module_name: module_name.to_string(),
|
module_name: module_name.to_string(),
|
||||||
params,
|
params,
|
||||||
|
@ -316,63 +338,63 @@ impl AirTree {
|
||||||
variant_name: variant_name.to_string(),
|
variant_name: variant_name.to_string(),
|
||||||
func_body: func_body.into(),
|
func_body: func_body.into(),
|
||||||
hoisted_over: hoisting_over.into(),
|
hoisted_over: hoisting_over.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn anon_func(params: Vec<String>, func_body: AirTree) -> AirTree {
|
pub fn anon_func(params: Vec<String>, func_body: AirTree) -> AirTree {
|
||||||
AirTree::Fn {
|
AirTree::Expression(AirExpression::Fn {
|
||||||
params,
|
params,
|
||||||
func_body: func_body.into(),
|
func_body: func_body.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn builtin(func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
pub fn builtin(func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
||||||
AirTree::Builtin { func, tipo, args }
|
AirTree::Expression(AirExpression::Builtin { func, tipo, args })
|
||||||
}
|
}
|
||||||
pub fn binop(op: BinOp, tipo: Arc<Type>, left: AirTree, right: AirTree) -> AirTree {
|
pub fn binop(op: BinOp, tipo: Arc<Type>, left: AirTree, right: AirTree) -> AirTree {
|
||||||
AirTree::BinOp {
|
AirTree::Expression(AirExpression::BinOp {
|
||||||
name: op,
|
name: op,
|
||||||
tipo,
|
tipo,
|
||||||
left: left.into(),
|
left: left.into(),
|
||||||
right: right.into(),
|
right: right.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn unop(op: UnOp, arg: AirTree) -> AirTree {
|
pub fn unop(op: UnOp, arg: AirTree) -> AirTree {
|
||||||
AirTree::UnOp {
|
AirTree::Expression(AirExpression::UnOp {
|
||||||
op,
|
op,
|
||||||
arg: arg.into(),
|
arg: arg.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn let_assignment(name: impl ToString, value: AirTree) -> AirTree {
|
pub fn let_assignment(name: impl ToString, value: AirTree) -> AirTree {
|
||||||
AirTree::Let {
|
AirTree::Statement(AirStatement::Let {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
hoisted_over: None.into(),
|
hoisted_over: None.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn unwrap_data(value: AirTree, tipo: Arc<Type>) -> AirTree {
|
pub fn unwrap_data(value: AirTree, tipo: Arc<Type>) -> AirTree {
|
||||||
AirTree::UnWrapData {
|
AirTree::Expression(AirExpression::UnWrapData {
|
||||||
tipo,
|
tipo,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn wrap_data(value: AirTree, tipo: Arc<Type>) -> AirTree {
|
pub fn wrap_data(value: AirTree, tipo: Arc<Type>) -> AirTree {
|
||||||
AirTree::WrapData {
|
AirTree::Expression(AirExpression::WrapData {
|
||||||
tipo,
|
tipo,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn assert_constr_index(constr_index: usize, constr: AirTree) -> AirTree {
|
pub fn assert_constr_index(constr_index: usize, constr: AirTree) -> AirTree {
|
||||||
AirTree::AssertConstr {
|
AirTree::Statement(AirStatement::AssertConstr {
|
||||||
constr_index,
|
constr_index,
|
||||||
constr: constr.into(),
|
constr: constr.into(),
|
||||||
hoisted_over: None.into(),
|
hoisted_over: None.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree {
|
pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree {
|
||||||
AirTree::AssertBool {
|
AirTree::Statement(AirStatement::AssertBool {
|
||||||
is_true,
|
is_true,
|
||||||
value: value.into(),
|
value: value.into(),
|
||||||
hoisted_over: None.into(),
|
hoisted_over: None.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn when(
|
pub fn when(
|
||||||
subject_name: impl ToString,
|
subject_name: impl ToString,
|
||||||
|
@ -380,12 +402,12 @@ impl AirTree {
|
||||||
clauses: Vec<AirTree>,
|
clauses: Vec<AirTree>,
|
||||||
final_clause: AirTree,
|
final_clause: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::When {
|
AirTree::Expression(AirExpression::When {
|
||||||
tipo,
|
tipo,
|
||||||
subject_name: subject_name.to_string(),
|
subject_name: subject_name.to_string(),
|
||||||
clauses,
|
clauses,
|
||||||
final_clause: final_clause.into(),
|
final_clause: final_clause.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn clause(
|
pub fn clause(
|
||||||
subject_name: impl ToString,
|
subject_name: impl ToString,
|
||||||
|
@ -395,14 +417,14 @@ impl AirTree {
|
||||||
otherwise: AirTree,
|
otherwise: AirTree,
|
||||||
complex_clause: bool,
|
complex_clause: bool,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::Clause {
|
AirTree::Expression(AirExpression::Clause {
|
||||||
tipo,
|
tipo,
|
||||||
subject_name: subject_name.to_string(),
|
subject_name: subject_name.to_string(),
|
||||||
complex_clause,
|
complex_clause,
|
||||||
pattern: pattern.into(),
|
pattern: pattern.into(),
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
otherwise: otherwise.into(),
|
otherwise: otherwise.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn list_clause(
|
pub fn list_clause(
|
||||||
tail_name: impl ToString,
|
tail_name: impl ToString,
|
||||||
|
@ -412,14 +434,14 @@ impl AirTree {
|
||||||
next_tail_name: Option<String>,
|
next_tail_name: Option<String>,
|
||||||
complex_clause: bool,
|
complex_clause: bool,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::ListClause {
|
AirTree::Expression(AirExpression::ListClause {
|
||||||
tipo,
|
tipo,
|
||||||
tail_name: tail_name.to_string(),
|
tail_name: tail_name.to_string(),
|
||||||
next_tail_name,
|
next_tail_name,
|
||||||
complex_clause,
|
complex_clause,
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
otherwise: otherwise.into(),
|
otherwise: otherwise.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn tuple_clause(
|
pub fn tuple_clause(
|
||||||
subject_name: impl ToString,
|
subject_name: impl ToString,
|
||||||
|
@ -432,7 +454,7 @@ impl AirTree {
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
let type_count = tipo.get_inner_types().len();
|
let type_count = tipo.get_inner_types().len();
|
||||||
|
|
||||||
AirTree::TupleClause {
|
AirTree::Expression(AirExpression::TupleClause {
|
||||||
tipo,
|
tipo,
|
||||||
indices,
|
indices,
|
||||||
predefined_indices,
|
predefined_indices,
|
||||||
|
@ -441,13 +463,13 @@ impl AirTree {
|
||||||
complex_clause,
|
complex_clause,
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
otherwise: otherwise.into(),
|
otherwise: otherwise.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn wrap_clause(then: AirTree, otherwise: AirTree) -> AirTree {
|
pub fn wrap_clause(then: AirTree, otherwise: AirTree) -> AirTree {
|
||||||
AirTree::WrapClause {
|
AirTree::Expression(AirExpression::WrapClause {
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
otherwise: otherwise.into(),
|
otherwise: otherwise.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn clause_guard(
|
pub fn clause_guard(
|
||||||
subject_name: impl ToString,
|
subject_name: impl ToString,
|
||||||
|
@ -455,12 +477,12 @@ impl AirTree {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::ClauseGuard {
|
AirTree::Expression(AirExpression::ClauseGuard {
|
||||||
subject_name: subject_name.to_string(),
|
subject_name: subject_name.to_string(),
|
||||||
tipo,
|
tipo,
|
||||||
pattern: pattern.into(),
|
pattern: pattern.into(),
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn list_clause_guard(
|
pub fn list_clause_guard(
|
||||||
tail_name: impl ToString,
|
tail_name: impl ToString,
|
||||||
|
@ -469,19 +491,19 @@ impl AirTree {
|
||||||
then: AirTree,
|
then: AirTree,
|
||||||
next_tail_name: Option<String>,
|
next_tail_name: Option<String>,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::ListClauseGuard {
|
AirTree::Expression(AirExpression::ListClauseGuard {
|
||||||
tipo,
|
tipo,
|
||||||
tail_name: tail_name.to_string(),
|
tail_name: tail_name.to_string(),
|
||||||
next_tail_name,
|
next_tail_name,
|
||||||
inverse,
|
inverse,
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn finally(pattern: AirTree, then: AirTree) -> AirTree {
|
pub fn finally(pattern: AirTree, then: AirTree) -> AirTree {
|
||||||
AirTree::Finally {
|
AirTree::Expression(AirExpression::Finally {
|
||||||
pattern: pattern.into(),
|
pattern: pattern.into(),
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn if_branches(
|
pub fn if_branches(
|
||||||
mut branches: Vec<(AirTree, AirTree)>,
|
mut branches: Vec<(AirTree, AirTree)>,
|
||||||
|
@ -491,26 +513,26 @@ impl AirTree {
|
||||||
assert!(!branches.is_empty());
|
assert!(!branches.is_empty());
|
||||||
let last_if = branches.pop().unwrap();
|
let last_if = branches.pop().unwrap();
|
||||||
|
|
||||||
let mut final_if = AirTree::If {
|
let mut final_if = AirTree::Expression(AirExpression::If {
|
||||||
tipo: tipo.clone(),
|
tipo: tipo.clone(),
|
||||||
pattern: last_if.0.into(),
|
pattern: last_if.0.into(),
|
||||||
then: last_if.1.into(),
|
then: last_if.1.into(),
|
||||||
otherwise: otherwise.into(),
|
otherwise: otherwise.into(),
|
||||||
};
|
});
|
||||||
|
|
||||||
while let Some(branch) = branches.pop() {
|
while let Some(branch) = branches.pop() {
|
||||||
final_if = AirTree::If {
|
final_if = AirTree::Expression(AirExpression::If {
|
||||||
tipo: tipo.clone(),
|
tipo: tipo.clone(),
|
||||||
pattern: branch.0.into(),
|
pattern: branch.0.into(),
|
||||||
then: branch.1.into(),
|
then: branch.1.into(),
|
||||||
otherwise: final_if.into(),
|
otherwise: final_if.into(),
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
final_if
|
final_if
|
||||||
}
|
}
|
||||||
pub fn create_constr(tag: usize, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
pub fn create_constr(tag: usize, tipo: Arc<Type>, args: Vec<AirTree>) -> AirTree {
|
||||||
AirTree::Constr { tag, tipo, args }
|
AirTree::Expression(AirExpression::Constr { tag, tipo, args })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn record_update(
|
pub fn record_update(
|
||||||
|
@ -520,20 +542,20 @@ impl AirTree {
|
||||||
record: AirTree,
|
record: AirTree,
|
||||||
args: Vec<AirTree>,
|
args: Vec<AirTree>,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::RecordUpdate {
|
AirTree::Expression(AirExpression::RecordUpdate {
|
||||||
highest_index,
|
highest_index,
|
||||||
indices,
|
indices,
|
||||||
tipo,
|
tipo,
|
||||||
record: record.into(),
|
record: record.into(),
|
||||||
args,
|
args,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn record_access(field_index: u64, tipo: Arc<Type>, record: AirTree) -> AirTree {
|
pub fn record_access(field_index: u64, tipo: Arc<Type>, record: AirTree) -> AirTree {
|
||||||
AirTree::RecordAccess {
|
AirTree::Expression(AirExpression::RecordAccess {
|
||||||
field_index,
|
field_index,
|
||||||
tipo,
|
tipo,
|
||||||
record: record.into(),
|
record: record.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields_expose(
|
pub fn fields_expose(
|
||||||
|
@ -541,11 +563,12 @@ impl AirTree {
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
record: AirTree,
|
record: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::FieldsExpose {
|
AirTree::Statement(AirStatement::FieldsExpose {
|
||||||
indices,
|
indices,
|
||||||
check_last_item,
|
check_last_item,
|
||||||
record: record.into(),
|
record: record.into(),
|
||||||
}
|
hoisted_over: None.into(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn list_access(
|
pub fn list_access(
|
||||||
names: Vec<String>,
|
names: Vec<String>,
|
||||||
|
@ -554,13 +577,14 @@ impl AirTree {
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
list: AirTree,
|
list: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::ListAccessor {
|
AirTree::Statement(AirStatement::ListAccessor {
|
||||||
tipo,
|
tipo,
|
||||||
names,
|
names,
|
||||||
tail,
|
tail,
|
||||||
check_last_item,
|
check_last_item,
|
||||||
list: list.into(),
|
list: list.into(),
|
||||||
}
|
hoisted_over: None.into(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn list_expose(
|
pub fn list_expose(
|
||||||
tail_head_names: Vec<(String, String)>,
|
tail_head_names: Vec<(String, String)>,
|
||||||
|
@ -568,12 +592,13 @@ impl AirTree {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
list: AirTree,
|
list: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::ListExpose {
|
AirTree::Statement(AirStatement::ListExpose {
|
||||||
tipo,
|
tipo,
|
||||||
tail_head_names,
|
tail_head_names,
|
||||||
tail,
|
tail,
|
||||||
list: list.into(),
|
list: list.into(),
|
||||||
}
|
hoisted_over: None.into(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn tuple_access(
|
pub fn tuple_access(
|
||||||
names: Vec<String>,
|
names: Vec<String>,
|
||||||
|
@ -581,213 +606,80 @@ impl AirTree {
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
tuple: AirTree,
|
tuple: AirTree,
|
||||||
) -> AirTree {
|
) -> AirTree {
|
||||||
AirTree::TupleAccessor {
|
AirTree::Statement(AirStatement::TupleAccessor {
|
||||||
names,
|
names,
|
||||||
tipo,
|
tipo,
|
||||||
check_last_item,
|
check_last_item,
|
||||||
tuple: tuple.into(),
|
tuple: tuple.into(),
|
||||||
}
|
hoisted_over: None.into(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn tuple_index(tuple_index: usize, tipo: Arc<Type>, tuple: AirTree) -> AirTree {
|
pub fn tuple_index(tuple_index: usize, tipo: Arc<Type>, tuple: AirTree) -> AirTree {
|
||||||
AirTree::TupleIndex {
|
AirTree::Expression(AirExpression::TupleIndex {
|
||||||
tipo,
|
tipo,
|
||||||
tuple_index,
|
tuple_index,
|
||||||
tuple: tuple.into(),
|
tuple: tuple.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn error(tipo: Arc<Type>) -> AirTree {
|
pub fn error(tipo: Arc<Type>) -> AirTree {
|
||||||
AirTree::ErrorTerm { tipo }
|
AirTree::Expression(AirExpression::ErrorTerm { tipo })
|
||||||
}
|
}
|
||||||
pub fn trace(msg: AirTree, tipo: Arc<Type>, then: AirTree) -> AirTree {
|
pub fn trace(msg: AirTree, tipo: Arc<Type>, then: AirTree) -> AirTree {
|
||||||
AirTree::Trace {
|
AirTree::Expression(AirExpression::Trace {
|
||||||
tipo,
|
tipo,
|
||||||
msg: msg.into(),
|
msg: msg.into(),
|
||||||
then: then.into(),
|
then: then.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn no_op() -> AirTree {
|
pub fn no_op() -> AirTree {
|
||||||
AirTree::NoOp {
|
AirTree::Statement(AirStatement::NoOp {
|
||||||
hoisted_over: None.into(),
|
hoisted_over: None.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn fields_empty(constr: AirTree) -> AirTree {
|
pub fn fields_empty(constr: AirTree) -> AirTree {
|
||||||
AirTree::FieldsEmpty {
|
AirTree::Expression(AirExpression::FieldsEmpty {
|
||||||
constr: constr.into(),
|
constr: constr.into(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
pub fn list_empty(list: AirTree) -> AirTree {
|
pub fn list_empty(list: AirTree) -> AirTree {
|
||||||
AirTree::ListEmpty { list: list.into() }
|
AirTree::Expression(AirExpression::ListEmpty { list: list.into() })
|
||||||
|
}
|
||||||
|
pub fn hoist_over(mut assignment: AirTree, next_exp: AirTree) -> AirTree {
|
||||||
|
match &mut assignment {
|
||||||
|
AirTree::Statement(st) => match st {
|
||||||
|
AirStatement::Let { hoisted_over, .. }
|
||||||
|
| AirStatement::AssertConstr { hoisted_over, .. }
|
||||||
|
| AirStatement::AssertBool { hoisted_over, .. }
|
||||||
|
| AirStatement::FieldsExpose { hoisted_over, .. }
|
||||||
|
| AirStatement::ListAccessor { hoisted_over, .. }
|
||||||
|
| AirStatement::NoOp { hoisted_over }
|
||||||
|
| AirStatement::ListExpose { hoisted_over, .. }
|
||||||
|
| AirStatement::TupleAccessor { hoisted_over, .. } => {
|
||||||
|
*hoisted_over = Some(next_exp).into();
|
||||||
|
assignment
|
||||||
|
}
|
||||||
|
AirStatement::DefineFunc { .. } => {
|
||||||
|
unreachable!("Should not use this function to hoist defined functions.")
|
||||||
}
|
}
|
||||||
pub fn hoist_let(assignment: AirTree, next_exp: AirTree) -> AirTree {
|
|
||||||
match assignment {
|
|
||||||
AirTree::Let { name, value, .. } => AirTree::Let {
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
hoisted_over: Some(next_exp).into(),
|
|
||||||
},
|
},
|
||||||
AirTree::AssertBool { is_true, value, .. } => AirTree::AssertBool {
|
AirTree::Expression(_) => {
|
||||||
is_true,
|
unreachable!("Trying to hoist an expression onto an expression.")
|
||||||
value,
|
}
|
||||||
hoisted_over: Some(next_exp).into(),
|
AirTree::IncompleteSequence(seq) => {
|
||||||
},
|
let mut final_exp = next_exp;
|
||||||
AirTree::AssertConstr {
|
while let Some(assign) = seq.pop() {
|
||||||
constr_index,
|
final_exp = Self::hoist_over(assign, final_exp);
|
||||||
constr,
|
}
|
||||||
..
|
final_exp
|
||||||
} => 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(air_vec: &mut Vec<Air>, tree: AirTree) {
|
pub fn to_air_vec(_air_vec: &mut Vec<Air>, tree: AirTree) {
|
||||||
match tree {
|
match tree {
|
||||||
AirTree::Int { value } => air_vec.push(todo!()),
|
AirTree::Statement(_) => todo!(),
|
||||||
AirTree::String { value } => todo!(),
|
AirTree::Expression(_) => todo!(),
|
||||||
AirTree::ByteArray { bytes } => todo!(),
|
AirTree::IncompleteSequence(_) => todo!(),
|
||||||
AirTree::Bool { value } => todo!(),
|
|
||||||
AirTree::List { tipo, tail, items } => todo!(),
|
|
||||||
AirTree::Tuple { tipo, items } => todo!(),
|
|
||||||
AirTree::Void => todo!(),
|
|
||||||
AirTree::Var {
|
|
||||||
constructor,
|
|
||||||
name,
|
|
||||||
variant_name,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::Call { tipo, func, args } => todo!(),
|
|
||||||
AirTree::DefineFunc {
|
|
||||||
func_name,
|
|
||||||
module_name,
|
|
||||||
params,
|
|
||||||
recursive,
|
|
||||||
variant_name,
|
|
||||||
func_body,
|
|
||||||
hoisted_over,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::Fn { params, func_body } => todo!(),
|
|
||||||
AirTree::Builtin { func, tipo, args } => todo!(),
|
|
||||||
AirTree::BinOp {
|
|
||||||
name,
|
|
||||||
tipo,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::UnOp { op, arg } => todo!(),
|
|
||||||
AirTree::Let {
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
hoisted_over,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::UnWrapData { tipo, value } => todo!(),
|
|
||||||
AirTree::WrapData { tipo, value } => todo!(),
|
|
||||||
AirTree::AssertConstr { .. } => todo!(),
|
|
||||||
AirTree::AssertBool { .. } => todo!(),
|
|
||||||
AirTree::When {
|
|
||||||
tipo,
|
|
||||||
subject_name,
|
|
||||||
clauses,
|
|
||||||
final_clause,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::Clause {
|
|
||||||
tipo,
|
|
||||||
subject_name,
|
|
||||||
complex_clause,
|
|
||||||
pattern,
|
|
||||||
then,
|
|
||||||
otherwise,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::ListClause {
|
|
||||||
tipo,
|
|
||||||
tail_name,
|
|
||||||
next_tail_name,
|
|
||||||
complex_clause,
|
|
||||||
then,
|
|
||||||
otherwise,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::WrapClause { then, otherwise } => todo!(),
|
|
||||||
AirTree::TupleClause {
|
|
||||||
tipo,
|
|
||||||
indices,
|
|
||||||
predefined_indices,
|
|
||||||
subject_name,
|
|
||||||
type_count,
|
|
||||||
complex_clause,
|
|
||||||
then,
|
|
||||||
otherwise,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::ClauseGuard {
|
|
||||||
subject_name,
|
|
||||||
tipo,
|
|
||||||
pattern,
|
|
||||||
then,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::ListClauseGuard {
|
|
||||||
tipo,
|
|
||||||
tail_name,
|
|
||||||
next_tail_name,
|
|
||||||
inverse,
|
|
||||||
then,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::Finally { pattern, then } => todo!(),
|
|
||||||
AirTree::If {
|
|
||||||
tipo,
|
|
||||||
pattern,
|
|
||||||
then,
|
|
||||||
otherwise,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::Constr { tag, tipo, args } => todo!(),
|
|
||||||
AirTree::RecordUpdate {
|
|
||||||
highest_index,
|
|
||||||
indices,
|
|
||||||
tipo,
|
|
||||||
record,
|
|
||||||
args,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::RecordAccess {
|
|
||||||
field_index,
|
|
||||||
tipo,
|
|
||||||
record,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::FieldsExpose {
|
|
||||||
indices,
|
|
||||||
check_last_item,
|
|
||||||
record,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::ListAccessor {
|
|
||||||
tipo,
|
|
||||||
names,
|
|
||||||
tail,
|
|
||||||
check_last_item,
|
|
||||||
list,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::ListExpose {
|
|
||||||
tipo,
|
|
||||||
tail_head_names,
|
|
||||||
tail,
|
|
||||||
list,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::TupleAccessor {
|
|
||||||
names,
|
|
||||||
tipo,
|
|
||||||
check_last_item,
|
|
||||||
tuple,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::TupleIndex {
|
|
||||||
tipo,
|
|
||||||
tuple_index,
|
|
||||||
tuple,
|
|
||||||
} => todo!(),
|
|
||||||
AirTree::ErrorTerm { tipo } => todo!(),
|
|
||||||
AirTree::Trace { tipo, msg, then } => todo!(),
|
|
||||||
AirTree::NoOp { .. } => todo!(),
|
|
||||||
AirTree::FieldsEmpty { constr } => todo!(),
|
|
||||||
AirTree::ListEmpty { list } => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
mod builder;
|
mod builder;
|
||||||
|
|
||||||
use std::{rc::Rc, sync::Arc};
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use uplc::ast::{Name, Program, Term};
|
use uplc::ast::{Name, Program, Term};
|
||||||
|
|
||||||
|
@ -84,12 +82,16 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::Sequence { expressions, .. } | TypedExpr::Pipeline { expressions, .. } => {
|
TypedExpr::Sequence { expressions, .. } | TypedExpr::Pipeline { expressions, .. } => {
|
||||||
let mut expressions = expressions.clone();
|
let mut expressions = expressions.clone();
|
||||||
|
|
||||||
let mut last_exp = self.build(&expressions.pop().unwrap());
|
let mut last_exp = self.build(&expressions.pop().unwrap_or_else(|| {
|
||||||
|
unreachable!("Sequence or Pipeline should have at least one expression")
|
||||||
|
}));
|
||||||
|
|
||||||
|
assert!(matches!(last_exp, AirTree::Expression(_)));
|
||||||
|
|
||||||
while let Some(expression) = expressions.pop() {
|
while let Some(expression) = expressions.pop() {
|
||||||
let exp_tree = self.build(&expression);
|
let exp_tree = self.build(&expression);
|
||||||
|
|
||||||
last_exp = AirTree::hoist_let(exp_tree, last_exp);
|
last_exp = AirTree::hoist_over(exp_tree, last_exp);
|
||||||
}
|
}
|
||||||
last_exp
|
last_exp
|
||||||
}
|
}
|
||||||
|
@ -243,6 +245,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AssignmentProperties {
|
AssignmentProperties {
|
||||||
value_type: value.tipo(),
|
value_type: value.tipo(),
|
||||||
kind: *kind,
|
kind: *kind,
|
||||||
|
remove_unused: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -260,7 +263,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let mut clauses = clauses.clone();
|
let mut clauses = clauses.clone();
|
||||||
|
|
||||||
if clauses.is_empty() {
|
if clauses.is_empty() {
|
||||||
panic!("We should have one clause at least")
|
unreachable!("We should have one clause at least")
|
||||||
} else if clauses.len() == 1 {
|
} else if clauses.len() == 1 {
|
||||||
let last_clause = clauses.pop().unwrap();
|
let last_clause = clauses.pop().unwrap();
|
||||||
|
|
||||||
|
@ -275,10 +278,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
AssignmentProperties {
|
AssignmentProperties {
|
||||||
value_type: subject.tipo(),
|
value_type: subject.tipo(),
|
||||||
kind: AssignmentKind::Let,
|
kind: AssignmentKind::Let,
|
||||||
|
remove_unused: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
AirTree::hoist_let(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.clone())
|
||||||
|
@ -336,7 +340,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
field_map: field_map.clone(),
|
field_map: field_map.clone(),
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
module: module_name.clone(),
|
module: module_name.clone(),
|
||||||
constructors_count: data_type.unwrap().constructors.len() as u16,
|
constructors_count: data_type
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
unreachable!("Created a module type without a definition?")
|
||||||
|
})
|
||||||
|
.constructors
|
||||||
|
.len() as u16,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{AssignmentKind, BinOp, Constant, Pattern},
|
ast::{BinOp, Constant, Pattern},
|
||||||
builtins::int,
|
builtins::int,
|
||||||
gen_uplc::{
|
gen_uplc::{
|
||||||
air::{self, Air},
|
|
||||||
builder::AssignmentProperties,
|
builder::AssignmentProperties,
|
||||||
tree::AirTree,
|
tree::{AirStatement, AirTree},
|
||||||
},
|
},
|
||||||
tipo::{PatternConstructor, Type},
|
tipo::{PatternConstructor, Type},
|
||||||
};
|
};
|
||||||
|
@ -26,10 +28,14 @@ pub fn assignment_air_tree(
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::Int {
|
Pattern::Int {
|
||||||
value: expected_int,
|
value: expected_int,
|
||||||
|
location,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if props.kind.is_expect() {
|
if props.kind.is_expect() {
|
||||||
let name = format!("__expected_by_{}", expected_int);
|
let name = format!(
|
||||||
|
"__expected_by_{}_span_{}_{}",
|
||||||
|
expected_int, location.start, location.end
|
||||||
|
);
|
||||||
let assignment = AirTree::let_assignment(&name, value);
|
let assignment = AirTree::let_assignment(&name, value);
|
||||||
|
|
||||||
let expect = AirTree::binop(
|
let expect = AirTree::binop(
|
||||||
|
@ -38,19 +44,20 @@ pub fn assignment_air_tree(
|
||||||
AirTree::int(expected_int),
|
AirTree::int(expected_int),
|
||||||
AirTree::local_var(name, int()),
|
AirTree::local_var(name, int()),
|
||||||
);
|
);
|
||||||
|
AirTree::assert_bool(true, AirTree::hoist_over(assignment, expect))
|
||||||
AirTree::assert_bool(true, AirTree::hoist_let(assignment, expect))
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!("Code Gen should never reach here")
|
unreachable!("Code Gen should never reach here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() {
|
if props.kind.is_expect() && props.value_type.is_data() && !tipo.is_data() {
|
||||||
|
let mut index_map = IndexMap::new();
|
||||||
|
let tipo = convert_opaque_type();
|
||||||
let assignment = AirTree::let_assignment(name, value);
|
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());
|
let val = AirTree::local_var(name, tipo.clone());
|
||||||
AirTree::let_assignment(name, AirTree::hoist_let(assign, val))
|
let expect = expect_type(&tipo, val.clone(), &mut index_map);
|
||||||
|
let assign = AirTree::let_assignment("_", AirTree::hoist_over(assignment, expect));
|
||||||
|
AirTree::let_assignment(name, AirTree::hoist_over(assign, val))
|
||||||
} else {
|
} else {
|
||||||
AirTree::let_assignment(name, value)
|
AirTree::let_assignment(name, value)
|
||||||
}
|
}
|
||||||
|
@ -58,33 +65,188 @@ pub fn assignment_air_tree(
|
||||||
Pattern::Assign { name, pattern, .. } => {
|
Pattern::Assign { name, pattern, .. } => {
|
||||||
let inner_pattern =
|
let inner_pattern =
|
||||||
assignment_air_tree(pattern, AirTree::local_var(name, tipo.clone()), tipo, props);
|
assignment_air_tree(pattern, AirTree::local_var(name, tipo.clone()), tipo, props);
|
||||||
|
|
||||||
AirTree::let_assignment(name, inner_pattern)
|
AirTree::let_assignment(name, inner_pattern)
|
||||||
}
|
}
|
||||||
Pattern::Discard { name, .. } => {
|
Pattern::Discard { name, .. } => {
|
||||||
if props.kind.is_expect() {
|
if props.kind.is_expect() || !props.remove_unused {
|
||||||
AirTree::let_assignment(name, value)
|
AirTree::let_assignment(name, value)
|
||||||
} else {
|
} else {
|
||||||
AirTree::no_op()
|
AirTree::no_op()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pattern::List {
|
Pattern::List {
|
||||||
location,
|
|
||||||
elements,
|
elements,
|
||||||
tail,
|
tail,
|
||||||
} => todo!(),
|
|
||||||
Pattern::Constructor {
|
|
||||||
is_record,
|
|
||||||
location,
|
location,
|
||||||
name,
|
..
|
||||||
arguments,
|
} => {
|
||||||
module,
|
let list_name = format!("__expect_list_span_{}_{}", location.start, location.end);
|
||||||
constructor,
|
assert!(tipo.is_list());
|
||||||
with_spread,
|
assert!(props.kind.is_expect());
|
||||||
tipo,
|
let list_elem_types = tipo.get_inner_types();
|
||||||
} => todo!(),
|
|
||||||
Pattern::Tuple { location, elems } => todo!(),
|
let list_elem_type = list_elem_types
|
||||||
|
.get(0)
|
||||||
|
.unwrap_or_else(|| unreachable!("No list element type?"));
|
||||||
|
|
||||||
|
let mut elems = elements
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, elem)| {
|
||||||
|
let elem_name = match elem {
|
||||||
|
Pattern::Var { name, .. } => name.to_string(),
|
||||||
|
Pattern::Assign { name, .. } => name.to_string(),
|
||||||
|
Pattern::Discard { .. } => "_".to_string(),
|
||||||
|
_ => format!(
|
||||||
|
"elem_{}_span_{}_{}",
|
||||||
|
index,
|
||||||
|
elem.location().start,
|
||||||
|
elem.location().end
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let val = AirTree::local_var(&elem_name, list_elem_type.clone());
|
||||||
|
|
||||||
|
(
|
||||||
|
elem_name,
|
||||||
|
assignment_air_tree(elem, val, list_elem_type, props.clone()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
// If Some then push tail onto elems
|
||||||
|
tail.iter().for_each(|tail| {
|
||||||
|
let tail_name = match tail.as_ref() {
|
||||||
|
Pattern::Var { name, .. } => name.to_string(),
|
||||||
|
Pattern::Assign { name, .. } => name.to_string(),
|
||||||
|
Pattern::Discard { .. } => "_".to_string(),
|
||||||
|
_ => format!(
|
||||||
|
"tail_span_{}_{}",
|
||||||
|
tail.location().start,
|
||||||
|
tail.location().end
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let val = AirTree::local_var(&tail_name, tipo.clone());
|
||||||
|
|
||||||
|
elems.push((
|
||||||
|
tail_name,
|
||||||
|
assignment_air_tree(tail, val, tipo, props.clone()),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
let names = elems.iter().map(|(name, _)| name.to_string()).collect_vec();
|
||||||
|
|
||||||
|
let mut sequence = vec![AirTree::list_access(
|
||||||
|
names,
|
||||||
|
tipo.clone(),
|
||||||
|
tail.is_some(),
|
||||||
|
tail.is_none(),
|
||||||
|
value,
|
||||||
|
)];
|
||||||
|
|
||||||
|
sequence.append(&mut elems.into_iter().map(|(_, elem)| elem).collect_vec());
|
||||||
|
|
||||||
|
AirTree::IncompleteSequence(sequence)
|
||||||
}
|
}
|
||||||
|
Pattern::Constructor {
|
||||||
|
arguments,
|
||||||
|
constructor,
|
||||||
|
is_record,
|
||||||
|
name,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if props.kind.is_expect() {
|
||||||
|
todo!()
|
||||||
|
} else {
|
||||||
|
assert!(is_record);
|
||||||
|
|
||||||
|
let field_map = match constructor {
|
||||||
|
PatternConstructor::Record { field_map, .. } => field_map.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
|
||||||
|
|
||||||
|
println!("tipo is {tipo:#?}");
|
||||||
|
|
||||||
|
for (index, arg) in tipo.arg_types().unwrap().iter().enumerate() {
|
||||||
|
let field_type = arg.clone();
|
||||||
|
type_map.insert(index, field_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fields = arguments
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, arg)| {
|
||||||
|
let label = arg.label.clone().unwrap_or_default();
|
||||||
|
|
||||||
|
let field_index = if let Some(field_map) = &field_map {
|
||||||
|
*field_map.fields.get(&label).map(|x| &x.0).unwrap_or(&index)
|
||||||
|
} else {
|
||||||
|
index
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_name = match &arg.value {
|
||||||
|
Pattern::Var { name, .. } => name.to_string(),
|
||||||
|
Pattern::Assign { name, .. } => name.to_string(),
|
||||||
|
Pattern::Discard { .. } => "_".to_string(),
|
||||||
|
_ => format!(
|
||||||
|
"field_{}_span_{}_{}",
|
||||||
|
field_index,
|
||||||
|
arg.value.location().start,
|
||||||
|
arg.value.location().end
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let arg_type = type_map.get(&field_index).unwrap_or_else(|| {
|
||||||
|
unreachable!(
|
||||||
|
"Missing type for field {} of constr {}",
|
||||||
|
field_index, name
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let val = AirTree::local_var(field_name.to_string(), arg_type.clone());
|
||||||
|
|
||||||
|
(
|
||||||
|
field_index,
|
||||||
|
field_name,
|
||||||
|
arg_type.clone(),
|
||||||
|
assignment_air_tree(&arg.value, val, arg_type, props.clone()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let indices = fields
|
||||||
|
.iter()
|
||||||
|
.map(|(index, name, tipo, _)| (*index, name.to_string(), tipo.clone()))
|
||||||
|
.collect_vec();
|
||||||
|
|
||||||
|
let mut sequence = vec![AirTree::fields_expose(indices, false, value)];
|
||||||
|
|
||||||
|
sequence.append(
|
||||||
|
&mut fields
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, _, _, field)| field)
|
||||||
|
.collect_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
|
AirTree::IncompleteSequence(sequence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pattern::Tuple { elems, .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_type(
|
||||||
|
tipo: &Arc<Type>,
|
||||||
|
value: AirTree,
|
||||||
|
defined_data_types: &mut IndexMap<String, u64>,
|
||||||
|
) -> AirTree {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn convert_opaque_type() -> Arc<Type> {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_each_clause(
|
pub fn handle_each_clause(
|
||||||
|
|
Loading…
Reference in New Issue