DEV Community

Mohammad Amin Khakzadan
Mohammad Amin Khakzadan

Posted on • Edited on

5 2

Write lisp in python

I recently thought about how I can merge lisp programming language and python, and tried to write a lisp syntax like compiler in python. Some thing that can convert the following lisp code:

(repeat 2 (write-ln (+ 10 20)))
Enter fullscreen mode Exit fullscreen mode

to this tree:

word: "repeat"
    int: 2
    word: "write-ln"
        symbol: +
            int: 10
            int: 20
Enter fullscreen mode Exit fullscreen mode

And then write an executor for executing tree.

But I figured out that I don't need to write a lisp syntax parser. Instead I can use python builtins types directly.

for example:

('repeat', ('print', ('add', 10, 20)))
Enter fullscreen mode Exit fullscreen mode

And then the result of my thoughts was that I wrote this simple python builtins types compiler. (pbtc for shorthand)

#!/usr/bin/python3

# filename: main.py

import itertools
import sys

def add(*args):
    result = args[0] if len(args) != 0 else None
    for arg in args[1:]:
        result += arg
    return result

def sub(*args):
    result = args[0] if len(args) != 0 else None
    for arg in args[1:]:
        result -= arg
    return result

def mul(*args):
    result = args[0] if len(args) != 0 else None
    for arg in args[1:]:
        result *= arg
    return result

def div(*args):
    result = args[0] if len(args) != 0 else None
    for arg in args[1:]:
        result /= arg
    return result

def true_div(*args):
    result = args[0] if len(args) != 0 else None
    for arg in args[1:]:
        result //= arg
    return result

def join(sep, args):
    return sep.join(args)

tuple_compilers = {
    'add': add,
    'sub': sub,
    'mul': mul,
    'div': div,
    'tdiv': true_div,
    'print': lambda *args: print(*args),

    'join': join,
    'repeat': itertools.repeat,
}

def compile_tuple(tree, memory, compile):
    if len(tree) == 0:
        raise ValueError('invalid tuple length: {}'.format(len(tree)))
    if not isinstance(tree[0], str):
        raise ValueError('invalid tuple instruction: {}'.format(tree[0]))
    if tree[0] not in tuple_compilers:
        raise ValueError('unknown tuple instruction: {}'.format(tree[0]))
    args = []
    for node in tree[1:]:
        args.append(compile(node, memory))
    return tuple_compilers[tree[0]](*args)

compilers = {
    tuple: compile_tuple,
    (list, dict, str, int, float, bytes): 
        lambda tree, memory, compile: tree,
}

def compile_tree(tree, compilers, memory = None):
    self = lambda tree, memory: compile_tree(tree, compilers, memory)
    for _type, compile in compilers.items():
        if isinstance(tree, _type):
            return compile(tree, memory, self)
    raise TypeError(type(tree).__name__)

with open(sys.argv[1]) as infile:
    globals_dict = {}
    exec('grammar = ' + infile.read())

compile_tree(grammar, compilers)
Enter fullscreen mode Exit fullscreen mode

it's not safe, it's slow, but works.

testing:


# filename: lispy

('print', 
    ('join', ' ', ('repeat', ('join', ' ', ['hi', 'bye']), 10))
    )
Enter fullscreen mode Exit fullscreen mode

$./main.py lispy:

hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye
Enter fullscreen mode Exit fullscreen mode

It's fun...

Maybe later, I wrote a more complete version of this and publish it somewhere, as open source.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (2)

Collapse
 
jcubic profile image
Jakub T. Jankiewicz

I don't see any compilation step, it seems that what you've built is interpreter not the compiler. Example compiler would be script that generate python code based on your lips like syntax and you would execute that outside of the compiler.

Collapse
 
christopheriolo profile image
Christophe Riolo

Are you aware of Hy, that is exactly a lisp dialect of Python?

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay