Arity-based functio deinterlacing
This commit is contained in:
parent
db95d2f718
commit
57939a87b0
44
able-script-test/interlace.able
Normal file
44
able-script-test/interlace.able
Normal file
|
@ -0,0 +1,44 @@
|
|||
functio arity_0() {
|
||||
"this function has arity 0" print;
|
||||
}
|
||||
|
||||
functio arity_1(arg1) {
|
||||
"this function has arity 1" print;
|
||||
arg1 print;
|
||||
}
|
||||
|
||||
functio arity_2(arg1, arg2) {
|
||||
"this function has arity 2" print;
|
||||
arg1 print;
|
||||
arg2 print;
|
||||
}
|
||||
|
||||
functio arity_3(arg1, arg2, arg3) {
|
||||
"this function has arity 3" print;
|
||||
arg1 print;
|
||||
arg2 print;
|
||||
arg3 print;
|
||||
}
|
||||
|
||||
owo arity_0();
|
||||
owo arity_1("foo");
|
||||
owo arity_2("foo", "bar");
|
||||
owo arity_3("foo", "bar", "baz");
|
||||
|
||||
var i1 = arity_0 * arity_1;
|
||||
i1("second");
|
||||
|
||||
"----" print;
|
||||
|
||||
var i2 = arity_1 * arity_0;
|
||||
i2("first");
|
||||
|
||||
"----" print;
|
||||
|
||||
var ifancy = arity_3 * arity_3;
|
||||
ifancy("left1", "right1", "left2", "right2", "left3", "right3");
|
||||
|
||||
"----" print;
|
||||
|
||||
var another = arity_0 * arity_3;
|
||||
another("right1", "right2", "right3");
|
|
@ -9,6 +9,7 @@
|
|||
#![deny(missing_docs)]
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
cmp::Ordering,
|
||||
collections::{HashMap, VecDeque},
|
||||
io::{stdin, stdout, Read, Write},
|
||||
mem::take,
|
||||
|
@ -408,12 +409,18 @@ impl ExecEnv {
|
|||
Functio::Chain { functios, kind } => {
|
||||
let (left_functio, right_functio) = *functios;
|
||||
let (left_args, right_args) = match kind {
|
||||
crate::variables::FunctioChainKind::Ordered => args.split_at(args.len() / 2),
|
||||
crate::variables::FunctioChainKind::Interlaced => todo!(),
|
||||
crate::variables::FunctioChainKind::Ordered => {
|
||||
let (l, r) = args.split_at(args.len() / 2);
|
||||
// TODO: avoid this clone
|
||||
(l.to_owned(), r.to_owned())
|
||||
}
|
||||
crate::variables::FunctioChainKind::Interlaced => {
|
||||
Self::deinterlace(args, (left_functio.arity(), right_functio.arity()))
|
||||
}
|
||||
};
|
||||
|
||||
self.fn_call_with_values(left_functio, left_args, span)?;
|
||||
self.fn_call_with_values(right_functio, right_args, span)?;
|
||||
self.fn_call_with_values(left_functio, &left_args, span)?;
|
||||
self.fn_call_with_values(right_functio, &right_args, span)?;
|
||||
}
|
||||
Functio::Eval(code) => {
|
||||
if !args.is_empty() {
|
||||
|
@ -430,6 +437,41 @@ impl ExecEnv {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn deinterlace(
|
||||
args: &[Rc<RefCell<Value>>],
|
||||
arities: (usize, usize),
|
||||
) -> (Vec<Rc<RefCell<Value>>>, Vec<Rc<RefCell<Value>>>) {
|
||||
let n_alternations = usize::min(arities.0, arities.1);
|
||||
let (extra_l, extra_r) = match Ord::cmp(&arities.0, &arities.1) {
|
||||
Ordering::Less => (0, arities.1 - arities.0),
|
||||
Ordering::Equal => (0, 0),
|
||||
Ordering::Greater => (arities.0 - arities.1, 0),
|
||||
};
|
||||
|
||||
(
|
||||
args.chunks(2)
|
||||
.take(n_alternations)
|
||||
.map(|chunk| Rc::clone(&chunk[0]))
|
||||
.chain(
|
||||
args[2 * n_alternations..]
|
||||
.iter()
|
||||
.map(|r| Rc::clone(r))
|
||||
.take(extra_l),
|
||||
)
|
||||
.collect(),
|
||||
args.chunks(2)
|
||||
.take(n_alternations)
|
||||
.map(|chunk| Rc::clone(&chunk[1]))
|
||||
.chain(
|
||||
args[2 * n_alternations..]
|
||||
.iter()
|
||||
.map(|r| Rc::clone(r))
|
||||
.take(extra_r),
|
||||
)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Get a single bit from the bit buffer, or refill it from
|
||||
/// standard input if it is empty.
|
||||
fn get_bit(&mut self) -> Result<bool, Error> {
|
||||
|
|
|
@ -51,6 +51,20 @@ pub enum Functio {
|
|||
Eval(String),
|
||||
}
|
||||
|
||||
impl Functio {
|
||||
pub fn arity(&self) -> usize {
|
||||
match self {
|
||||
Functio::Bf {
|
||||
instructions: _,
|
||||
tape_len: _,
|
||||
} => 0,
|
||||
Functio::Able { params, body: _ } => params.len(),
|
||||
Functio::Chain { functios, kind: _ } => functios.0.arity() + functios.1.arity(),
|
||||
Functio::Eval(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, Hash)]
|
||||
pub enum FunctioChainKind {
|
||||
Ordered,
|
||||
|
@ -504,7 +518,7 @@ impl ops::Sub for Value {
|
|||
Functio::Chain { functios, .. } => {
|
||||
let rhs = rhs.into_functio();
|
||||
let (a, b) = *functios;
|
||||
|
||||
|
||||
match (a == rhs, b == rhs) {
|
||||
(_, true) => a,
|
||||
(true, _) => b,
|
||||
|
|
Loading…
Reference in a new issue