feat: Finish up assert feature
Better error reporing on NonFunctionalApplication Error Refactor redundant code Add handling of whens with one clause.
This commit is contained in:
parent
4c8089c28a
commit
afd040fda5
|
@ -96,12 +96,6 @@ pub enum Air {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Assignment
|
// Assignment
|
||||||
Assert {
|
|
||||||
scope: Vec<u64>,
|
|
||||||
tipo: Arc<Type>,
|
|
||||||
value_is_data: bool,
|
|
||||||
},
|
|
||||||
|
|
||||||
Let {
|
Let {
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -112,14 +106,6 @@ pub enum Air {
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
|
|
||||||
ListAssert {
|
|
||||||
scope: Vec<u64>,
|
|
||||||
tipo: Arc<Type>,
|
|
||||||
names: Vec<String>,
|
|
||||||
tail: bool,
|
|
||||||
value_is_data: bool,
|
|
||||||
},
|
|
||||||
|
|
||||||
// When
|
// When
|
||||||
When {
|
When {
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
|
@ -275,8 +261,6 @@ impl Air {
|
||||||
| Air::Builtin { scope, .. }
|
| Air::Builtin { scope, .. }
|
||||||
| Air::BinOp { scope, .. }
|
| Air::BinOp { scope, .. }
|
||||||
| Air::UnOp { scope, .. }
|
| Air::UnOp { scope, .. }
|
||||||
| Air::Assert { scope, .. }
|
|
||||||
| Air::ListAssert { scope, .. }
|
|
||||||
| Air::Let { scope, .. }
|
| Air::Let { scope, .. }
|
||||||
| Air::UnWrapData { scope, .. }
|
| Air::UnWrapData { scope, .. }
|
||||||
| Air::When { scope, .. }
|
| Air::When { scope, .. }
|
||||||
|
@ -356,8 +340,6 @@ impl Air {
|
||||||
| Air::Call { tipo, .. }
|
| Air::Call { tipo, .. }
|
||||||
| Air::Builtin { tipo, .. }
|
| Air::Builtin { tipo, .. }
|
||||||
| Air::BinOp { tipo, .. }
|
| Air::BinOp { tipo, .. }
|
||||||
| Air::Assert { tipo, .. }
|
|
||||||
| Air::ListAssert { tipo, .. }
|
|
||||||
| Air::UnWrapData { tipo, .. }
|
| Air::UnWrapData { tipo, .. }
|
||||||
| Air::When { tipo, .. }
|
| Air::When { tipo, .. }
|
||||||
| Air::Clause { tipo, .. }
|
| Air::Clause { tipo, .. }
|
||||||
|
|
|
@ -4,7 +4,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{
|
ast::{
|
||||||
builder::{apply_wrap, choose_list, delayed_choose_list, if_else},
|
builder::{apply_wrap, delayed_choose_list, if_else},
|
||||||
Constant as UplcConstant, Name, Term, Type as UplcType,
|
Constant as UplcConstant, Name, Term, Type as UplcType,
|
||||||
},
|
},
|
||||||
builtins::DefaultFunction,
|
builtins::DefaultFunction,
|
||||||
|
@ -484,83 +484,50 @@ pub fn list_access_to_uplc(
|
||||||
tipos: Vec<Arc<Type>>,
|
tipos: Vec<Arc<Type>>,
|
||||||
check_last_item: bool,
|
check_last_item: bool,
|
||||||
) -> Term<Name> {
|
) -> Term<Name> {
|
||||||
let (first, names) = names.split_first().unwrap();
|
if let Some((first, names)) = names.split_first() {
|
||||||
let (current_tipo, tipos) = tipos.split_first().unwrap();
|
let (current_tipo, tipos) = tipos.split_first().unwrap();
|
||||||
|
|
||||||
let head_list = if current_tipo.is_map() {
|
let head_list = if current_tipo.is_map() {
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::HeadList).force_wrap(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
convert_data_to_type(
|
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
Term::Builtin(DefaultFunction::HeadList).force_wrap(),
|
Term::Builtin(DefaultFunction::HeadList).force_wrap(),
|
||||||
Term::Var(Name {
|
Term::Var(Name {
|
||||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
¤t_tipo.to_owned(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if names.len() == 1 && tail {
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: apply_wrap(
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: first.clone(),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: apply_wrap(
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: names[0].clone(),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: term.into(),
|
|
||||||
},
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: format!(
|
|
||||||
"tail_index_{}_{}",
|
|
||||||
current_index, id_list[current_index]
|
|
||||||
),
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
},
|
|
||||||
head_list,
|
|
||||||
)
|
)
|
||||||
.into(),
|
} else {
|
||||||
}
|
convert_data_to_type(
|
||||||
} else if names.is_empty() {
|
apply_wrap(
|
||||||
// Maybe check list is actually empty or should we leave that to when .. is only
|
Term::Builtin(DefaultFunction::HeadList).force_wrap(),
|
||||||
// this would replace term.into() if we decide to
|
Term::Var(Name {
|
||||||
Term::Lambda {
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
parameter_name: Name {
|
|
||||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: apply_wrap(
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: first.clone(),
|
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
},
|
}),
|
||||||
body: if check_last_item {
|
),
|
||||||
delayed_choose_list(
|
¤t_tipo.to_owned(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if names.len() == 1 && tail {
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: apply_wrap(
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: first.clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: apply_wrap(
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: names[0].clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: term.into(),
|
||||||
|
},
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
||||||
Term::Var(Name {
|
Term::Var(Name {
|
||||||
|
@ -571,66 +538,101 @@ pub fn list_access_to_uplc(
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
term,
|
|
||||||
apply_wrap(
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::Trace).force_wrap(),
|
|
||||||
Term::Constant(UplcConstant::String(
|
|
||||||
"List/Tuple contains more items than it should".to_string(),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
Term::Delay(Term::Error.into()),
|
|
||||||
)
|
|
||||||
.force_wrap(),
|
|
||||||
)
|
)
|
||||||
.into()
|
.into(),
|
||||||
} else {
|
|
||||||
term.into()
|
|
||||||
},
|
},
|
||||||
|
head_list,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
} else if names.is_empty() {
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
|
unique: 0.into(),
|
||||||
},
|
},
|
||||||
head_list,
|
body: apply_wrap(
|
||||||
)
|
Term::Lambda {
|
||||||
.into(),
|
parameter_name: Name {
|
||||||
|
text: first.clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: if check_last_item {
|
||||||
|
delayed_choose_list(
|
||||||
|
apply_wrap(
|
||||||
|
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: format!(
|
||||||
|
"tail_index_{}_{}",
|
||||||
|
current_index, id_list[current_index]
|
||||||
|
),
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
term,
|
||||||
|
apply_wrap(
|
||||||
|
apply_wrap(
|
||||||
|
Term::Builtin(DefaultFunction::Trace).force_wrap(),
|
||||||
|
Term::Constant(UplcConstant::String(
|
||||||
|
"List/Tuple contains more items than it should"
|
||||||
|
.to_string(),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Term::Delay(Term::Error.into()),
|
||||||
|
)
|
||||||
|
.force_wrap(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
term.into()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
head_list,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: apply_wrap(
|
||||||
|
Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: first.clone(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: apply_wrap(
|
||||||
|
list_access_to_uplc(
|
||||||
|
names,
|
||||||
|
id_list,
|
||||||
|
tail,
|
||||||
|
current_index + 1,
|
||||||
|
term,
|
||||||
|
tipos.to_owned(),
|
||||||
|
check_last_item,
|
||||||
|
),
|
||||||
|
apply_wrap(
|
||||||
|
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: format!(
|
||||||
|
"tail_index_{}_{}",
|
||||||
|
current_index, id_list[current_index]
|
||||||
|
),
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
},
|
||||||
|
head_list,
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Term::Lambda {
|
term
|
||||||
parameter_name: Name {
|
|
||||||
text: format!("tail_index_{}_{}", current_index, id_list[current_index]),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: apply_wrap(
|
|
||||||
Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: first.clone(),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: apply_wrap(
|
|
||||||
list_access_to_uplc(
|
|
||||||
names,
|
|
||||||
id_list,
|
|
||||||
tail,
|
|
||||||
current_index + 1,
|
|
||||||
term,
|
|
||||||
tipos.to_owned(),
|
|
||||||
check_last_item,
|
|
||||||
),
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: format!(
|
|
||||||
"tail_index_{}_{}",
|
|
||||||
current_index, id_list[current_index]
|
|
||||||
),
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
},
|
|
||||||
head_list,
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,7 @@ impl Type {
|
||||||
match self {
|
match self {
|
||||||
Self::Fn { args, .. } => Some(args.clone()),
|
Self::Fn { args, .. } => Some(args.clone()),
|
||||||
Self::App { args, .. } => Some(args.clone()),
|
Self::App { args, .. } => Some(args.clone()),
|
||||||
|
Self::Var { tipo } => tipo.borrow().arg_types(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,6 +499,13 @@ impl TypeVar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn arg_types(&self) -> Option<Vec<Arc<Type>>> {
|
||||||
|
match self {
|
||||||
|
Self::Link { tipo } => tipo.arg_types(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_inner_type(&self) -> Vec<Arc<Type>> {
|
pub fn get_inner_type(&self) -> Vec<Arc<Type>> {
|
||||||
match self {
|
match self {
|
||||||
Self::Link { tipo } => tipo.get_inner_types(),
|
Self::Link { tipo } => tipo.get_inner_types(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{clone, sync::Arc, vec};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -19,7 +19,7 @@ use uplc::{
|
||||||
use crate::{
|
use crate::{
|
||||||
air::Air,
|
air::Air,
|
||||||
ast::{
|
ast::{
|
||||||
ArgName, AssignmentKind, BinOp, CallArg, Clause, Pattern, Span, TypedArg, TypedDataType,
|
ArgName, AssignmentKind, BinOp, Clause, Pattern, Span, TypedArg, TypedDataType,
|
||||||
TypedFunction, UnOp,
|
TypedFunction, UnOp,
|
||||||
},
|
},
|
||||||
builder::{
|
builder::{
|
||||||
|
@ -32,8 +32,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
expr::TypedExpr,
|
expr::TypedExpr,
|
||||||
tipo::{
|
tipo::{
|
||||||
fields::FieldMap, ModuleValueConstructor, PatternConstructor, Type, TypeInfo, TypeVar,
|
ModuleValueConstructor, PatternConstructor, Type, TypeInfo, ValueConstructor,
|
||||||
ValueConstructor, ValueConstructorVariant,
|
ValueConstructorVariant,
|
||||||
},
|
},
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
@ -80,13 +80,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let scope = vec![self.id_gen.next()];
|
let scope = vec![self.id_gen.next()];
|
||||||
|
|
||||||
self.build_ir(&body, &mut ir_stack, scope);
|
self.build_ir(&body, &mut ir_stack, scope);
|
||||||
println!("{:#?}", ir_stack);
|
|
||||||
|
|
||||||
self.define_ir(&mut ir_stack);
|
self.define_ir(&mut ir_stack);
|
||||||
println!("{:#?}", ir_stack);
|
|
||||||
|
|
||||||
self.convert_opaque_type_to_inner_ir(&mut ir_stack);
|
self.convert_opaque_type_to_inner_ir(&mut ir_stack);
|
||||||
println!("{:#?}", ir_stack);
|
|
||||||
|
|
||||||
let mut term = self.uplc_code_gen(&mut ir_stack);
|
let mut term = self.uplc_code_gen(&mut ir_stack);
|
||||||
|
|
||||||
|
@ -115,7 +112,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
version: (1, 0, 0),
|
version: (1, 0, 0),
|
||||||
term,
|
term,
|
||||||
};
|
};
|
||||||
println!("{}", program.to_pretty());
|
|
||||||
|
|
||||||
let mut interner = Interner::new();
|
let mut interner = Interner::new();
|
||||||
|
|
||||||
|
@ -324,104 +320,124 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
// assuming one subject at the moment
|
// assuming one subject at the moment
|
||||||
let subject = subjects[0].clone();
|
let subject = subjects[0].clone();
|
||||||
|
|
||||||
if clauses.len() <= 1 {
|
if clauses.len() <= 1 {
|
||||||
todo!("Single clause cases not implemented")
|
let mut value_vec: Vec<Air> = vec![];
|
||||||
}
|
let mut pattern_vec: Vec<Air> = vec![];
|
||||||
|
let mut subject_vec: Vec<Air> = vec![];
|
||||||
|
|
||||||
let clauses = if matches!(clauses[0].pattern[0], Pattern::List { .. }) {
|
self.build_ir(&clauses[0].then, &mut value_vec, scope.clone());
|
||||||
rearrange_clauses(clauses.clone())
|
|
||||||
} else {
|
|
||||||
clauses.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some((last_clause, clauses)) = clauses.split_last() {
|
self.build_ir(&subject, &mut value_vec, scope.clone());
|
||||||
let mut pattern_vec = vec![];
|
|
||||||
|
|
||||||
let mut clause_properties = ClauseProperties::init(
|
self.assignment_ir(
|
||||||
&subject.tipo(),
|
&clauses[0].pattern[0],
|
||||||
constr_var.clone(),
|
|
||||||
subject_name.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.handle_each_clause(
|
|
||||||
&mut pattern_vec,
|
&mut pattern_vec,
|
||||||
&mut clause_properties,
|
&mut subject_vec,
|
||||||
clauses,
|
|
||||||
&subject.tipo(),
|
&subject.tipo(),
|
||||||
scope.clone(),
|
AssignmentProperties {
|
||||||
|
value_is_data: false,
|
||||||
|
kind: AssignmentKind::Let,
|
||||||
|
},
|
||||||
|
scope,
|
||||||
);
|
);
|
||||||
|
|
||||||
let last_pattern = &last_clause.pattern[0];
|
|
||||||
|
|
||||||
let mut final_scope = scope.clone();
|
|
||||||
|
|
||||||
final_scope.push(self.id_gen.next());
|
|
||||||
|
|
||||||
pattern_vec.push(Air::Finally {
|
|
||||||
scope: final_scope.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut final_clause_vec = vec![];
|
|
||||||
|
|
||||||
self.build_ir(
|
|
||||||
&last_clause.then,
|
|
||||||
&mut final_clause_vec,
|
|
||||||
final_scope.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.when_ir(
|
|
||||||
last_pattern,
|
|
||||||
&mut pattern_vec,
|
|
||||||
&mut final_clause_vec,
|
|
||||||
&subject.tipo(),
|
|
||||||
&mut clause_properties,
|
|
||||||
final_scope,
|
|
||||||
);
|
|
||||||
|
|
||||||
if *clause_properties.needs_constr_var() {
|
|
||||||
ir_stack.push(Air::Let {
|
|
||||||
scope: scope.clone(),
|
|
||||||
name: constr_var.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
self.build_ir(&subject, ir_stack, scope.clone());
|
|
||||||
|
|
||||||
ir_stack.push(Air::When {
|
|
||||||
scope: scope.clone(),
|
|
||||||
subject_name,
|
|
||||||
tipo: subject.tipo(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut scope = scope;
|
|
||||||
scope.push(self.id_gen.next());
|
|
||||||
|
|
||||||
ir_stack.push(Air::Var {
|
|
||||||
scope,
|
|
||||||
constructor: ValueConstructor::public(
|
|
||||||
subject.tipo(),
|
|
||||||
ValueConstructorVariant::LocalVariable {
|
|
||||||
location: Span::empty(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
name: constr_var,
|
|
||||||
variant_name: String::new(),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
ir_stack.push(Air::When {
|
|
||||||
scope: scope.clone(),
|
|
||||||
subject_name,
|
|
||||||
tipo: subject.tipo(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut scope = scope;
|
|
||||||
scope.push(self.id_gen.next());
|
|
||||||
|
|
||||||
self.build_ir(&subject, ir_stack, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
ir_stack.append(&mut pattern_vec);
|
ir_stack.append(&mut pattern_vec);
|
||||||
};
|
ir_stack.append(&mut value_vec);
|
||||||
|
} else {
|
||||||
|
let clauses = if matches!(clauses[0].pattern[0], Pattern::List { .. }) {
|
||||||
|
rearrange_clauses(clauses.clone())
|
||||||
|
} else {
|
||||||
|
clauses.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((last_clause, clauses)) = clauses.split_last() {
|
||||||
|
let mut pattern_vec = vec![];
|
||||||
|
|
||||||
|
let mut clause_properties = ClauseProperties::init(
|
||||||
|
&subject.tipo(),
|
||||||
|
constr_var.clone(),
|
||||||
|
subject_name.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.handle_each_clause(
|
||||||
|
&mut pattern_vec,
|
||||||
|
&mut clause_properties,
|
||||||
|
clauses,
|
||||||
|
&subject.tipo(),
|
||||||
|
scope.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let last_pattern = &last_clause.pattern[0];
|
||||||
|
|
||||||
|
let mut final_scope = scope.clone();
|
||||||
|
|
||||||
|
final_scope.push(self.id_gen.next());
|
||||||
|
|
||||||
|
pattern_vec.push(Air::Finally {
|
||||||
|
scope: final_scope.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut final_clause_vec = vec![];
|
||||||
|
|
||||||
|
self.build_ir(
|
||||||
|
&last_clause.then,
|
||||||
|
&mut final_clause_vec,
|
||||||
|
final_scope.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.when_ir(
|
||||||
|
last_pattern,
|
||||||
|
&mut pattern_vec,
|
||||||
|
&mut final_clause_vec,
|
||||||
|
&subject.tipo(),
|
||||||
|
&mut clause_properties,
|
||||||
|
final_scope,
|
||||||
|
);
|
||||||
|
|
||||||
|
if *clause_properties.needs_constr_var() {
|
||||||
|
ir_stack.push(Air::Let {
|
||||||
|
scope: scope.clone(),
|
||||||
|
name: constr_var.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.build_ir(&subject, ir_stack, scope.clone());
|
||||||
|
|
||||||
|
ir_stack.push(Air::When {
|
||||||
|
scope: scope.clone(),
|
||||||
|
subject_name,
|
||||||
|
tipo: subject.tipo(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut scope = scope;
|
||||||
|
scope.push(self.id_gen.next());
|
||||||
|
|
||||||
|
ir_stack.push(Air::Var {
|
||||||
|
scope,
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
subject.tipo(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: constr_var,
|
||||||
|
variant_name: String::new(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ir_stack.push(Air::When {
|
||||||
|
scope: scope.clone(),
|
||||||
|
subject_name,
|
||||||
|
tipo: subject.tipo(),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut scope = scope;
|
||||||
|
scope.push(self.id_gen.next());
|
||||||
|
|
||||||
|
self.build_ir(&subject, ir_stack, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
ir_stack.append(&mut pattern_vec);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TypedExpr::If {
|
TypedExpr::If {
|
||||||
branches,
|
branches,
|
||||||
|
@ -479,7 +495,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
tipo,
|
tipo,
|
||||||
..
|
..
|
||||||
} => match constructor {
|
} => match constructor {
|
||||||
ModuleValueConstructor::Record { .. } => todo!(),
|
ModuleValueConstructor::Record { .. } => {
|
||||||
|
todo!("Records from modules not yet implemented.")
|
||||||
|
}
|
||||||
ModuleValueConstructor::Fn { name, module, .. } => {
|
ModuleValueConstructor::Fn { name, module, .. } => {
|
||||||
let func = self.functions.get(&FunctionAccessKey {
|
let func = self.functions.get(&FunctionAccessKey {
|
||||||
module_name: module_name.clone(),
|
module_name: module_name.clone(),
|
||||||
|
@ -798,7 +816,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
pattern_vec.append(values);
|
pattern_vec.append(values);
|
||||||
}
|
}
|
||||||
Pattern::String { .. } => todo!(),
|
Pattern::String { .. } => todo!("String matching in whens not yet implemented"),
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
pattern_vec.push(Air::Void {
|
pattern_vec.push(Air::Void {
|
||||||
scope: scope.clone(),
|
scope: scope.clone(),
|
||||||
|
@ -821,7 +839,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
});
|
});
|
||||||
pattern_vec.append(values);
|
pattern_vec.append(values);
|
||||||
}
|
}
|
||||||
Pattern::VarUsage { .. } => todo!(),
|
Pattern::VarUsage { .. } => unreachable!(),
|
||||||
Pattern::Assign { name, pattern, .. } => {
|
Pattern::Assign { name, pattern, .. } => {
|
||||||
let mut new_vec = vec![];
|
let mut new_vec = vec![];
|
||||||
new_vec.push(Air::Let {
|
new_vec.push(Air::Let {
|
||||||
|
@ -988,11 +1006,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
) {
|
) {
|
||||||
match pattern {
|
match pattern {
|
||||||
Pattern::Int { .. } => todo!(),
|
Pattern::Int { .. } => unreachable!(),
|
||||||
Pattern::String { .. } => todo!(),
|
Pattern::String { .. } => unreachable!(),
|
||||||
Pattern::Var { .. } => todo!(),
|
Pattern::Var { .. } => unreachable!(),
|
||||||
Pattern::VarUsage { .. } => todo!(),
|
Pattern::VarUsage { .. } => unreachable!(),
|
||||||
Pattern::Assign { .. } => todo!(),
|
Pattern::Assign { .. } => todo!("Nested assign not yet implemented"),
|
||||||
Pattern::Discard { .. } => {
|
Pattern::Discard { .. } => {
|
||||||
pattern_vec.push(Air::Void { scope });
|
pattern_vec.push(Air::Void { scope });
|
||||||
|
|
||||||
|
@ -1022,7 +1040,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
tail_name = name.clone();
|
tail_name = name.clone();
|
||||||
}
|
}
|
||||||
Pattern::Discard { .. } => {}
|
Pattern::Discard { .. } => {}
|
||||||
_ => todo!(),
|
_ => unreachable!("Patterns in tail of list should not allow this"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1458,7 +1476,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
Some(item_name)
|
Some(item_name)
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
Pattern::Assign { .. } => todo!("Nested assign is not yet done"),
|
||||||
|
Pattern::Int { .. } => unimplemented!(),
|
||||||
|
Pattern::String { .. } => unimplemented!(),
|
||||||
|
Pattern::VarUsage { .. } => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1506,8 +1527,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pattern_vec.append(&mut assert_vec);
|
pattern_vec.append(&mut assert_vec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pattern::VarUsage { .. } => todo!(),
|
Pattern::VarUsage { .. } => unreachable!(),
|
||||||
Pattern::Assign { .. } => todo!(),
|
Pattern::Assign { .. } => todo!("Assign not yet implemented yet"),
|
||||||
Pattern::Discard { .. } => {
|
Pattern::Discard { .. } => {
|
||||||
pattern_vec.push(Air::Let {
|
pattern_vec.push(Air::Let {
|
||||||
name: "_".to_string(),
|
name: "_".to_string(),
|
||||||
|
@ -1616,7 +1637,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Var { name, .. } => {
|
Pattern::Var { name, .. } => {
|
||||||
names.push(name.clone());
|
names.push(name.clone());
|
||||||
}
|
}
|
||||||
a @ Pattern::List { .. } => {
|
a @ (Pattern::List { .. }
|
||||||
|
| Pattern::Constructor { .. }
|
||||||
|
| Pattern::Tuple { .. }) => {
|
||||||
let mut var_vec = vec![];
|
let mut var_vec = vec![];
|
||||||
let item_name = format!("list_item_id_{}", self.id_gen.next());
|
let item_name = format!("list_item_id_{}", self.id_gen.next());
|
||||||
names.push(item_name.clone());
|
names.push(item_name.clone());
|
||||||
|
@ -1646,7 +1669,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
scope.clone(),
|
scope.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
Pattern::Int { .. } => todo!(),
|
||||||
|
Pattern::String { .. } => todo!(),
|
||||||
|
Pattern::VarUsage { .. } => todo!(),
|
||||||
|
Pattern::Assign { .. } => todo!(),
|
||||||
|
Pattern::Discard { .. } => {
|
||||||
|
names.push("_".to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1700,9 +1729,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&item.value,
|
&item.value,
|
||||||
*field_index,
|
*field_index,
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
|
type_map.get(field_index).unwrap(),
|
||||||
&assignment_properties,
|
&assignment_properties,
|
||||||
&scope,
|
&scope,
|
||||||
false,
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
||||||
|
@ -1726,59 +1755,45 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pattern_vec.append(&mut nested_pattern);
|
pattern_vec.append(&mut nested_pattern);
|
||||||
}
|
}
|
||||||
Pattern::Tuple { elems, .. } => {
|
Pattern::Tuple { elems, .. } => {
|
||||||
let mut elements_vec = vec![];
|
let mut nested_pattern = vec![];
|
||||||
|
let mut type_map: IndexMap<usize, Arc<Type>> = IndexMap::new();
|
||||||
|
|
||||||
let mut names = vec![];
|
for (index, arg) in tipo.get_inner_types().iter().enumerate() {
|
||||||
for element in elems {
|
let field_type = arg.clone();
|
||||||
match element {
|
type_map.insert(index, field_type);
|
||||||
Pattern::Var { name, .. } => {
|
}
|
||||||
names.push(name.clone());
|
|
||||||
}
|
let arguments_index = elems
|
||||||
Pattern::Discard { .. } => {
|
.iter()
|
||||||
names.push("_".to_string());
|
.enumerate()
|
||||||
}
|
.filter_map(|(tuple_index, item)| {
|
||||||
a @ Pattern::List { .. } => {
|
self.extract_arg_and_index(
|
||||||
let mut var_vec = vec![];
|
item,
|
||||||
let item_name = format!("list_item_id_{}", self.id_gen.next());
|
tuple_index,
|
||||||
names.push(item_name.clone());
|
&mut nested_pattern,
|
||||||
var_vec.push(Air::Var {
|
type_map.get(&tuple_index).unwrap(),
|
||||||
constructor: ValueConstructor::public(
|
&assignment_properties,
|
||||||
Type::App {
|
&scope,
|
||||||
public: true,
|
)
|
||||||
module: String::new(),
|
})
|
||||||
name: String::new(),
|
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
||||||
args: vec![],
|
.collect::<Vec<(String, usize)>>();
|
||||||
}
|
|
||||||
.into(),
|
if !arguments_index.is_empty() {
|
||||||
ValueConstructorVariant::LocalVariable {
|
pattern_vec.push(Air::TupleAccessor {
|
||||||
location: Span::empty(),
|
scope,
|
||||||
},
|
names: arguments_index
|
||||||
),
|
.into_iter()
|
||||||
name: item_name,
|
.map(|(item, _)| item)
|
||||||
scope: scope.clone(),
|
.collect_vec(),
|
||||||
variant_name: String::new(),
|
tipo: tipo.clone().into(),
|
||||||
});
|
check_last_item: true,
|
||||||
self.pattern_ir(
|
});
|
||||||
a,
|
|
||||||
&mut elements_vec,
|
|
||||||
&mut var_vec,
|
|
||||||
&tipo.get_inner_types()[0],
|
|
||||||
assignment_properties.clone(),
|
|
||||||
scope.clone(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pattern_vec.push(Air::TupleAccessor {
|
|
||||||
names,
|
|
||||||
scope,
|
|
||||||
tipo: tipo.clone().into(),
|
|
||||||
check_last_item: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
pattern_vec.append(values);
|
pattern_vec.append(values);
|
||||||
pattern_vec.append(&mut elements_vec);
|
|
||||||
|
pattern_vec.append(&mut nested_pattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1819,7 +1834,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
Pattern::VarUsage { .. } => todo!(),
|
Pattern::VarUsage { .. } => todo!(),
|
||||||
Pattern::Assign { .. } => todo!(),
|
Pattern::Assign { .. } => todo!(),
|
||||||
l @ Pattern::List { .. } => {
|
l @ (Pattern::List { .. }
|
||||||
|
| Pattern::Constructor { .. }
|
||||||
|
| Pattern::Tuple { .. }) => {
|
||||||
let name = format!("list_item_id_{}", self.id_gen.next());
|
let name = format!("list_item_id_{}", self.id_gen.next());
|
||||||
names.push(name.clone());
|
names.push(name.clone());
|
||||||
|
|
||||||
|
@ -1842,8 +1859,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
scope.clone(),
|
scope.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Pattern::Constructor { .. } => todo!(),
|
|
||||||
Pattern::Tuple { elems, .. } => todo!(),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1899,8 +1914,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
type_map.insert(index, field_type);
|
type_map.insert(index, field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("TYPE IS {:#?}", type_map);
|
|
||||||
|
|
||||||
let arguments_index = arguments
|
let arguments_index = arguments
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
|
@ -1910,9 +1923,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&item.value,
|
&item.value,
|
||||||
*field_index,
|
*field_index,
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
|
type_map.get(field_index).unwrap(),
|
||||||
&assignment_properties,
|
&assignment_properties,
|
||||||
&scope,
|
&scope,
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
||||||
|
@ -1974,9 +1987,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
item,
|
item,
|
||||||
field_index,
|
field_index,
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
|
type_map.get(&field_index).unwrap(),
|
||||||
&assignment_properties,
|
&assignment_properties,
|
||||||
&scope,
|
&scope,
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
.sorted_by(|item1, item2| item1.1.cmp(&item2.1))
|
||||||
|
@ -2003,7 +2016,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !arguments_index.is_empty() {
|
if !final_args.is_empty() {
|
||||||
pattern_vec.push(Air::TupleAccessor {
|
pattern_vec.push(Air::TupleAccessor {
|
||||||
scope,
|
scope,
|
||||||
names: final_args.into_iter().map(|(item, _)| item).collect_vec(),
|
names: final_args.into_iter().map(|(item, _)| item).collect_vec(),
|
||||||
|
@ -2336,7 +2349,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
assert_vec.push(Air::ErrorTerm {
|
assert_vec.push(Air::ErrorTerm {
|
||||||
scope,
|
scope,
|
||||||
tipo: tipo.clone().into(),
|
tipo: tipo.clone().into(),
|
||||||
label: None,
|
label: Some("Constr index did not match any type variant".to_string()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2346,15 +2359,63 @@ impl<'a> CodeGenerator<'a> {
|
||||||
item: &Pattern<PatternConstructor, Arc<Type>>,
|
item: &Pattern<PatternConstructor, Arc<Type>>,
|
||||||
field_index: usize,
|
field_index: usize,
|
||||||
nested_pattern: &mut Vec<Air>,
|
nested_pattern: &mut Vec<Air>,
|
||||||
|
tipo: &Type,
|
||||||
assignment_properties: &AssignmentProperties,
|
assignment_properties: &AssignmentProperties,
|
||||||
scope: &[u64],
|
scope: &[u64],
|
||||||
assert: bool,
|
|
||||||
) -> Option<(String, usize)> {
|
) -> Option<(String, usize)> {
|
||||||
{
|
{
|
||||||
let (discard, var_name) = match item {
|
let (discard, var_name) = match item {
|
||||||
Pattern::Var { name, .. } => (false, name.clone()),
|
Pattern::Var { name, .. } => (false, name.clone()),
|
||||||
Pattern::Discard { .. } => (true, "".to_string()),
|
Pattern::Discard { .. } => (true, "".to_string()),
|
||||||
Pattern::List { .. } => todo!(),
|
a @ Pattern::List { .. } => {
|
||||||
|
let id = self.id_gen.next();
|
||||||
|
let list_name = format!("__list_{id}");
|
||||||
|
|
||||||
|
if matches!(assignment_properties.kind, AssignmentKind::Assert)
|
||||||
|
&& assignment_properties.value_is_data
|
||||||
|
&& !tipo.is_data()
|
||||||
|
{
|
||||||
|
self.recursive_assert_pattern(
|
||||||
|
a,
|
||||||
|
nested_pattern,
|
||||||
|
&mut vec![Air::Var {
|
||||||
|
scope: scope.to_owned(),
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo.clone().into(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: list_name.clone(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
}],
|
||||||
|
tipo,
|
||||||
|
assignment_properties.clone(),
|
||||||
|
scope.to_owned(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.pattern_ir(
|
||||||
|
a,
|
||||||
|
nested_pattern,
|
||||||
|
&mut vec![Air::Var {
|
||||||
|
scope: scope.to_owned(),
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo.clone().into(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: list_name.clone(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
}],
|
||||||
|
tipo,
|
||||||
|
assignment_properties.clone(),
|
||||||
|
scope.to_owned(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(false, list_name)
|
||||||
|
}
|
||||||
a @ Pattern::Constructor {
|
a @ Pattern::Constructor {
|
||||||
tipo,
|
tipo,
|
||||||
name: constr_name,
|
name: constr_name,
|
||||||
|
@ -2363,7 +2424,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let id = self.id_gen.next();
|
let id = self.id_gen.next();
|
||||||
let constr_name = format!("{constr_name}_{id}");
|
let constr_name = format!("{constr_name}_{id}");
|
||||||
|
|
||||||
if assert {
|
if matches!(assignment_properties.kind, AssignmentKind::Assert)
|
||||||
|
&& assignment_properties.value_is_data
|
||||||
|
&& !tipo.is_data()
|
||||||
|
{
|
||||||
self.recursive_assert_pattern(
|
self.recursive_assert_pattern(
|
||||||
a,
|
a,
|
||||||
nested_pattern,
|
nested_pattern,
|
||||||
|
@ -2405,7 +2469,59 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
(false, constr_name)
|
(false, constr_name)
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
a @ Pattern::Tuple { .. } => {
|
||||||
|
let id = self.id_gen.next();
|
||||||
|
let tuple_name = format!("__tuple_name_{id}");
|
||||||
|
|
||||||
|
if matches!(assignment_properties.kind, AssignmentKind::Assert)
|
||||||
|
&& assignment_properties.value_is_data
|
||||||
|
&& !tipo.is_data()
|
||||||
|
{
|
||||||
|
self.recursive_assert_pattern(
|
||||||
|
a,
|
||||||
|
nested_pattern,
|
||||||
|
&mut vec![Air::Var {
|
||||||
|
scope: scope.to_owned(),
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo.clone().into(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: tuple_name.clone(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
}],
|
||||||
|
tipo,
|
||||||
|
assignment_properties.clone(),
|
||||||
|
scope.to_owned(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.pattern_ir(
|
||||||
|
a,
|
||||||
|
nested_pattern,
|
||||||
|
&mut vec![Air::Var {
|
||||||
|
scope: scope.to_owned(),
|
||||||
|
constructor: ValueConstructor::public(
|
||||||
|
tipo.clone().into(),
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
|
location: Span::empty(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
name: tuple_name.clone(),
|
||||||
|
variant_name: String::new(),
|
||||||
|
}],
|
||||||
|
tipo,
|
||||||
|
assignment_properties.clone(),
|
||||||
|
scope.to_owned(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(false, tuple_name)
|
||||||
|
}
|
||||||
|
Pattern::Int { .. } => todo!(),
|
||||||
|
Pattern::String { .. } => todo!(),
|
||||||
|
Pattern::VarUsage { .. } => todo!(),
|
||||||
|
Pattern::Assign { .. } => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if discard {
|
if discard {
|
||||||
|
@ -3367,10 +3483,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
ValueConstructorVariant::Record {
|
ValueConstructorVariant::Record {
|
||||||
name: constr_name,
|
name: constr_name, ..
|
||||||
field_map,
|
|
||||||
arity,
|
|
||||||
..
|
|
||||||
} => {
|
} => {
|
||||||
if constructor.tipo.is_bool() {
|
if constructor.tipo.is_bool() {
|
||||||
arg_stack
|
arg_stack
|
||||||
|
@ -3391,59 +3504,10 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.find(|(_, x)| x.name == *constr_name)
|
.find(|(_, x)| x.name == *constr_name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut fields =
|
let fields =
|
||||||
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]));
|
Term::Constant(UplcConstant::ProtoList(UplcType::Data, vec![]));
|
||||||
|
|
||||||
let tipo = constructor.tipo;
|
let term = apply_wrap(
|
||||||
|
|
||||||
let args_type = tipo.arg_types().unwrap();
|
|
||||||
|
|
||||||
if let Some(field_map) = field_map.clone() {
|
|
||||||
for field in field_map
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.sorted_by(|item1, item2| {
|
|
||||||
let (a, _) = item1.1;
|
|
||||||
let (b, _) = item2.1;
|
|
||||||
a.cmp(b)
|
|
||||||
})
|
|
||||||
.zip(&args_type)
|
|
||||||
.rev()
|
|
||||||
{
|
|
||||||
// TODO revisit
|
|
||||||
fields = apply_wrap(
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::MkCons).force_wrap(),
|
|
||||||
convert_type_to_data(
|
|
||||||
Term::Var(Name {
|
|
||||||
text: field.0 .0.clone(),
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
field.1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
fields,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (index, arg) in args_type.iter().enumerate().take(*arity) {
|
|
||||||
fields = apply_wrap(
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::MkCons).force_wrap(),
|
|
||||||
convert_type_to_data(
|
|
||||||
Term::Var(Name {
|
|
||||||
text: format!("__arg_{}", index),
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
arg,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
fields,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut term = apply_wrap(
|
|
||||||
apply_wrap(
|
apply_wrap(
|
||||||
Term::Builtin(DefaultFunction::ConstrData),
|
Term::Builtin(DefaultFunction::ConstrData),
|
||||||
Term::Constant(UplcConstant::Integer(
|
Term::Constant(UplcConstant::Integer(
|
||||||
|
@ -3453,37 +3517,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
fields,
|
fields,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(field_map) = field_map {
|
|
||||||
for field in field_map
|
|
||||||
.fields
|
|
||||||
.iter()
|
|
||||||
.sorted_by(|item1, item2| {
|
|
||||||
let (a, _) = item1.1;
|
|
||||||
let (b, _) = item2.1;
|
|
||||||
a.cmp(b)
|
|
||||||
})
|
|
||||||
.rev()
|
|
||||||
{
|
|
||||||
term = Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: field.0.clone(),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: term.into(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (index, _) in args_type.iter().enumerate().take(*arity) {
|
|
||||||
term = Term::Lambda {
|
|
||||||
parameter_name: Name {
|
|
||||||
text: format!("__arg_{}", index),
|
|
||||||
unique: 0.into(),
|
|
||||||
},
|
|
||||||
body: term.into(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4094,46 +4127,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
};
|
};
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
}
|
}
|
||||||
Air::Assert {
|
|
||||||
tipo,
|
|
||||||
value_is_data,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let constr = arg_stack.pop().unwrap();
|
|
||||||
|
|
||||||
let mut term = arg_stack.pop().unwrap();
|
|
||||||
|
|
||||||
let trace_error = apply_wrap(
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::Trace).force_wrap(),
|
|
||||||
Term::Constant(UplcConstant::String("Assert Failed".to_string())),
|
|
||||||
),
|
|
||||||
Term::Delay(Term::Error.into()),
|
|
||||||
)
|
|
||||||
.force_wrap();
|
|
||||||
todo!();
|
|
||||||
|
|
||||||
// let condition = apply_wrap(
|
|
||||||
// apply_wrap(
|
|
||||||
// DefaultFunction::EqualsInteger.into(),
|
|
||||||
// Term::Constant(UplcConstant::Integer(constr_index as i128)),
|
|
||||||
// ),
|
|
||||||
// constr_index_exposer(constr),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// term = delayed_if_else(condition, term, trace_error);
|
|
||||||
|
|
||||||
arg_stack.push(term);
|
|
||||||
}
|
|
||||||
Air::ListAssert {
|
|
||||||
scope,
|
|
||||||
tipo,
|
|
||||||
names,
|
|
||||||
tail,
|
|
||||||
value_is_data,
|
|
||||||
} => {
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
Air::DefineFunc {
|
Air::DefineFunc {
|
||||||
func_name,
|
func_name,
|
||||||
params,
|
params,
|
||||||
|
@ -4735,6 +4728,29 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let names = indices.iter().cloned().map(|item| item.1).collect_vec();
|
let names = indices.iter().cloned().map(|item| item.1).collect_vec();
|
||||||
let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec();
|
let inner_types = indices.iter().cloned().map(|item| item.2).collect_vec();
|
||||||
|
|
||||||
|
let tail_list = if !indices.is_empty() {
|
||||||
|
apply_wrap(
|
||||||
|
list_access_to_uplc(
|
||||||
|
&names,
|
||||||
|
&id_list,
|
||||||
|
false,
|
||||||
|
current_index,
|
||||||
|
term,
|
||||||
|
inner_types,
|
||||||
|
check_last_item,
|
||||||
|
),
|
||||||
|
apply_wrap(
|
||||||
|
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
||||||
|
Term::Var(Name {
|
||||||
|
text: format!("__constr_fields_{}", list_id),
|
||||||
|
unique: 0.into(),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
term
|
||||||
|
};
|
||||||
|
|
||||||
term = apply_wrap(
|
term = apply_wrap(
|
||||||
Term::Lambda {
|
Term::Lambda {
|
||||||
parameter_name: Name {
|
parameter_name: Name {
|
||||||
|
@ -4747,25 +4763,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
text: first_name.1.clone(),
|
text: first_name.1.clone(),
|
||||||
unique: 0.into(),
|
unique: 0.into(),
|
||||||
},
|
},
|
||||||
body: apply_wrap(
|
body: tail_list.into(),
|
||||||
list_access_to_uplc(
|
|
||||||
&names,
|
|
||||||
&id_list,
|
|
||||||
false,
|
|
||||||
current_index,
|
|
||||||
term,
|
|
||||||
inner_types,
|
|
||||||
check_last_item,
|
|
||||||
),
|
|
||||||
apply_wrap(
|
|
||||||
Term::Builtin(DefaultFunction::TailList).force_wrap(),
|
|
||||||
Term::Var(Name {
|
|
||||||
text: format!("__constr_fields_{}", list_id),
|
|
||||||
unique: 0.into(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
},
|
},
|
||||||
head_list,
|
head_list,
|
||||||
)
|
)
|
||||||
|
|
|
@ -343,7 +343,7 @@ impl Machine {
|
||||||
Err(Error::UnexpectedBuiltinTermArgument(t.as_ref().clone()))
|
Err(Error::UnexpectedBuiltinTermArgument(t.as_ref().clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rest => Err(Error::NonFunctionalApplication(rest)),
|
rest => Err(Error::NonFunctionalApplication(rest, argument)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ pub enum Error {
|
||||||
EvaluationFailure,
|
EvaluationFailure,
|
||||||
#[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")]
|
#[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")]
|
||||||
NonPolymorphicInstantiation(Value),
|
NonPolymorphicInstantiation(Value),
|
||||||
#[error("Attempted to apply a non-function:\n\n{0:#?}")]
|
#[error("Attempted to apply a non-function:\n\n{0:#?} to argument:\n\n{1:#?}")]
|
||||||
NonFunctionalApplication(Value),
|
NonFunctionalApplication(Value, Value),
|
||||||
#[error("Type mismatch expected '{0}' got '{1}'")]
|
#[error("Type mismatch expected '{0}' got '{1}'")]
|
||||||
TypeMismatch(Type, Type),
|
TypeMismatch(Type, Type),
|
||||||
#[error("Type mismatch expected '(list a)' got '{0}'")]
|
#[error("Type mismatch expected '(list a)' got '{0}'")]
|
||||||
|
|
Loading…
Reference in New Issue