Threi
Jump to navigation
Jump to search
Threi is an esoteric programming language desgined by User:Infinitehexagon.
Instructions
| Command | Name | Description |
|---|---|---|
< |
move pointer left | change the cell pointer to the left. |
> |
move pointer right | change the cell pointer to the right. |
h |
Invert bit | Flip the bit that the cell pointer is on. |
x |
random bit | Set the bit that the cell pointer is pointing to a value to a random bit. |
& |
AND gate | If the cell before it and the current cell both have a value of 1, replace the 3rd cell after the current cell with 1. |
o |
Output | Output the bit at the cell pointer. |
e |
Clear | set the bit at the cell pointer to 0. |
{} |
While not 0 | jump back to the { while the current bit is not 0.
|
Programs
Truth machine
h --remove for 0
>h{&
>o<<
}
Hello world program
This program prints the message “Hello, World!” to the standard output:
o>ho>o>o>ho>o>o>o> o>ho>ho>o>o>ho>o>ho> o>ho>ho>o>ho>ho>o>o> o>ho>ho>o>ho>ho>o>o> o>ho>ho>o>ho>ho>ho>ho> o>o>ho>o>ho>ho>o>o> o>o>ho>o>o>o>o>o> o>ho>o>ho>o>ho>ho>ho> o>ho>ho>o>ho>ho>ho>ho> o>ho>ho>ho>o>o>ho>o> o>ho>ho>o>ho>ho>o>o> o>ho>ho>o>o>ho>o>o> o>o>ho>o>o>o>o>ho
Computational class
Language is Turing complete because instructions h<>{} correspond directly to Smallfuck *<>[], deviating merely from the latter's program termination aspect on leaving the memory boundaries.
Implementation
The following presents an implementation in Common Lisp:
(deftype hash-table-of (&optional (key-type '*) (value-type '*))
"Defines a hash table composed whose keys assume 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))
(and
(hash-table-p candidate)
(loop
for key being the hash-keys in (the hash-table candidate)
using (hash-value value)
always (and (typep key key-type) (typep value value-type))))))
`(satisfies ,predicate)))
(deftype list-of (&optional (element-type '*))
"Defines a list composed of the zero or more elements of the ELEMENT-TYPE."
(let ((predicate (gensym)))
(declare (type symbol predicate))
(setf (symbol-function predicate)
#'(lambda (candidate)
(declare (type T candidate))
(loop for element of-type T in (the list candidate) always
(typep element element-type))))
`(satisfies ,predicate)))
(deftype jump-table ()
"Maps the forward jump positions to that of the back jumps, and vice versa."
'(hash-table-of fixnum fixnum))
(defun compute-jump-table (code)
"Computes and returns the jump-table for the piece of Threi source CODE."
(declare (type string code))
(let ((jump-table (make-hash-table :test #'eql))
(forward-jump-points NIL))
(declare (type jump-table) (type (list-of fixnum) forward-jump-points))
(loop
for token of-type character across code
and position of-type fixnum from 0 by 1
if (char= token #\{) do
(push position forward-jump-points)
else if (char= token #\}) do
(if forward-jump-points
(let ((start-point (pop forward-jump-points))
(end-point position))
(declare (type fixnum start-point))
(declare (type fixnum end-point))
(setf (gethash start-point jump-table) end-point)
(setf (gethash end-point jump-table) start-point))
(error "Unmatched back jump point at position ~d." position))
end
finally
(when forward-jump-points
(error "Unmatched forward jump point~p at position~:p ~
~{~d~^, ~}."
(length forward-jump-points)
(nreverse forward-jump-points))))
(the jump-table jump-table)))
(defclass Memory ()
((cells
:initform (make-array 0 :element-type 'bit :initial-element 0)
:type simple-bit-vector
:documentation "A tape of cells which grows along the positive axis.")
(pointer
:initform 0
:type fixnum
:documentation "The index (key) of the current cell among the CELLS."))
(:documentation "Maintains a bit vector with a cell pointer."))
(defun accommodate-space-for (memory index)
"Ascertains the MEMORY's capacity to answer to the cell INDEX and
returns no value."
(declare (type Memory memory) (type fixnum index))
(when (>= index (length (slot-value memory 'cells)))
(setf (slot-value memory 'cells)
(adjust-array (slot-value memory 'cells) (1+ index) :initial-element 0)))
(values))
(defun cell-at (memory index)
"Returns the MEMORY cell value at the INDEX."
(declare (type Memory memory) (type fixnum index))
(accommodate-space-for memory index)
(the bit (sbit (slot-value memory 'cells) index)))
(defun (setf cell-at) (new-value memory index)
"Sets the MEMORY cell value the INDEX to the NEW-VALUE and returns no value."
(declare (type bit new-value) (type Memory memory) (type fixnum index))
(accommodate-space-for memory index)
(setf (sbit (slot-value memory 'cells) index) new-value)
(values))
(defun current-cell (memory)
"Returns the value of the current MEMORY cell."
(declare (type Memory memory))
(the bit (cell-at memory (slot-value memory 'pointer))))
(defun (setf current-cell) (new-value memory)
"Stores the NEW-VALUE in the MEMORY's current cell and returns no value."
(declare (type Memory memory) (type bit new-value))
(setf (cell-at memory (slot-value memory 'pointer)) new-value)
(values))
(defun and-combine-cells (memory)
"If the current and its preceding cell contain the value 1, stores the
value 1 in the cell three positions right to the current cell, in any
case returning no value."
(declare (type Memory memory))
(when (and (plusp (slot-value memory 'pointer))
(= (cell-at memory (1- (slot-value memory 'pointer))) 1))
(setf (cell-at memory (+ (slot-value memory 'pointer) 3)) 1))
(values))
(defun move-cell-pointer-left (memory)
"Translates the MEMROY's cell pointer one step to the left, if no
already on the first position, and returns no value."
(declare (type Memory memory))
(when (plusp (slot-value memory 'pointer))
(decf (slot-value memory 'pointer)))
(values))
(defun move-cell-pointer-right (memory)
"Translates the MEMORY's cell pointer on step to the right and returns
no value."
(declare (type Memory memory))
(incf (slot-value memory 'pointer))
(values))
(defun interpret-Threi (code)
"Interprets the piece of Threi source CODE and returns no value."
(declare (type string code))
(let ((jump-table (compute-jump-table code))
(memory (make-instance 'Memory)))
(declare (type jump-table jump-table))
(declare (type Memory memory))
(loop with ip of-type fixnum = 0 while (< ip (length code)) do
(case (char code ip)
(#\> (move-cell-pointer-right memory))
(#\< (move-cell-pointer-left memory))
(#\h (setf (current-cell memory) (- 1 (current-cell memory))))
(#\x (setf (current-cell memory) (random 2)))
(#\e (setf (current-cell memory) 0))
(#\& (and-combine-cells memory))
(#\o (format T "~d" (current-cell memory)))
(#\{ (when (zerop (current-cell memory))
(setf ip
(or (gethash ip jump-table)
(error "No back jump position associated with ~d." ip)))))
(#\} (unless (zerop (current-cell memory))
(setf ip
(or (gethash ip jump-table)
(error "No back jump position associated with ~d." ip)))))
(otherwise NIL))
(incf ip)))
(values))
;; Initialize the random number generator.
(setf *random-state* (make-random-state T))