Mildfuck
Jump to navigation
Jump to search
Mildfuck is a brainfuck and infinite abacus inspired esolang created by Yb1 with only 6 commands. The name is derived from the first 4 commands, reading mild
.
Storing data is a carbon copy of brainfuck, a tape with cells containing values from 0 to 255.
Designed by | User:Yb1 |
---|---|
Appeared in | 2024 |
Dimensions | one-dimensional |
Computational class | ? |
Reference implementation | See Mildfuck#Implementation |
File extension(s) | .mild |
Commands
Command | Description |
---|---|
m |
Move pointer in pointer direction (right on start). |
i |
Increase current cell if less than 255. |
l |
No op, used as a skipping point for d .
|
d |
Invert pointer direction and if current cell is 0, skip to last l or else decrease the current cell.
|
g |
Get 1 ascii character input, and store it into the cell. |
o |
Output current cells value as an ascii character. |
Computational class
I have reasonable suspicion that this is Turing-complete, because this is very similar to an infinite abacus, which is Turing-complete.
Examples
Truth Machine
Not yet programmed, sorry. Replace this with a truth machine.
Cat program
The following furnishes a perpetually repeating cat program:
lmidgomd
Hello, World!
iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiomiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiio
Implementation
The following implementation in Common Lisp assumes that the d
instruction jumps back to the nearest preceding l
token:
(deftype octet () "Defines an unsigned byte value in the range [0, 255]." '(unsigned-byte 8)) (deftype hash-table-of (&optional (key-type T) (value-type T)) "Defines a hash table whose keys conform to the KEY-TYPE and whose values adhere to the VALUE-TYPE." (let ((predicate (gensym))) (declare (type symbol predicate)) (setf (symbol-function predicate) #'(lambda (candidate) (declare (type T candidate) (ignorable candidate)) (and (hash-table-p candidate) (loop for key of-type T being the hash-keys in candidate using (hash-value value) always (and (typep key key-type) (typep value value-type)))))) `(satisfies ,predicate))) (deftype list-of (&optional (element-type T)) "Defines a list whose elements comply with the ELEMENT-TYPE." (let ((predicate (gensym))) (declare (type symbol predicate)) (setf (symbol-function predicate) #'(lambda (candidate) (declare (type T candidate) (ignorable candidate)) (and (listp candidate) (loop for element of-type T in candidate always (typep element element-type))))) `(satisfies ,predicate))) (defun build-skip-table (code) "Creates and returns a skip table for the piece of Mildfuck CODE." (declare (type string code)) (let ((skip-table (make-hash-table :test #'eql)) (skip-targets NIL)) (declare (type (hash-table-of fixnum fixnum) skip-table)) (declare (type (list-of fixnum) skip-targets)) (loop for token of-type character across code and position of-type fixnum from 0 by 1 if (char= token #\l) do (push position skip-targets) else if (char= token #\d) do (if skip-targets (setf (gethash position skip-table) (first skip-targets)) (error "No skip target exists for the \"d\" instruction ~ at position ~d." position)) end) (the (hash-table-of fixnum fixnum) skip-table))) (defun interpret-Mildfuck (code) "Interprets the piece of Mildfuck CODE and returns no value." (declare (type string code)) (let ((ip 0) (skip-table (build-skip-table code)) (memory (make-hash-table :test #'eql)) (cell-pointer 0) (pointer-direction :right)) (declare (type fixnum ip) (type (hash-table-of fixnum fixnum) skip-table) (type (hash-table-of integer octet) memory) (type integer cell-pointer) (type (member :left :right) pointer-direction)) (flet ((current-cell () "Returns the current cell value." (the octet (gethash cell-pointer memory 0))) ((setf current-cell) (new-value) "Stores the NEW-VALUE in the current cell, wrapping on necessity in the valid byte range, and returns no value." (declare (type integer new-value)) (setf (gethash cell-pointer memory 0) (mod new-value 256)) (values))) (loop while (< ip (length code)) do (case (char code ip) (#\m (case pointer-direction (:right (incf cell-pointer)) (:left (decf cell-pointer)) (otherwise (error "Invalid pointer direction: ~s." pointer-direction)))) (#\i (when (< (current-cell) 255) (incf (current-cell)))) (#\l NIL) (#\d (setf pointer-direction (case pointer-direction (:right :left) (:left :right) (otherwise (error "Invalid pointer direction: ~s." pointer-direction)))) (if (zerop (current-cell)) (setf ip (gethash ip skip-table)) (decf (current-cell)))) (#\g (format T "~&>> ") (finish-output) (setf (current-cell) (char-code (read-char))) (clear-input)) (#\o (write-char (code-char (current-cell)))) (otherwise NIL)) (incf ip)))) (values))