feat: add support for unconstr_data

-Builitins IR now acts like Record IR in terms of argument consumption
-UnConstrData returns as Pair(Data,Data) to conform with how pairs are treated behind the scenes.
This commit is contained in:
Kasey White 2023-02-25 23:51:07 -05:00 committed by Kasey
parent 81e072a14e
commit 665a8dec67
7 changed files with 318 additions and 103 deletions

View File

@ -78,6 +78,7 @@ pub enum Air {
Builtin { Builtin {
scope: Vec<u64>, scope: Vec<u64>,
count: usize,
func: DefaultFunction, func: DefaultFunction,
tipo: Arc<Type>, tipo: Arc<Type>,
}, },

View File

@ -1485,12 +1485,22 @@ pub fn monomorphize(
needs_variant = true; needs_variant = true;
} }
} }
Air::Builtin { scope, func, tipo } => { Air::Builtin {
scope,
func,
tipo,
count,
} => {
if tipo.is_generic() { if tipo.is_generic() {
let mut tipo = tipo.clone(); let mut tipo = tipo.clone();
find_generics_to_replace(&mut tipo, &generic_types); find_generics_to_replace(&mut tipo, &generic_types);
new_air[index] = Air::Builtin { scope, func, tipo }; new_air[index] = Air::Builtin {
scope,
func,
tipo,
count,
};
needs_variant = true; needs_variant = true;
} }
} }

View File

@ -999,8 +999,8 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
start: location.start, start: location.start,
end: location.start + kind.location_offset(), end: location.start + kind.location_offset(),
}, },
pattern_location: dbg!(untyped_pattern.location()), pattern_location: untyped_pattern.location(),
value_location: dbg!(untyped_value.location()), value_location: untyped_value.location(),
sample: UntypedExpr::Assignment { sample: UntypedExpr::Assignment {
location: Span::empty(), location: Span::empty(),
value: Box::new(untyped_value), value: Box::new(untyped_value),

View File

@ -174,6 +174,7 @@ impl<'a> CodeGenerator<'a> {
scope, scope,
func: *builtin, func: *builtin,
tipo: constructor.tipo.clone(), tipo: constructor.tipo.clone(),
count: 0,
}); });
} }
_ => { _ => {
@ -233,11 +234,13 @@ impl<'a> CodeGenerator<'a> {
TypedExpr::Call { TypedExpr::Call {
fun, args, tipo, .. fun, args, tipo, ..
} => { } => {
if let Some(data_type) = lookup_data_type_by_tipo(self.data_types.clone(), tipo) { match &**fun {
if let TypedExpr::Var { constructor, .. } = &**fun { TypedExpr::Var { constructor, .. } => match &constructor.variant {
if let ValueConstructorVariant::Record { ValueConstructorVariant::Record {
name: constr_name, .. name: constr_name, ..
} = &constructor.variant } => {
if let Some(data_type) =
lookup_data_type_by_tipo(self.data_types.clone(), tipo)
{ {
let (constr_index, _) = data_type let (constr_index, _) = data_type
.constructors .constructors
@ -267,10 +270,132 @@ impl<'a> CodeGenerator<'a> {
self.build_ir(&arg.value, ir_stack, scope); self.build_ir(&arg.value, ir_stack, scope);
} }
} else {
unreachable!()
}
return; return;
} }
} }
ValueConstructorVariant::ModuleFn { builtin, .. } => {
if let Some(func) = builtin {
ir_stack.push(Air::Builtin {
scope: scope.clone(),
count: func.arity(),
func: func.clone(),
tipo: tipo.clone(),
});
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 {
unreachable!()
}
return;
}
}
_ => {}
},
TypedExpr::ModuleSelect {
constructor,
module_name,
..
} => match constructor {
ModuleValueConstructor::Record {
name: constr_name,
tipo,
..
} => {
if let Some(data_type) =
lookup_data_type_by_tipo(self.data_types.clone(), tipo)
{
let (constr_index, _) = data_type
.constructors
.iter()
.enumerate()
.find(|(_, dt)| &dt.name == constr_name)
.unwrap();
ir_stack.push(Air::Record {
scope: scope.clone(),
constr_index,
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) {
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 {
unreachable!()
}
return;
}
}
ModuleValueConstructor::Fn { name, .. } => {
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.clone(),
tipo: tipo.clone(),
});
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 {
unreachable!()
}
return;
}
}
_ => unreachable!(),
}
}
_ => {}
},
_ => {}
} }
ir_stack.push(Air::Call { ir_stack.push(Air::Call {
@ -575,14 +700,15 @@ impl<'a> CodeGenerator<'a> {
let value = type_info.values.get(name).unwrap(); let value = type_info.values.get(name).unwrap();
match &value.variant { match &value.variant {
ValueConstructorVariant::ModuleFn { builtin, .. } => { ValueConstructorVariant::ModuleFn { builtin, .. } => {
let builtin = builtin.unwrap(); if let Some(builtin) = builtin {
ir_stack.push(Air::Builtin { ir_stack.push(Air::Builtin {
func: builtin, func: *builtin,
scope, scope,
tipo: tipo.clone(), tipo: tipo.clone(),
count: 0,
}); });
} }
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -2339,16 +2465,11 @@ impl<'a> CodeGenerator<'a> {
let inner_list_type = &tipo.get_inner_types()[0]; let inner_list_type = &tipo.get_inner_types()[0];
let inner_pair_types = inner_list_type.get_inner_types(); let inner_pair_types = inner_list_type.get_inner_types();
assert_vec.push(Air::Call {
scope: scope.clone(),
count: 2,
tipo: tipo.clone(),
});
assert_vec.push(Air::Builtin { assert_vec.push(Air::Builtin {
scope: scope.clone(), scope: scope.clone(),
func: DefaultFunction::ChooseUnit, func: DefaultFunction::ChooseUnit,
tipo: tipo.clone(), tipo: tipo.clone(),
count: DefaultFunction::ChooseUnit.arity(),
}); });
assert_vec.push(Air::Call { assert_vec.push(Air::Call {
@ -2428,16 +2549,11 @@ impl<'a> CodeGenerator<'a> {
let new_id = self.id_gen.next(); let new_id = self.id_gen.next();
let inner_list_type = &tipo.get_inner_types()[0]; let inner_list_type = &tipo.get_inner_types()[0];
assert_vec.push(Air::Call {
scope: scope.clone(),
count: 2,
tipo: tipo.clone(),
});
assert_vec.push(Air::Builtin { assert_vec.push(Air::Builtin {
scope: scope.clone(), scope: scope.clone(),
func: DefaultFunction::ChooseUnit, func: DefaultFunction::ChooseUnit,
tipo: tipo.clone(), tipo: tipo.clone(),
count: DefaultFunction::ChooseUnit.arity(),
}); });
assert_vec.push(Air::Call { assert_vec.push(Air::Call {
@ -2549,16 +2665,11 @@ impl<'a> CodeGenerator<'a> {
let data_type = lookup_data_type_by_tipo(self.data_types.clone(), &tipo).unwrap(); let data_type = lookup_data_type_by_tipo(self.data_types.clone(), &tipo).unwrap();
let new_id = self.id_gen.next(); let new_id = self.id_gen.next();
assert_vec.push(Air::Call {
scope: scope.clone(),
count: 2,
tipo: tipo.clone(),
});
assert_vec.push(Air::Builtin { assert_vec.push(Air::Builtin {
scope: scope.clone(), scope: scope.clone(),
func: DefaultFunction::ChooseUnit, func: DefaultFunction::ChooseUnit,
tipo: tipo.clone(), tipo: tipo.clone(),
count: DefaultFunction::ChooseUnit.arity(),
}); });
assert_vec.push(Air::When { assert_vec.push(Air::When {
@ -3409,13 +3520,19 @@ impl<'a> CodeGenerator<'a> {
tail, tail,
}; };
} }
Air::Builtin { tipo, scope, func } => { Air::Builtin {
tipo,
scope,
func,
count,
} => {
let mut replaced_type = tipo.clone(); let mut replaced_type = tipo.clone();
replace_opaque_type(&mut replaced_type, self.data_types.clone()); replace_opaque_type(&mut replaced_type, self.data_types.clone());
ir_stack[index] = Air::Builtin { ir_stack[index] = Air::Builtin {
scope, scope,
func, func,
count,
tipo: replaced_type, tipo: replaced_type,
}; };
} }
@ -4157,53 +4274,138 @@ impl<'a> CodeGenerator<'a> {
} }
} }
} }
Air::Builtin { func, tipo, .. } => match func { Air::Builtin {
DefaultFunction::FstPair | DefaultFunction::SndPair | DefaultFunction::HeadList => { func, tipo, count, ..
let id = self.id_gen.next(); } => {
let mut term: Term<Name> = func.into(); let mut term: Term<Name> = Term::Builtin(func);
for _ in 0..func.force_count() { for _ in 0..func.force_count() {
term = term.force_wrap(); term = term.force_wrap();
} }
let mut arg_vec = vec![];
for _ in 0..count {
arg_vec.push(arg_stack.pop().unwrap());
}
for arg in arg_vec.iter() {
term = apply_wrap(term, arg.clone());
}
match func {
DefaultFunction::FstPair
| DefaultFunction::SndPair
| DefaultFunction::HeadList => {
let temp_var = format!("__item_{}", self.id_gen.next());
if count == 0 {
term = apply_wrap( term = apply_wrap(
term, term,
Term::Var( Term::Var(
Name { Name {
text: format!("__arg_{id}"), text: temp_var.clone(),
unique: 0.into(), unique: 0.into(),
} }
.into(), .into(),
), ),
); );
}
let inner_type = if matches!(func, DefaultFunction::SndPair) { term = convert_data_to_type(term, &tipo);
tipo.get_inner_types()[0].get_inner_types()[1].clone()
} else {
tipo.get_inner_types()[0].get_inner_types()[0].clone()
};
term = convert_data_to_type(term, &inner_type); if count == 0 {
term = Term::Lambda { term = Term::Lambda {
parameter_name: Name { parameter_name: Name {
text: format!("__arg_{id}"), text: temp_var,
unique: 0.into(), unique: 0.into(),
} }
.into(), .into(),
body: term.into(), body: term.into(),
}; };
}
}
DefaultFunction::UnConstrData => {
let temp_tuple = format!("__unconstr_tuple_{}", self.id_gen.next());
arg_stack.push(term); let temp_var = format!("__item_{}", self.id_gen.next());
if count == 0 {
term = apply_wrap(
term,
Term::Var(
Name {
text: temp_var.clone(),
unique: 0.into(),
} }
DefaultFunction::MkCons => todo!(), .into(),
DefaultFunction::MkPairData => todo!(), ),
_ => { );
let mut term = Term::Builtin(func);
for _ in 0..func.force_count() {
term = term.force_wrap();
} }
arg_stack.push(term);
term = apply_wrap(
Term::Lambda {
parameter_name: Name {
text: temp_tuple.clone(),
unique: 0.into(),
} }
.into(),
body: apply_wrap(
apply_wrap(
Term::Builtin(DefaultFunction::MkPairData),
apply_wrap(
Term::Builtin(DefaultFunction::IData),
apply_wrap(
Term::Builtin(DefaultFunction::FstPair)
.force_wrap()
.force_wrap(),
Term::Var(
Name {
text: temp_tuple.clone(),
unique: 0.into(),
}
.into(),
),
),
),
),
apply_wrap(
Term::Builtin(DefaultFunction::ListData),
apply_wrap(
Term::Builtin(DefaultFunction::SndPair)
.force_wrap()
.force_wrap(),
Term::Var(
Name {
text: temp_tuple,
unique: 0.into(),
}
.into(),
),
),
),
)
.into(),
}, },
term,
);
if count == 0 {
term = Term::Lambda {
parameter_name: Name {
text: temp_var,
unique: 0.into(),
}
.into(),
body: term.into(),
};
}
}
DefaultFunction::MkCons => {
unimplemented!("Use brackets instead.");
}
_ => {}
}
arg_stack.push(term);
}
Air::BinOp { name, tipo, .. } => { Air::BinOp { name, tipo, .. } => {
let left = arg_stack.pop().unwrap(); let left = arg_stack.pop().unwrap();
let right = arg_stack.pop().unwrap(); let right = arg_stack.pop().unwrap();
@ -4927,7 +5129,6 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
} }
Air::WrapClause { .. } => { Air::WrapClause { .. } => {
let _ = arg_stack.pop().unwrap(); let _ = arg_stack.pop().unwrap();

View File

@ -1,7 +1,8 @@
{ {
"preamble": { "preamble": {
"title": "aiken-lang/acceptance_test_036", "title": "aiken-lang/acceptance_test_036",
"version": "0.0.0" "version": "0.0.0",
"plutusVersion": "v2"
}, },
"validators": [ "validators": [
{ {

View File

@ -1,7 +1,8 @@
{ {
"preamble": { "preamble": {
"title": "aiken-lang/acceptance_test_047", "title": "aiken-lang/acceptance_test_047",
"version": "0.0.0" "version": "0.0.0",
"plutusVersion": "v2"
}, },
"validators": [ "validators": [
{ {

View File

@ -1,7 +1,8 @@
{ {
"preamble": { "preamble": {
"title": "aiken-lang/acceptance_test_048", "title": "aiken-lang/acceptance_test_048",
"version": "0.0.0" "version": "0.0.0",
"plutusVersion": "v2"
}, },
"validators": [ "validators": [
{ {