Implemented halfway of functio sub

This commit is contained in:
Erin 2021-12-09 00:33:45 +01:00 committed by ondra05
parent 3c98caf2d6
commit 3bfe600103
3 changed files with 146 additions and 11 deletions

View file

@ -17,7 +17,6 @@
//! [`interpret_with_output`]: Interpreter::interpret_with_output //! [`interpret_with_output`]: Interpreter::interpret_with_output
#![deny(missing_docs)] #![deny(missing_docs)]
// Putting this here because we still don't use the entire capabilities of this module. ~~Alex // Putting this here because we still don't use the entire capabilities of this module. ~~Alex
#![allow(dead_code)] #![allow(dead_code)]
@ -33,6 +32,8 @@ use std::{
/// The default limit for the tape size. This is the value used by methods that don't take it as a parameter /// The default limit for the tape size. This is the value used by methods that don't take it as a parameter
pub const DEFAULT_TAPE_SIZE_LIMIT: usize = 30_000; pub const DEFAULT_TAPE_SIZE_LIMIT: usize = 30_000;
/// Mappings from integers to BF instructions
pub const INSTRUCTION_MAPPINGS: &[u8] = b"[]+-,.<>";
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
/// A brainfuck interpreter. Read the [module level documentation](self) for more /// A brainfuck interpreter. Read the [module level documentation](self) for more
pub struct Interpreter<'a, I> { pub struct Interpreter<'a, I> {

View file

@ -396,6 +396,7 @@ impl ExecEnv {
self.stack.pop(); self.stack.pop();
res?; res?;
} }
Functio::Chain { .. } => todo!(),
Functio::Eval(code) => { Functio::Eval(code) => {
if !args.is_empty() { if !args.is_empty() {
return Err(Error { return Err(Error {

View file

@ -5,7 +5,7 @@ use std::{
use rand::Rng; use rand::Rng;
use crate::{ast::Stmt, consts}; use crate::{ast::Stmt, brian::INSTRUCTION_MAPPINGS, consts};
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum Abool { pub enum Abool {
@ -44,9 +44,19 @@ pub enum Functio {
params: Vec<String>, params: Vec<String>,
body: Vec<Stmt>, body: Vec<Stmt>,
}, },
Chain {
functios: Box<(Functio, Functio)>,
kind: FunctioChainKind,
},
Eval(String), Eval(String),
} }
#[derive(Debug, PartialEq, Copy, Clone, Hash)]
pub enum FunctioChainKind {
Ordered,
Interlaced,
}
pub type Cart = HashMap<Value, Rc<RefCell<Value>>>; pub type Cart = HashMap<Value, Rc<RefCell<Value>>>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -107,8 +117,20 @@ impl Value {
instructions, instructions,
tape_len, tape_len,
} => (instructions.len() + tape_len) as _, } => (instructions.len() + tape_len) as _,
Functio::Able { params, body } => { Functio::Able { params, body } => (params.len() + format!("{:?}", body).len()) as _,
(params.len() + format!("{:?}", body).len()) as _ Functio::Chain { functios, kind } => {
let (lhs, rhs) = *functios;
match kind {
FunctioChainKind::Ordered => {
Value::Int(Value::Functio(lhs).into_i32())
+ Value::Int(Value::Functio(rhs).into_i32())
}
FunctioChainKind::Interlaced => {
Value::Int(Value::Functio(lhs).into_i32())
* Value::Int(Value::Functio(rhs).into_i32())
}
}
.into_i32()
} }
Functio::Eval(s) => s.len() as _, Functio::Eval(s) => s.len() as _,
}, },
@ -186,6 +208,20 @@ impl Value {
Value::Int((params + body) % 3 - 1).into_abool() Value::Int((params + body) % 3 - 1).into_abool()
} }
Functio::Chain { functios, kind } => {
let (lhs, rhs) = *functios;
match kind {
FunctioChainKind::Ordered => {
Value::Abool(Value::Functio(lhs).into_abool())
+ Value::Abool(Value::Functio(rhs).into_abool())
}
FunctioChainKind::Interlaced => {
Value::Abool(Value::Functio(lhs).into_abool())
* Value::Abool(Value::Functio(rhs).into_abool())
}
}
.into_abool()
}
Functio::Eval(code) => Value::Str(code).into_abool(), Functio::Eval(code) => Value::Str(code).into_abool(),
}, },
Value::Cart(c) => { Value::Cart(c) => {
@ -208,12 +244,11 @@ impl Value {
Value::Str(s) => Functio::Eval(s), Value::Str(s) => Functio::Eval(s),
Value::Int(i) => Functio::Bf { Value::Int(i) => Functio::Bf {
instructions: { instructions: {
let instruction_mappings = b"[]+-,.<>";
std::iter::successors(Some(i as usize), |i| { std::iter::successors(Some(i as usize), |i| {
Some(i / instruction_mappings.len()) Some(i / INSTRUCTION_MAPPINGS.len())
}) })
.take_while(|&i| i != 0) .take_while(|&i| i != 0)
.map(|i| instruction_mappings[i % instruction_mappings.len()]) .map(|i| INSTRUCTION_MAPPINGS[i % INSTRUCTION_MAPPINGS.len()])
.collect() .collect()
}, },
tape_len: crate::brian::DEFAULT_TAPE_SIZE_LIMIT, tape_len: crate::brian::DEFAULT_TAPE_SIZE_LIMIT,
@ -238,7 +273,28 @@ impl Value {
Abool::Always => r#"loop{"Buy Able products!"print;}"#.to_owned(), Abool::Always => r#"loop{"Buy Able products!"print;}"#.to_owned(),
}), }),
Value::Functio(f) => f, Value::Functio(f) => f,
Value::Cart(_) => todo!(), Value::Cart(c) => {
let kind = if let Some(114514) = c
.get(&Value::Str("1452251871514141792252515212116".to_owned()))
.map(|x| x.borrow().to_owned().into_i32())
{
FunctioChainKind::Ordered
} else {
FunctioChainKind::Interlaced
};
let mut cart_vec = c.iter().collect::<Vec<_>>();
cart_vec.sort_by(|x, y| x.0.partial_cmp(y.0).unwrap_or(std::cmp::Ordering::Less));
cart_vec
.into_iter()
.map(|(_, x)| x.borrow().to_owned().into_functio())
.reduce(|acc, x| Functio::Chain {
functios: Box::new((acc, x)),
kind,
})
.unwrap_or_else(|| Functio::Eval(r#""Buy Able Products!"print;"#.to_owned()))
}
} }
} }
@ -321,6 +377,20 @@ impl Value {
); );
cart cart
} }
Functio::Chain { functios, kind } => {
let (lhs, rhs) = *functios;
match kind {
FunctioChainKind::Ordered => {
Value::Cart(Value::Functio(lhs).into_cart())
+ Value::Cart(Value::Functio(rhs).into_cart())
}
FunctioChainKind::Interlaced => {
Value::Cart(Value::Functio(lhs).into_cart())
* Value::Cart(Value::Functio(rhs).into_cart())
}
}
.into_cart()
}
Functio::Eval(s) => Value::Str(s).into_cart(), Functio::Eval(s) => Value::Str(s).into_cart(),
}, },
Value::Cart(c) => c, Value::Cart(c) => c,
@ -348,7 +418,10 @@ impl ops::Add for Value {
Value::Abool(_) => { Value::Abool(_) => {
Value::Abool(Value::Int(self.into_i32().max(rhs.into_i32())).into_abool()) Value::Abool(Value::Int(self.into_i32().max(rhs.into_i32())).into_abool())
} }
Value::Functio(_) => todo!(), Value::Functio(f) => Value::Functio(Functio::Chain {
functios: Box::new((f, rhs.into_functio())),
kind: FunctioChainKind::Ordered,
}),
Value::Cart(c) => { Value::Cart(c) => {
Value::Cart(c.into_iter().chain(rhs.into_cart().into_iter()).collect()) Value::Cart(c.into_iter().chain(rhs.into_cart().into_iter()).collect())
} }
@ -374,7 +447,41 @@ impl ops::Sub for Value {
Value::Int(i) => Value::Int(i.wrapping_sub(rhs.into_i32())), Value::Int(i) => Value::Int(i.wrapping_sub(rhs.into_i32())),
Value::Bool(b) => Value::Bool(b ^ rhs.into_bool()), Value::Bool(b) => Value::Bool(b ^ rhs.into_bool()),
Value::Abool(_) => (self.clone() + rhs.clone()) * !(self * rhs), Value::Abool(_) => (self.clone() + rhs.clone()) * !(self * rhs),
Value::Functio(_) => todo!(), Value::Functio(f) => Value::Functio(match f {
Functio::Bf {
instructions: lhs_ins,
tape_len: lhs_tl,
} => match rhs.into_functio() {
Functio::Bf {
instructions: rhs_ins,
tape_len: rhs_tl,
} => Functio::Bf {
instructions: lhs_ins
.into_iter()
.zip(rhs_ins.into_iter())
.filter_map(|(l, r)| if l != r { Some(l) } else { None })
.collect(),
tape_len: lhs_tl - rhs_tl,
},
rhs => Functio::Bf {
instructions: lhs_ins
.into_iter()
.zip(Value::Functio(rhs).to_string().bytes())
.filter_map(|(l, r)| if l != r { Some(l) } else { None })
.collect(),
tape_len: lhs_tl,
},
},
Functio::Able { params, body } => todo!(),
Functio::Chain { functios, kind } => todo!(),
Functio::Eval(lhs_code) => Functio::Eval(lhs_code.replace(
&match rhs.into_functio() {
Functio::Eval(code) => code,
rhs => Value::Functio(rhs).to_string(),
},
"",
)),
}),
Value::Cart(c) => Value::Cart({ Value::Cart(c) => Value::Cart({
let rhs_cart = rhs.into_cart(); let rhs_cart = rhs.into_cart();
c.into_iter() c.into_iter()
@ -405,7 +512,10 @@ impl ops::Mul for Value {
Value::Abool(_) => { Value::Abool(_) => {
Value::Abool(Value::Int(self.into_i32().min(rhs.into_i32())).into_abool()) Value::Abool(Value::Int(self.into_i32().min(rhs.into_i32())).into_abool())
} }
Value::Functio(_) => todo!(), Value::Functio(f) => Value::Functio(Functio::Chain {
functios: Box::new((f, rhs.into_functio())),
kind: FunctioChainKind::Interlaced,
}),
Value::Cart(c) => { Value::Cart(c) => {
let rhsc = rhs.into_cart(); let rhsc = rhs.into_cart();
@ -514,6 +624,16 @@ impl ops::Not for Value {
Functio::Able { params, body } Functio::Able { params, body }
} }
Functio::Chain { functios, kind } => {
let (a, b) = *functios;
Functio::Chain {
functios: Box::new((
(!Value::Functio(b)).into_functio(),
(!Value::Functio(a)).into_functio(),
)),
kind,
}
}
Functio::Eval(code) => Functio::Eval(code.chars().rev().collect()), Functio::Eval(code) => Functio::Eval(code.chars().rev().collect()),
}), }),
Value::Cart(c) => Value::Cart( Value::Cart(c) => Value::Cart(
@ -597,6 +717,19 @@ impl Display for Value {
body, body,
) )
} }
Functio::Chain { functios, kind } => {
let (a, b) = *functios.clone();
write!(
f,
"{} {} {} ",
Value::Functio(a),
match kind {
FunctioChainKind::Ordered => '+',
FunctioChainKind::Interlaced => '*',
},
Value::Functio(b)
)
}
Functio::Eval(s) => write!(f, "{}", s), Functio::Eval(s) => write!(f, "{}", s),
}, },
Value::Cart(c) => { Value::Cart(c) => {