forked from AbleScript/ablescript
Implemented halfway of functio sub
This commit is contained in:
parent
3c98caf2d6
commit
3bfe600103
|
@ -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> {
|
||||
|
|
|
@ -396,6 +396,7 @@ impl ExecEnv {
|
|||
self.stack.pop();
|
||||
res?;
|
||||
}
|
||||
Functio::Chain { .. } => todo!(),
|
||||
Functio::Eval(code) => {
|
||||
if !args.is_empty() {
|
||||
return Err(Error {
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in a new issue