Skip to content

A Lisp-style language whose programs consist entirely of parentheses.

Notifications You must be signed in to change notification settings

hpr/ParentheticLisp

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

#ParentheticLisp

ParentheticLisp is an extension of cammckinnon/Parenthetic, which is a programming language that uses only ( and ) as code. All other characters are considered comments.

ParentheticLisp is fully backwards-compatibile with the original Parenthetic, but it adds the ability to read from STDIN as well as several standard library commands (mostly to deal with reading input). The vast majority of the code was still written by cammckinnon.

##Hello World

The following Parenthetic program prints "Hello World" followed by a trailing newline:

((()()())(()(((()))))((())()()()()()()()()()()()()()()()()()()()()()()()()()()()
()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()))((()()())(()(((())
))())((())()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()
()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()))((()()())(()(((())
))()())((()(())(())())((())()()()()()()()()()()()()()()()()()()()()()()()()()()(
)()()()()())))((()()())(()(((())))()()())((()(())(())())((())()()()()()()()()()(
))))((()(()))((()(())(())())((()(()))(()(((())))())((())()()()()()()())))((()(()
)(())())((()(()))(()(((()))))((())()()()())))((()(())(())())((()(()))(()(((())))
)((())()()()()()()()()()()())))((()(())(())())((()(()))(()(((()))))((())()()()()
()()()()()()())))((()(())(())())((()(()))(()(((()))))((())()()()()()()()()()()()
()()())))(()(((())))()())((()(())(())())((()(()))(()(((())))())((())()()()()()()
()()()()()()()()()()()()()()()())))((()(())(())())((()(()))(()(((()))))((())()()
()()()()()()()()()()()())))((()(())(())())((()(()))(()(((()))))((())()()()()()()
()()()()()()()()()()())))((()(())(())())((()(()))(()(((()))))((())()()()()()()()
()()()())))((()(())(())())((()(()))(()(((()))))((())()()())))(()(((())))()()()))

##Installation

  1. Clone the repo, which includes an interpreter written in Python 2.7:

    git clone git@github.com:habstinat/ParentheticLisp.git

  2. Navigate to the ParentheticLisp directory and run the interpreter by typing:

    python parenthetic.py [filename.par]

  3. Or you can read input from stdin (terminated by Ctrl-D) by just running the program with no arguments:

    python parenthetic.py

##Syntax

ParentheticLisp uses Lisp-style expressions, where parentheses enclose expressions:

(foo arg1 arg2)

Note that parenthetic 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:

() () ()

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 (()) 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:

(
    integer macro
    (())
    3 sets of parentheses
    () () ()
)

Output: 3.0

Or equivalently:

((()) ()()())

Output: 3.0

Note that it doesn't matter how the parentheses in the sequence are nested within each other. For instance the following Parenthetic program prints 5.0 to the console:

((()) ((())) () () )

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 ()(()). Like with integers, there is a macro for interpreting parenthesis sequences as symbols. It is ().

For example, the following Parenthetic program prints 10 by using the multiplication function ()(()) to multiply 5 times 2:

(
    multiply [note the use of the [] macro]
    (() ()(()))

    2
    ((()) ()())

    5
    ((()) ()()()()())
)

Output: 10.0

Equivalent Lisp code:

(* 2 5)

It is also possible to define your own symbols, using the built-in 'define' function, whose symbol is ()().

Important: If you want to write portable ParentheticLisp code that doesn't shadow any standard library functions, present or future, you should begin your user-defined symbols with (((()))). Any standard library functions that are added in the future will not start with (((()))).

For example, the following code defines (())(()) as 6, then adds multiplies by 2 to get 12. Remember that all characters other than ( and ) characters are comments (including [ and ]).:

define [[]][[]] as 6
(
    define
    (() ()())

    [[]][[]]
    (() (())(()))
    
    6
    ((()) ()()()()()())
)

[[]][[]] * 2
(
    multiply
    (() ()(()))

    [[]][[]]
    (() (())(()))

    2
    ((()) ()())
)

Output: 12.0

Equivalent Lisp code:

(define x 6)
(* x 2)

##Standard Library

Parenthetic has a built-in standard library that is available by default (no includes/library imports necessary):

###define Symbol: ()()

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: (()())
  • multiply: ()(())
  • divide: (())()
  • add: (()). Note: You can also use add for concatenating characters/strings together (see the string section below).

Example:

(
    plus
    (() (()))
    
    3
    ((()) ()()())

    6
    ((()) ()()()()()())
)

Output: 9.0

Equivalent Lisp code:

(+ 3 6)

###lambda Symbol: ()

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
(
    define
    (() ()())

    [][][]
    (() ()()())

    (
        lambda
        (() ())

        (
            n [[]][]
            (() (())())
        )

        n + 1
        (
            plus
            (() (()))
            
            n [[]][]
            (() (())())

            1
            ((()) ())
        )
    )
)

7 + 1
(
    plus
    (() ()()())
    7
    ((()) ()()()()()()())
)

Output: 8.0

Equivalent Lisp code:

(define f
  (lambda (n)
    (+ n 1)))

(f 7)

###equal

Symbol: (())(())

Takes in two arguments. If they are equal, the True primitive is returned. Otherwise the False primitive is returned.

Example:

[equal 2 2]
(
    equal
    (() (())(()))
    2
    ((()) ()())
    2
    ((()) (()))
)

Output: True

Equivalent Lisp code:

(equal? 2 2)

###<=

Symbol: ()(())()

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]
(
    <=
    (() ()(())())
    3
    ((()) ()()())
    4
    ((()) (())(()))
)

Output: True

Equivalent Lisp code:

(<= 3 4)

###if

Symbol: ()()()

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
(
    if
    (() ()()())

    [equal 3 4]
    (
        equal
        (() (())(()))
        3
        ((()) ()()())
        4
        ((()) ((()))())
    )

    1
    ((()) ())
    2
    ((()) ()())
)

Output: 2.0

Equivalent Lisp code:

(if (equal? 3 4) 1 2)

###not

Symbol: ()(()())

If the argument is neither 0.0 nor False, True is returned. Otherwise, False is returned.

Example:

[not [equal 1 1]]
(
    not
    (() ()(()()))

    [equal 1 1]
    (
        equal
        (() ()(())())
        1
        ((()) ())
        1
        ((()) ())
    )
)

Output: False

Equivalent Lisp code:

(not (equal? 1 1))

###cons

Symbol: ((()))()

Takes in two arguments a and b and returns a pair (a, b).

Example:

(
    cons
    (() ((()))())

    1
    ((()) ())

    2
    ((()) ()())
)

Output: (1.0, 2.0)

Equivalent Lisp code:

(cons 1 2)

###car

Symbol: ((()))(())

Given a pair (a, b), returns a.

Example:

(
    car
    (() ((()))(()))

    (
        cons
        (() ((()))())

        1
        ((()) ())

        2
        ((()) ()())
    )
)

Output: 1.0

Equivalent Lisp code:

(car (cons 1 2))

###cdr

Symbol: ((()))()()

(
    cdr
    (() ((()))()())

    (
        cons
        (() ((()))())

        1
        ((()) ())

        2
        ((()) ()())
    )
)

Output: 2.0

Equivalent Lisp code:

(cdr (cons 1 2))

###empty

Symbol: ((()))

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 ().

Example:

(() ((())))

Output: ()

Equivalent Lisp code:

(list)

###charsof

Symbol: ()()()()

charsof takes an object of type String as its parameter and outputs a linked list of characters in the order of that string. It is useful for iterating through user input generated by readline.

Example:

Trim the first column from a line of user input
( exec
    (() (())()(())) string
    (
        (() ((()))()()) cdr
        (
            (() ()()()()) charsof
            ( (() ()((()))) ) readline[]
        )
    )
)

Input: Hello

Output: ello

###reverse

Symbol: ()()(())

reverse takes in a list and outputs a copy of that list reversed. It does not reverse the list in-place.

Example:

Reverses a line of user input
( exec
    (() (())()(())) string
    (
        (() ()()(())) reverse
        (
            (() ()()()()) charsof
            ( (() ()((()))) ) readline[]
        )
    )
)

Input: Hello

Output: olleH

###readline

Symbol: ()((()))

readline outputs a line read from stdin. Because readline uses mutable state, you would usually want to enclose it in an extra set of parentheses, as is done in the example.

Example:

Surrounds the input in parentheses
( exec
    (() ()()) define
    (() (((())))) 40 [[[[]]]]
    (
        (() ()(())) mult
        ((()) ()()()()()()()()()()) 10
        ((()) ()()()()) 4
    )
)
( exec
    (() ()()) define
    (() (((())))()) input [[[[]]]] []
    ( (() ()((()))) ) readline[]
)
( exec
    (() (())) concat
    (
        (() (())(())()) char
        (() (((())))) 40
    )
    (() (((())))()) input
    (
        (() (())(())()) char
        (
            (() (())) plus
            (() (((())))) 40
            ((()) ()) 1
        )
    )
)

Input Hello

Output (Hello)

###ord

Accepts one ascii character argument, and returns the corresponding integer.

Example:

Outputs the first input lowercase character as uppercase
( exec
    (() (())(())()) char
    (
        (() (()())) minus
        (
            (() (())()()) ord
            (
                (() ((()))(())) car
                (
                    (() ()()()()) charsof
                    ( (() ()((()))) ) readline[]
                )
            )
        )
        (
            (() ()(())) mult
            ((()) ()()()()()()()()) 8
            ((()) ()()()()) 4 
        )
    )
)

Input: a

Output: A

###char

Symbol: (())(())()

Accepts one integer argument, and returns the corresponding ascii character.

Example:

(
    char
    (() (())(())())

    33 [ascii value for '!']
    ((()) ()()()()()()()()()()
          ()()()()()()()()()()
          ()()()()()()()()()()
          ()()())
)

Output: !

###string

Symbol: (())()(())

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
(   define
    (() ()())
    97
    (() (()()))
    [+ 7 [* 9 10]]
    (
        (() (()))
        ((()) ()()()()()()())
        (
            (() ()(()))
            ((()) ()()()()()()()()())
            ((()) ()()()()()()()()()())
        )
    )
)

[string ['a', ['b', []]]]
(
    string
    (() (())()(()))
    (   
        cons
        (() ((()))())
        a
        (
            (() (())(())())
            (   
                (() (()))
                ((()) )
                (() (()()))
            )
        )

        (   
            cons
            (() ((()))())
            b
            (
                (() (())(())())
                (   
                    (() (()))
                    ((()) ())
                    (() (()()))
                )
            )
            empty
            (() ((())))
            
        )
    )   
)

Output: ab

Tip: You can also pass any combination of characters and strings into the add function (see above) 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

The original Parenthetic language was inspired by a conversation with Lucas, who said that scheme looks like this: ())()()()))))(). Well, it does now!

Also the esoteric language Parenthesis Hell was a great inspiration.

About

A Lisp-style language whose programs consist entirely of parentheses.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%