⍝ Masturbation - Implement the esoteric Masturbation language. ⍝ Copyright 2017,2018,2019 Prince Trippy programmer@verisimilitudes.net . ⍝ This program is free software: you can redistribute it and/or modify it under the terms of the ⍝ GNU Affero General Public License version 3 as published by the Free Software Foundation. ⍝ This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without ⍝ even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ⍝ See the GNU Affero General Public License for more details. ⍝ You should have received a copy of the GNU Affero General Public License along with this program. ⍝ If not, see . size←256 ⍝ The size of a memory cell. ∇ z←convert x;⎕IO ⍝ This exists purely because of the ⎕AV differences across implementations. ⎕IO←0◊z←size|⎕AV⍳x ∇ ∇ z←unconvert x;⎕IO ⍝ As does this. ⎕IO←0◊z←⎕AV[(⍴⎕AV)|x] ∇ keys←'+-<>.,[]=' ⍝ These are the ``keywords'' of the language. commands←convert keys ⍝ Adjust as wanted. length←30000 ⍝ The length of the memory buffer and maximum length of a program. debug←1 ⍝ This exists so that one can say ``debug masturbation thread'' where thread is a program. probe←1 ⍝ This is another debug variable. ∇ z←search x;⎕IO ⍝ This is a searching routine for [ and ]; it returns the index of the corresponding bracket. ⎕IO←0◊z←0⍳⍨+\(-x=convert'[')+x=convert']' ∇ ∇ z←balanced x;⎕IO;t ⍝ This predicate determines whether [ and ] are balanced properly or not. ⎕IO←0◊t←0=+/(-x=convert'[')+x=convert']'◊z←t∧~∨/1=+\(-x=convert'[')+x=convert']' ∇ ∇ buffers←debug masturbation thread;memory;ip;index;program;output;⎕IO memory←length⍴index←ip←⎕IO←0◊output←''◊program←convert(length>⍴,thread)⊃(length↑,thread)(,thread)◊→done↓⍨0≠⍴program◊→flaw↓⍨balanced program debug←('' '''Cell '',(5 0⍕index),'' : '',(3 0⍕memory[index]),'' Instruction '',(5 0⍕ip),'' : '',unconvert program[ip]')⊃⍨0≠⎕NC'debug' process: ⍎debug◊→(plus minus less more dot comma open close equals comment)[commands⍳program[ip]] plus: memory[index]←size|memory[index]+1◊→comment minus: memory[index]←size|memory[index]-1◊→comment less: index←length|index-1◊→comment more: index←length|index+1◊→comment dot: output←output,unconvert memory[index]◊→comment comma: output◊output←''◊memory[index]←convert↑⍞◊→comment open: ip←((ip+search ip↓memory)ip)[0≠memory[index]]◊→comment close: ip←((ip-search⌽(1+ip)↑memory)ip)[0=memory[index]]◊→comment equals: (program memory ip index)←(0≠memory[index])⊃(program(program,(⍴program)↓memory)ip 0)(((⍴program)↑memory)memory ¯1 0) →flaw↓⍨balanced program◊ip←1+ip◊→(process done)↓⍨ip≥⍴program ⍝ The equals implementation resembles a ] underflow, otherwise. comment: ip←1+ip◊→process↓⍨(ip≤0)∨ip≥⍴program ⍝ This also handles the common case in the interpreter. done: output◊buffers←program,memory◊→0 flaw: 'Your program uses improper brackets.' ∇ .