- Option for different integer types for stack and funge-space, funge-space position still isize.
- Bugfix in skipping a step.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rusty_funge"
|
name = "rusty_funge"
|
||||||
version = "2022.12.2"
|
version = "2022.12.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
@@ -10,3 +10,4 @@ clap = { version = "4.0.29", features = ["derive"] }
|
|||||||
chrono = "0.4.23"
|
chrono = "0.4.23"
|
||||||
cursive = { version = "0.20.0", features = ["termion-backend"] }
|
cursive = { version = "0.20.0", features = ["termion-backend"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
num = "0.4.0"
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/usr/bin/env rusty_funge
|
#!/usr/bin/env rusty_funge
|
||||||
00gg00@
|
zz; ;zz#r#;1jr1j;zz@
|
||||||
33
src/debug.rs
33
src/debug.rs
@@ -1,23 +1,20 @@
|
|||||||
use std::cmp::{min, max};
|
use std::cmp::{min, max};
|
||||||
use std::error::Error;
|
use std::{error::Error, time::Duration};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread::{sleep, spawn};
|
use std::thread::{sleep, spawn};
|
||||||
use std::time::Duration;
|
use cursive::{Cursive, CursiveExt, Printer, Vec2};
|
||||||
use cursive::{Cursive, CursiveExt, Vec2};
|
use cursive::{theme::ColorStyle, view::View};
|
||||||
use cursive::view::View;
|
|
||||||
use cursive::Printer;
|
|
||||||
use cursive::event::{Event, EventResult};
|
use cursive::event::{Event, EventResult};
|
||||||
use cursive::theme::ColorStyle;
|
use rusty_funge::{Int, Funge};
|
||||||
use crate::Funge;
|
|
||||||
|
|
||||||
|
|
||||||
struct FungeMutex {
|
struct FungeMutex<I: Int> {
|
||||||
funge: Option<Funge>
|
funge: Option<Funge<I>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FungeMutex {
|
impl<I: Int> FungeMutex<I> {
|
||||||
fn new(funge: Funge) -> Self {
|
fn new(funge: Funge<I>) -> Self {
|
||||||
Self { funge: Some(funge) }
|
Self { funge: Some(funge) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,24 +28,24 @@ impl FungeMutex {
|
|||||||
Ok(terminated)
|
Ok(terminated)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn funge_ref(&self) -> Option<&Funge> {
|
fn funge_ref(&self) -> Option<&Funge<I>> {
|
||||||
self.funge.as_ref()
|
self.funge.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FungeMutex {
|
impl<I: Int> Display for FungeMutex<I> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.funge.as_ref().expect("No funge found"))
|
write!(f, "{}", self.funge.as_ref().expect("No funge found"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub(crate) struct FungeView {
|
pub(crate) struct FungeView<I: Int> {
|
||||||
funge: Arc<Mutex<FungeMutex>>
|
funge: Arc<Mutex<FungeMutex<I>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FungeView {
|
impl<I: Int> FungeView<I> {
|
||||||
pub (crate) fn new(funge: Funge) -> Result<Self, Box<dyn Error>> {
|
pub (crate) fn new(funge: Funge<I>) -> Result<Self, Box<dyn Error>> {
|
||||||
Ok(FungeView { funge: Arc::new(Mutex::new(FungeMutex::new(funge.with_output()?))) } )
|
Ok(FungeView { funge: Arc::new(Mutex::new(FungeMutex::new(funge.with_output()?))) } )
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +83,7 @@ impl FungeView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for FungeView {
|
impl<I: Int> View for FungeView<I> {
|
||||||
fn draw(&self, printer: &Printer) {
|
fn draw(&self, printer: &Printer) {
|
||||||
let (text, ips_pos, terminated) = {
|
let (text, ips_pos, terminated) = {
|
||||||
let lock = self.funge.lock();
|
let lock = self.funge.lock();
|
||||||
|
|||||||
365
src/lib.rs
365
src/lib.rs
@@ -1,15 +1,19 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{env, fs, fmt, fmt::{Debug, Display, Formatter}};
|
use std::{env, fs, fmt, fmt::{Debug, Display, Formatter}};
|
||||||
use std::io::stdin;
|
use std::ops::{Add, Deref, DerefMut, Index, IndexMut, Sub};
|
||||||
use std::ops::{Deref, DerefMut, Index, IndexMut};
|
use std::{error::Error, hash::Hash, path::Path, str::FromStr, io::stdin};
|
||||||
use std::{error::Error, hash::Hash, path::Path};
|
|
||||||
use chrono::{offset::Local, {Datelike, Timelike}};
|
use chrono::{offset::Local, {Datelike, Timelike}};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use num::{Integer, NumCast};
|
||||||
|
|
||||||
|
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
|
||||||
|
pub trait Int: Integer + NumCast + FromStr + Hash + Clone + Copy + Sync + Send + Display + 'static {}
|
||||||
|
impl<I: Integer + NumCast + FromStr + Hash + Clone + Copy + Sync + Send + Display + 'static> Int for I {}
|
||||||
|
|
||||||
|
|
||||||
fn join<T: ToString>(v: &Vec<T>, s: &str) -> String {
|
fn join<T: ToString>(v: &Vec<T>, s: &str) -> String {
|
||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
if v.len() > 1 {
|
if v.len() > 1 {
|
||||||
@@ -24,19 +28,34 @@ fn join<T: ToString>(v: &Vec<T>, s: &str) -> String {
|
|||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ord(c: char) -> Result<isize, Box<dyn Error>> {
|
fn cast_int<I: NumCast, J: NumCast>(j: J) -> Result<I, Box<dyn Error>> {
|
||||||
Ok(u32::try_from(c)?.try_into()?)
|
Ok(I::from(j).ok_or("Could not convert from primitive")?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chr(i: isize) -> Result<char, Box<dyn Error>> {
|
fn cast_vec_int<I: NumCast, J: NumCast>(j: Vec<J>) -> Result<Vec<I>, Box<dyn Error>> {
|
||||||
Ok(u32::try_from(i)?.try_into()?)
|
let mut i = Vec::<I>::new();
|
||||||
|
for n in j {
|
||||||
|
i.push(cast_int(n)?);
|
||||||
|
}
|
||||||
|
Ok(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(a: &Vec<isize>, b: &Vec<isize>) -> Vec<isize> {
|
fn ord<I: NumCast>(c: char) -> Result<I, Box<dyn Error>>
|
||||||
|
{
|
||||||
|
Ok(cast_int::<_, u32>(c.try_into()?)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn chr<I: NumCast>(i: I) -> Result<char, Box<dyn Error>> {
|
||||||
|
Ok(cast_int::<u32, _>(i)?.try_into()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add<I: Add + Copy>(a: &Vec<I>, b: &Vec<I>) -> Vec<I> where
|
||||||
|
Vec<I>: FromIterator<<I as Add>::Output> {
|
||||||
a.iter().zip(b.iter()).map(|(&a, &b)| a + b).collect()
|
a.iter().zip(b.iter()).map(|(&a, &b)| a + b).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sub(a: &Vec<isize>, b: &Vec<isize>) -> Vec<isize> {
|
fn sub<I: Sub + Copy>(a: &Vec<I>, b: &Vec<I>) -> Vec<I> where
|
||||||
|
Vec<I>: FromIterator<<I as Sub>::Output> {
|
||||||
a.iter().zip(b.iter()).map(|(&a, &b)| a - b).collect()
|
a.iter().zip(b.iter()).map(|(&a, &b)| a - b).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,38 +107,38 @@ impl Output {
|
|||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Stack {
|
struct Stack<I: Int> {
|
||||||
stack: Vec<isize>
|
stack: Vec<I>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Stack {
|
impl<I: Int> Stack<I> {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self { stack: Vec::new() }
|
Self { stack: Vec::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> isize {
|
fn pop(&mut self) -> I {
|
||||||
match self.stack.pop() {
|
match self.stack.pop() {
|
||||||
Some(value) => { value }
|
Some(value) => { value }
|
||||||
None => { 0 }
|
None => { I::zero() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, cell: isize) {
|
fn push(&mut self, cell: I) {
|
||||||
self.stack.push(cell)
|
self.stack.push(cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize { self.stack.len() }
|
fn len(&self) -> usize { self.stack.len() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Stack {
|
impl<I: Int> Display for Stack<I> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "[{}]", join(&self.stack, ", "))
|
write!(f, "[{}]", join(&self.stack, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for Stack {
|
impl<I: Int> Index<usize> for Stack<I> {
|
||||||
type Output = isize;
|
type Output = I;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
&self.stack[index]
|
&self.stack[index]
|
||||||
@@ -127,11 +146,11 @@ impl Index<usize> for Stack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct StackStack {
|
struct StackStack<I: Int> {
|
||||||
stackstack: Vec<Stack>
|
stackstack: Vec<Stack<I>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackStack {
|
impl<I: Int> StackStack<I> {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self { stackstack: vec![Stack::new()] }
|
Self { stackstack: vec![Stack::new()] }
|
||||||
}
|
}
|
||||||
@@ -142,26 +161,26 @@ impl StackStack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> isize {
|
fn pop(&mut self) -> I {
|
||||||
self.check_stack();
|
self.check_stack();
|
||||||
let x = self.len_stack();
|
let x = self.len_stack();
|
||||||
self.stackstack[x - 1].pop()
|
self.stackstack[x - 1].pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, cell: isize) {
|
fn push(&mut self, cell: I) {
|
||||||
self.check_stack();
|
self.check_stack();
|
||||||
let x = self.len_stack();
|
let x = self.len_stack();
|
||||||
self.stackstack[x - 1].push(cell);
|
self.stackstack[x - 1].push(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_stack(&mut self) -> Stack {
|
fn pop_stack(&mut self) -> Stack<I> {
|
||||||
match self.stackstack.pop() {
|
match self.stackstack.pop() {
|
||||||
Some(stack) => { stack }
|
Some(stack) => { stack }
|
||||||
None => { Stack::new() }
|
None => { Stack::new() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_stack(&mut self, stack: Stack) {
|
fn push_stack(&mut self, stack: Stack<I>) {
|
||||||
self.stackstack.push(stack)
|
self.stackstack.push(stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,21 +207,21 @@ impl StackStack {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for StackStack {
|
impl<I: Int> Index<usize> for StackStack<I> {
|
||||||
type Output = Stack;
|
type Output = Stack<I>;
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
&self.stackstack[index]
|
&self.stackstack[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<usize> for StackStack {
|
impl<I: Int> IndexMut<usize> for StackStack<I> {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
&mut self.stackstack[index]
|
&mut self.stackstack[index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for StackStack {
|
impl<I: Int> Display for StackStack<I> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", join(&self.stackstack, "\n"))
|
write!(f, "{}", join(&self.stackstack, "\n"))
|
||||||
}
|
}
|
||||||
@@ -210,19 +229,19 @@ impl Display for StackStack {
|
|||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct IP {
|
struct IP<I: Int> {
|
||||||
id: usize,
|
id: usize,
|
||||||
position: Vec<isize>,
|
position: Vec<isize>,
|
||||||
delta: Vec<isize>,
|
delta: Vec<isize>,
|
||||||
offset: Vec<isize>,
|
offset: Vec<isize>,
|
||||||
string: bool,
|
string: bool,
|
||||||
stack: StackStack,
|
stack: StackStack<I>,
|
||||||
fingerprint_ops: HashMap<isize, ()>,
|
fingerprint_ops: HashMap<I, ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl IP {
|
impl<I: Int> IP<I> {
|
||||||
fn new(funge: &Funge) -> Result<Self, Box<dyn Error>> {
|
fn new(funge: &Funge<I>) -> Result<Self, Box<dyn Error>> {
|
||||||
let mut new = IP {
|
let mut new = IP {
|
||||||
id: funge.ips.len(),
|
id: funge.ips.len(),
|
||||||
position: vec![0, 0],
|
position: vec![0, 0],
|
||||||
@@ -232,13 +251,13 @@ impl IP {
|
|||||||
stack: StackStack::new(),
|
stack: StackStack::new(),
|
||||||
fingerprint_ops: HashMap::new()
|
fingerprint_ops: HashMap::new()
|
||||||
};
|
};
|
||||||
if (new.op(funge) == ord(' ')?) | (new.op(funge) == ord(';')?) {
|
if let Ok(32 | 59) = cast_int(new.op(funge)) {
|
||||||
new.advance(funge);
|
new.advance(funge)?;
|
||||||
};
|
};
|
||||||
Ok(new)
|
Ok(new)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy(&self, funge: &Funge) -> Self {
|
fn copy(&self, funge: &Funge<I>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: funge.ips.len(),
|
id: funge.ips.len(),
|
||||||
position: self.position.to_owned(),
|
position: self.position.to_owned(),
|
||||||
@@ -250,7 +269,7 @@ impl IP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn op(&self, funge: &Funge) -> isize {
|
fn op(&self, funge: &Funge<I>) -> I {
|
||||||
funge.code[&self.position]
|
funge.code[&self.position]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,10 +285,12 @@ impl IP {
|
|||||||
self.delta = vec![self.delta[1], -self.delta[0]];
|
self.delta = vec![self.delta[1], -self.delta[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance(&mut self, funge: &Funge) {
|
fn advance(&mut self, funge: &Funge<I>) -> Result<(), Box<dyn Error>> {
|
||||||
if self.string {
|
let space: I = cast_int(32)?;
|
||||||
if funge.code[&self.position] == 32 {
|
let semicolon: I = cast_int(59)?;
|
||||||
while funge.code[&self.position] == 32 {
|
Ok(if self.string {
|
||||||
|
if self.op(funge) == space {
|
||||||
|
while self.op(funge) == space {
|
||||||
self.movep(funge)
|
self.movep(funge)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -277,36 +298,44 @@ impl IP {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
if self.op(funge) != 59 {
|
if self.op(funge) != semicolon {
|
||||||
self.movep(funge)
|
self.movep(funge)
|
||||||
}
|
}
|
||||||
if self.op(funge) == 59 {
|
if self.op(funge) == semicolon {
|
||||||
self.movep(funge);
|
self.movep(funge);
|
||||||
while self.op(funge) == 59 {
|
while self.op(funge) != semicolon {
|
||||||
self.movep(funge)
|
self.movep(funge)
|
||||||
}
|
}
|
||||||
self.movep(funge)
|
self.movep(funge)
|
||||||
}
|
}
|
||||||
while self.op(funge) == 32 {
|
while self.op(funge) == space {
|
||||||
self.movep(funge)
|
self.movep(funge)
|
||||||
}
|
}
|
||||||
if self.op(funge) != 59 {
|
if self.op(funge) != semicolon {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn movep(&mut self, funge: &Funge) {
|
fn movep(&mut self, funge: &Funge<I>) {
|
||||||
self.position = self.next_pos(funge);
|
self.position = self.next_pos(funge);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pos(&self, pos: &Vec<isize>, funge: &Funge) -> bool {
|
fn skip(mut self, funge: Funge<I>) -> Result<(Funge<I>, Option<Vec<Self>>), Box<dyn Error>> {
|
||||||
|
self.movep(&funge);
|
||||||
|
if let Ok(32 | 59) = cast_int(self.op(&funge)) {
|
||||||
|
self.advance(&funge)?;
|
||||||
|
};
|
||||||
|
return Ok((funge, Some(vec![self])))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_pos(&self, pos: &Vec<isize>, funge: &Funge<I>) -> bool {
|
||||||
(funge.extent[0] <= pos[0]) & (pos[0] < funge.extent[1]) &
|
(funge.extent[0] <= pos[0]) & (pos[0] < funge.extent[1]) &
|
||||||
(funge.extent[2] <= pos[1]) & (pos[1] < funge.extent[3])
|
(funge.extent[2] <= pos[1]) & (pos[1] < funge.extent[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_pos(&self, funge: &Funge) -> Vec<isize> {
|
fn next_pos(&self, funge: &Funge<I>) -> Vec<isize> {
|
||||||
let mut pos= add(&self.position, &self.delta);
|
let mut pos= add(&self.position, &self.delta);
|
||||||
if !self.check_pos(&pos, funge) {
|
if !self.check_pos(&pos, funge) {
|
||||||
loop {
|
loop {
|
||||||
@@ -324,7 +353,7 @@ impl IP {
|
|||||||
let mut string = String::new();
|
let mut string = String::new();
|
||||||
loop {
|
loop {
|
||||||
let f = self.stack.pop();
|
let f = self.stack.pop();
|
||||||
if f == 0 {
|
if f == I::zero() {
|
||||||
return Ok(string)
|
return Ok(string)
|
||||||
} else {
|
} else {
|
||||||
string.push_str(&chr(f)?.to_string())
|
string.push_str(&chr(f)?.to_string())
|
||||||
@@ -332,36 +361,38 @@ impl IP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_info(&self, funge: &Funge, n: isize) -> Result<Vec<isize>, Box<dyn Error>> {
|
fn get_info(&self, funge: &Funge<I>, n: I) -> Result<Vec<I>, Box<dyn Error>> {
|
||||||
let time = Local::now();
|
let time = Local::now();
|
||||||
|
match n.to_usize() {
|
||||||
|
Some(n @ 1..=20) => {
|
||||||
Ok(match n {
|
Ok(match n {
|
||||||
1 => { vec![15] }
|
1 => vec![cast_int(15)?],
|
||||||
2 => { vec![isize::BITS as isize] }
|
2 => vec![cast_int(8 * std::mem::size_of::<I>())?],
|
||||||
3 => {
|
3 => {
|
||||||
let mut f = 0;
|
let mut f = 0;
|
||||||
for (i, c) in "wprustyfunge".chars().enumerate() {
|
for (i, c) in "wprustyfunge".chars().enumerate() {
|
||||||
f += (256 as isize).pow(i as u32) * ord(c)?;
|
f += (256 as isize).pow(i as u32) * ord::<isize>(c)?;
|
||||||
}
|
}
|
||||||
vec![f]
|
vec![cast_int(f)?]
|
||||||
}
|
}
|
||||||
4 => vec![VERSION.replace(".", "").parse()?],
|
4 => vec![cast_int(VERSION.replace(".", "").parse::<isize>()?)?],
|
||||||
5 => vec![1],
|
5 => vec![I::one()],
|
||||||
6 => vec![ord(std::path::MAIN_SEPARATOR)?],
|
6 => vec![ord(std::path::MAIN_SEPARATOR)?],
|
||||||
7 => vec![2],
|
7 => vec![cast_int(2)?],
|
||||||
8 => vec![*&self.id as isize],
|
8 => vec![cast_int(*&self.id)?],
|
||||||
9 => vec![0],
|
9 => vec![I::zero()],
|
||||||
10 => self.position.to_owned(),
|
10 => cast_vec_int(self.position.to_owned())?,
|
||||||
11 => self.delta.to_owned(),
|
11 => cast_vec_int(self.delta.to_owned())?,
|
||||||
12 => self.offset.to_owned(),
|
12 => cast_vec_int(self.offset.to_owned())?,
|
||||||
13 => funge.extent.chunks(2).map(|i| i[0]).collect(),
|
13 => cast_vec_int(funge.extent.chunks(2).map(|i| i[0]).collect())?,
|
||||||
14 => funge.extent.chunks(2).map(|i| i[1]).collect(),
|
14 => cast_vec_int(funge.extent.chunks(2).map(|i| i[1]).collect())?,
|
||||||
15 => vec![((time.year() as isize) - 1900) * 256 * 256 + (time.month() as isize) * 256 + (time.day() as isize)],
|
15 => vec![cast_int((time.year() - 1900) * 256 * 256 + (time.month() as i32) * 256 + (time.day() as i32))?],
|
||||||
16 => vec![(time.hour() as isize) * 256 * 256 + (time.minute() as isize) * 256 + (time.second() as isize)],
|
16 => vec![cast_int(time.hour() * 256 * 256 + time.minute() * 256 + time.second())?],
|
||||||
17 => vec![self.stack.len_stack() as isize],
|
17 => vec![cast_int(self.stack.len_stack())?],
|
||||||
18 => {
|
18 => {
|
||||||
let mut l = Vec::new();
|
let mut l = Vec::new();
|
||||||
for stack in &self.stack.stackstack {
|
for stack in &self.stack.stackstack {
|
||||||
l.push(stack.len() as isize);
|
l.push(cast_int(stack.len())?);
|
||||||
}
|
}
|
||||||
l.reverse();
|
l.reverse();
|
||||||
l
|
l
|
||||||
@@ -371,20 +402,20 @@ impl IP {
|
|||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
if args.len() > 1 {
|
if args.len() > 1 {
|
||||||
for i in 1..args.len() {
|
for i in 1..args.len() {
|
||||||
let j: Vec<isize> = args[i].chars().map(|i| ord(i).expect("")).collect();
|
let j: Vec<I> = args[i].chars().map(|i| ord(i).expect("")).collect();
|
||||||
r.extend(j);
|
r.extend(j);
|
||||||
r.push(0);
|
r.push(I::zero());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.push(0);
|
r.push(I::zero());
|
||||||
let file = &args[0];
|
let file = &args[0];
|
||||||
let path = Path::new(&file);
|
let path = Path::new(&file);
|
||||||
let j: Vec<isize> = path.file_name().ok_or("No file name.")?
|
let j: Vec<I> = path.file_name().ok_or("No file name.")?
|
||||||
.to_str().ok_or("Cannot convert String.")?
|
.to_str().ok_or("Cannot convert String.")?
|
||||||
.chars().map(|i| ord(i).expect("")).collect();
|
.chars().map(|i| ord(i).expect("")).collect();
|
||||||
r.extend(j);
|
r.extend(j);
|
||||||
r.push(0);
|
r.push(I::zero());
|
||||||
r.push(0);
|
r.push(I::zero());
|
||||||
r.reverse();
|
r.reverse();
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
@@ -392,14 +423,14 @@ impl IP {
|
|||||||
let mut r = Vec::new();
|
let mut r = Vec::new();
|
||||||
let vars = env::vars();
|
let vars = env::vars();
|
||||||
for (key, value) in vars {
|
for (key, value) in vars {
|
||||||
let j: Vec<isize> = key.chars().map(|i| ord(i).expect("")).collect();
|
let j: Vec<I> = key.chars().map(|i| ord(i).expect("")).collect();
|
||||||
r.extend(j);
|
r.extend(j);
|
||||||
r.push(ord('=')?);
|
r.push(ord('=')?);
|
||||||
let j: Vec<isize> = value.chars().map(|i| ord(i).expect("")).collect();
|
let j: Vec<I> = value.chars().map(|i| ord(i).expect("")).collect();
|
||||||
r.extend(j);
|
r.extend(j);
|
||||||
r.push(0);
|
r.push(I::zero());
|
||||||
}
|
}
|
||||||
r.push(0);
|
r.push(I::zero());
|
||||||
r.reverse();
|
r.reverse();
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
@@ -409,28 +440,38 @@ impl IP {
|
|||||||
if l >= j {
|
if l >= j {
|
||||||
vec![self.stack.stackstack[0][l - j]]
|
vec![self.stack.stackstack[0][l - j]]
|
||||||
} else {
|
} else {
|
||||||
vec![0]
|
vec![I::zero()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
// TODO: return Error
|
||||||
|
println!("{}", "Stack size overflow");
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn not_implemented(&mut self, funge: &Funge) {
|
fn not_implemented(&mut self, funge: &Funge<I>) {
|
||||||
|
// TODO: reverse or quit option
|
||||||
println!("operator {} at {} not implemented", self.op(funge), join(&self.position, ", "));
|
println!("operator {} at {} not implemented", self.op(funge), join(&self.position, ", "));
|
||||||
self.reverse()
|
self.reverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(mut self, mut funge: Funge, k: bool) -> Result<(Funge, Option<Vec<Self>>), Box<dyn Error>> {
|
fn step(mut self, mut funge: Funge<I>, k: bool) -> Result<(Funge<I>, Option<Vec<Self>>), Box<dyn Error>> {
|
||||||
let mut new_ips = Vec::new();
|
let mut new_ips = Vec::new();
|
||||||
|
let op = self.op(&funge);
|
||||||
|
let op8 = op.to_u8();
|
||||||
if self.string {
|
if self.string {
|
||||||
match self.op(&funge) {
|
match op8 {
|
||||||
34 => { self.string = false } // '
|
Some(34) => { self.string = false } // "
|
||||||
s => { self.stack.push(s) }
|
_ => { self.stack.push(op) }
|
||||||
}
|
}
|
||||||
} else if self.fingerprint_ops.contains_key(&self.op(&funge)) {
|
} else if self.fingerprint_ops.contains_key(&op) {
|
||||||
// self.fingerprint_ops[self.op(funge)]?
|
// self.fingerprint_ops[self.op(funge)]?
|
||||||
} else if (0 <= self.op(&funge)) & (self.op(&funge) < 255) {
|
} else if let Some(0..=255) = op8 {
|
||||||
match self.op(&funge) {
|
match op8.expect("Could not convert.") {
|
||||||
43 => { // +
|
43 => { // +
|
||||||
let b = self.stack.pop();
|
let b = self.stack.pop();
|
||||||
let a = self.stack.pop();
|
let a = self.stack.pop();
|
||||||
@@ -449,8 +490,8 @@ impl IP {
|
|||||||
47 => { // /
|
47 => { // /
|
||||||
let b = self.stack.pop();
|
let b = self.stack.pop();
|
||||||
let a = self.stack.pop();
|
let a = self.stack.pop();
|
||||||
if b == 0 {
|
if b == I::zero() {
|
||||||
self.stack.push(0);
|
self.stack.push(I::zero());
|
||||||
} else {
|
} else {
|
||||||
self.stack.push(a / b);
|
self.stack.push(a / b);
|
||||||
}
|
}
|
||||||
@@ -462,16 +503,20 @@ impl IP {
|
|||||||
}
|
}
|
||||||
33 => { // !
|
33 => { // !
|
||||||
let a = self.stack.pop();
|
let a = self.stack.pop();
|
||||||
if a == 0 {
|
if a == I::zero() {
|
||||||
self.stack.push(1);
|
self.stack.push(I::one());
|
||||||
} else {
|
} else {
|
||||||
self.stack.push(0);
|
self.stack.push(I::zero());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
96 => { // `
|
96 => { // `
|
||||||
let b = self.stack.pop();
|
let b = self.stack.pop();
|
||||||
let a = self.stack.pop();
|
let a = self.stack.pop();
|
||||||
self.stack.push((a > b) as isize);
|
if a > b {
|
||||||
|
self.stack.push(I::one());
|
||||||
|
} else {
|
||||||
|
self.stack.push(I::zero());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
62 => self.delta = vec![1, 0], // >
|
62 => self.delta = vec![1, 0], // >
|
||||||
60 => self.delta = vec![-1, 0], // <
|
60 => self.delta = vec![-1, 0], // <
|
||||||
@@ -487,14 +532,14 @@ impl IP {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
95 => { // _
|
95 => { // _
|
||||||
if self.stack.pop() == 0 {
|
if self.stack.pop() == I::zero() {
|
||||||
self.delta = vec![1, 0]
|
self.delta = vec![1, 0]
|
||||||
} else {
|
} else {
|
||||||
self.delta = vec![-1, 0]
|
self.delta = vec![-1, 0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
124 => { // |
|
124 => { // |
|
||||||
if self.stack.pop() == 0 {
|
if self.stack.pop() == I::zero() {
|
||||||
self.delta = vec![0, 1];
|
self.delta = vec![0, 1];
|
||||||
} else {
|
} else {
|
||||||
self.delta = vec![0, -1];
|
self.delta = vec![0, -1];
|
||||||
@@ -515,24 +560,30 @@ impl IP {
|
|||||||
36 => { self.stack.pop(); } // $
|
36 => { self.stack.pop(); } // $
|
||||||
46 => funge.output.print(format!("{} ", self.stack.pop())), // .
|
46 => funge.output.print(format!("{} ", self.stack.pop())), // .
|
||||||
44 => funge.output.print(format!("{}", chr(self.stack.pop())?)), // ,
|
44 => funge.output.print(format!("{}", chr(self.stack.pop())?)), // ,
|
||||||
35 => self.movep(&funge), // #
|
35 => { // #
|
||||||
|
self.movep(&funge);
|
||||||
|
return self.skip(funge)
|
||||||
|
}
|
||||||
112 => { // p
|
112 => { // p
|
||||||
let y = self.stack.pop();
|
let y: isize = cast_int(self.stack.pop())?;
|
||||||
let x = self.stack.pop();
|
let x: isize = cast_int(self.stack.pop())?;
|
||||||
let v = self.stack.pop();
|
let v = self.stack.pop();
|
||||||
funge.insert(v, x + self.offset[0], y + self.offset[1]);
|
funge.insert(v, x + self.offset[0], y + self.offset[1]);
|
||||||
}
|
}
|
||||||
103 => { // g
|
103 => { // g
|
||||||
let y = self.stack.pop();
|
let y: isize = cast_int(self.stack.pop())?;
|
||||||
let x = self.stack.pop();
|
let x: isize = cast_int(self.stack.pop())?;
|
||||||
self.stack.push(funge.code[&vec![x + self.offset[0], y + self.offset[1]]]);
|
self.stack.push(*&funge.code[&vec![x + self.offset[0], y + self.offset[1]]]);
|
||||||
}
|
}
|
||||||
38 => { // &
|
38 => { // &
|
||||||
let s = funge.inputs.get()?;
|
let s = funge.inputs.get()?;
|
||||||
let i: Vec<char> = s.chars()
|
let i: Vec<char> = s.chars()
|
||||||
.skip_while(|i| !i.is_digit(10))
|
.skip_while(|i| !i.is_digit(10))
|
||||||
.take_while(|i| i.is_digit(10)).collect();
|
.take_while(|i| i.is_digit(10)).collect();
|
||||||
self.stack.push(join(&i, "").parse()?);
|
match join(&i, "").parse() {
|
||||||
|
Ok(n) => self.stack.push(n),
|
||||||
|
_ => println!("Cannot convert input to number.") // TODO: Error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
126 => { // ~
|
126 => { // ~
|
||||||
let s = funge.inputs.get()?;
|
let s = funge.inputs.get()?;
|
||||||
@@ -540,8 +591,8 @@ impl IP {
|
|||||||
}
|
}
|
||||||
64 => { return Ok((funge, Some(Vec::new()))); } // @
|
64 => { return Ok((funge, Some(Vec::new()))); } // @
|
||||||
32 => { // space
|
32 => { // space
|
||||||
self.advance(&funge);
|
self.advance(&funge)?;
|
||||||
return self.step(funge, false);
|
return Ok(self.step(funge,false)?);
|
||||||
}
|
}
|
||||||
// 98 from here
|
// 98 from here
|
||||||
91 => self.turn_left(), // [
|
91 => self.turn_left(), // [
|
||||||
@@ -549,21 +600,22 @@ impl IP {
|
|||||||
39 => { // '
|
39 => { // '
|
||||||
self.movep(&funge);
|
self.movep(&funge);
|
||||||
self.stack.push(self.op(&funge));
|
self.stack.push(self.op(&funge));
|
||||||
|
return self.skip(funge)
|
||||||
}
|
}
|
||||||
123 => { // {
|
123 => { // {
|
||||||
let n = self.stack.pop();
|
let n = self.stack.pop();
|
||||||
let cells = if n > 0 {
|
let cells = if n > I::zero() {
|
||||||
let mut cells = Vec::new();
|
let mut cells = Vec::new();
|
||||||
for _ in 0..n {
|
for _ in 0..cast_int(n)? {
|
||||||
cells.push(self.stack.pop());
|
cells.push(self.stack.pop());
|
||||||
}
|
}
|
||||||
cells.reverse();
|
cells.reverse();
|
||||||
cells
|
cells
|
||||||
} else {
|
} else {
|
||||||
vec![0; -n as usize]
|
vec![I::zero(); -cast_int::<isize, _>(n)? as usize]
|
||||||
};
|
};
|
||||||
for coordinate in &self.offset {
|
for coordinate in &self.offset {
|
||||||
self.stack.push(*coordinate);
|
self.stack.push(cast_int(*coordinate)?);
|
||||||
}
|
}
|
||||||
self.stack.push_stack(Stack::new());
|
self.stack.push_stack(Stack::new());
|
||||||
for cell in cells {
|
for cell in cells {
|
||||||
@@ -573,19 +625,19 @@ impl IP {
|
|||||||
}
|
}
|
||||||
125 => { // }
|
125 => { // }
|
||||||
let n = self.stack.pop();
|
let n = self.stack.pop();
|
||||||
let cells = if n > 0 {
|
let cells = if n > I::zero() {
|
||||||
let mut cells = Vec::new();
|
let mut cells = Vec::new();
|
||||||
for _ in 0..n {
|
for _ in 0..cast_int(n)? {
|
||||||
cells.push(self.stack.pop());
|
cells.push(self.stack.pop());
|
||||||
}
|
}
|
||||||
cells.reverse();
|
cells.reverse();
|
||||||
cells
|
cells
|
||||||
} else {
|
} else {
|
||||||
vec![0; -n as usize]
|
vec![I::zero(); -cast_int::<isize, _>(n)? as usize]
|
||||||
};
|
};
|
||||||
self.stack.pop_stack();
|
self.stack.pop_stack();
|
||||||
let y = self.stack.pop();
|
let y = cast_int(self.stack.pop())?;
|
||||||
let x = self.stack.pop();
|
let x = cast_int(self.stack.pop())?;
|
||||||
self.offset = vec![x, y];
|
self.offset = vec![x, y];
|
||||||
for cell in cells {
|
for cell in cells {
|
||||||
self.stack.push(cell);
|
self.stack.push(cell);
|
||||||
@@ -608,10 +660,10 @@ impl IP {
|
|||||||
105 => { // i
|
105 => { // i
|
||||||
let file = self.read_string()?;
|
let file = self.read_string()?;
|
||||||
let flags = self.stack.pop();
|
let flags = self.stack.pop();
|
||||||
let y0 = self.stack.pop();
|
let y0 = cast_int(self.stack.pop())?;
|
||||||
let x0 = self.stack.pop();
|
let x0 = cast_int(self.stack.pop())?;
|
||||||
let text = fs::read_to_string(file)?;
|
let text = fs::read_to_string(file)?;
|
||||||
let (width, height) = if flags % 2 != 0 {
|
let (width, height) = if flags.is_odd() {
|
||||||
let code: Vec<char> = text.chars().collect();
|
let code: Vec<char> = text.chars().collect();
|
||||||
funge.insert_code(vec![join(&code, "")], x0, y0)?;
|
funge.insert_code(vec![join(&code, "")], x0, y0)?;
|
||||||
(text.len(), 1)
|
(text.len(), 1)
|
||||||
@@ -627,19 +679,20 @@ impl IP {
|
|||||||
funge.insert_code(code, x0, y0)?;
|
funge.insert_code(code, x0, y0)?;
|
||||||
(width, height)
|
(width, height)
|
||||||
};
|
};
|
||||||
self.stack.push(x0);
|
self.stack.push(cast_int(x0)?);
|
||||||
self.stack.push(y0);
|
self.stack.push(cast_int(y0)?);
|
||||||
self.stack.push(width as isize);
|
self.stack.push(cast_int(width)?);
|
||||||
self.stack.push(height as isize);
|
self.stack.push(cast_int(height)?);
|
||||||
}
|
}
|
||||||
106 => { // j
|
106 => { // j
|
||||||
for _ in 0..self.stack.pop() {
|
for _ in 0..cast_int(self.stack.pop())? {
|
||||||
self.movep(&funge);
|
self.movep(&funge);
|
||||||
}
|
}
|
||||||
|
return self.skip(funge)
|
||||||
}
|
}
|
||||||
107 => { // k
|
107 => { // k
|
||||||
self.advance(&funge);
|
self.advance(&funge)?;
|
||||||
let n = self.stack.pop();
|
let n = cast_int(self.stack.pop())?;
|
||||||
let mut ips = vec![self];
|
let mut ips = vec![self];
|
||||||
for _ in 0..n {
|
for _ in 0..n {
|
||||||
let mut new_ips = Vec::new();
|
let mut new_ips = Vec::new();
|
||||||
@@ -660,12 +713,12 @@ impl IP {
|
|||||||
111 => { // o
|
111 => { // o
|
||||||
let file = self.read_string()?;
|
let file = self.read_string()?;
|
||||||
let flags = self.stack.pop();
|
let flags = self.stack.pop();
|
||||||
let x0 = self.stack.pop();
|
let x0 = cast_int(self.stack.pop())?;
|
||||||
let y0 = self.stack.pop();
|
let y0 = cast_int(self.stack.pop())?;
|
||||||
let width = self.stack.pop();
|
let width: isize = cast_int(self.stack.pop())?;
|
||||||
let height = self.stack.pop();
|
let height: isize = cast_int(self.stack.pop())?;
|
||||||
let mut text = Vec::new();
|
let mut text = Vec::new();
|
||||||
if flags % 2 != 0 {
|
if flags.is_odd() {
|
||||||
for x in x0..x0 + width {
|
for x in x0..x0 + width {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
for y in y0..y0 + height {
|
for y in y0..y0 + height {
|
||||||
@@ -701,7 +754,7 @@ impl IP {
|
|||||||
if self.stack.is_empty() {
|
if self.stack.is_empty() {
|
||||||
self.reverse();
|
self.reverse();
|
||||||
} else {
|
} else {
|
||||||
let n = self.stack.pop();
|
let n = cast_int(self.stack.pop())?;
|
||||||
let l = self.stack.len_stack();
|
let l = self.stack.len_stack();
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
for _ in 0..n {
|
for _ in 0..n {
|
||||||
@@ -726,15 +779,15 @@ impl IP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
120 => { // x
|
120 => { // x
|
||||||
let dy = self.stack.pop();
|
let dy = cast_int(self.stack.pop())?;
|
||||||
let dx = self.stack.pop();
|
let dx = cast_int(self.stack.pop())?;
|
||||||
self.delta = vec![dx, dy];
|
self.delta = vec![dx, dy];
|
||||||
}
|
}
|
||||||
121 => { // y
|
121 => { // y
|
||||||
let n = self.stack.pop();
|
let n = self.stack.pop();
|
||||||
if n <= 0 {
|
if n <= I::zero() {
|
||||||
for j in 1..21 {
|
for j in 1..21 {
|
||||||
for i in self.get_info(&funge,j) {
|
for i in self.get_info(&funge,cast_int(j)?) {
|
||||||
for cell in i {
|
for cell in i {
|
||||||
self.stack.push(cell);
|
self.stack.push(cell);
|
||||||
}
|
}
|
||||||
@@ -749,21 +802,15 @@ impl IP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
122 => { } // z
|
122 => { } // z
|
||||||
d => {
|
48..=57 => self.stack.push(self.op(&funge) - cast_int(48)?), // 0123456789
|
||||||
if (48 <= d) & (d <= 57) { // 0123456789
|
97..=102 => self.stack.push(self.op(&funge) - cast_int(87)?), // abcdef
|
||||||
self.stack.push(d - 48);
|
_ => self.not_implemented(&funge)
|
||||||
} else if (97 <= d) & (d <= 102) {
|
|
||||||
self.stack.push(d - 87);
|
|
||||||
} else {
|
|
||||||
self.not_implemented(&funge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.not_implemented(&funge);
|
self.not_implemented(&funge);
|
||||||
}
|
}
|
||||||
if !k {
|
if !k {
|
||||||
self.advance(&funge);
|
self.advance(&funge)?;
|
||||||
}
|
}
|
||||||
let mut ips = vec![self];
|
let mut ips = vec![self];
|
||||||
ips.extend(new_ips);
|
ips.extend(new_ips);
|
||||||
@@ -808,21 +855,21 @@ impl<K: Eq + Hash, V: Clone> Index<&K> for DefaultHashMap<K, V> {
|
|||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Funge {
|
pub struct Funge<I: Int> {
|
||||||
extent: Vec<isize>,
|
extent: Vec<isize>,
|
||||||
code: DefaultHashMap<Vec<isize>, isize>,
|
code: DefaultHashMap<Vec<isize>, I>,
|
||||||
steps: isize,
|
steps: isize,
|
||||||
ips: Vec<IP>,
|
ips: Vec<IP<I>>,
|
||||||
inputs: Input,
|
inputs: Input,
|
||||||
output: Output,
|
output: Output,
|
||||||
pub terminated: bool
|
pub terminated: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Funge {
|
impl<I: Int> Funge<I> {
|
||||||
pub fn new<T: ToString>(code: T) -> Result<Self, Box<dyn Error>> {
|
pub fn new<T: ToString>(code: T) -> Result<Self, Box<dyn Error>> {
|
||||||
let mut new = Self {
|
let mut new = Self {
|
||||||
extent: vec![0, 0, 0, 0],
|
extent: vec![0; 4],
|
||||||
code: DefaultHashMap::new(32),
|
code: DefaultHashMap::new(cast_int(32)?),
|
||||||
steps: 0,
|
steps: 0,
|
||||||
ips: Vec::new(),
|
ips: Vec::new(),
|
||||||
inputs: Input { source: InputEnum::StdIn },
|
inputs: Input { source: InputEnum::StdIn },
|
||||||
@@ -853,7 +900,7 @@ impl Funge {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(&mut self, i: isize, x: isize, y: isize) {
|
fn insert(&mut self, i: I, x: isize, y: isize) {
|
||||||
self.code.insert(vec![x, y], i);
|
self.code.insert(vec![x, y], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,7 +967,7 @@ impl Funge {
|
|||||||
pos
|
pos
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string(&self, show_ips: bool) -> String {
|
fn get_string(&self, show_ips: bool) -> String {
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
for (key, value) in (&*self.code).into_iter() {
|
for (key, value) in (&*self.code).into_iter() {
|
||||||
let x= key[0] as usize;
|
let x= key[0] as usize;
|
||||||
@@ -931,7 +978,7 @@ impl Funge {
|
|||||||
while lines[y].len() <= x {
|
while lines[y].len() <= x {
|
||||||
lines[y].push(String::from(" "));
|
lines[y].push(String::from(" "));
|
||||||
}
|
}
|
||||||
if ((&32 <= value) & (value <= &126)) | ((&161 <= value) & (value <= &255)) {
|
if let Some(32..=126) | Some(161..=255) = value.to_u8() {
|
||||||
lines[y][x] = chr(*value).unwrap().to_string();
|
lines[y][x] = chr(*value).unwrap().to_string();
|
||||||
} else {
|
} else {
|
||||||
lines[y][x] = chr(164).unwrap().to_string();
|
lines[y][x] = chr(164).unwrap().to_string();
|
||||||
@@ -965,14 +1012,14 @@ impl Funge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Funge {
|
impl<I: Int> Display for Funge<I> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.to_string(false))
|
write!(f, "{}", self.get_string(false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Funge {
|
impl<I: Int> Debug for Funge<I> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.to_string(true))
|
write!(f, "{}", self.get_string(true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
34
src/main.rs
34
src/main.rs
@@ -14,21 +14,41 @@ struct Args {
|
|||||||
#[arg(help = "debug, step on key press or steps / second",
|
#[arg(help = "debug, step on key press or steps / second",
|
||||||
short, long, value_name = "interval", num_args = 0..=1)]
|
short, long, value_name = "interval", num_args = 0..=1)]
|
||||||
debug: Option<Option<f64>>,
|
debug: Option<Option<f64>>,
|
||||||
|
#[arg(help = "number of bits in cell and funge values", short, long)]
|
||||||
|
bits: Option<u8>,
|
||||||
#[arg(id = "arguments to the funge (& or ~)")]
|
#[arg(id = "arguments to the funge (& or ~)")]
|
||||||
arguments: Vec<String>,
|
arguments: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
macro_rules! run {
|
||||||
let args = Args::parse();
|
($a:expr, $i:ty) => {
|
||||||
let mut funge = Funge::from_file(&args.input)?;
|
let mut funge = Funge::<$i>::from_file(&$a.input)?;
|
||||||
if args.arguments.len() > 0 {
|
if $a.arguments.len() > 0 {
|
||||||
funge = funge.with_inputs(args.arguments)?;
|
funge = funge.with_inputs($a.arguments)?;
|
||||||
}
|
}
|
||||||
|
match $a.debug {
|
||||||
match args.debug {
|
|
||||||
Some(interval) => FungeView::new(funge)?.debug(interval).unwrap(),
|
Some(interval) => FungeView::new(funge)?.debug(interval).unwrap(),
|
||||||
None => { funge.run()?; }
|
None => { funge.run()?; }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let args = Args::parse();
|
||||||
|
if let None = args.bits {
|
||||||
|
run!(args, isize);
|
||||||
|
} else if let Some(8) = args.bits {
|
||||||
|
run!(args, i8);
|
||||||
|
} else if let Some(16) = args.bits {
|
||||||
|
run!(args, i16);
|
||||||
|
} else if let Some(32) = args.bits {
|
||||||
|
run!(args, i32);
|
||||||
|
} else if let Some(64) = args.bits {
|
||||||
|
run!(args, i64);
|
||||||
|
} else if let Some(128) = args.bits {
|
||||||
|
run!(args, i128);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user