feat: start using AirStack methods

Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
rvcas 2023-03-21 23:17:51 -04:00 committed by Lucas
parent 3e6f688e2d
commit ca0d896b8d
4 changed files with 313 additions and 326 deletions

View File

@ -34,6 +34,8 @@ use builder::{
AssignmentProperties, ClauseProperties, DataTypeKey, FuncComponents, FunctionAccessKey, AssignmentProperties, ClauseProperties, DataTypeKey, FuncComponents, FunctionAccessKey,
}; };
use self::stack::AirStack;
#[derive(Clone)] #[derive(Clone)]
pub struct CodeGenerator<'a> { pub struct CodeGenerator<'a> {
defined_functions: IndexMap<FunctionAccessKey, ()>, defined_functions: IndexMap<FunctionAccessKey, ()>,
@ -81,10 +83,9 @@ impl<'a> CodeGenerator<'a> {
.. ..
}: &TypedValidator, }: &TypedValidator,
) -> Program<Name> { ) -> Program<Name> {
let mut ir_stack = vec![]; let mut ir_stack = AirStack::new(&mut self.id_gen);
let scope = vec![self.id_gen.next()];
self.build_ir(&fun.body, &mut ir_stack, scope); self.build_ir(&fun.body, &mut ir_stack);
self.define_ir(&mut ir_stack); self.define_ir(&mut ir_stack);
@ -132,10 +133,9 @@ impl<'a> CodeGenerator<'a> {
} }
pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> { pub fn generate_test(&mut self, test_body: &TypedExpr) -> Program<Name> {
let mut ir_stack = vec![]; let mut ir_stack = AirStack::new(&mut self.id_gen);
let scope = vec![self.id_gen.next()];
self.build_ir(test_body, &mut ir_stack, scope); self.build_ir(test_body, &mut ir_stack);
self.define_ir(&mut ir_stack); self.define_ir(&mut ir_stack);
@ -179,75 +179,52 @@ impl<'a> CodeGenerator<'a> {
program program
} }
pub(crate) fn build_ir(&mut self, body: &TypedExpr, ir_stack: &mut Vec<Air>, scope: Vec<u64>) { pub(crate) fn build_ir(&mut self, body: &TypedExpr, ir_stack: &mut AirStack) {
match body { match body {
TypedExpr::Int { value, .. } => ir_stack.push(Air::Int { TypedExpr::Int { value, .. } => ir_stack.integer(value.to_string()),
scope, TypedExpr::String { value, .. } => ir_stack.string(value.to_string()),
value: value.to_string(), TypedExpr::ByteArray { bytes, .. } => ir_stack.byte_array(bytes.to_vec()),
}),
TypedExpr::String { value, .. } => ir_stack.push(Air::String {
scope,
value: value.to_string(),
}),
TypedExpr::ByteArray { bytes, .. } => ir_stack.push(Air::ByteArray {
scope,
bytes: bytes.to_vec(),
}),
TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => { TypedExpr::Pipeline { expressions, .. } | TypedExpr::Sequence { expressions, .. } => {
let stacks = Vec::new();
for (index, expr) in expressions.iter().enumerate() { for (index, expr) in expressions.iter().enumerate() {
if index == 0 { if index == 0 {
self.build_ir(expr, ir_stack, scope.clone()); self.build_ir(expr, ir_stack);
} else { } else {
let mut branch_scope = scope.clone(); let mut stack = ir_stack.in_new_scope();
branch_scope.push(self.id_gen.next()); self.build_ir(expr, &mut stack);
self.build_ir(expr, ir_stack, branch_scope);
} }
} }
ir_stack.sequence(stacks);
} }
TypedExpr::Var { TypedExpr::Var {
constructor, name, .. constructor, name, ..
} => match &constructor.variant { } => match &constructor.variant {
ValueConstructorVariant::ModuleConstant { literal, .. } => { ValueConstructorVariant::ModuleConstant { literal, .. } => {
builder::constants_ir(literal, ir_stack, scope); builder::constants_ir(literal, ir_stack);
} }
ValueConstructorVariant::ModuleFn { ValueConstructorVariant::ModuleFn {
builtin: Some(builtin), builtin: Some(builtin),
.. ..
} => { } => {
ir_stack.push(Air::Builtin { ir_stack.builtin(*builtin, constructor.tipo.clone(), vec![]);
scope,
func: *builtin,
tipo: constructor.tipo.clone(),
count: 0,
});
} }
_ => { _ => {
ir_stack.push(Air::Var { ir_stack.var(constructor.clone(), name, "");
scope,
constructor: constructor.clone(),
name: name.clone(),
variant_name: String::new(),
});
} }
}, },
TypedExpr::Fn { args, body, .. } => { TypedExpr::Fn { args, body, .. } => {
let mut func_body = vec![]; let mut body_stack = ir_stack.in_new_scope();
let mut func_scope = scope.clone();
func_scope.push(self.id_gen.next());
self.build_ir(body, &mut func_body, func_scope);
let mut arg_names = vec![];
for arg in args {
let name = arg.arg_name.get_variable_name().unwrap_or("_").to_string();
arg_names.push(name); self.build_ir(body, &mut body_stack);
}
ir_stack.push(Air::Fn { let mut params = args
scope, .iter()
params: arg_names, .map(|arg| arg.arg_name.get_variable_name().unwrap_or("_").to_string())
}); .collect();
ir_stack.append(&mut func_body); ir_stack.anonymous_function(params, body_stack);
} }
TypedExpr::List { TypedExpr::List {
elements, elements,
@ -255,25 +232,24 @@ impl<'a> CodeGenerator<'a> {
tipo, tipo,
.. ..
} => { } => {
ir_stack.push(Air::List { let stacks = Vec::new();
scope: scope.clone(), for element in elements {
count: elements.len(), let mut stack = ir_stack.in_new_scope();
tipo: tipo.clone(),
tail: tail.is_some(), self.build_ir(element, &mut stack);
stacks.push(stack);
}
let tail = tail.as_ref().map(|tail| {
let mut tail_stack = ir_stack.in_new_scope();
self.build_ir(tail, &mut tail_stack);
tail_stack
}); });
for element in elements { ir_stack.list(tipo.clone(), stacks, tail);
let mut scope = scope.clone();
scope.push(self.id_gen.next());
self.build_ir(element, ir_stack, scope.clone())
}
if let Some(tail) = tail {
let mut scope = scope;
scope.push(self.id_gen.next());
self.build_ir(tail, ir_stack, scope);
}
} }
TypedExpr::Call { TypedExpr::Call {
fun, args, tipo, .. fun, args, tipo, ..
@ -293,30 +269,26 @@ impl<'a> CodeGenerator<'a> {
.find(|(_, dt)| &dt.name == constr_name) .find(|(_, dt)| &dt.name == constr_name)
.unwrap(); .unwrap();
ir_stack.push(Air::Record { let Some(fun_arg_types) = fun.tipo().arg_types() else {
scope: scope.clone(), unreachable!()
constr_index, };
tipo: constructor.tipo.clone(),
count: args.len(), let stacks = Vec::new();
});
if let Some(fun_arg_types) = fun.tipo().arg_types() {
for (arg, func_type) in args.iter().zip(fun_arg_types) { for (arg, func_type) in args.iter().zip(fun_arg_types) {
let mut scope = scope.clone(); let mut stack = ir_stack.in_new_scope();
scope.push(self.id_gen.next());
if func_type.is_data() && !arg.value.tipo().is_data() { if func_type.is_data() && !arg.value.tipo().is_data() {
ir_stack.push(Air::WrapData { stack.wrap_data(arg.value.tipo());
scope: scope.clone(),
tipo: arg.value.tipo(),
})
} }
self.build_ir(&arg.value, ir_stack, scope); self.build_ir(&arg.value, &mut stack);
}
} else { stacks.push(stack);
unreachable!()
} }
ir_stack.record(constructor.tipo.clone(), constr_index, stacks);
return; return;
} }
} }
@ -324,31 +296,22 @@ impl<'a> CodeGenerator<'a> {
builtin: Some(func), builtin: Some(func),
.. ..
} => { } => {
ir_stack.push(Air::Builtin { let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!()};
scope: scope.clone(),
count: func.arity(), let stacks = Vec::new();
func: *func,
tipo: tipo.clone(),
});
if let Some(fun_arg_types) = fun.tipo().arg_types() {
for (arg, func_type) in args.iter().zip(fun_arg_types) { for (arg, func_type) in args.iter().zip(fun_arg_types) {
let mut scope = scope.clone(); let mut stack = ir_stack.in_new_scope();
scope.push(self.id_gen.next());
if func_type.is_data() && !arg.value.tipo().is_data() { if func_type.is_data() && !arg.value.tipo().is_data() {
ir_stack.push(Air::WrapData { stack.wrap_data(arg.value.tipo());
scope: scope.clone(),
tipo: arg.value.tipo(),
})
} }
self.build_ir(&arg.value, ir_stack, scope); self.build_ir(&arg.value, &mut stack);
}
} else {
unreachable!()
} }
ir_stack.builtin(*func, tipo.clone(), stacks);
return; return;
} }
_ => {} _ => {}
@ -373,30 +336,22 @@ impl<'a> CodeGenerator<'a> {
.find(|(_, dt)| &dt.name == constr_name) .find(|(_, dt)| &dt.name == constr_name)
.unwrap(); .unwrap();
ir_stack.push(Air::Record { let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!()};
scope: scope.clone(),
constr_index, let mut stacks = Vec::new();
tipo: tipo.clone(),
count: args.len(),
});
if let Some(fun_arg_types) = fun.tipo().arg_types() {
for (arg, func_type) in args.iter().zip(fun_arg_types) { for (arg, func_type) in args.iter().zip(fun_arg_types) {
let mut scope = scope.clone(); let mut stack = ir_stack.in_new_scope();
scope.push(self.id_gen.next());
if func_type.is_data() && !arg.value.tipo().is_data() { if func_type.is_data() && !arg.value.tipo().is_data() {
ir_stack.push(Air::WrapData { stack.wrap_data(arg.value.tipo());
scope: scope.clone(),
tipo: arg.value.tipo(),
})
} }
self.build_ir(&arg.value, ir_stack, scope); self.build_ir(&arg.value, &mut stack);
}
} else {
unreachable!()
} }
ir_stack.record(tipo.clone(), constr_index, stacks);
return; return;
} }
} }
@ -404,88 +359,61 @@ impl<'a> CodeGenerator<'a> {
let type_info = self.module_types.get(module_name).unwrap(); let type_info = self.module_types.get(module_name).unwrap();
let value = type_info.values.get(name).unwrap(); let value = type_info.values.get(name).unwrap();
match &value.variant { let ValueConstructorVariant::ModuleFn { builtin, .. } = &value.variant else {unreachable!()};
ValueConstructorVariant::ModuleFn { builtin, .. } => {
if let Some(func) = builtin { if let Some(func) = builtin {
ir_stack.push(Air::Builtin { let Some(fun_arg_types) = fun.tipo().arg_types() else {unreachable!()};
scope: scope.clone(),
count: func.arity(),
func: *func,
tipo: tipo.clone(),
});
if let Some(fun_arg_types) = fun.tipo().arg_types() { let mut stacks = Vec::new();
for (arg, func_type) in args.iter().zip(fun_arg_types) { for (arg, func_type) in args.iter().zip(fun_arg_types) {
let mut scope = scope.clone(); let mut stack = ir_stack.in_new_scope();
scope.push(self.id_gen.next());
if func_type.is_data() if func_type.is_data() && !arg.value.tipo().is_data() {
&& !arg.value.tipo().is_data() stack.wrap_data(arg.value.tipo());
{
ir_stack.push(Air::WrapData {
scope: scope.clone(),
tipo: arg.value.tipo(),
})
} }
self.build_ir(&arg.value, ir_stack, scope); self.build_ir(&arg.value, &mut stack);
}
} else {
unreachable!()
} }
ir_stack.builtin(*func, tipo.clone(), stacks);
return; return;
} }
} }
_ => unreachable!(),
}
}
_ => {} _ => {}
}, },
_ => {} _ => {}
} }
ir_stack.push(Air::Call { let mut fun_stack = ir_stack.in_new_scope();
scope: scope.clone(),
count: args.len(),
tipo: tipo.clone(),
});
let mut scope_fun = scope.clone();
scope_fun.push(self.id_gen.next());
self.build_ir(fun, ir_stack, scope_fun);
if let Some(fun_arg_types) = fun.tipo().arg_types() { self.build_ir(fun, &mut fun_stack);
let fun_arg_types = fun.tipo().arg_types().unwrap_or_default();
let mut stacks = Vec::new();
for (arg, func_type) in args.iter().zip(fun_arg_types) { for (arg, func_type) in args.iter().zip(fun_arg_types) {
let mut scope = scope.clone(); let mut stack = ir_stack.in_new_scope();
scope.push(self.id_gen.next());
if func_type.is_data() && !arg.value.tipo().is_data() { if func_type.is_data() && !arg.value.tipo().is_data() {
ir_stack.push(Air::WrapData { stack.wrap_data(arg.value.tipo());
scope: scope.clone(),
tipo: arg.value.tipo(),
})
} }
self.build_ir(&arg.value, ir_stack, scope); self.build_ir(&arg.value, &mut stack);
}
} }
ir_stack.call(tipo.clone(), fun_stack, stacks);
} }
TypedExpr::BinOp { TypedExpr::BinOp {
name, left, right, .. name, left, right, ..
} => { } => {
ir_stack.push(Air::BinOp { let mut left_stack = ir_stack.in_new_scope();
scope: scope.clone(), let mut right_stack = ir_stack.in_new_scope();
name: *name,
count: 2,
tipo: left.tipo(),
});
let mut scope_left = scope.clone();
scope_left.push(self.id_gen.next());
let mut scope_right = scope; self.build_ir(left, &mut left_stack);
scope_right.push(self.id_gen.next()); self.build_ir(right, &mut right_stack);
self.build_ir(left, ir_stack, scope_left); ir_stack.binop(*name, left.tipo(), left_stack, right_stack);
self.build_ir(right, ir_stack, scope_right);
} }
TypedExpr::Assignment { TypedExpr::Assignment {
value, value,
@ -494,30 +422,26 @@ impl<'a> CodeGenerator<'a> {
tipo, tipo,
.. ..
} => { } => {
let mut value_vec: Vec<Air> = vec![]; let mut value_stack = ir_stack.in_new_scope();
let mut pattern_vec: Vec<Air> = vec![]; let mut pattern_stack = ir_stack.in_new_scope();
let mut value_scope = scope.clone();
value_scope.push(self.id_gen.next());
let mut replaced_type = tipo.clone(); let mut replaced_type = tipo.clone();
builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); builder::replace_opaque_type(&mut replaced_type, self.data_types.clone());
self.build_ir(value, &mut value_vec, value_scope); self.build_ir(value, &mut value_stack);
self.assignment_ir( self.assignment_ir(
pattern, pattern,
&mut pattern_vec, &mut pattern_stack,
&mut value_vec, value_stack,
&replaced_type, &replaced_type,
AssignmentProperties { AssignmentProperties {
value_type: value.tipo(), value_type: value.tipo(),
kind: *kind, kind: *kind,
}, },
scope,
); );
ir_stack.append(&mut pattern_vec); ir_stack.merge(pattern_stack);
} }
TypedExpr::When { TypedExpr::When {
subject, clauses, .. subject, clauses, ..
@ -1823,74 +1747,57 @@ impl<'a> CodeGenerator<'a> {
fn assignment_ir( fn assignment_ir(
&mut self, &mut self,
pattern: &Pattern<PatternConstructor, Arc<Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, pattern_stack: &mut AirStack,
value_vec: &mut Vec<Air>, value_stack: AirStack,
tipo: &Type, tipo: &Type,
assignment_properties: AssignmentProperties, assignment_properties: AssignmentProperties,
scope: Vec<u64>,
) { ) {
if assignment_properties.value_type.is_data() && !tipo.is_data() && !pattern.is_discard() { let value_stack = if assignment_properties.value_type.is_data()
let mut scope = scope.clone(); && !tipo.is_data()
scope.push(self.id_gen.next()); && !pattern.is_discard()
{
let mut wrap_stack = pattern_stack.in_new_scope();
wrap_stack.un_wrap_data(tipo.clone().into());
wrap_stack.merge(value_stack);
wrap_stack
} else if !assignment_properties.value_type.is_data()
&& tipo.is_data()
&& !pattern.is_discard()
{
let mut wrap_stack = pattern_stack.in_new_scope();
wrap_stack.wrap_data(assignment_properties.value_type.clone());
wrap_stack.merge(value_stack);
wrap_stack
} else {
value_stack
};
value_vec.insert(
0,
Air::UnWrapData {
scope: scope.clone(),
tipo: tipo.clone().into(),
},
);
}
if !assignment_properties.value_type.is_data() && tipo.is_data() && !pattern.is_discard() {
let mut scope = scope.clone();
scope.push(self.id_gen.next());
value_vec.insert(
0,
Air::WrapData {
scope: scope.clone(),
tipo: assignment_properties.value_type.clone(),
},
)
}
match pattern { match pattern {
Pattern::Int { .. } => unreachable!(), Pattern::Int { .. } => todo!(),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
pattern_vec.push(Air::Let { let assert_value_stack = value_stack.in_new_scope();
name: name.clone(), pattern_stack.let_assignment(name, value_stack);
scope: scope.clone(),
});
pattern_vec.append(value_vec);
if matches!(assignment_properties.kind, AssignmentKind::Expect) if matches!(assignment_properties.kind, AssignmentKind::Expect)
&& assignment_properties.value_type.is_data() && assignment_properties.value_type.is_data()
&& !tipo.is_data() && !tipo.is_data()
{ {
let mut assert_vec = vec![]; let mut assert_stack = pattern_stack.in_new_scope();
let mut scope = scope;
scope.push(self.id_gen.next());
self.recursive_assert_pattern( self.recursive_assert_pattern(
pattern, pattern,
&mut assert_vec, &mut assert_stack,
value_vec, assert_value_stack,
tipo, tipo,
assignment_properties, assignment_properties,
scope,
); );
pattern_vec.append(&mut assert_vec);
}
}
Pattern::Assign { .. } => todo!("Assign not yet implemented yet"),
Pattern::Discard { .. } => {
pattern_vec.push(Air::Let {
name: "_".to_string(),
scope,
});
pattern_vec.append(value_vec); pattern_stack.merge(assert_stack);
}
}
Pattern::Assign { .. } => todo!("Assign not yet implemented"),
Pattern::Discard { .. } => {
pattern_stack.let_assignment("_", value_stack);
} }
list @ Pattern::List { .. } => { list @ Pattern::List { .. } => {
if matches!(assignment_properties.kind, AssignmentKind::Expect) if matches!(assignment_properties.kind, AssignmentKind::Expect)
@ -2261,18 +2168,17 @@ impl<'a> CodeGenerator<'a> {
pub fn recursive_assert_pattern( pub fn recursive_assert_pattern(
&mut self, &mut self,
pattern: &Pattern<PatternConstructor, Arc<Type>>, pattern: &Pattern<PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<Air>, assert_stack: &mut AirStack,
value_vec: &mut Vec<Air>, value_stack: AirStack,
tipo: &Type, tipo: &Type,
assignment_properties: AssignmentProperties, assignment_properties: AssignmentProperties,
scope: Vec<u64>,
) { ) {
match pattern { match pattern {
Pattern::Int { .. } => unreachable!(), Pattern::Int { .. } => unreachable!(),
Pattern::Var { name, .. } => { Pattern::Var { name, .. } => {
pattern_vec.append(value_vec); assert_stack.merge(value_stack);
self.recursive_assert_tipo(tipo, pattern_vec, name, scope); self.recursive_assert_tipo(tipo, assert_stack, name);
} }
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => unreachable!(), Pattern::Discard { .. } => unreachable!(),
@ -2530,13 +2436,7 @@ impl<'a> CodeGenerator<'a> {
} }
} }
fn recursive_assert_tipo( fn recursive_assert_tipo(&mut self, tipo: &Type, assert_vec: &mut AirStack, name: &str) {
&mut self,
tipo: &Type,
assert_vec: &mut Vec<Air>,
name: &str,
scope: Vec<u64>,
) {
let mut tipo = tipo.clone().into(); let mut tipo = tipo.clone().into();
builder::replace_opaque_type(&mut tipo, self.data_types.clone()); builder::replace_opaque_type(&mut tipo, self.data_types.clone());
@ -3675,19 +3575,13 @@ impl<'a> CodeGenerator<'a> {
tipo: replaced_type, tipo: replaced_type,
}; };
} }
Air::BinOp { Air::BinOp { tipo, scope, name } => {
tipo,
scope,
name,
count,
} => {
let mut replaced_type = tipo.clone(); let mut replaced_type = tipo.clone();
builder::replace_opaque_type(&mut replaced_type, self.data_types.clone()); builder::replace_opaque_type(&mut replaced_type, self.data_types.clone());
ir_stack[index] = Air::BinOp { ir_stack[index] = Air::BinOp {
scope, scope,
name, name,
count,
tipo: replaced_type, tipo: replaced_type,
}; };
} }
@ -3872,7 +3766,7 @@ impl<'a> CodeGenerator<'a> {
}; };
} }
Air::Record { Air::Record {
constr_index, tag: constr_index,
tipo, tipo,
count, count,
scope, scope,
@ -3885,7 +3779,7 @@ impl<'a> CodeGenerator<'a> {
ir_stack[index] = Air::Record { ir_stack[index] = Air::Record {
scope, scope,
constr_index, tag: constr_index,
tipo: replaced_type, tipo: replaced_type,
count, count,
}; };
@ -4884,7 +4778,7 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
} }
Air::Record { Air::Record {
constr_index, tag: constr_index,
tipo, tipo,
count, count,
.. ..

View File

@ -74,7 +74,6 @@ pub enum Air {
BinOp { BinOp {
scope: Vec<u64>, scope: Vec<u64>,
name: BinOp, name: BinOp,
count: usize,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },
UnOp { UnOp {
@ -156,7 +155,7 @@ pub enum Air {
// Record Creation // Record Creation
Record { Record {
scope: Vec<u64>, scope: Vec<u64>,
constr_index: usize, tag: usize,
tipo: Arc<Type>, tipo: Arc<Type>,
count: usize, count: usize,
}, },

View File

@ -22,7 +22,7 @@ use crate::{
tipo::{PatternConstructor, Type, TypeVar, ValueConstructor, ValueConstructorVariant}, tipo::{PatternConstructor, Type, TypeVar, ValueConstructor, ValueConstructorVariant},
}; };
use super::air::Air; use super::{air::Air, stack::AirStack};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FuncComponents { pub struct FuncComponents {
@ -713,25 +713,16 @@ pub fn check_when_pattern_needs(
} }
} }
pub fn constants_ir(literal: &Constant, ir_stack: &mut Vec<Air>, scope: Vec<u64>) { pub fn constants_ir(literal: &Constant, ir_stack: &mut AirStack) {
match literal { match literal {
Constant::Int { value, .. } => { Constant::Int { value, .. } => {
ir_stack.push(Air::Int { ir_stack.integer(value.clone());
scope,
value: value.clone(),
});
} }
Constant::String { value, .. } => { Constant::String { value, .. } => {
ir_stack.push(Air::String { ir_stack.string(value.clone());
scope,
value: value.clone(),
});
} }
Constant::ByteArray { bytes, .. } => { Constant::ByteArray { bytes, .. } => {
ir_stack.push(Air::ByteArray { ir_stack.byte_array(bytes.clone());
scope,
bytes: bytes.clone(),
});
} }
}; };
} }
@ -1110,22 +1101,12 @@ pub fn monomorphize(
needs_variant = true; needs_variant = true;
} }
} }
Air::BinOp { Air::BinOp { scope, name, tipo } => {
scope,
name,
count,
tipo,
} => {
if tipo.is_generic() { if tipo.is_generic() {
let mut tipo = tipo.clone(); let mut tipo = tipo.clone();
find_and_replace_generics(&mut tipo, &mono_types); find_and_replace_generics(&mut tipo, &mono_types);
new_air[index] = Air::BinOp { new_air[index] = Air::BinOp { scope, name, tipo };
scope,
name,
tipo,
count,
};
needs_variant = true; needs_variant = true;
} }
} }
@ -1332,7 +1313,7 @@ pub fn monomorphize(
} }
Air::Record { Air::Record {
scope, scope,
constr_index, tag: constr_index,
tipo, tipo,
count, count,
} => { } => {
@ -1343,7 +1324,7 @@ pub fn monomorphize(
new_air[index] = Air::Record { new_air[index] = Air::Record {
scope, scope,
tipo, tipo,
constr_index, tag: constr_index,
count, count,
}; };
needs_variant = true; needs_variant = true;
@ -1719,7 +1700,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::Eq, name: BinOp::Eq,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1729,7 +1709,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::NotEq, name: BinOp::NotEq,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1739,7 +1718,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::GtInt, name: BinOp::GtInt,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1749,7 +1727,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::GtEqInt, name: BinOp::GtEqInt,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1759,7 +1736,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::LtInt, name: BinOp::LtInt,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1769,7 +1745,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::LtEqInt, name: BinOp::LtEqInt,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1779,7 +1754,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::Or, name: BinOp::Or,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1789,7 +1763,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp { clause_guard_vec.push(Air::BinOp {
scope: scope.clone(), scope: scope.clone(),
name: BinOp::And, name: BinOp::And,
count: 2,
tipo: left.tipo(), tipo: left.tipo(),
}); });
handle_clause_guard(left, clause_guard_vec, scope.clone()); handle_clause_guard(left, clause_guard_vec, scope.clone());

View File

@ -1,4 +1,11 @@
use crate::IdGenerator; use std::sync::Arc;
use uplc::builtins::DefaultFunction;
use crate::{
tipo::{Type, ValueConstructor},
IdGenerator,
};
use super::air::Air; use super::air::Air;
@ -12,7 +19,7 @@ impl<'a> AirStack<'a> {
pub fn new(id_gen: &'a mut IdGenerator) -> Self { pub fn new(id_gen: &'a mut IdGenerator) -> Self {
AirStack { AirStack {
id_gen, id_gen,
scope: vec![0], scope: vec![id_gen.next()],
air: vec![], air: vec![],
} }
} }
@ -25,44 +32,158 @@ impl<'a> AirStack<'a> {
} }
} }
pub fn merge(mut self, other: AirStack) -> Self { pub fn in_new_scope(&mut self) -> Self {
self.air.extend(other.air.into_iter()); let mut new_stack = AirStack::with_scope(&mut self.id_gen, self.scope.clone());
self new_stack.new_scope();
new_stack
} }
pub fn int(self, value: String) -> Self { pub fn new_scope(&mut self) {
let mut air = self.air.clone(); self.scope.push(self.id_gen.next());
}
air.push(Air::Int { pub fn merge(&mut self, mut other: AirStack) {
self.air.append(&mut other.air);
}
pub fn sequence(&mut self, stacks: Vec<AirStack>) {
for stack in stacks {
self.merge(stack)
}
}
pub fn integer(&mut self, value: String) {
self.air.push(Air::Int {
scope: self.scope.clone(), scope: self.scope.clone(),
value, value,
}); });
AirStack {
id_gen: self.id_gen,
scope: self.scope,
air,
}
} }
pub fn string(mut self, value: String) -> Self { pub fn string(&mut self, value: String) {
self.air.push(Air::String { self.air.push(Air::String {
scope: self.scope.clone(), scope: self.scope.clone(),
value, value,
}); });
self
} }
pub fn byte_array(mut self, bytes: Vec<u8>) -> Self { pub fn byte_array(&mut self, bytes: Vec<u8>) {
self.air.push(Air::ByteArray { self.air.push(Air::ByteArray {
scope: self.scope.clone(), scope: self.scope.clone(),
bytes, bytes,
}); });
self
} }
// pub fn sequence(mut self, expressions: AirEnv) -> Self {} pub fn builtin(&mut self, func: DefaultFunction, tipo: Arc<Type>, args: Vec<AirStack>) {
self.air.push(Air::Builtin {
scope: self.scope.clone(),
count: args.len(),
func,
tipo,
});
self.sequence(args);
}
pub fn var(
&mut self,
constructor: ValueConstructor,
name: impl ToString,
variant_name: impl ToString,
) {
self.air.push(Air::Var {
scope: self.scope.clone(),
constructor,
name: name.to_string(),
variant_name: variant_name.to_string(),
});
}
pub fn anonymous_function(&mut self, params: Vec<String>, body: AirStack) {
self.air.push(Air::Fn {
scope: self.scope.clone(),
params,
});
self.merge(body);
}
pub fn list(&mut self, tipo: Arc<Type>, elements: Vec<AirStack>, tail: Option<AirStack>) {
self.air.push(Air::List {
scope: self.scope.clone(),
count: elements.len(),
tipo,
tail: tail.is_some(),
});
self.sequence(elements);
if let Some(tail) = tail {
self.merge(tail);
}
}
pub fn record(&mut self, tipo: Arc<Type>, tag: usize, fields: Vec<AirStack>) {
self.air.push(Air::Record {
scope: self.scope.clone(),
tag,
tipo,
count: fields.len(),
});
self.sequence(fields);
}
pub fn call(&mut self, tipo: Arc<Type>, fun: AirStack, args: Vec<AirStack>) {
self.air.push(Air::Call {
scope: self.scope.clone(),
count: args.len(),
tipo,
});
self.merge(fun);
self.sequence(args);
}
pub fn binop(
&mut self,
name: crate::ast::BinOp,
tipo: Arc<Type>,
left: AirStack,
right: AirStack,
) {
self.air.push(Air::BinOp {
scope: self.scope.clone(),
name,
tipo,
});
self.merge(left);
self.merge(right);
}
pub fn let_assignment(&mut self, name: impl ToString, value: AirStack) {
self.air.push(Air::Let {
scope: self.scope.clone(),
name: name.to_string(),
});
self.merge(value);
}
pub fn wrap_data(&mut self, tipo: Arc<Type>) {
self.air.push(Air::WrapData {
scope: self.scope.clone(),
tipo,
})
}
pub fn un_wrap_data(&mut self, tipo: Arc<Type>) {
self.air.push(Air::UnWrapData {
scope: self.scope.clone(),
tipo,
})
}
} }