checkpoint

This commit is contained in:
Kasey White 2022-11-27 22:10:17 -05:00 committed by Lucas
parent 86ea41adc3
commit 3fb3a3240a
3 changed files with 267 additions and 55 deletions

View File

@ -96,6 +96,10 @@ pub enum IR {
count: usize, count: usize,
}, },
Lam {
name: String,
},
// Try { // Try {
// tipo: Arc<Type>, // tipo: Arc<Type>,
// value: Box<Self>, // value: Box<Self>,
@ -104,6 +108,7 @@ pub enum IR {
// }, // },
When { When {
count: usize, count: usize,
tipo: Arc<Type>,
subject_name: String, subject_name: String,
}, },
@ -136,6 +141,7 @@ pub enum IR {
FieldsExpose { FieldsExpose {
count: usize, count: usize,
indices: Vec<usize>,
}, },
// ModuleSelect { // ModuleSelect {

View File

@ -1,5 +1,6 @@
use std::{collections::HashMap, fmt::format, ops::Deref, sync::Arc}; use std::{collections::HashMap, ops::Deref, sync::Arc};
use itertools::Itertools;
use uplc::{ use uplc::{
ast::{ ast::{
builder::{self, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD}, builder::{self, CONSTR_FIELDS_EXPOSER, CONSTR_GET_FIELD},
@ -194,40 +195,80 @@ impl<'a> CodeGenerator<'a> {
subjects, clauses, .. subjects, clauses, ..
} => { } => {
let subject_name = format!("__subject_name_{}", self.id_gen.next()); let subject_name = format!("__subject_name_{}", self.id_gen.next());
let constr_var = format!("__constr_name_{}", self.id_gen.next());
// assuming one subject at the moment // assuming one subject at the moment
ir_stack.push(IR::When {
count: clauses.len() + 1,
subject_name: subject_name.clone(),
});
let subject = subjects[0].clone(); let subject = subjects[0].clone();
let mut needs_constr_var = false;
self.build_ir(&subject, ir_stack);
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![];
let mut pattern_vec = vec![]; let mut pattern_vec = vec![];
for clause in clauses { for clause in clauses {
self.build_ir(&clause.then, &mut clauses_vec); pattern_vec.push(IR::Clause {
count: 2,
tipo: subject.tipo().clone(),
subject_name: subject_name.clone(),
});
self.build_ir(&clause.then, &mut clauses_vec);
self.when_ir( self.when_ir(
&clause.pattern[0], &clause.pattern[0],
&mut pattern_vec, &mut pattern_vec,
&mut clauses_vec, &mut clauses_vec,
&subject.tipo(), &subject.tipo(),
subject_name.clone(), constr_var.clone(),
) &mut needs_constr_var,
);
}
let last_pattern = &last_clause.pattern[0];
pattern_vec.push(IR::Finally);
self.build_ir(&last_clause.then, &mut clauses_vec);
self.when_ir(
last_pattern,
&mut pattern_vec,
&mut clauses_vec,
&subject.tipo(),
constr_var.clone(),
&mut needs_constr_var,
);
if needs_constr_var {
ir_stack.push(IR::Lam {
name: constr_var.clone(),
});
self.build_ir(&subject, ir_stack);
ir_stack.push(IR::When {
count: clauses.len() + 1,
subject_name,
tipo: subject.tipo(),
});
ir_stack.push(IR::Var {
constructor: ValueConstructor::public(
subject.tipo(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: constr_var,
})
} else {
ir_stack.push(IR::When {
count: clauses.len() + 1,
subject_name,
tipo: subject.tipo(),
});
self.build_ir(&subject, ir_stack);
} }
ir_stack.append(&mut pattern_vec); ir_stack.append(&mut pattern_vec);
let last_pattern = &last_clause.pattern[0];
ir_stack.push(IR::Finally);
self.build_ir(&last_clause.then, &mut clauses_vec);
self.pattern_ir(last_pattern, ir_stack, &mut clauses_vec);
}; };
} }
TypedExpr::If { .. } => todo!(), TypedExpr::If { .. } => todo!(),
@ -313,7 +354,7 @@ impl<'a> CodeGenerator<'a> {
} }
fn assignment_ir( fn assignment_ir(
&self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<Type>>,
pattern_vec: &mut Vec<IR>, pattern_vec: &mut Vec<IR>,
value_vec: &mut Vec<IR>, value_vec: &mut Vec<IR>,
@ -342,21 +383,16 @@ impl<'a> CodeGenerator<'a> {
} }
fn when_ir( fn when_ir(
&self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
pattern_vec: &mut Vec<IR>, pattern_vec: &mut Vec<IR>,
values: &mut Vec<IR>, values: &mut Vec<IR>,
tipo: &Type, tipo: &Type,
subject_name: String, constr_var: String,
needs_constr_var: &mut bool,
) { ) {
match pattern { match pattern {
Pattern::Int { value, .. } => { Pattern::Int { value, .. } => {
pattern_vec.push(IR::Clause {
count: 2,
tipo: tipo.clone().into(),
subject_name,
});
pattern_vec.push(IR::Int { pattern_vec.push(IR::Int {
value: value.clone(), value: value.clone(),
}); });
@ -369,17 +405,48 @@ impl<'a> CodeGenerator<'a> {
Pattern::Assign { .. } => todo!(), Pattern::Assign { .. } => todo!(),
Pattern::Discard { .. } => unreachable!(), Pattern::Discard { .. } => unreachable!(),
Pattern::List { .. } => todo!(), Pattern::List { .. } => todo!(),
Pattern::Constructor { .. } => todo!(), Pattern::Constructor { arguments, .. } => {
let mut needs_access_to_constr_var = false;
for arg in arguments {
match arg.value {
Pattern::Var { .. }
| Pattern::List { .. }
| Pattern::Constructor { .. } => {
needs_access_to_constr_var = true;
}
_ => {}
}
}
let mut new_vec = vec![IR::Var {
constructor: ValueConstructor::public(
tipo.clone().into(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: constr_var,
}];
if needs_access_to_constr_var {
*needs_constr_var = true;
new_vec.append(values);
self.pattern_ir(pattern, pattern_vec, &mut new_vec);
} else {
self.pattern_ir(pattern, pattern_vec, values);
}
}
} }
} }
fn pattern_ir( fn pattern_ir(
&self, &mut self,
pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>, pattern: &Pattern<tipo::PatternConstructor, Arc<tipo::Type>>,
pattern_vec: &mut Vec<IR>, pattern_vec: &mut Vec<IR>,
values: &mut Vec<IR>, values: &mut Vec<IR>,
) { ) {
match pattern { match dbg!(pattern) {
Pattern::Int { .. } => todo!(), Pattern::Int { .. } => todo!(),
Pattern::String { .. } => todo!(), Pattern::String { .. } => todo!(),
Pattern::Var { .. } => todo!(), Pattern::Var { .. } => todo!(),
@ -440,7 +507,101 @@ impl<'a> CodeGenerator<'a> {
pattern_vec.append(values); pattern_vec.append(values);
pattern_vec.append(&mut elements_vec); pattern_vec.append(&mut elements_vec);
} }
Pattern::Constructor {
is_record,
name: constr_name,
arguments,
constructor,
tipo,
..
} => {
if *is_record {
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!(),
},
_ => unreachable!(),
};
let data_type = self.data_types.get(&data_type_key).unwrap();
let (index, constructor_type) = data_type
.constructors
.iter()
.enumerate()
.find(|(_, dt)| &dt.name == constr_name)
.unwrap();
let field_map = match constructor {
tipo::PatternConstructor::Record { field_map, .. } => {
field_map.clone().unwrap()
}
};
let mut type_map: HashMap<String, Arc<Type>> = HashMap::new();
for arg in &constructor_type.arguments {
let label = arg.label.clone().unwrap();
let field_type = arg.tipo.clone();
type_map.insert(label, field_type);
}
let arguments_index = arguments
.iter()
.map(|item| {
let label = item.label.clone().unwrap_or_default();
let field_index = field_map.fields.get(&label).unwrap_or(&0);
let (discard, var_name) = match &item.value {
Pattern::Var { name, .. } => (false, name.clone()),
Pattern::Discard { .. } => (true, "".to_string()),
Pattern::List { .. } => todo!(),
Pattern::Constructor { .. } => todo!(), Pattern::Constructor { .. } => todo!(),
_ => todo!(),
};
(label, var_name, *field_index, discard)
})
.filter(|(_, _, _, discard)| !discard)
.sorted_by(|item1, item2| item1.2.cmp(&item2.2))
.collect::<Vec<(String, String, usize, bool)>>();
// push constructor Index
pattern_vec.push(IR::Int {
value: index.to_string(),
});
if !arguments_index.is_empty() {
pattern_vec.push(IR::FieldsExpose {
count: arguments_index.len() + 2,
indices: arguments_index
.iter()
.map(|(_, _, index, _)| *index)
.collect_vec(),
});
for arg in arguments_index {
let field_label = arg.0;
let field_type = type_map.get(&field_label).unwrap();
let field_var = arg.1;
pattern_vec.push(IR::Var {
constructor: ValueConstructor::public(
field_type.clone(),
ValueConstructorVariant::LocalVariable {
location: Span::empty(),
},
),
name: field_var,
})
}
}
pattern_vec.append(values);
} else {
println!("todo");
}
}
} }
} }
@ -807,7 +968,7 @@ impl<'a> CodeGenerator<'a> {
arg_stack.push(term); arg_stack.push(term);
} }
IR::DefineFunc { func_name, .. } => { IR::DefineFunc { .. } => {
let _body = arg_stack.pop().unwrap(); let _body = arg_stack.pop().unwrap();
todo!() todo!()
@ -815,11 +976,34 @@ impl<'a> CodeGenerator<'a> {
IR::DefineConst { .. } => todo!(), IR::DefineConst { .. } => todo!(),
IR::DefineConstrFields { .. } => todo!(), IR::DefineConstrFields { .. } => todo!(),
IR::DefineConstrFieldAccess { .. } => todo!(), IR::DefineConstrFieldAccess { .. } => todo!(),
IR::When { .. } => todo!(), IR::Lam { .. } => todo!(),
IR::When {
subject_name, tipo, ..
} => {
let subject = arg_stack.pop().unwrap();
let mut term = arg_stack.pop().unwrap();
term = if tipo.is_int() {
Term::Apply {
function: Term::Lambda {
parameter_name: Name {
text: subject_name,
unique: 0.into(),
},
body: term.into(),
}
.into(),
argument: subject.into(),
}
} else {
todo!()
};
arg_stack.push(term);
}
IR::Clause { IR::Clause {
count, tipo, subject_name, ..
tipo,
subject_name,
} => { } => {
// clause to compare // clause to compare
let clause = arg_stack.pop().unwrap(); let clause = arg_stack.pop().unwrap();
@ -831,17 +1015,45 @@ impl<'a> CodeGenerator<'a> {
let mut term = arg_stack.pop().unwrap(); let mut term = arg_stack.pop().unwrap();
let checker = if tipo.is_int() { let checker = if tipo.is_int() {
DefaultFunction::EqualsInteger.into() Term::Apply {
function: DefaultFunction::EqualsInteger.into(),
argument: Term::Var(Name {
text: subject_name,
unique: 0.into(),
})
.into(),
}
} else if tipo.is_bytearray() { } else if tipo.is_bytearray() {
DefaultFunction::EqualsByteString.into() Term::Apply {
function: DefaultFunction::EqualsByteString.into(),
argument: Term::Var(Name {
text: subject_name,
unique: 0.into(),
})
.into(),
}
} else if tipo.is_bool() { } else if tipo.is_bool() {
todo!() todo!()
} else if tipo.is_string() { } else if tipo.is_string() {
DefaultFunction::EqualsString.into() Term::Apply {
function: DefaultFunction::EqualsString.into(),
argument: Term::Var(Name {
text: subject_name,
unique: 0.into(),
})
.into(),
}
} else if tipo.is_list() { } else if tipo.is_list() {
todo!() todo!()
} else { } else {
DefaultFunction::EqualsData.into() Term::Apply {
function: DefaultFunction::EqualsInteger.into(),
argument: Term::Var(Name {
text: subject_name,
unique: 0.into(),
})
.into(),
}
}; };
term = Term::Apply { term = Term::Apply {
@ -849,24 +1061,16 @@ impl<'a> CodeGenerator<'a> {
function: Term::Apply { function: Term::Apply {
function: Term::Force(DefaultFunction::IfThenElse.into()).into(), function: Term::Force(DefaultFunction::IfThenElse.into()).into(),
argument: Term::Apply { argument: Term::Apply {
function: Term::Apply { function: checker.into(),
function: checker,
argument: Term::Var(Name {
text: subject_name,
unique: 0.into(),
})
.into(),
}
.into(),
argument: clause.into(), argument: clause.into(),
} }
.into(), .into(),
} }
.into(), .into(),
argument: body.into(), argument: Term::Delay(body.into()).into(),
} }
.into(), .into(),
argument: term.into(), argument: Term::Delay(term.into()).into(),
} }
.force_wrap(); .force_wrap();

View File

@ -44,13 +44,15 @@ pub fn who(a: ByteArray) -> ByteArray {
} }
pub type Datum { pub type Datum {
thing: Int, Offer { price: Int, asset_class: ByteArray }
stuff: Int, Sell
Hold(Int)
} }
pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool { pub fn spend(datum: Datum, _rdmr: Nil, _ctx: Nil) -> Bool {
when datum.thing is { when datum is {
0 -> True Offer { price, .. } -> price > 0
_ -> False Hold(less) -> less < 0
Sell -> False
} }
} }