From 656926387b7df34909edefed7adc4d3158802b48 Mon Sep 17 00:00:00 2001 From: Erin Date: Thu, 9 Dec 2021 00:33:45 +0100 Subject: [PATCH] Implemented halfway of functio sub --- ablescript/src/brian.rs | 3 +- ablescript/src/interpret.rs | 1 + ablescript/src/variables.rs | 153 +++++++++++++++++++++++++++++++++--- 3 files changed, 146 insertions(+), 11 deletions(-) diff --git a/ablescript/src/brian.rs b/ablescript/src/brian.rs index 91c7d2e..a915156 100644 --- a/ablescript/src/brian.rs +++ b/ablescript/src/brian.rs @@ -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> { diff --git a/ablescript/src/interpret.rs b/ablescript/src/interpret.rs index 23fc846..8aad7ab 100644 --- a/ablescript/src/interpret.rs +++ b/ablescript/src/interpret.rs @@ -396,6 +396,7 @@ impl ExecEnv { self.stack.pop(); res?; } + Functio::Chain { .. } => todo!(), Functio::Eval(code) => { if !args.is_empty() { return Err(Error { diff --git a/ablescript/src/variables.rs b/ablescript/src/variables.rs index e1f4459..ffe4cbf 100644 --- a/ablescript/src/variables.rs +++ b/ablescript/src/variables.rs @@ -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, body: Vec, }, + Chain { + functios: Box<(Functio, Functio)>, + kind: FunctioChainKind, + }, Eval(String), } +#[derive(Debug, PartialEq, Copy, Clone, Hash)] +pub enum FunctioChainKind { + Ordered, + Interlaced, +} + pub type Cart = HashMap>>; #[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::>(); + 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) => {