multi stack problem
This commit is contained in:
parent
bcb9d130c7
commit
9abb9d1feb
@ -64,7 +64,6 @@ impl ToTokens for Extract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure stacks have enough values
|
|
||||||
let conditions = counts.iter().map(|(stack, count)| {
|
let conditions = counts.iter().map(|(stack, count)| {
|
||||||
let inner_stack = &stack.0;
|
let inner_stack = &stack.0;
|
||||||
quote! { #inner_state.#inner_stack.len() >= #count }
|
quote! { #inner_state.#inner_stack.len() >= #count }
|
||||||
@ -77,7 +76,7 @@ impl ToTokens for Extract {
|
|||||||
quote! { let #var_name = #inner_state.#inner_stack.pop().unwrap(); }
|
quote! { let #var_name = #inner_state.#inner_stack.pop().unwrap(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create slices of variable names for restoration
|
// Create slices of variable names for restoration and function call
|
||||||
let value_vars = (0..stacks.len())
|
let value_vars = (0..stacks.len())
|
||||||
.map(|i| quote::format_ident!("val_{}", i))
|
.map(|i| quote::format_ident!("val_{}", i))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -88,13 +87,12 @@ impl ToTokens for Extract {
|
|||||||
.zip(value_vars.iter().rev())
|
.zip(value_vars.iter().rev())
|
||||||
.map(|(stack, var)| {
|
.map(|(stack, var)| {
|
||||||
let inner_stack = &&stack.0;
|
let inner_stack = &&stack.0;
|
||||||
quote! { #inner_state.#inner_stack.push(#var); }
|
quote! { #inner_state.#inner_stack.push(#var.clone()); }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Run the function using auxiliary mode if needed
|
|
||||||
let aux_run = match aux {
|
let aux_run = match aux {
|
||||||
true => quote! {
|
true => quote! {
|
||||||
let result = #inner_func(#(#value_vars),*);
|
let result = #inner_func(#(#value_vars.clone()),*);
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
#inner_state.#inner_out_stack.extend(result.iter());
|
#inner_state.#inner_out_stack.extend(result.iter());
|
||||||
} else {
|
} else {
|
||||||
@ -102,7 +100,7 @@ impl ToTokens for Extract {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
false => quote! {
|
false => quote! {
|
||||||
let result = #inner_func(#(#value_vars),*);
|
let result = #inner_func(#(#value_vars.clone()),*);
|
||||||
if let Some(result) = result {
|
if let Some(result) = result {
|
||||||
#inner_state.#inner_out_stack.push(result);
|
#inner_state.#inner_out_stack.push(result);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,32 +5,29 @@ use crate::push::state::{Gene, PushState};
|
|||||||
use super::common::{code_from_exec, code_pop, int_pop};
|
use super::common::{code_from_exec, code_pop, int_pop};
|
||||||
|
|
||||||
/// Checks to see if a single gene is a block.
|
/// Checks to see if a single gene is a block.
|
||||||
fn _is_block(vals: Vec<Gene>) -> Option<bool> {
|
fn _is_block(a: Gene) -> Option<bool> {
|
||||||
Some(match vals[0] {
|
Some(match a {
|
||||||
Gene::Block(_) => true,
|
Gene::Block(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, boolean, _is_block, Gene, 1);
|
|
||||||
|
|
||||||
/// Checks to see if a single gene is not a block.
|
/// Checks to see if a single gene is not a block.
|
||||||
fn _is_singular(vals: Vec<Gene>) -> Option<bool> {
|
fn _is_singular(a: Gene) -> Option<bool> {
|
||||||
Some(_is_block(vals)?.not())
|
Some(_is_block(a)?.not())
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, boolean, _is_singular, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the length of a block, else 1 if not a block
|
/// Returns the length of a block, else 1 if not a block
|
||||||
fn _length(vals: Vec<Gene>) -> Option<i128> {
|
fn _length(a: Gene) -> Option<i128> {
|
||||||
Some(match &vals[0] {
|
Some(match &a {
|
||||||
Gene::Block(x) => x.len() as i128,
|
Gene::Block(x) => x.len() as i128,
|
||||||
_ => 1,
|
_ => 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, int, _length, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the first item in a block if doable, else None
|
/// Returns the first item in a block if doable, else None
|
||||||
fn _first(vals: Vec<Gene>) -> Option<Gene> {
|
fn _first(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
if x.len() > 1 {
|
if x.len() > 1 {
|
||||||
Some(x[0].clone())
|
Some(x[0].clone())
|
||||||
@ -41,11 +38,10 @@ fn _first(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _first, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the first item in a block if applicable, else None
|
/// Returns the first item in a block if applicable, else None
|
||||||
fn _last(vals: Vec<Gene>) -> Option<Gene> {
|
fn _last(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
if x.len() > 1 {
|
if x.len() > 1 {
|
||||||
Some(x.last()?.clone())
|
Some(x.last()?.clone())
|
||||||
@ -56,11 +52,10 @@ fn _last(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _last, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns all but the first code item in a block if applicable, else None
|
/// Returns all but the first code item in a block if applicable, else None
|
||||||
fn _rest(vals: Vec<Gene>) -> Option<Gene> {
|
fn _rest(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
if x.len() > 1 {
|
if x.len() > 1 {
|
||||||
Some(Gene::Block(x[1..].to_vec()))
|
Some(Gene::Block(x[1..].to_vec()))
|
||||||
@ -71,11 +66,10 @@ fn _rest(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _rest, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns all but the first code item in a block if applicable, else None
|
/// Returns all but the first code item in a block if applicable, else None
|
||||||
fn _but_last(vals: Vec<Gene>) -> Option<Gene> {
|
fn _but_last(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
let x_len = x.len();
|
let x_len = x.len();
|
||||||
if x_len > 1 {
|
if x_len > 1 {
|
||||||
@ -87,19 +81,17 @@ fn _but_last(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _but_last, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns all the vals wrapped in a code block
|
/// Returns a gene wrapped in a block
|
||||||
fn _wrap_block(vals: Vec<Gene>) -> Option<Gene> {
|
fn _wrap_block(a: Gene) -> Option<Gene> {
|
||||||
Some(Gene::Block(vals))
|
Some(Gene::Block(vec![a]))
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _wrap_block, Gene, 1);
|
|
||||||
|
|
||||||
/// Combines two genes into one. Accounts for blocks.
|
/// Combines two genes into one. Accounts for blocks.
|
||||||
/// If the second gene is a block and the first one isn't,
|
/// If the second gene is a block and the first one isn't,
|
||||||
/// appends the first gene to the second gene.
|
/// appends the first gene to the second gene.
|
||||||
fn _combine(vals: Vec<Gene>) -> Option<Gene> {
|
fn _combine(a: Gene, b: Gene) -> Option<Gene> {
|
||||||
match (&vals[0], &vals[1]) {
|
match (&a, &b) {
|
||||||
(Gene::Block(x), Gene::Block(y)) => {
|
(Gene::Block(x), Gene::Block(y)) => {
|
||||||
let x_clone = x.clone();
|
let x_clone = x.clone();
|
||||||
let mut y_clone = y.clone();
|
let mut y_clone = y.clone();
|
||||||
@ -119,7 +111,6 @@ fn _combine(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
(x, y) => Some(Gene::Block(vec![x.clone(), y.clone()])),
|
(x, y) => Some(Gene::Block(vec![x.clone(), y.clone()])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _combine, Gene, 2);
|
|
||||||
|
|
||||||
/// Pushes `code_pop` and the top item of the code stack to the exec stack.
|
/// Pushes `code_pop` and the top item of the code stack to the exec stack.
|
||||||
/// Top code item gets executed before being removed from code stack.
|
/// Top code item gets executed before being removed from code stack.
|
||||||
@ -330,15 +321,9 @@ pub fn code_map(state: &mut PushState) {
|
|||||||
|
|
||||||
/// If top bool is true, execute top element of code/exec stack and skip the second.
|
/// If top bool is true, execute top element of code/exec stack and skip the second.
|
||||||
/// If false, execute second element and skip the top.
|
/// If false, execute second element and skip the top.
|
||||||
pub fn _if(vals: Vec<Gene>, auxs: Vec<bool>) -> Option<Gene> {
|
pub fn _if(a: Gene, b: Gene, cond: bool) -> Option<Gene> {
|
||||||
Some(if auxs[0] {
|
Some(if cond { a } else { b })
|
||||||
vals[0].clone()
|
|
||||||
} else {
|
|
||||||
vals[1].clone()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
make_instruction_aux!(code, exec, _if, Gene, 2, boolean, 1, bool);
|
|
||||||
make_instruction_aux!(exec, exec, _if, Gene, 2, boolean, 1, bool);
|
|
||||||
|
|
||||||
/// Evaluates the top code item if the top code is true, else pops it.
|
/// Evaluates the top code item if the top code is true, else pops it.
|
||||||
pub fn code_when(state: &mut PushState) {
|
pub fn code_when(state: &mut PushState) {
|
||||||
@ -450,7 +435,7 @@ pub fn _insert(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
|||||||
val => Gene::Block(vec![val]),
|
val => Gene::Block(vec![val]),
|
||||||
};
|
};
|
||||||
if block.rec_len() == 0 {
|
if block.rec_len() == 0 {
|
||||||
return _combine(vec![block, vals[1].clone()]);
|
return _combine(block, vals[1].clone());
|
||||||
}
|
}
|
||||||
let ndx = auxs[0].abs() as usize % block.rec_len();
|
let ndx = auxs[0].abs() as usize % block.rec_len();
|
||||||
block.with_code_inserted_at_point(vals[1].clone(), ndx);
|
block.with_code_inserted_at_point(vals[1].clone(), ndx);
|
||||||
@ -498,6 +483,30 @@ pub fn _reverse(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _reverse, Gene, 1);
|
make_instruction_clone!(code, code, _reverse, Gene, 1);
|
||||||
|
|
||||||
|
macro_rules! make_code_instructions {
|
||||||
|
($stack:ident) => {
|
||||||
|
make_instruction_new!(_is_block, $stack, boolean, $stack);
|
||||||
|
make_instruction_new!(_is_singular, $stack, boolean, $stack);
|
||||||
|
make_instruction_new!(_length, $stack, int, $stack);
|
||||||
|
make_instruction_new!(_first, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_last, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_rest, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_but_last, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_wrap_block, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_combine, $stack, $stack, $stack, $stack);
|
||||||
|
//make_instruction_new!(_if, $stack, $stack, $stack, $stack, boolean);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! all_code_instructions {
|
||||||
|
() => {
|
||||||
|
make_code_instructions!(code);
|
||||||
|
make_code_instructions!(exec);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
all_code_instructions!();
|
||||||
|
make_instruction_new!(_if, code, code, code, code, boolean);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -883,7 +892,7 @@ mod tests {
|
|||||||
let mut test_state = EMPTY_STATE;
|
let mut test_state = EMPTY_STATE;
|
||||||
|
|
||||||
// Code tests
|
// Code tests
|
||||||
test_state.code = vec![Gene::GeneInt(0), Gene::GeneInt(1)];
|
/*test_state.code = vec![Gene::GeneInt(0), Gene::GeneInt(1)];
|
||||||
test_state.boolean = vec![true];
|
test_state.boolean = vec![true];
|
||||||
code_if(&mut test_state);
|
code_if(&mut test_state);
|
||||||
assert_eq!(vec![Gene::GeneInt(1)], test_state.exec);
|
assert_eq!(vec![Gene::GeneInt(1)], test_state.exec);
|
||||||
@ -906,7 +915,7 @@ mod tests {
|
|||||||
test_state.boolean = vec![false];
|
test_state.boolean = vec![false];
|
||||||
exec_if(&mut test_state);
|
exec_if(&mut test_state);
|
||||||
assert_eq!(vec![Gene::GeneInt(0)], test_state.exec);
|
assert_eq!(vec![Gene::GeneInt(0)], test_state.exec);
|
||||||
test_state.exec.clear();
|
test_state.exec.clear();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -9,6 +9,10 @@ fn aux_iadd(x: i128, y: i128) -> Option<Vec<i128>> {
|
|||||||
Some(vec![x + y, x - y])
|
Some(vec![x + y, x - y])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn two_stacks(x: i128, y: i128, cond: bool) -> Option<i128> {
|
||||||
|
if cond { Some(x + y) } else { Some(x - y) }
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn run_extract_test() {
|
fn run_extract_test() {
|
||||||
let mut test_state = EMPTY_STATE;
|
let mut test_state = EMPTY_STATE;
|
||||||
@ -26,4 +30,8 @@ fn run_extract_test() {
|
|||||||
test_state.int = vec![1, 2];
|
test_state.int = vec![1, 2];
|
||||||
run_instruction!(aux_iadd, int, test_state, int, int;);
|
run_instruction!(aux_iadd, int, test_state, int, int;);
|
||||||
assert_eq!(vec![3, 1], test_state.int);
|
assert_eq!(vec![3, 1], test_state.int);
|
||||||
|
|
||||||
|
test_state.int = vec![1, 2];
|
||||||
|
test_state.boolean = vec![true];
|
||||||
|
run_instruction!(two_stacks, int, test_state, int, int, boolean);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user