...

From Esolang
Jump to navigation Jump to search

... is an esolang created by randomIdiot. There are only 3 Symbols:

  • .
  • :
  • Spaces

The code is seperated in 2-Symbol-Blocks. Here is what they mean:

Combination Action
.: Increase Cell Value
:. Decrease Cell Value
.. Change Cell Action
:: Execute Cell
.SPACE Increase Pointer
SPACE. Decrease Pointer

The Cell-System is like in Brainfuck. You have cells which you can go to (de-/increase pointer) and store values. But in ... you can also store actions. Every cell is an executable program.

Actions

There are 2 Actions: Input and output. They work like in Brainfuck. Input saves the input as a number in the current cell. Output prints the current cell value. Standard action saved in a cell is output.

Compiler

Coming soon

Examples

Cat program

A one-time cat program assumes the following form:

..::..::

Implementations

An implementation in Common Lisp shall be presented:

(deftype octet ()
  "Defines an unsigned byte composed of eight bits."
  '(unsigned-byte 8))

(deftype action ()
  "Enumerates the valid cell actions."
  '(member :input :output))

(deftype cell ()
  "Defines a cell's (cellValue, cellAction) componency in terms of
   an octet value and an action keyword."
  '(cons octet action))

(defun memory-p (candidate)
  "Determines whether the CANDIDATE is a hash table that maps integer
   keys to cell values, the former acting a cell indices, the latter
   as associated (cellValue, cellAction) compounds."
  (declare (type T candidate))
  (and (hash-table-p candidate)
       (loop for key of-type T being the hash-keys in candidate
             using (hash-value value)
             always (and (integerp key) (typep value 'cell)))))

(deftype memory ()
  "Defines the program memory as a hash table that maps integer cell
   indices to byte-action (cellValue, cellAction) tuples."
  '(satisfies memory-p))

(defun interpret-|...| (code)
  "Interprets the piece of ... source CODE and returns NIL."
  (declare (type string code))
  (let ((memory       (make-hash-table :test #'eql))
        (cell-pointer 0))
    (declare (type memory memory) (type integer cell-pointer))
    (labels
        ((code-section-equals-p (start expected-string)
          (declare (type fixnum start) (type string expected-string))
          (the boolean
            (not (null
              (string= code expected-string
                :start1 start :end1  (min (+ start 2) (length code)))))))
        (current-cell ()
          (multiple-value-bind (cell contains-cell-p)
              (gethash cell-pointer memory)
            (declare (type (or null cell) cell) (type T contains-cell-p))
            (the cell
              (cond
                (contains-cell-p cell)
                (T  (setf (gethash cell-pointer memory) (cons 0 :output))
                    (gethash cell-pointer memory))))))
        (current-cell-value ()
          (the octet (car (current-cell))))
        ((setf current-cell-value) (new-value)
          (declare (type integer new-value))
          (setf (car (current-cell)) (mod new-value 256))
          (values))
        (current-cell-action ()
          (the action (cdr (current-cell))))
        ((setf current-cell-action) (new-action)
          (declare (type action new-action))
          (setf (cdr (current-cell)) new-action)
          (values))
        (change-action ()
          (setf (current-cell-action)
            (case (current-cell-action)
              (:output   :input)
              (:input    :output)
              (otherwise (error "Invalid current action: ~s."
                           (current-cell)))))
          (values)))
      (loop for ip of-type fixnum from 0 below (length code) by 2 do
        (cond
          ((code-section-equals-p ip ".:") (incf (current-cell-value)))
          ((code-section-equals-p ip ":.") (decf (current-cell-value)))
          ((code-section-equals-p ip "..") (change-action))
          ((code-section-equals-p ip "::")
            (case (current-cell-action)
              (:output   (format T "~c" (code-char (current-cell-value))))
              (:input    (format T "~&>> ")
                         (force-output)
                         (setf (current-cell-value) (char-code (read-char)))
                         (clear-input))
              (otherwise (error "Invalid action: ~s." (current-cell-action)))))
          ((code-section-equals-p ip ". ") (incf cell-pointer))
          ((code-section-equals-p ip " .") (decf cell-pointer))
          (T (error "Invalid command token: ~s."
               (subseq code ip (min (+ ip 2) (length code))))))))))