++C+=C++ + ++C;
Jump to navigation
Jump to search
This is still a work in progress. It may be changed in the future.
++C+=C++ + ++C; is an esolang by User:FiveUnderlines.
Please make sure you don't spell any different characters.
Description
The name of esolang looks like a classic undefined behavior in C++.In fact, it is a brainfuck dialect.
Commands
| Command | Mode | |
|---|---|---|
| 0 | 1 | |
C
|
Switch the modes. | |
+
|
Decrement the current cell by one. brainfuck equivalent: -.
|
Increment the current cell by one. brainfuck equivalent: +.
|
=
|
Move the cell pointer one step to the left. brainfuck equivalent: <.
|
Move the cell pointer one step to the right. brainfuck equivalent: >.
|
,
|
Print the character whose ASCII code equals the current cell value to the standard output. brainfuck equivalent: ..
|
Query the standard input for a character and store its ASCII code in the current cell. brainfuck equivalent: ,.
|
(
|
If the current cell value equals zero, jump forward past the matching ).brainfuck equivalent: [.
| |
)
|
If the current cell value does not equal zero, jump back to the matching (.brainfuck equivalent: ].
| |
;
|
End the program immediately. | |
Please make sure there is one at the end of your program ;, otherwise,it may cause runtime errors.
Some program examples
Cat
C+C(C,);
Truth-machine
C,C,C=++++++(C+=++++++++C=) +++++++++++++++++++++++++++++++++++++++++++++++++ C=(C=C,=);
Implementations
The following proposes a tentative implementation in Common Lisp:
(deftype list-of (&optional (element-type T))
"Defines a list composed of zero or more members of the ELEMENT-TYPE."
(let ((predicate (gensym)))
(declare (type symbol predicate))
(setf (symbol-function predicate)
#'(lambda (candidate)
(declare (type T candidate))
(and (listp candidate)
(loop
for element of-type T in (the list candidate)
always (typep element element-type)))))
`(satisfies ,predicate)))
(deftype hash-table-of (&optional (key-type T) (value-type T))
"Defines a hash table whose zero or more entries are composed of keys
of the KEY-TYPE which associate with values of 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 of-type T
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 jump-table ()
"Connects the forward jump and back jump commands in a program by
mediation of their positions in the code."
'(hash-table-of fixnum fixnum))
(deftype octet ()
"An unsigned byte compact of eight adjacent bits, covering the
integral range [0, 255]."
'(unsigned-byte 8))
(deftype memory ()
"The program memory as a sparse vector of unsigned-byte-valued cells,
implemented as a hash table whose keys provide the indices to the
cell objects as the entry values."
'(hash-table-of integer octet))
(deftype mode ()
"The mode as a bit-valued switch."
'bit)
(deftype destination ()
"Defines a sink for output operations."
'(or null (eql T) stream string))
(define-condition Runtime-Error (error)
((position
:initarg :position
:initform (error "No position specified.")
:reader runtime-error-position
:type fixnum
:documentation "The missing semicolon position in the code."))
(:report
(lambda (condition stream)
(declare (type Runtime-Error condition))
(declare (type destination stream))
(format stream "No semicolon found at position ~d."
(runtime-error-position condition))))
(:documentation
"Serves to signal a missing semicolon (\";\")."))
(defun generate-jump-table (code)
"Connects the forward and back jump points in the ++C+=C++ + ++C;
CODE by adminicle of a jump table, which is subsequently returned."
(declare (type string code))
(let ((jump-table (make-hash-table :test #'eql))
(forward-jump-points NIL))
(declare (type jump-table 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 jump end point at position ~d." position))
finally
(when forward-jump-points
(error "Unmatched jump start points at positions ~{~d~^, ~}."
forward-jump-points)))
(the jump-table jump-table)))
(defun interpret-|++C+=C++ + ++C;| (code)
"Interprets the piece of \"++C+=C++ + ++C;\" CODE and returns NIL."
(declare (type string code))
(let ((ip 0)
(instruction (when (plusp (length code))
(char code 0)))
(jump-table (generate-jump-table code))
(mode 0)
(memory (make-hash-table :test #'eql))
(cell-pointer 0)
(semicolon-set-p NIL))
(declare (type fixnum ip)
(type (or null character) instruction)
(type jump-table jump-table)
(type mode mode)
(type memory memory)
(type integer cell-pointer)
(type boolean semicolon-set-p))
(labels
((advance ()
"Advances the instruction pointer (IP) to the next location."
(setf instruction
(when (array-in-bounds-p code (1+ ip))
(char code (incf ip))))
(values))
(jump ()
"Moves the instruction pointer (IP) to the jump destination."
(setf ip (or (gethash ip jump-table)
(error "No jump point at ~d." ip)))
(values))
(switch-mode ()
"Flips the mode switch."
(setf mode (- 1 mode))
(values))
(current-cell ()
"Returns the byte value stored in the current cell."
(the octet (gethash cell-pointer memory 0)))
((setf current-cell) (new-value)
"Stores the NEW-VALUE in the memory, on necessity wrapping it
around into the range [0, 255] prior to its admission."
(declare (type integer new-value))
(setf (gethash cell-pointer memory 0) (mod new-value 256))
(values)))
(loop while instruction do
(case instruction
((NIL) (loop-finish))
(#\C (switch-mode))
(#\+ (case mode
(0 (decf (current-cell)))
(1 (incf (current-cell)))
(T (error "Invalid mode: ~d." mode))))
(#\= (case mode
(0 (decf cell-pointer))
(1 (incf cell-pointer))
(T (error "Invalid mode: ~d." mode))))
(#\, (case mode
(0 (write-char (code-char (current-cell))))
(1 (format T "~&>> ")
(finish-output)
(setf (current-cell) (char-code (read-char)))
(clear-input))
(T (error "Invalid mode: ~d." mode))))
(#\( (when (zerop (current-cell))
(jump)))
(#\) (unless (zerop (current-cell))
(jump)))
(#\; (setf semicolon-set-p T)
(loop-finish))
(T NIL))
(advance))
(unless semicolon-set-p
(error 'Runtime-Error :position ip)))))