Add ability to generate ir with complex constructor cases
This commit is contained in:
parent
64cbae938d
commit
f48039fd4f
|
@ -138,10 +138,13 @@ pub enum IR {
|
||||||
count: usize,
|
count: usize,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
subject_name: String,
|
subject_name: String,
|
||||||
|
complex_clause: bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
ClauseGuard {
|
ClauseGuard {
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
|
subject_name: String,
|
||||||
|
tipo: Arc<Type>,
|
||||||
},
|
},
|
||||||
|
|
||||||
Discard {
|
Discard {
|
||||||
|
@ -242,7 +245,7 @@ impl IR {
|
||||||
| IR::Lam { scope, .. }
|
| IR::Lam { scope, .. }
|
||||||
| IR::When { scope, .. }
|
| IR::When { scope, .. }
|
||||||
| IR::Clause { scope, .. }
|
| IR::Clause { scope, .. }
|
||||||
| IR::ClauseGuard { scope }
|
| IR::ClauseGuard { scope, .. }
|
||||||
| IR::Discard { scope }
|
| IR::Discard { scope }
|
||||||
| IR::Finally { scope }
|
| IR::Finally { scope }
|
||||||
| IR::If { scope, .. }
|
| IR::If { scope, .. }
|
||||||
|
|
|
@ -37,6 +37,12 @@ pub struct FuncComponents {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
pub struct ClauseComplexity {
|
||||||
|
subject_var_name: String,
|
||||||
|
needs_subject_var: bool,
|
||||||
|
is_complex_clause: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CodeGenerator<'a> {
|
pub struct CodeGenerator<'a> {
|
||||||
defined_functions: HashMap<FunctionAccessKey, ()>,
|
defined_functions: HashMap<FunctionAccessKey, ()>,
|
||||||
functions: &'a HashMap<FunctionAccessKey, &'a Function<Arc<tipo::Type>, TypedExpr>>,
|
functions: &'a HashMap<FunctionAccessKey, &'a Function<Arc<tipo::Type>, TypedExpr>>,
|
||||||
|
@ -259,7 +265,7 @@ 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();
|
||||||
let mut needs_constr_var = false;
|
let mut needs_subject_var = false;
|
||||||
|
|
||||||
if let Some((last_clause, clauses)) = clauses.split_last() {
|
if let Some((last_clause, clauses)) = clauses.split_last() {
|
||||||
let mut clauses_vec = vec![];
|
let mut clauses_vec = vec![];
|
||||||
|
@ -268,28 +274,48 @@ impl<'a> CodeGenerator<'a> {
|
||||||
for clause in clauses {
|
for clause in clauses {
|
||||||
let mut scope = scope.clone();
|
let mut scope = scope.clone();
|
||||||
scope.push(self.id_gen.next());
|
scope.push(self.id_gen.next());
|
||||||
|
let mut clause_subject_vec = vec![];
|
||||||
|
|
||||||
|
let mut clause_complexity = ClauseComplexity {
|
||||||
|
subject_var_name: constr_var.clone(),
|
||||||
|
needs_subject_var: false,
|
||||||
|
is_complex_clause: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.build_ir(&clause.then, &mut clauses_vec, scope.clone());
|
||||||
|
|
||||||
|
self.when_ir(
|
||||||
|
&clause.pattern[0],
|
||||||
|
&mut clause_subject_vec,
|
||||||
|
&mut clauses_vec,
|
||||||
|
&subject.tipo(),
|
||||||
|
&mut clause_complexity,
|
||||||
|
scope.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
pattern_vec.push(IR::Clause {
|
pattern_vec.push(IR::Clause {
|
||||||
scope: scope.clone(),
|
scope: scope.clone(),
|
||||||
count: 2,
|
count: 2,
|
||||||
tipo: subject.tipo().clone(),
|
tipo: subject.tipo().clone(),
|
||||||
subject_name: subject_name.clone(),
|
subject_name: subject_name.clone(),
|
||||||
|
complex_clause: clause_complexity.is_complex_clause,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.build_ir(&clause.then, &mut clauses_vec, scope.clone());
|
pattern_vec.append(&mut clause_subject_vec);
|
||||||
self.when_ir(
|
|
||||||
&clause.pattern[0],
|
if clause_complexity.needs_subject_var {
|
||||||
&mut pattern_vec,
|
needs_subject_var = true;
|
||||||
&mut clauses_vec,
|
}
|
||||||
&subject.tipo(),
|
|
||||||
constr_var.clone(),
|
|
||||||
&mut needs_constr_var,
|
|
||||||
scope,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_pattern = &last_clause.pattern[0];
|
let last_pattern = &last_clause.pattern[0];
|
||||||
|
|
||||||
|
let mut final_clause_complexity = ClauseComplexity {
|
||||||
|
subject_var_name: constr_var.clone(),
|
||||||
|
needs_subject_var: false,
|
||||||
|
is_complex_clause: false,
|
||||||
|
};
|
||||||
|
|
||||||
let mut final_scope = scope.clone();
|
let mut final_scope = scope.clone();
|
||||||
final_scope.push(self.id_gen.next());
|
final_scope.push(self.id_gen.next());
|
||||||
pattern_vec.push(IR::Finally {
|
pattern_vec.push(IR::Finally {
|
||||||
|
@ -302,12 +328,11 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&mut pattern_vec,
|
&mut pattern_vec,
|
||||||
&mut clauses_vec,
|
&mut clauses_vec,
|
||||||
&subject.tipo(),
|
&subject.tipo(),
|
||||||
constr_var.clone(),
|
&mut final_clause_complexity,
|
||||||
&mut needs_constr_var,
|
|
||||||
final_scope,
|
final_scope,
|
||||||
);
|
);
|
||||||
|
|
||||||
if needs_constr_var {
|
if needs_subject_var || final_clause_complexity.needs_subject_var {
|
||||||
ir_stack.push(IR::Lam {
|
ir_stack.push(IR::Lam {
|
||||||
scope: scope.clone(),
|
scope: scope.clone(),
|
||||||
name: constr_var.clone(),
|
name: constr_var.clone(),
|
||||||
|
@ -460,8 +485,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pattern_vec: &mut Vec<IR>,
|
pattern_vec: &mut Vec<IR>,
|
||||||
values: &mut Vec<IR>,
|
values: &mut Vec<IR>,
|
||||||
tipo: &Type,
|
tipo: &Type,
|
||||||
constr_var: String,
|
when_complexity: &mut ClauseComplexity,
|
||||||
needs_constr_var: &mut bool,
|
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
) {
|
) {
|
||||||
match pattern {
|
match pattern {
|
||||||
|
@ -500,8 +524,8 @@ impl<'a> CodeGenerator<'a> {
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let mut needs_access_to_constr_var = false;
|
let mut needs_access_to_constr_var = false;
|
||||||
|
|
||||||
let mut needs_clause_guard = false;
|
let mut needs_clause_guard = false;
|
||||||
|
|
||||||
for arg in arguments {
|
for arg in arguments {
|
||||||
match arg.value {
|
match arg.value {
|
||||||
Pattern::Var { .. } => {
|
Pattern::Var { .. } => {
|
||||||
|
@ -550,18 +574,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
name: constr_var,
|
name: when_complexity.subject_var_name.clone(),
|
||||||
scope: scope.clone(),
|
scope: scope.clone(),
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// if only one constructor, no need to check
|
// if only one constructor, no need to check
|
||||||
if data_type.constructors.len() > 1 {
|
if data_type.constructors.len() > 1 {
|
||||||
if needs_clause_guard {
|
|
||||||
pattern_vec.push(IR::ClauseGuard {
|
|
||||||
scope: scope.clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// push constructor Index
|
// push constructor Index
|
||||||
pattern_vec.push(IR::Int {
|
pattern_vec.push(IR::Int {
|
||||||
value: index.to_string(),
|
value: index.to_string(),
|
||||||
|
@ -569,8 +587,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if needs_clause_guard {
|
||||||
|
when_complexity.is_complex_clause = true;
|
||||||
|
}
|
||||||
|
|
||||||
if needs_access_to_constr_var {
|
if needs_access_to_constr_var {
|
||||||
*needs_constr_var = true;
|
when_complexity.needs_subject_var = true;
|
||||||
|
|
||||||
self.when_recursive_ir(pattern, pattern_vec, &mut new_vec, tipo, scope);
|
self.when_recursive_ir(pattern, pattern_vec, &mut new_vec, tipo, scope);
|
||||||
pattern_vec.append(values);
|
pattern_vec.append(values);
|
||||||
|
@ -717,18 +739,48 @@ 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_var_name = format!("{constr_name}_{id}");
|
||||||
|
let data_type_key = match tipo.as_ref() {
|
||||||
|
Type::Fn { ret, .. } => match &**ret {
|
||||||
|
Type::App { module, name, .. } => DataTypeKey {
|
||||||
|
module_name: module.clone(),
|
||||||
|
defined_type: name.clone(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
Type::App { module, name, .. } => DataTypeKey {
|
||||||
|
module_name: module.clone(),
|
||||||
|
defined_type: name.clone(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let data_type = self.data_types.get(&data_type_key).unwrap();
|
||||||
|
|
||||||
|
if data_type.constructors.len() > 1 {
|
||||||
|
nested_pattern.push(IR::ClauseGuard {
|
||||||
|
scope: scope.clone(),
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
subject_name: constr_var_name.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut clause_complexity = ClauseComplexity {
|
||||||
|
subject_var_name: constr_var_name.clone(),
|
||||||
|
needs_subject_var: false,
|
||||||
|
is_complex_clause: false,
|
||||||
|
};
|
||||||
|
|
||||||
self.when_ir(
|
self.when_ir(
|
||||||
a,
|
a,
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
&mut vec![],
|
&mut vec![],
|
||||||
tipo,
|
tipo,
|
||||||
constr_name.clone(),
|
&mut clause_complexity,
|
||||||
&mut false,
|
|
||||||
scope.clone(),
|
scope.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
(false, constr_name)
|
(false, constr_var_name)
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
@ -775,18 +827,47 @@ 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_var_name = format!("{constr_name}_{id}");
|
||||||
|
let data_type_key = match tipo.as_ref() {
|
||||||
|
Type::Fn { ret, .. } => match &**ret {
|
||||||
|
Type::App { module, name, .. } => DataTypeKey {
|
||||||
|
module_name: module.clone(),
|
||||||
|
defined_type: name.clone(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
Type::App { module, name, .. } => DataTypeKey {
|
||||||
|
module_name: module.clone(),
|
||||||
|
defined_type: name.clone(),
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let data_type = self.data_types.get(&data_type_key).unwrap();
|
||||||
|
|
||||||
|
if data_type.constructors.len() > 1 {
|
||||||
|
nested_pattern.push(IR::ClauseGuard {
|
||||||
|
scope: scope.clone(),
|
||||||
|
tipo: tipo.clone(),
|
||||||
|
subject_name: constr_var_name.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let mut clause_complexity = ClauseComplexity {
|
||||||
|
subject_var_name: constr_var_name.clone(),
|
||||||
|
needs_subject_var: false,
|
||||||
|
is_complex_clause: false,
|
||||||
|
};
|
||||||
|
|
||||||
self.when_ir(
|
self.when_ir(
|
||||||
a,
|
a,
|
||||||
&mut nested_pattern,
|
&mut nested_pattern,
|
||||||
&mut vec![],
|
&mut vec![],
|
||||||
tipo,
|
tipo,
|
||||||
constr_name.clone(),
|
&mut clause_complexity,
|
||||||
&mut false,
|
|
||||||
scope.clone(),
|
scope.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
(false, constr_name)
|
(false, constr_var_name)
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
@ -1426,7 +1507,14 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.into(),
|
.into(),
|
||||||
argument: right.into(),
|
argument: right.into(),
|
||||||
},
|
},
|
||||||
BinOp::GtEqInt => todo!(),
|
BinOp::GtEqInt => Term::Apply {
|
||||||
|
function: Term::Apply {
|
||||||
|
function: Term::Builtin(DefaultFunction::LessThanEqualsInteger).into(),
|
||||||
|
argument: right.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: left.into(),
|
||||||
|
},
|
||||||
BinOp::GtInt => Term::Apply {
|
BinOp::GtInt => Term::Apply {
|
||||||
function: Term::Apply {
|
function: Term::Apply {
|
||||||
function: Term::Builtin(DefaultFunction::LessThanInteger).into(),
|
function: Term::Builtin(DefaultFunction::LessThanInteger).into(),
|
||||||
|
@ -1736,7 +1824,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
arg_stack.push(term);
|
arg_stack.push(term);
|
||||||
}
|
}
|
||||||
IR::ClauseGuard { .. } => todo!(),
|
IR::ClauseGuard { .. } => {
|
||||||
|
let _condition = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
let _then = arg_stack.pop().unwrap();
|
||||||
|
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
IR::Finally { .. } => {
|
IR::Finally { .. } => {
|
||||||
let _clause = arg_stack.pop().unwrap();
|
let _clause = arg_stack.pop().unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ pub fn who(a: ByteArray) -> ByteArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Datum {
|
pub type Datum {
|
||||||
Offer { prices: List(Int), asset_class: ByteArray, other_thing: Redeemer }
|
Offer { prices: List(Int), asset_class: ByteArray, other_thing: Datum }
|
||||||
Sell
|
Sell
|
||||||
Hold(Int)
|
Hold(Int)
|
||||||
}
|
}
|
||||||
|
@ -58,11 +58,11 @@ pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool {
|
||||||
Offer {
|
Offer {
|
||||||
prices: p,
|
prices: p,
|
||||||
asset_class: ac,
|
asset_class: ac,
|
||||||
other_thing: Redeemer {
|
other_thing: Offer {
|
||||||
other_thing: Redeemer { signer: nested_signer, amount, .. },
|
other_thing: Offer { asset_class: nested_signer, prices: amounts, .. },
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
} -> True
|
} -> 1 == 1
|
||||||
_ -> False
|
_ -> False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue