#Charactetic
Charactetic is a programming language that uses only a left
and right
characters as code. All other characters are considered comments.
It's forked from Parenthetic.
##Hello World
The following Charactetic program prints 'hello world', using 0 as left character and 1 as right:
00010101100100101110001001110001101010101010101100010100111000110101010101010101011
00011010101010101010101011111000101011001001010111000100110011011000110101010101010
10101010101010101010101010101010101010101010101010111100010011100010011001101100010
01110010010111000110101010101010111100010011001101100010011100100101110001101010101
11100010011001101100010011100100101110001101010101010101010101011110001001100110110
00100111001001011100011010101010101010101010111100010011001101100010011100100101110
00110101010101010101010101010101111001001010111000100110011011000100111001001011100
01101010101010101010101010101010101010101010101111000100110011011000100111001001011
10001101010101010101010101010101011110001001100110110001001110010010111000110101010
10101010101010101010101010111100010011001101100010011100100101110001101010101010101
010101011110001001100110110001001110010010111000110101011111
The following Charactetic program prints 'hello world' using • and ·:
•••·•·•··••·••·•···•••·••···•••··•·•·•·•·•·•·•··•••·•·••···•••··•·•·•·•·•·•·•·•·•··
•••··•·•·•·•·•·•·•·•·•·•·····•••·•·•··••·••·•·•···•••·••··••··•··•••··•·•·•·•·•·•·•
·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•····•••·••···•••·••··••··•··•••·•
•···••·••·•···•••··•·•·•·•·•·•·•····•••·••··••··•··•••·••···••·••·•···•••··•·•·•·•·
···•••·••··••··•··•••·••···••·••·•···•••··•·•·•·•·•·•·•·•·•·•·•····•••·••··••··•··•
••·••···••·••·•···•••··•·•·•·•·•·•·•·•·•·•·•····•••·••··••··•··•••·••···••·••·•···•
••··•·•·•·•·•·•·•·•·•·•·•·•·•·•····••·••·•·•···•••·••··••··•··•••·••···••·••·•···••
•··•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•·•····•••·••··••··•··•••·••···••·••·•··
·•••··•·•·•·•·•·•·•·•·•·•·•·•·•·•····•••·••··••··•··•••·••···••·••·•···•••··•·•·•·•
·•·•·•·•·•·•·•·•·•·•·•·•·•····•••·••··••··•··•••·••···••·••·•···•••··•·•·•·•·•·•·•·
•·•·•·•····•••·••··••··•··•••·••···••·••·•···•••··•·•·•·····
##Installation
-
Clone the repo, which includes an interpreter written in Python 2.7:
git clone [email protected]:cammckinnon/Charactetic.git
-
Navigate to the Charactetic directory and run the interpreter by typing:
python Charactetic.py
It accepts code as input from standard input. Input is read until EOF is found, after which the output is written to the console.
-
Or you can read input from a file like this:
cat program.p | python Charactetic.py
##Syntax
Charactetic uses Lisp-style expressions, where parentheses enclose expressions:
Lfoo arg1 arg2R
Note that Charactetic programs with unmatched parentheses are invalid
###Integers
A sequence of n parenthesis sets can be used to represent the integer n. For example the following sequence could represent the number 3:
LR LR LR
In order to tell the interpreter that you want the sequence to represent an integer, you must pass it as an argument to the built-in LLRR
macro. The macro acts like a function that accepts parenthesis sequences and returns integers. For example, the following program prints 3.0 to the console:
L
integer macro
LLRR
3 sets of parentheses
LR LR LR
R
Output: 3.0
Or equivalently:
LLLRR LRLRLRR
Output: 3.0
Note that it doesn't matter how the parentheses in the sequence are nested within each other. For instance the following Charactetic program prints 5.0 to the console:
LLLRR LLLRRR LR LR R
Output: 5.0
###Symbols
A symbol is a sequence of parentheses that corresponds to some data or a function. For example, the symbol for the built-in multiplication function is LRLLRR
. Like with integers, there is a macro for interpreting parenthesis sequences as symbols. It is LR
.
For example, the following Charactetic program prints 10 by using the multiplication function LRLLRR
to multiply 5 times 2:
L
multiply [note the use of the [] macro]
LLR LRLLRRR
2
LLLRR LRLRR
5
LLLRR LRLRLRLRLRR
R
Output: 10.0
Equivalent Lisp code:
L* 2 5R
It is also possible to define your own symbols, using the built-in 'define' function, whose symbol is LRLR
. For example, the following code defines LLRRLLRR
as 6, then adds multiplies by 2 to get 12. Remember that all characters other than L
and R
characters are comments Lincluding [
and ]
R.:
define [[]][[]] as 6
L
define
LLR LRLRR
[[]][[]]
LLR LLRRLLRRR
6
LLLRR LRLRLRLRLRLRR
R
[[]][[]] * 2
L
multiply
LLR LRLLRRR
[[]][[]]
LLR LLRRLLRRR
2
LLLRR LRLRR
R
Output: 12.0
Equivalent Lisp code:
Ldefine x 6R
L* x 2R
##Standard Library
Charactetic has a built-in standard library that is available by default Lno includes/library imports necessaryR:
###define
Symbol: LRLR
For details on define and its usage, see the Syntax->Symbols section above.
###multiply, divide, subtract, add These math operations can be performed on one or more numbers. Here are their symbols:
- subtract:
LLRLRR
- multiply:
LRLLRR
- divide:
LLRRLR
- add:
LLRR
. Note: You can also use add for concatenating characters/strings together Lsee the string section belowR.
Example:
L
plus
LLR LLRRR
3
LLLRR LRLRLRR
6
LLLRR LRLRLRLRLRLRR
R
Output: 9.0
Equivalent Lisp code:
L+ 3 6R
###lambda
Symbol: LR
Facilitates anonymous functions. Here's an example where we use define and lambda to create a function that takes in a number and adds 1 to it:
define a [][][] as a function that
takes in a number n and returns n + 1
L
define
LLR LRLRR
[][][]
LLR LRLRLRR
L
lambda
LLR LRR
L
n [[]][]
LLR LLRRLRR
R
n + 1
L
plus
LLR LLRRR
n [[]][]
LLR LLRRLRR
1
LLLRR LRR
R
R
R
7 + 1
L
plus
LLR LRLRLRR
7
LLLRR LRLRLRLRLRLRLRR
R
Output: 8.0
Equivalent Lisp code:
Ldefine f
Llambda LnR
L+ n 1RRR
Lf 7R
###equal
Symbol: LLRRLLRR
Takes in two arguments. If they are equal, the True primitive is returned. Otherwise the False primitive is returned.
Example:
[equal 2 2]
L
equal
LLR LLRRLLRRR
2
LLLRR LRLRR
2
LLLRR LLRRR
R
Output: True
Equivalent Lisp code:
Lequal? 2 2R
###<=
Symbol: LRLLRRLR
Takes in two numeric arguments a and b. If a <= b, the True primitive is returned. Otherwise the False primitive is returned.
Example:
[<= 3 4]
L
<=
LLR LRLLRRLRR
3
LLLRR LRLRLRR
4
LLLRR LLRRLLRRR
R
Output: True
Equivalent Lisp code:
L<= 3 4R
###if
Symbol: LRLRLR
Takes in three arguments: condition, then, and else. If condition is not false and not 0, the then argument is evaluated and returned. Otherwise, the else argument is evaluated and returned.
Example:
if 3 = 4, return 1, otherwise return 2
L
if
LLR LRLRLRR
[equal 3 4]
L
equal
LLR LLRRLLRRR
3
LLLRR LRLRLRR
4
LLLRR LLLRRRLRR
R
1
LLLRR LRR
2
LLLRR LRLRR
R
Output: 2.0
Equivalent Lisp code:
Lif Lequal? 3 4R 1 2R
###not
Symbol: LRLLRLRR
If the argument is neither 0.0 nor False, True is returned. Otherwise, False is returned.
Example:
[not [equal 1 1]]
L
not
LLR LRLLRLRRR
[equal 1 1]
L
equal
LLR LRLLRRLRR
1
LLLRR LRR
1
LLLRR LRR
R
R
Output: False
Equivalent Lisp code:
Lnot Lequal? 1 1RR
###cons
Symbol: LLLRRRLR
Takes in two arguments a and b and returns a pair La, bR
.
Example:
L
cons
LLR LLLRRRLRR
1
LLLRR LRR
2
LLLRR LRLRR
R
Output: L1.0, 2.0R
Equivalent Lisp code:
Lcons 1 2R
###car
Symbol: LLLRRRLLRR
Given a pair La, bR
, returns a
.
Example:
L
car
LLR LLLRRRLLRRR
L
cons
LLR LLLRRRLRR
1
LLLRR LRR
2
LLLRR LRLRR
R
R
Output: 1.0
Equivalent Lisp code:
Lcar Lcons 1 2RR
###cdr
Symbol: LLLRRRLRLR
L
cdr
LLR LLLRRRLRLRR
L
cons
LLR LLLRRRLRR
1
LLLRR LRR
2
LLLRR LRLRR
R
R
Output: 2.0
Equivalent Lisp code:
Lcdr Lcons 1 2RR
###empty
Symbol: LLLRRR
empty exists to facilitate lists. We define a list as a pair such that applying cdr one or more times to the list will return empty. Note - empty is not a function; it can be accessed directly. When printed to the console, empty appears as LR
.
Example:
LLR LLLRRRR
Output: LR
Equivalent Lisp code:
LlistR
###char
Symbol: LLRRLLRRLR
Accepts one integer argument, and returns the corresponding ascii character.
Example:
L
char
LLR LLRRLLRRLRR
33 [ascii value for '!']
LLLRR LRLRLRLRLRLRLRLRLRLR
LRLRLRLRLRLRLRLRLRLR
LRLRLRLRLRLRLRLRLRLR
LRLRLRR
R
Output: !
###string
Symbol: LLRRLRLLRR
Accepts a list of characters, and returns a string. string is useful for displaying messages.
Example:
define 97 for easy access to a and b
L define
LLR LRLRR
97
LLR LLRLRRR
[+ 7 [* 9 10]]
L
LLR LLRRR
LLLRR LRLRLRLRLRLRLRR
L
LLR LRLLRRR
LLLRR LRLRLRLRLRLRLRLRLRR
LLLRR LRLRLRLRLRLRLRLRLRLRR
R
R
R
[string ['a', ['b', []]]]
L
string
LLR LLRRLRLLRRR
L
cons
LLR LLLRRRLRR
a
L
LLR LLRRLLRRLRR
L
LLR LLRRR
LLLRR R
LLR LLRLRRR
R
R
L
cons
LLR LLLRRRLRR
b
L
LLR LLRRLLRRLRR
L
LLR LLRRR
LLLRR LRR
LLR LLRLRRR
R
R
empty
LLR LLLRRRR
R
R
R
Output: ab
Tip: You can also pass any combination of characters and strings into the add function Lsee aboveR to create strings.
##Error handling
If your program has a runtime error or a compiletime error the interpreter will print "Parenthesis Mismatch" to standard output and then exit.
##Test Suite
In the ./tests
folder there is a series of tests that check the interpreter for correctness.
python tests.py
You may find this useful if you wish to modify the interpreter's source code.
##Inspiration
This language was inspired by a conversation with [Lucas]Lhttp://www.lucaswoj.comR, who said that scheme looks like this: LRRLRLRLRRRRRLR. Well, it does now!
Also the esoteric language [Parenthesis Hell]Lhttp://esolangs.org/wiki/Parenthesis_HellR was a great inspiration.