chore: move tree to gen_uplc2 and create a duplicate air file without scope

This commit is contained in:
microproofs 2023-06-29 13:30:24 -04:00 committed by Kasey
parent 7cee9a4d15
commit ba3265054c
5 changed files with 461 additions and 32 deletions

View File

@ -33,7 +33,6 @@ pub mod air;
pub mod builder;
pub mod scope;
pub mod stack;
pub mod tree;
use air::Air;
use builder::{

View File

@ -1,4 +1,6 @@
pub mod air;
mod builder;
pub mod tree;
use std::sync::Arc;
@ -10,16 +12,12 @@ use uplc::{
};
use crate::{
ast::{
AssignmentKind, BinOp, DataType, Pattern, Span, TypedDataType, TypedFunction,
TypedValidator,
},
ast::{AssignmentKind, BinOp, Pattern, Span, TypedDataType, TypedFunction, TypedValidator},
builtins::{int, void},
expr::TypedExpr,
gen_uplc::{
air::Air,
builder::{self as build, AssignmentProperties, DataTypeKey, FunctionAccessKey},
tree::AirTree,
},
tipo::{
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
@ -27,6 +25,8 @@ use crate::{
},
};
use self::tree::AirTree;
#[derive(Clone, Debug)]
pub enum CodeGenFunction {
Function(AirTree, Vec<String>),

View File

@ -0,0 +1,291 @@
use indexmap::IndexSet;
use std::sync::Arc;
use uplc::builtins::DefaultFunction;
use crate::{
ast::{BinOp, UnOp},
tipo::{Type, ValueConstructor},
};
#[derive(Debug, Clone, PartialEq)]
pub enum Air {
// Primitives
Int {
value: String,
},
String {
value: String,
},
ByteArray {
bytes: Vec<u8>,
},
Bool {
value: bool,
},
List {
count: usize,
tipo: Arc<Type>,
tail: bool,
},
Tuple {
tipo: Arc<Type>,
count: usize,
},
Void {},
Var {
constructor: ValueConstructor,
name: String,
variant_name: String,
},
// Functions
Call {
count: usize,
tipo: Arc<Type>,
},
DefineFunc {
func_name: String,
module_name: String,
params: Vec<String>,
recursive: bool,
variant_name: String,
},
Fn {
params: Vec<String>,
},
Builtin {
count: usize,
func: DefaultFunction,
tipo: Arc<Type>,
},
// Operators
BinOp {
name: BinOp,
tipo: Arc<Type>,
},
UnOp {
op: UnOp,
},
// Assignment
Let {
name: String,
},
UnWrapData {
tipo: Arc<Type>,
},
WrapData {
tipo: Arc<Type>,
},
AssertConstr {
constr_index: usize,
},
AssertBool {
is_true: bool,
},
// When
When {
tipo: Arc<Type>,
subject_name: String,
},
Clause {
tipo: Arc<Type>,
subject_name: String,
complex_clause: bool,
},
ListClause {
tipo: Arc<Type>,
tail_name: String,
next_tail_name: Option<String>,
complex_clause: bool,
},
WrapClause {},
TupleClause {
tipo: Arc<Type>,
indices: IndexSet<(usize, String)>,
predefined_indices: IndexSet<(usize, String)>,
subject_name: String,
count: usize,
complex_clause: bool,
},
ClauseGuard {
subject_name: String,
tipo: Arc<Type>,
},
ListClauseGuard {
tipo: Arc<Type>,
tail_name: String,
next_tail_name: Option<String>,
inverse: bool,
},
Finally {},
// If
If {
tipo: Arc<Type>,
},
// Record Creation
Record {
tag: usize,
tipo: Arc<Type>,
count: usize,
},
RecordUpdate {
highest_index: usize,
indices: Vec<(usize, Arc<Type>)>,
tipo: Arc<Type>,
},
// Field Access
RecordAccess {
record_index: u64,
tipo: Arc<Type>,
},
FieldsExpose {
indices: Vec<(usize, String, Arc<Type>)>,
check_last_item: bool,
},
// ListAccess
ListAccessor {
tipo: Arc<Type>,
names: Vec<String>,
tail: bool,
check_last_item: bool,
},
ListExpose {
tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>,
},
// Tuple Access
TupleAccessor {
names: Vec<String>,
tipo: Arc<Type>,
check_last_item: bool,
},
TupleIndex {
tipo: Arc<Type>,
tuple_index: usize,
},
// Misc.
ErrorTerm {
tipo: Arc<Type>,
},
Trace {
tipo: Arc<Type>,
},
NoOp {},
FieldsEmpty {},
ListEmpty {},
}
impl Air {
pub fn tipo(&self) -> Option<Arc<Type>> {
match self {
Air::Int { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Int".to_string(),
args: vec![],
}
.into(),
),
Air::String { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "String".to_string(),
args: vec![],
}
.into(),
),
Air::ByteArray { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "ByteArray".to_string(),
args: vec![],
}
.into(),
),
Air::Bool { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Bool".to_string(),
args: vec![],
}
.into(),
),
Air::Void { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Void".to_string(),
args: vec![],
}
.into(),
),
Air::WrapData { .. } => Some(
Type::App {
public: true,
module: String::new(),
name: "Data".to_string(),
args: vec![],
}
.into(),
),
Air::Var { constructor, .. } => Some(constructor.tipo.clone()),
Air::List { tipo, .. }
| Air::Tuple { tipo, .. }
| Air::Call { tipo, .. }
| Air::Builtin { tipo, .. }
| Air::BinOp { tipo, .. }
| Air::UnWrapData { tipo, .. }
| Air::When { tipo, .. }
| Air::Clause { tipo, .. }
| Air::ListClause { tipo, .. }
| Air::TupleClause { tipo, .. }
| Air::ClauseGuard { tipo, .. }
| Air::If { tipo, .. }
| Air::ListClauseGuard { tipo, .. }
| Air::Record { tipo, .. }
| Air::RecordUpdate { tipo, .. }
| Air::RecordAccess { tipo, .. }
| Air::ListAccessor { tipo, .. }
| Air::ListExpose { tipo, .. }
| Air::TupleAccessor { tipo, .. }
| Air::TupleIndex { tipo, .. }
| Air::ErrorTerm { tipo, .. }
| Air::Trace { tipo, .. } => Some(tipo.clone()),
Air::DefineFunc { .. }
| Air::Fn { .. }
| Air::Let { .. }
| Air::WrapClause { .. }
| Air::AssertConstr { .. }
| Air::AssertBool { .. }
| Air::Finally { .. }
| Air::FieldsExpose { .. }
| Air::FieldsEmpty { .. }
| Air::ListEmpty { .. }
| Air::NoOp { .. } => None,
Air::UnOp { op, .. } => match op {
UnOp::Not => Some(
Type::App {
public: true,
module: String::new(),
name: "Bool".to_string(),
args: vec![],
}
.into(),
),
UnOp::Negate => Some(
Type::App {
public: true,
module: String::new(),
name: "Int".to_string(),
args: vec![],
}
.into(),
),
},
}
}
}

View File

@ -2,10 +2,12 @@ use std::sync::Arc;
use crate::{
ast::{Constant, Pattern},
gen_uplc::{builder::AssignmentProperties, tree::AirTree},
gen_uplc::builder::AssignmentProperties,
tipo::{PatternConstructor, Type},
};
use super::tree::AirTree;
pub fn convert_opaque_type() -> Arc<Type> {
todo!()
}

View File

@ -23,7 +23,7 @@ pub enum AirStatement {
Let {
name: String,
value: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
DefineFunc {
func_name: String,
@ -38,19 +38,19 @@ pub enum AirStatement {
AssertConstr {
constr_index: usize,
constr: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
AssertBool {
is_true: bool,
value: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
// Field Access
FieldsExpose {
indices: Vec<(usize, String, Arc<Type>)>,
check_last_item: bool,
record: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
// List Access
ListAccessor {
@ -59,14 +59,14 @@ pub enum AirStatement {
tail: bool,
check_last_item: bool,
list: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
ListExpose {
tipo: Arc<Type>,
tail_head_names: Vec<(String, String)>,
tail: Option<(String, String)>,
list: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
// Tuple Access
TupleAccessor {
@ -74,11 +74,11 @@ pub enum AirStatement {
tipo: Arc<Type>,
check_last_item: bool,
tuple: Box<AirTree>,
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
// Misc.
NoOp {
hoisted_over: Box<Option<AirTree>>,
hoisted_over: Option<Box<AirTree>>,
},
}
@ -368,7 +368,7 @@ impl AirTree {
AirTree::Statement(AirStatement::Let {
name: name.to_string(),
value: value.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn unwrap_data(value: AirTree, tipo: Arc<Type>) -> AirTree {
@ -387,14 +387,14 @@ impl AirTree {
AirTree::Statement(AirStatement::AssertConstr {
constr_index,
constr: constr.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn assert_bool(is_true: bool, value: AirTree) -> AirTree {
AirTree::Statement(AirStatement::AssertBool {
is_true,
value: value.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn when(
@ -568,7 +568,7 @@ impl AirTree {
indices,
check_last_item,
record: record.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn list_access(
@ -584,7 +584,7 @@ impl AirTree {
tail,
check_last_item,
list: list.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn list_expose(
@ -598,7 +598,7 @@ impl AirTree {
tail_head_names,
tail,
list: list.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn tuple_access(
@ -612,7 +612,7 @@ impl AirTree {
tipo,
check_last_item,
tuple: tuple.into(),
hoisted_over: None.into(),
hoisted_over: None,
})
}
pub fn tuple_index(tuple_index: usize, tipo: Arc<Type>, tuple: AirTree) -> AirTree {
@ -633,9 +633,7 @@ impl AirTree {
})
}
pub fn no_op() -> AirTree {
AirTree::Statement(AirStatement::NoOp {
hoisted_over: None.into(),
})
AirTree::Statement(AirStatement::NoOp { hoisted_over: None })
}
pub fn fields_empty(constr: AirTree) -> AirTree {
AirTree::Expression(AirExpression::FieldsEmpty {
@ -657,7 +655,7 @@ impl AirTree {
| AirStatement::ListExpose { hoisted_over, .. }
| AirStatement::TupleAccessor { hoisted_over, .. } => {
assert!(hoisted_over.is_none());
*hoisted_over = Some(next_exp).into();
*hoisted_over = Some(next_exp.into());
assignment
}
AirStatement::DefineFunc { .. } => {
@ -691,7 +689,7 @@ impl AirTree {
let head_list = AirTree::builtin(DefaultFunction::HeadList, data(), vec![list_var]);
let expect_on_head = AirTree::call(
let _expect_on_head = AirTree::call(
AirTree::local_var("__check_with", void()),
void(),
vec![head_list],
@ -727,11 +725,150 @@ impl AirTree {
// self.call(void(), expect_stack, vec![tail_stack, arg_stack2])
}
pub fn to_air_vec(_air_vec: &mut Vec<Air>, tree: AirTree) {
match tree {
AirTree::Statement(_) => todo!(),
AirTree::Expression(_) => todo!(),
AirTree::UnhoistedSequence(_) => todo!(),
pub fn to_air_vec(&self, air_vec: &mut Vec<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);
}
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);
}
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);
}
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);
}
AirStatement::ListAccessor {
tipo,
names,
tail,
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);
}
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);
}
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);
}
AirStatement::NoOp {
hoisted_over: Some(exp),
} => {
// No need to push NoOp. It does nothing.
exp.to_air_vec(air_vec);
}
_ => unreachable!("SHOULD NOT HAVE A HOISTED OVER RESOLVING TO NONE"),
},
AirTree::Expression(exp) => match exp {
AirExpression::Int { value } => air_vec.push(Air::Int {
value: value.clone(),
}),
AirExpression::String { value } => air_vec.push(Air::String {
value: value.clone(),
}),
AirExpression::ByteArray { bytes } => air_vec.push(Air::ByteArray {
bytes: bytes.clone(),
}),
AirExpression::Bool { value } => air_vec.push(Air::Bool { value: *value }),
AirExpression::List { .. } => todo!(),
AirExpression::Tuple { .. } => todo!(),
AirExpression::Void => todo!(),
AirExpression::Var { .. } => todo!(),
AirExpression::Call { .. } => todo!(),
AirExpression::Fn { .. } => todo!(),
AirExpression::Builtin { .. } => todo!(),
AirExpression::BinOp { .. } => todo!(),
AirExpression::UnOp { .. } => todo!(),
AirExpression::UnWrapData { .. } => todo!(),
AirExpression::WrapData { .. } => todo!(),
AirExpression::When { .. } => todo!(),
AirExpression::Clause { .. } => todo!(),
AirExpression::ListClause { .. } => todo!(),
AirExpression::WrapClause { .. } => todo!(),
AirExpression::TupleClause { .. } => todo!(),
AirExpression::ClauseGuard { .. } => todo!(),
AirExpression::ListClauseGuard { .. } => todo!(),
AirExpression::Finally { .. } => todo!(),
AirExpression::If { .. } => todo!(),
AirExpression::Constr { .. } => todo!(),
AirExpression::RecordUpdate { .. } => todo!(),
AirExpression::RecordAccess { .. } => todo!(),
AirExpression::TupleIndex { .. } => todo!(),
AirExpression::ErrorTerm { .. } => todo!(),
AirExpression::Trace { .. } => todo!(),
AirExpression::FieldsEmpty { .. } => todo!(),
AirExpression::ListEmpty { .. } => todo!(),
},
AirTree::UnhoistedSequence(_) => {
unreachable!("SHOULD FIRST RESOLVE ALL UNHOISTED SEQUENCES")
}
}
}
}