feat: when statements with field access now work
This commit is contained in:
parent
8d1e73bbea
commit
f10c78d800
|
@ -9,7 +9,7 @@ use uplc::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{BinOp, DataType, Function, Pattern, Span, TypedArg, TypedPattern},
|
ast::{AssignmentKind, BinOp, DataType, Function, Pattern, Span, TypedArg, TypedPattern},
|
||||||
expr::TypedExpr,
|
expr::TypedExpr,
|
||||||
tipo::{self, ModuleValueConstructor, Type, ValueConstructorVariant},
|
tipo::{self, ModuleValueConstructor, Type, ValueConstructorVariant},
|
||||||
};
|
};
|
||||||
|
@ -120,12 +120,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pub fn generate(&mut self, body: TypedExpr, arguments: Vec<TypedArg>) -> Program<Name> {
|
pub fn generate(&mut self, body: TypedExpr, arguments: Vec<TypedArg>) -> Program<Name> {
|
||||||
self.recurse_scope_level(&body, ScopeLevels::new());
|
self.recurse_scope_level(&body, ScopeLevels::new());
|
||||||
|
|
||||||
println!(
|
|
||||||
"DATA USAGE HOLDER IS {:#?}",
|
|
||||||
self.uplc_data_usage_holder_lookup
|
|
||||||
);
|
|
||||||
println!("DATA HOLDER IS {:#?}", self.uplc_data_holder_lookup);
|
|
||||||
|
|
||||||
self.uplc_function_holder_lookup
|
self.uplc_function_holder_lookup
|
||||||
.sort_by(|_key1, value1, _key2, value2| {
|
.sort_by(|_key1, value1, _key2, value2| {
|
||||||
if value1.is_less_than(value2, true) {
|
if value1.is_less_than(value2, true) {
|
||||||
|
@ -219,7 +213,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn recurse_scope_level(&mut self, body: &TypedExpr, scope_level: ScopeLevels) {
|
pub(crate) fn recurse_scope_level(&mut self, body: &TypedExpr, scope_level: ScopeLevels) {
|
||||||
match dbg!(body) {
|
match body {
|
||||||
TypedExpr::Int { .. } => {}
|
TypedExpr::Int { .. } => {}
|
||||||
TypedExpr::String { .. } => {}
|
TypedExpr::String { .. } => {}
|
||||||
TypedExpr::ByteArray { .. } => {}
|
TypedExpr::ByteArray { .. } => {}
|
||||||
|
@ -233,52 +227,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypedExpr::Var {
|
TypedExpr::Var { constructor, .. } => {
|
||||||
constructor, name, ..
|
|
||||||
} => {
|
|
||||||
match constructor.variant.clone() {
|
match constructor.variant.clone() {
|
||||||
ValueConstructorVariant::LocalVariable { .. } => {
|
ValueConstructorVariant::LocalVariable { .. } => {}
|
||||||
let mut is_done_loop = false;
|
|
||||||
let mut current_tipo: Type = (*constructor.tipo).clone();
|
|
||||||
let mut current_module = "".to_string();
|
|
||||||
while !is_done_loop {
|
|
||||||
match current_tipo.clone() {
|
|
||||||
Type::App { module, .. } => {
|
|
||||||
is_done_loop = true;
|
|
||||||
|
|
||||||
current_module = module.clone();
|
|
||||||
}
|
|
||||||
Type::Fn { .. } => {
|
|
||||||
is_done_loop = true;
|
|
||||||
}
|
|
||||||
Type::Var { tipo } => {
|
|
||||||
let x = tipo.borrow().clone();
|
|
||||||
|
|
||||||
match x {
|
|
||||||
tipo::TypeVar::Unbound { .. } => todo!(),
|
|
||||||
tipo::TypeVar::Link { tipo } => {
|
|
||||||
current_tipo = (*tipo).clone();
|
|
||||||
}
|
|
||||||
tipo::TypeVar::Generic { .. } => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(val) = self
|
|
||||||
.uplc_data_usage_holder_lookup
|
|
||||||
.get(&(current_module.to_string(), name.clone()))
|
|
||||||
{
|
|
||||||
if scope_level.is_less_than(val, false) {
|
|
||||||
println!(
|
|
||||||
"DATA USAGE HOLDER CHANGED 1 IS {:#?}",
|
|
||||||
self.uplc_data_usage_holder_lookup
|
|
||||||
);
|
|
||||||
self.uplc_data_usage_holder_lookup
|
|
||||||
.insert((current_module, name.clone()), scope_level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ValueConstructorVariant::ModuleConstant { .. } => todo!(),
|
ValueConstructorVariant::ModuleConstant { .. } => todo!(),
|
||||||
ValueConstructorVariant::ModuleFn { name, module, .. } => {
|
ValueConstructorVariant::ModuleFn { name, module, .. } => {
|
||||||
if self
|
if self
|
||||||
|
@ -333,7 +284,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pattern,
|
pattern,
|
||||||
value,
|
value,
|
||||||
scope_level.scope_increment(1),
|
scope_level.scope_increment(1),
|
||||||
&vec![],
|
&[],
|
||||||
),
|
),
|
||||||
TypedExpr::Try { .. } => todo!(),
|
TypedExpr::Try { .. } => todo!(),
|
||||||
TypedExpr::When {
|
TypedExpr::When {
|
||||||
|
@ -439,10 +390,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.get(&(module.to_string(), current_var_name.clone()))
|
.get(&(module.to_string(), current_var_name.clone()))
|
||||||
{
|
{
|
||||||
if current_scope.is_less_than(val, false) {
|
if current_scope.is_less_than(val, false) {
|
||||||
println!(
|
|
||||||
"DATA USAGE HOLDER CHANGED 2 IS {:#?}",
|
|
||||||
self.uplc_data_usage_holder_lookup
|
|
||||||
);
|
|
||||||
self.uplc_data_usage_holder_lookup
|
self.uplc_data_usage_holder_lookup
|
||||||
.insert((module, current_var_name), current_scope);
|
.insert((module, current_var_name), current_scope);
|
||||||
}
|
}
|
||||||
|
@ -503,9 +450,9 @@ impl<'a> CodeGenerator<'a> {
|
||||||
pattern: &TypedPattern,
|
pattern: &TypedPattern,
|
||||||
value: &TypedExpr,
|
value: &TypedExpr,
|
||||||
scope_level: ScopeLevels,
|
scope_level: ScopeLevels,
|
||||||
vars: &Vec<TypedExpr>,
|
vars: &[TypedExpr],
|
||||||
) {
|
) {
|
||||||
match dbg!(pattern) {
|
match pattern {
|
||||||
Pattern::Int { .. } | Pattern::String { .. } | Pattern::Var { .. } => {
|
Pattern::Int { .. } | Pattern::String { .. } | Pattern::Var { .. } => {
|
||||||
self.recurse_scope_level(value, scope_level);
|
self.recurse_scope_level(value, scope_level);
|
||||||
}
|
}
|
||||||
|
@ -543,10 +490,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
let mut mapping_index: IndexMap<String, usize> = IndexMap::new();
|
let mut mapping_index: IndexMap<String, usize> = IndexMap::new();
|
||||||
|
|
||||||
match constructor {
|
match constructor {
|
||||||
tipo::PatternConstructor::Record {
|
tipo::PatternConstructor::Record { field_map, .. } => {
|
||||||
name: _name,
|
|
||||||
field_map,
|
|
||||||
} => {
|
|
||||||
if let Some(fields_mapping) = field_map {
|
if let Some(fields_mapping) = field_map {
|
||||||
mapping_index.extend(fields_mapping.fields.clone());
|
mapping_index.extend(fields_mapping.fields.clone());
|
||||||
mapping_index
|
mapping_index
|
||||||
|
@ -556,8 +500,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("MAPPING INDEX IS {mapping_index:?}");
|
|
||||||
|
|
||||||
let module = module.clone().unwrap();
|
let module = module.clone().unwrap();
|
||||||
// TODO: support multiple subjects
|
// TODO: support multiple subjects
|
||||||
let (var_name, tipo) = match &vars[0] {
|
let (var_name, tipo) = match &vars[0] {
|
||||||
|
@ -596,7 +538,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Pattern::Var {
|
Pattern::Var {
|
||||||
name: field_name, ..
|
name: field_name, ..
|
||||||
} => {
|
} => {
|
||||||
let record_access = TypedExpr::RecordAccess {
|
let record_access = TypedExpr::Assignment {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
tipo: Type::App {
|
tipo: Type::App {
|
||||||
public: true,
|
public: true,
|
||||||
|
@ -605,13 +547,23 @@ impl<'a> CodeGenerator<'a> {
|
||||||
args: vec![],
|
args: vec![],
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
label: field_name.clone(),
|
value: TypedExpr::RecordAccess {
|
||||||
|
location: Span::empty(),
|
||||||
|
tipo: Type::App {
|
||||||
|
public: true,
|
||||||
|
module: module.clone(),
|
||||||
|
name: constructor_name.to_string(),
|
||||||
|
args: vec![],
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
label: label.clone(),
|
||||||
index,
|
index,
|
||||||
record: TypedExpr::Var {
|
record: TypedExpr::Var {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
constructor: tipo::ValueConstructor {
|
constructor: tipo::ValueConstructor {
|
||||||
public: false,
|
public: false,
|
||||||
variant: ValueConstructorVariant::LocalVariable {
|
variant:
|
||||||
|
ValueConstructorVariant::LocalVariable {
|
||||||
location: Span::empty(),
|
location: Span::empty(),
|
||||||
},
|
},
|
||||||
tipo: Type::App {
|
tipo: Type::App {
|
||||||
|
@ -625,6 +577,13 @@ impl<'a> CodeGenerator<'a> {
|
||||||
name: var_name.clone(),
|
name: var_name.clone(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
pattern: TypedPattern::Var {
|
||||||
|
location: Span::empty(),
|
||||||
|
name: field_name.clone(),
|
||||||
|
},
|
||||||
|
kind: AssignmentKind::Let,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(val) = self.uplc_data_holder_lookup.get(&(
|
if let Some(val) = self.uplc_data_holder_lookup.get(&(
|
||||||
|
@ -657,10 +616,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
.get(&(module.to_string(), var_name.clone()))
|
.get(&(module.to_string(), var_name.clone()))
|
||||||
{
|
{
|
||||||
if scope_level.is_less_than(val, false) {
|
if scope_level.is_less_than(val, false) {
|
||||||
println!(
|
|
||||||
"DATA USAGE HOLDER CHANGED 3 IS {:#?}",
|
|
||||||
self.uplc_data_usage_holder_lookup
|
|
||||||
);
|
|
||||||
self.uplc_data_usage_holder_lookup.insert(
|
self.uplc_data_usage_holder_lookup.insert(
|
||||||
(module.to_string(), var_name.clone()),
|
(module.to_string(), var_name.clone()),
|
||||||
scope_level.clone(),
|
scope_level.clone(),
|
||||||
|
@ -1118,58 +1073,6 @@ impl<'a> CodeGenerator<'a> {
|
||||||
TypedExpr::When {
|
TypedExpr::When {
|
||||||
subjects, clauses, ..
|
subjects, clauses, ..
|
||||||
} => {
|
} => {
|
||||||
let current_clauses = clauses.clone();
|
|
||||||
|
|
||||||
let mut data_type = "".to_string();
|
|
||||||
|
|
||||||
let mut current_module = "".to_string();
|
|
||||||
|
|
||||||
let mut total_constr_length = 0;
|
|
||||||
|
|
||||||
let mut new_current_clauses: Vec<(usize, TypedExpr)> = current_clauses
|
|
||||||
.iter()
|
|
||||||
.map(|clause| {
|
|
||||||
let pattern = &clause.pattern[0];
|
|
||||||
let index = match pattern {
|
|
||||||
Pattern::Constructor {
|
|
||||||
name, tipo, module, ..
|
|
||||||
} => {
|
|
||||||
let mut is_app = false;
|
|
||||||
let mut tipo = &**tipo;
|
|
||||||
let mut key: (String, String) = ("".to_string(), "".to_string());
|
|
||||||
while !is_app {
|
|
||||||
match tipo {
|
|
||||||
Type::App { module, name, .. } => {
|
|
||||||
is_app = true;
|
|
||||||
key = (module.clone(), name.clone());
|
|
||||||
}
|
|
||||||
Type::Fn { ret, .. } => {
|
|
||||||
tipo = ret;
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let dt = self.data_types.get(&key).unwrap();
|
|
||||||
|
|
||||||
let index =
|
|
||||||
dt.constructors.iter().position(|c| name.clone() == c.name);
|
|
||||||
data_type = dt.name.clone();
|
|
||||||
current_module = module.clone().unwrap_or_default();
|
|
||||||
total_constr_length = dt.constructors.len();
|
|
||||||
|
|
||||||
index.unwrap_or(dt.constructors.len())
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
};
|
|
||||||
(index, clause.then.clone())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
new_current_clauses.sort_by(|a, b| a.0.cmp(&b.0));
|
|
||||||
|
|
||||||
println!("NEW CURRENT CLAUSES {new_current_clauses:?}");
|
|
||||||
|
|
||||||
let subject = &subjects[0];
|
let subject = &subjects[0];
|
||||||
|
|
||||||
let mut is_var = false;
|
let mut is_var = false;
|
||||||
|
@ -1208,6 +1111,104 @@ impl<'a> CodeGenerator<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let current_clauses = clauses.clone();
|
||||||
|
|
||||||
|
let mut current_module = "".to_string();
|
||||||
|
|
||||||
|
let mut total_constr_length = 0;
|
||||||
|
let pattern = &clauses[0].pattern[0];
|
||||||
|
|
||||||
|
let key = match pattern {
|
||||||
|
Pattern::Constructor { tipo, .. } => {
|
||||||
|
let mut is_app = false;
|
||||||
|
let mut tipo = &**tipo;
|
||||||
|
let mut key: (String, String) = ("".to_string(), "".to_string());
|
||||||
|
while !is_app {
|
||||||
|
match tipo {
|
||||||
|
Type::App { module, name, .. } => {
|
||||||
|
is_app = true;
|
||||||
|
key = (module.clone(), name.clone());
|
||||||
|
}
|
||||||
|
Type::Fn { ret, .. } => {
|
||||||
|
tipo = ret;
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
key
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let dt = self.data_types.get(&key).unwrap();
|
||||||
|
let data_type = &dt.name;
|
||||||
|
let mut new_current_clauses: Vec<(usize, Term<Name>)> = current_clauses
|
||||||
|
.iter()
|
||||||
|
.map(|clause| {
|
||||||
|
let pattern = &clause.pattern[0];
|
||||||
|
let pair = match pattern {
|
||||||
|
Pattern::Constructor { name, module, .. } => {
|
||||||
|
let index =
|
||||||
|
dt.constructors.iter().position(|c| name.clone() == c.name);
|
||||||
|
|
||||||
|
let mut current_term = self.recurse_code_gen(
|
||||||
|
&clause.then,
|
||||||
|
scope_level.scope_increment_sequence(1),
|
||||||
|
);
|
||||||
|
if let Some(ind) = index {
|
||||||
|
for (index, field) in
|
||||||
|
dt.constructors[ind].arguments.iter().enumerate()
|
||||||
|
{
|
||||||
|
let label =
|
||||||
|
field.clone().label.unwrap_or(format!("{index}"));
|
||||||
|
|
||||||
|
if let Some((_, TypedExpr::Assignment { pattern, .. })) =
|
||||||
|
self.uplc_data_holder_lookup.get(&(
|
||||||
|
key.0.clone(),
|
||||||
|
current_var_name.to_string(),
|
||||||
|
label.clone(),
|
||||||
|
))
|
||||||
|
{
|
||||||
|
let var_name = match pattern {
|
||||||
|
Pattern::Var { name, .. } => name,
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
current_term = Term::Apply {
|
||||||
|
function: Term::Lambda {
|
||||||
|
parameter_name: Name {
|
||||||
|
text: var_name.to_string(),
|
||||||
|
unique: 0.into(),
|
||||||
|
},
|
||||||
|
body: current_term.into(),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
argument: Term::Var(Name {
|
||||||
|
text: format!(
|
||||||
|
"{current_var_name}_field_{label}"
|
||||||
|
),
|
||||||
|
unique: 0.into(),
|
||||||
|
})
|
||||||
|
.into(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current_module = module.clone().unwrap_or_default();
|
||||||
|
total_constr_length = dt.constructors.len();
|
||||||
|
|
||||||
|
(index.unwrap_or(dt.constructors.len()), current_term)
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
pair
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
new_current_clauses.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
|
||||||
let mut term = Term::Apply {
|
let mut term = Term::Apply {
|
||||||
function: Term::Var(Name {
|
function: Term::Var(Name {
|
||||||
text: format!("choose_{current_module}_{data_type}_constr"),
|
text: format!("choose_{current_module}_{data_type}_constr"),
|
||||||
|
@ -1226,21 +1227,16 @@ impl<'a> CodeGenerator<'a> {
|
||||||
|
|
||||||
let mut new_current_clauses = new_current_clauses.to_vec();
|
let mut new_current_clauses = new_current_clauses.to_vec();
|
||||||
new_current_clauses.reverse();
|
new_current_clauses.reverse();
|
||||||
let last_term =
|
let last_term = last.1.clone();
|
||||||
self.recurse_code_gen(&last.1, scope_level.scope_increment_sequence(1));
|
|
||||||
|
|
||||||
println!("NEW CURRENT CLAUSES AFTER SPLIT {new_current_clauses:?}");
|
let mut current: Option<(usize, Term<Name>)> = None;
|
||||||
|
|
||||||
let mut current: Option<(usize, TypedExpr)> = None;
|
|
||||||
for index in 0..total_constr_length - 1 {
|
for index in 0..total_constr_length - 1 {
|
||||||
if current.is_none() {
|
if current.is_none() {
|
||||||
current = new_current_clauses.pop();
|
current = new_current_clauses.pop();
|
||||||
}
|
}
|
||||||
println!("CURRENT IS {current:?}");
|
|
||||||
if let Some(val) = current.clone() {
|
if let Some(val) = current.clone() {
|
||||||
if val.0 == index {
|
if val.0 == index {
|
||||||
let branch_term = self
|
let branch_term = val.1;
|
||||||
.recurse_code_gen(&val.1, scope_level.scope_increment_sequence(1));
|
|
||||||
|
|
||||||
term = Term::Apply {
|
term = Term::Apply {
|
||||||
function: term.into(),
|
function: term.into(),
|
||||||
|
@ -1630,6 +1626,19 @@ impl<'a> CodeGenerator<'a> {
|
||||||
};
|
};
|
||||||
(index, name.clone())
|
(index, name.clone())
|
||||||
}
|
}
|
||||||
|
TypedExpr::Assignment { value, .. } => match &**value {
|
||||||
|
TypedExpr::RecordAccess { index, tipo, .. } => {
|
||||||
|
let tipo = &**tipo;
|
||||||
|
|
||||||
|
let name = match tipo {
|
||||||
|
Type::App { name, .. } => name,
|
||||||
|
Type::Fn { .. } => todo!(),
|
||||||
|
Type::Var { .. } => todo!(),
|
||||||
|
};
|
||||||
|
(index, name.clone())
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,9 @@ pub type ScriptContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Redeem {
|
pub type Redeem {
|
||||||
Buy
|
Buy { tipo: ByteArray, fin: Int }
|
||||||
Sell
|
Sell { twice: ByteArray, find: Int }
|
||||||
|
Hold(Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Datum {
|
pub type Datum {
|
||||||
|
|
|
@ -33,8 +33,10 @@ pub fn spend(
|
||||||
rdmr: Redeemer,
|
rdmr: Redeemer,
|
||||||
ctx: spend.ScriptContext,
|
ctx: spend.ScriptContext,
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
let a = datum.fin
|
let x = datum.rdmr
|
||||||
a
|
when x is {
|
||||||
|> add_two
|
sample.Buy(tipo1, fin) -> fin > 0
|
||||||
|> final_check
|
sample.Sell(twice, find: fin) -> fin > 0
|
||||||
|
sample.Hold(some) -> some > 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue