feat: add module constants except for tuple

This commit is contained in:
Kasey White 2022-12-05 01:45:58 -05:00 committed by Lucas
parent de9302a877
commit 0fda535c50
3 changed files with 100 additions and 28 deletions

View File

@ -5,7 +5,7 @@ use itertools::Itertools;
use uplc::{ use uplc::{
ast::{ ast::{
builder::{self, constr_index_exposer, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD}, builder::{self, constr_index_exposer, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD},
Constant, Name, Program, Term, Constant as UplcConstant, Name, Program, Term,
}, },
builtins::DefaultFunction, builtins::DefaultFunction,
parser::interner::Interner, parser::interner::Interner,
@ -13,7 +13,10 @@ use uplc::{
}; };
use crate::{ use crate::{
ast::{ArgName, AssignmentKind, BinOp, Clause, DataType, Function, Pattern, Span, TypedArg}, ast::{
ArgName, AssignmentKind, BinOp, Clause, Constant, DataType, Function, Pattern, Span,
TypedArg,
},
expr::TypedExpr, expr::TypedExpr,
ir::IR, ir::IR,
tipo::{self, PatternConstructor, Type, TypeInfo, ValueConstructor, ValueConstructorVariant}, tipo::{self, PatternConstructor, Type, TypeInfo, ValueConstructor, ValueConstructorVariant},
@ -499,9 +502,17 @@ impl<'a> CodeGenerator<'a> {
} }
} }
} }
tipo::ModuleValueConstructor::Constant { .. } => todo!(), tipo::ModuleValueConstructor::Constant { literal, .. } => {
constants_ir(literal, ir_stack, scope);
}
}, },
TypedExpr::Todo { .. } => todo!(), TypedExpr::Todo { label, tipo, .. } => {
ir_stack.push(IR::Todo {
scope,
label: label.clone(),
tipo: tipo.clone(),
});
}
TypedExpr::RecordUpdate { .. } => todo!(), TypedExpr::RecordUpdate { .. } => todo!(),
TypedExpr::Negate { .. } => todo!(), TypedExpr::Negate { .. } => todo!(),
TypedExpr::Tuple { .. } => todo!(), TypedExpr::Tuple { .. } => todo!(),
@ -1335,17 +1346,17 @@ impl<'a> CodeGenerator<'a> {
IR::Int { value, .. } => { IR::Int { value, .. } => {
let integer = value.parse().unwrap(); let integer = value.parse().unwrap();
let term = Term::Constant(Constant::Integer(integer)); let term = Term::Constant(UplcConstant::Integer(integer));
arg_stack.push(term); arg_stack.push(term);
} }
IR::String { value, .. } => { IR::String { value, .. } => {
let term = Term::Constant(Constant::String(value)); let term = Term::Constant(UplcConstant::String(value));
arg_stack.push(term); arg_stack.push(term);
} }
IR::ByteArray { bytes, .. } => { IR::ByteArray { bytes, .. } => {
let term = Term::Constant(Constant::ByteString(bytes)); let term = Term::Constant(UplcConstant::ByteString(bytes));
arg_stack.push(term); arg_stack.push(term);
} }
IR::Var { IR::Var {
@ -1391,7 +1402,7 @@ impl<'a> CodeGenerator<'a> {
}; };
if data_type_key.defined_type == "Bool" { if data_type_key.defined_type == "Bool" {
arg_stack.push(Term::Constant(Constant::Bool(constr_name == "True"))); arg_stack.push(Term::Constant(UplcConstant::Bool(constr_name == "True")));
} else { } else {
let data_type = self.data_types.get(&data_type_key).unwrap(); let data_type = self.data_types.get(&data_type_key).unwrap();
let (constr_index, _constr) = data_type let (constr_index, _constr) = data_type
@ -1406,14 +1417,18 @@ impl<'a> CodeGenerator<'a> {
argument: Term::Apply { argument: Term::Apply {
function: Term::Apply { function: Term::Apply {
function: Term::Builtin(DefaultFunction::MkPairData).into(), function: Term::Builtin(DefaultFunction::MkPairData).into(),
argument: Term::Constant(Constant::Data(PlutusData::BigInt( argument: Term::Constant(UplcConstant::Data(
BigInt::Int((constr_index as i128).try_into().unwrap()), PlutusData::BigInt(BigInt::Int(
))) (constr_index as i128).try_into().unwrap(),
)),
))
.into(), .into(),
} }
.into(), .into(),
argument: Term::Constant(Constant::Data(PlutusData::Array(vec![]))) argument: Term::Constant(UplcConstant::Data(PlutusData::Array(
.into(), vec![],
)))
.into(),
} }
.into(), .into(),
}; };
@ -1423,7 +1438,7 @@ impl<'a> CodeGenerator<'a> {
} }
}, },
IR::Discard { .. } => { IR::Discard { .. } => {
arg_stack.push(Term::Constant(Constant::Unit)); arg_stack.push(Term::Constant(UplcConstant::Unit));
} }
IR::List { IR::List {
count, tipo, tail, .. count, tipo, tail, ..
@ -1447,15 +1462,17 @@ impl<'a> CodeGenerator<'a> {
}; };
if constants.len() == args.len() && !tail { if constants.len() == args.len() && !tail {
let list = let list = Term::Constant(UplcConstant::ProtoList(
Term::Constant(Constant::ProtoList(list_type.get_uplc_type(), constants)); list_type.get_uplc_type(),
constants,
));
arg_stack.push(list); arg_stack.push(list);
} else { } else {
let mut term = if tail { let mut term = if tail {
arg_stack.pop().unwrap() arg_stack.pop().unwrap()
} else { } else {
Term::Constant(Constant::ProtoList(list_type.get_uplc_type(), vec![])) Term::Constant(UplcConstant::ProtoList(list_type.get_uplc_type(), vec![]))
}; };
for arg in args { for arg in args {
@ -1648,14 +1665,16 @@ impl<'a> CodeGenerator<'a> {
argument: right.into(), argument: right.into(),
} }
.into(), .into(),
argument: Term::Constant(Constant::Bool( argument: Term::Constant(
false, UplcConstant::Bool(false),
)) )
.into(), .into(),
} }
.into(), .into(),
argument: Term::Constant(Constant::Bool(true)) argument: Term::Constant(UplcConstant::Bool(
.into(), true,
))
.into(),
} }
.into(), .into(),
) )
@ -2244,7 +2263,7 @@ impl<'a> CodeGenerator<'a> {
.into(), .into(),
} }
.into(), .into(),
argument: Term::Constant(Constant::Integer(index.into())).into(), argument: Term::Constant(UplcConstant::Integer(index.into())).into(),
}; };
if tipo.is_int() { if tipo.is_int() {
@ -2504,7 +2523,9 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(body); arg_stack.push(body);
} }
IR::Todo { .. } => todo!(), IR::Todo { .. } => {
arg_stack.push(Term::Error);
}
IR::RecordUpdate { .. } => todo!(), IR::RecordUpdate { .. } => todo!(),
IR::Negate { .. } => todo!(), IR::Negate { .. } => todo!(),
} }
@ -2816,6 +2837,46 @@ impl<'a> CodeGenerator<'a> {
} }
} }
fn constants_ir(literal: &Constant<Arc<Type>, String>, ir_stack: &mut Vec<IR>, scope: Vec<u64>) {
match literal {
Constant::Int { value, .. } => {
ir_stack.push(IR::Int {
scope,
value: value.clone(),
});
}
Constant::String { value, .. } => {
ir_stack.push(IR::String {
scope,
value: value.clone(),
});
}
Constant::Tuple { .. } => {
todo!()
}
Constant::List { elements, tipo, .. } => {
ir_stack.push(IR::List {
scope: scope.clone(),
count: elements.len(),
tipo: tipo.clone(),
tail: false,
});
for element in elements {
constants_ir(element, ir_stack, scope.clone());
}
}
Constant::Record { .. } => todo!(),
Constant::ByteArray { bytes, .. } => {
ir_stack.push(IR::ByteArray {
scope,
bytes: bytes.clone(),
});
}
Constant::Var { .. } => todo!(),
};
}
fn check_when_pattern_needs( fn check_when_pattern_needs(
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>,
needs_access_to_constr_var: &mut bool, needs_access_to_constr_var: &mut bool,
@ -3006,14 +3067,17 @@ fn rearrange_clauses(
let mut sorted_clauses = clauses; let mut sorted_clauses = clauses;
// if we have a list sort clauses so we can plug holes for cases not covered by clauses // if we have a list sort clauses so we can plug holes for cases not covered by clauses
// TODO: while having 10000000 element list is impossible to destructure in plutus budget,
// let's sort clauses by a safer manner
// TODO: how shall tails be weighted? Since any clause after will not run
sorted_clauses.sort_by(|clause1, clause2| { sorted_clauses.sort_by(|clause1, clause2| {
let clause1_len = match &clause1.pattern[0] { let clause1_len = match &clause1.pattern[0] {
Pattern::List { elements, tail, .. } => elements.len() + usize::from(tail.is_some()), Pattern::List { elements, tail, .. } => elements.len() + usize::from(tail.is_some()),
_ => 1000000, _ => 10000000,
}; };
let clause2_len = match &clause2.pattern[0] { let clause2_len = match &clause2.pattern[0] {
Pattern::List { elements, tail, .. } => elements.len() + usize::from(tail.is_some()), Pattern::List { elements, tail, .. } => elements.len() + usize::from(tail.is_some()),
_ => 1000001, _ => 10000001,
}; };
clause1_len.cmp(&clause2_len) clause1_len.cmp(&clause2_len)
@ -3043,6 +3107,7 @@ fn rearrange_clauses(
for (index, clause) in sorted_clauses.iter().enumerate() { for (index, clause) in sorted_clauses.iter().enumerate() {
if let Pattern::List { elements, .. } = &clause.pattern[0] { if let Pattern::List { elements, .. } = &clause.pattern[0] {
// found a hole and now we plug it
while elems_len < elements.len() { while elems_len < elements.len() {
let mut discard_elems = vec![]; let mut discard_elems = vec![];
@ -3053,6 +3118,7 @@ fn rearrange_clauses(
}); });
} }
// If we have a named catch all then in scope the name and create list of discards, otherwise list of discards
let clause_to_fill = if let Some(name) = assign_plug_in_name { let clause_to_fill = if let Some(name) = assign_plug_in_name {
Clause { Clause {
location: Span::empty(), location: Span::empty(),
@ -3089,6 +3155,7 @@ fn rearrange_clauses(
} }
} }
// if we have a pattern with no clause guards and a tail then no lists will get past here to other clauses
if let Pattern::List { if let Pattern::List {
elements, elements,
tail: Some(tail), tail: Some(tail),
@ -3107,6 +3174,7 @@ fn rearrange_clauses(
} }
} }
// If the last condition doesn't have a catch all or tail then add a catch all with a todo
if index == sorted_clauses.len() - 1 { if index == sorted_clauses.len() - 1 {
if let Pattern::List { if let Pattern::List {
elements, elements,
@ -3137,8 +3205,10 @@ fn rearrange_clauses(
elems_len += 1; elems_len += 1;
} }
// Encountered a tail so stop there with that as last clause
final_clauses = final_clauses[0..(last_clause_index + 1)].to_vec(); final_clauses = final_clauses[0..(last_clause_index + 1)].to_vec();
// insert hole fillers into clauses
for (index, clause) in holes_to_fill.into_iter().rev() { for (index, clause) in holes_to_fill.into_iter().rev() {
final_clauses.insert(index, clause); final_clauses.insert(index, clause);
} }

View File

@ -45,3 +45,5 @@ pub fn incrementor(counter: Int, target: Int) -> Int {
incrementor(counter + 1, target) incrementor(counter + 1, target)
} }
} }
pub const big_a = 5

View File

@ -64,8 +64,8 @@ pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool {
[] -> True [] -> True
[a] -> True [a] -> True
[a, b, c] -> True [a, b, c] -> True
[a, b, c, d, ..e] -> 1 == 1 [a, b, c, d, ..e] -> sample.big_a == a
rest -> False
} }
_ -> False _ -> False
} }