Implemented halfway of functio sub

pull/1/head
ondra05 2021-12-09 00:33:45 +01:00
parent d8ecfed5d5
commit 7525b434e6
3 changed files with 146 additions and 11 deletions

View File

@ -17,7 +17,6 @@
//! [`interpret_with_output`]: Interpreter::interpret_with_output
#![deny(missing_docs)]
// Putting this here because we still don't use the entire capabilities of this module. ~~Alex
#![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
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)]
/// A brainfuck interpreter. Read the [module level documentation](self) for more
pub struct Interpreter<'a, I> {

View File

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

View File

@ -5,7 +5,7 @@ use std::{
use rand::Rng;
use crate::{ast::Stmt, consts};
use crate::{ast::Stmt, brian::INSTRUCTION_MAPPINGS, consts};
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum Abool {
@ -44,9 +44,19 @@ pub enum Functio {
params: Vec<String>,
body: Vec<Stmt>,
},
Chain {
functios: Box<(Functio, Functio)>,
kind: FunctioChainKind,
},
Eval(String),
}
#[derive(Debug, PartialEq, Copy, Clone, Hash)]
pub enum FunctioChainKind {
Ordered,
Interlaced,
}
pub type Cart = HashMap<Value, Rc<RefCell<Value>>>;
#[derive(Debug, Clone)]
@ -107,8 +117,20 @@ impl Value {
instructions,
tape_len,
} => (instructions.len() + tape_len) as _,
Functio::Able { params, body } => {
(params.len() + format!("{:?}", body).len()) as _
Functio::Able { params, body } => (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 _,
},
@ -186,6 +208,20 @@ impl Value {
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(),
},
Value::Cart(c) => {
@ -208,12 +244,11 @@ impl Value {
Value::Str(s) => Functio::Eval(s),
Value::Int(i) => Functio::Bf {
instructions: {
let instruction_mappings = b"[]+-,.<>";
std::iter::successors(Some(i as usize), |i| {
Some(i / instruction_mappings.len())
Some(i / INSTRUCTION_MAPPINGS.len())
})
.take_while(|&i| i != 0)
.map(|i| instruction_mappings[i % instruction_mappings.len()])
.map(|i| INSTRUCTION_MAPPINGS[i % INSTRUCTION_MAPPINGS.len()])
.collect()
},
tape_len: crate::brian::DEFAULT_TAPE_SIZE_LIMIT,
@ -238,7 +273,28 @@ impl Value {
Abool::Always => r#"loop{"Buy Able products!"print;}"#.to_owned(),
}),
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
}
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(),
},
Value::Cart(c) => c,
@ -348,7 +418,10 @@ impl ops::Add for Value {
Value::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.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::Bool(b) => Value::Bool(b ^ rhs.into_bool()),
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({
let rhs_cart = rhs.into_cart();
c.into_iter()
@ -405,7 +512,10 @@ impl ops::Mul for Value {
Value::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) => {
let rhsc = rhs.into_cart();
@ -514,6 +624,16 @@ impl ops::Not for Value {
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()),
}),
Value::Cart(c) => Value::Cart(
@ -597,6 +717,19 @@ impl Display for Value {
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),
},
Value::Cart(c) => {