feat: finish list deconstruct
This commit is contained in:
parent
e6f6d8a42d
commit
dc510b1c7a
|
@ -248,7 +248,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn recurse_scope_level(&mut self, body: &TypedExpr, scope_level: ScopeLevels) {
|
||||
match dbg!(body) {
|
||||
match body {
|
||||
TypedExpr::Int { .. } => {}
|
||||
TypedExpr::String { .. } => {}
|
||||
TypedExpr::ByteArray { .. } => {}
|
||||
|
@ -537,7 +537,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
scope_level: ScopeLevels,
|
||||
vars: &[TypedExpr],
|
||||
) {
|
||||
match dbg!(pattern) {
|
||||
match pattern {
|
||||
Pattern::Int { .. }
|
||||
| Pattern::String { .. }
|
||||
| Pattern::Var { .. }
|
||||
|
@ -1304,7 +1304,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
let mut total_constr_length = 0;
|
||||
let pattern = &clauses[0].pattern[0];
|
||||
|
||||
let key = match dbg!(pattern) {
|
||||
let key = match pattern {
|
||||
Pattern::Constructor { tipo, .. } => {
|
||||
let mut is_app = false;
|
||||
let mut tipo = &**tipo;
|
||||
|
@ -1532,7 +1532,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
&clause.then,
|
||||
scope_level.scope_increment_sequence(1),
|
||||
);
|
||||
let triplet = match dbg!(pattern) {
|
||||
let triplet = match pattern {
|
||||
Pattern::List { elements, tail, .. } => {
|
||||
let element_names: Vec<String> = elements
|
||||
.clone()
|
||||
|
@ -1613,14 +1613,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
});
|
||||
|
||||
println!("{new_current_clauses:?}");
|
||||
|
||||
let (last, new_current_clauses) = new_current_clauses.split_last().unwrap();
|
||||
|
||||
println!("{new_current_clauses:?}");
|
||||
let new_current_clauses = new_current_clauses.to_vec();
|
||||
|
||||
let mut new_current_clauses = new_current_clauses.to_vec();
|
||||
new_current_clauses.reverse();
|
||||
let mut current_term: Term<Name> = last.2.clone();
|
||||
let last_term = last.2.clone();
|
||||
|
||||
|
@ -1645,7 +1641,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
|
||||
for (index, (array_length, has_tail, then)) in
|
||||
new_current_clauses.iter().enumerate()
|
||||
new_current_clauses.iter().enumerate().rev()
|
||||
{
|
||||
let prev_length: Option<usize> = if index == 0 {
|
||||
None
|
||||
|
@ -1655,22 +1651,81 @@ impl<'a> CodeGenerator<'a> {
|
|||
.and_then(|(index_opt, _, _)| *index_opt)
|
||||
};
|
||||
|
||||
match dbg!((*array_length, prev_length)) {
|
||||
match (*array_length, prev_length) {
|
||||
(Some(length), Some(prev_length)) => {
|
||||
let check_length = if prev_length == length {
|
||||
length + 2
|
||||
} else {
|
||||
length + 1
|
||||
};
|
||||
// 0, 3, 3, None
|
||||
// Go index by index to create cases for each possible len
|
||||
for expose_index in (prev_length + 1..check_length).rev() {
|
||||
let prev_exposed = expose_index - 1;
|
||||
let list_var_name =
|
||||
format!("{current_var_name}_tail_{prev_exposed}");
|
||||
|
||||
if prev_length != length {
|
||||
// Just expose head list and tail list. Check for empty list happens above
|
||||
current_term = Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"{current_var_name}_item_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
},
|
||||
body: Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
},
|
||||
body: current_term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Builtin(
|
||||
DefaultFunction::TailList,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.to_string(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Builtin(DefaultFunction::HeadList).into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.to_string(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
}
|
||||
|
||||
// For a given list length if we encounter a tail and we are checking a clause length = current index
|
||||
// then expose a var for tail and run clause then
|
||||
current_term = if *has_tail && expose_index == length - 1 {
|
||||
current_term = if *has_tail
|
||||
&& (expose_index == check_length - 1
|
||||
|| prev_length == length)
|
||||
{
|
||||
Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
|
@ -1682,14 +1737,14 @@ impl<'a> CodeGenerator<'a> {
|
|||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
"{current_var_name}_tail_{prev_exposed}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
// we are checking a clause length = current index so check empty tail list and run clause then if tail list is empty
|
||||
} else if expose_index == length - 1 {
|
||||
} else if expose_index == check_length - 1 {
|
||||
Term::Force(
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
|
@ -1706,7 +1761,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
"{current_var_name}_tail_{prev_exposed}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
})
|
||||
|
@ -1739,7 +1794,7 @@ impl<'a> CodeGenerator<'a> {
|
|||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
"{current_var_name}_tail_{prev_exposed}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
})
|
||||
|
@ -1755,64 +1810,10 @@ impl<'a> CodeGenerator<'a> {
|
|||
.into(),
|
||||
)
|
||||
};
|
||||
if prev_length != length {
|
||||
// Just expose head list and tail list. Check for empty list happens above
|
||||
current_term = Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"{current_var_name}_item_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
},
|
||||
body: Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
},
|
||||
body: current_term.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Builtin(
|
||||
DefaultFunction::TailList,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.to_string(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Builtin(DefaultFunction::HeadList).into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.to_string(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
(Some(length), None) => {
|
||||
for expose_index in (0..length + 1).rev() {
|
||||
for expose_index in 0..length + 1 {
|
||||
let list_var_name = if expose_index == 0 {
|
||||
current_var_name.clone()
|
||||
} else {
|
||||
|
@ -1820,94 +1821,6 @@ impl<'a> CodeGenerator<'a> {
|
|||
format!("{current_var_name}_tail_{prev_exposed}")
|
||||
};
|
||||
|
||||
// For a given list length if we encounter a tail and we are checking a clause length = current index
|
||||
// then expose a var for tail and run clause then
|
||||
current_term = if *has_tail && expose_index == length - 1 {
|
||||
Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("{current_var_name}_rest"),
|
||||
unique: 0.into(),
|
||||
},
|
||||
body: then.clone().into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
// we are checking a clause length = current index so check empty tail list and run clause then if tail list is empty
|
||||
} else if expose_index == length - 1 {
|
||||
Term::Force(
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Force(
|
||||
Term::Builtin(
|
||||
DefaultFunction::ChooseList,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(then.clone().into())
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(current_term.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
// We are not checking for a list of this length, so fallback to last clause then if tail list is empty
|
||||
} else {
|
||||
Term::Force(
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Force(
|
||||
Term::Builtin(
|
||||
DefaultFunction::ChooseList,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: format!(
|
||||
"{current_var_name}_tail_{expose_index}"
|
||||
),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(last_term.clone().into())
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(current_term.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
};
|
||||
|
||||
// Just expose head list and tail list. Check for empty list happens above
|
||||
current_term = Term::Apply {
|
||||
function: Term::Lambda {
|
||||
|
@ -1958,6 +1871,88 @@ impl<'a> CodeGenerator<'a> {
|
|||
}
|
||||
.into(),
|
||||
};
|
||||
|
||||
// For a given list length if we encounter a tail and we are checking a clause length = current index
|
||||
// then expose a var for tail and run clause then
|
||||
current_term = if *has_tail && expose_index == length {
|
||||
Term::Apply {
|
||||
function: Term::Lambda {
|
||||
parameter_name: Name {
|
||||
text: format!("{current_var_name}_rest"),
|
||||
unique: 0.into(),
|
||||
},
|
||||
body: then.clone().into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.clone(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
// we are checking a clause length = current index so check empty tail list and run clause then if tail list is empty
|
||||
} else if expose_index == length {
|
||||
Term::Force(
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Force(
|
||||
Term::Builtin(
|
||||
DefaultFunction::ChooseList,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.clone(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(then.clone().into())
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(current_term.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
// We are not checking for a list of this length, so fallback to last clause then if tail list is empty
|
||||
} else {
|
||||
Term::Force(
|
||||
Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Apply {
|
||||
function: Term::Force(
|
||||
Term::Force(
|
||||
Term::Builtin(
|
||||
DefaultFunction::ChooseList,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.into(),
|
||||
argument: Term::Var(Name {
|
||||
text: list_var_name.clone(),
|
||||
unique: 0.into(),
|
||||
})
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(last_term.clone().into())
|
||||
.into(),
|
||||
}
|
||||
.into(),
|
||||
argument: Term::Delay(current_term.into()).into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
(None, None) => todo!(),
|
||||
|
|
|
@ -38,8 +38,10 @@ pub fn spend(
|
|||
let z = [1, ..y]
|
||||
when z is {
|
||||
[] -> False
|
||||
[a] -> a == 1
|
||||
[a,b] -> b == 2
|
||||
[a,b,c] -> a > 1
|
||||
[a,b, c,..d] -> b > 1
|
||||
_other -> False
|
||||
_other -> True
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue