forked from AbleScript/ablescript
Implemented halfway of functio sub
This commit is contained in:
parent
920ff99a7f
commit
656926387b
|
@ -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> {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
Loading…
Reference in a new issue