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

View File

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

View File

@ -22,7 +22,7 @@ use crate::{
tipo::{PatternConstructor, Type, TypeVar, ValueConstructor, ValueConstructorVariant},
};
use super::air::Air;
use super::{air::Air, stack::AirStack};
#[derive(Clone, Debug)]
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 {
Constant::Int { value, .. } => {
ir_stack.push(Air::Int {
scope,
value: value.clone(),
});
ir_stack.integer(value.clone());
}
Constant::String { value, .. } => {
ir_stack.push(Air::String {
scope,
value: value.clone(),
});
ir_stack.string(value.clone());
}
Constant::ByteArray { bytes, .. } => {
ir_stack.push(Air::ByteArray {
scope,
bytes: bytes.clone(),
});
ir_stack.byte_array(bytes.clone());
}
};
}
@ -1110,22 +1101,12 @@ pub fn monomorphize(
needs_variant = true;
}
}
Air::BinOp {
scope,
name,
count,
tipo,
} => {
Air::BinOp { scope, name, tipo } => {
if tipo.is_generic() {
let mut tipo = tipo.clone();
find_and_replace_generics(&mut tipo, &mono_types);
new_air[index] = Air::BinOp {
scope,
name,
tipo,
count,
};
new_air[index] = Air::BinOp { scope, name, tipo };
needs_variant = true;
}
}
@ -1332,7 +1313,7 @@ pub fn monomorphize(
}
Air::Record {
scope,
constr_index,
tag: constr_index,
tipo,
count,
} => {
@ -1343,7 +1324,7 @@ pub fn monomorphize(
new_air[index] = Air::Record {
scope,
tipo,
constr_index,
tag: constr_index,
count,
};
needs_variant = true;
@ -1719,7 +1700,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::Eq,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1729,7 +1709,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::NotEq,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1739,7 +1718,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::GtInt,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1749,7 +1727,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::GtEqInt,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1759,7 +1736,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::LtInt,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1769,7 +1745,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::LtEqInt,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1779,7 +1754,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::Or,
count: 2,
tipo: left.tipo(),
});
handle_clause_guard(left, clause_guard_vec, scope.clone());
@ -1789,7 +1763,6 @@ pub fn handle_clause_guard(
clause_guard_vec.push(Air::BinOp {
scope: scope.clone(),
name: BinOp::And,
count: 2,
tipo: left.tipo(),
});
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;
@ -12,7 +19,7 @@ impl<'a> AirStack<'a> {
pub fn new(id_gen: &'a mut IdGenerator) -> Self {
AirStack {
id_gen,
scope: vec![0],
scope: vec![id_gen.next()],
air: vec![],
}
}
@ -25,44 +32,158 @@ impl<'a> AirStack<'a> {
}
}
pub fn merge(mut self, other: AirStack) -> Self {
self.air.extend(other.air.into_iter());
pub fn in_new_scope(&mut self) -> Self {
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 {
let mut air = self.air.clone();
pub fn new_scope(&mut self) {
self.scope.push(self.id_gen.next());
}
air.push(Air::Int {
scope: self.scope.clone(),
value,
});
pub fn merge(&mut self, mut other: AirStack) {
self.air.append(&mut other.air);
}
AirStack {
id_gen: self.id_gen,
scope: self.scope,
air,
pub fn sequence(&mut self, stacks: Vec<AirStack>) {
for stack in stacks {
self.merge(stack)
}
}
pub fn string(mut self, value: String) -> Self {
pub fn integer(&mut self, value: String) {
self.air.push(Air::Int {
scope: self.scope.clone(),
value,
});
}
pub fn string(&mut self, value: String) {
self.air.push(Air::String {
scope: self.scope.clone(),
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 {
scope: self.scope.clone(),
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,
})
}
}