feat: start using AirStack methods
Co-authored-by: Kasey White <kwhitemsg@gmail.com>
This commit is contained in:
parent
3e6f688e2d
commit
ca0d896b8d
|
@ -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,
|
||||||
..
|
..
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue