Рубрики
Без рубрики

Напишите LISP в Python

Недавно я подумал о том, как я могу объединить язык программирования LISP и Python, и попытался написать L … Tagged с Python, Lisp.

Недавно я подумал о том, как я могу объединить язык программирования LISP и Python, и попытался написать синтаксис LISP, как компилятор в Python. Что -то, что может преобразовать следующий код LISP:

(repeat 2 (write-ln (+ 10 20)))

к этому дереву:

word: "repeat"
    int: 2
    word: "write-ln"
        symbol: +
            int: 10
            int: 20

А затем напишите исполнителю для выполнения дерева.

Но я понял, что мне не нужно писать синтаксис -синтаксис Lisp. Вместо этого я могу использовать типы Python Builtins напрямую.

Например:

('repeat', ('print', ('add', 10, 20)))

А потом результатом моих мыслей было то, что я написал это простое Python Buldins Типы компилятора Анкет ( pbtc для сокращения)

#!/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)

Это не безопасно, это медленно, но работает.

Тестирование:

# filename: lispy

('print', 
    ('join', ' ', ('repeat', ('join', ' ', ['hi', 'bye']), 10))
    )

$./main.py Lispy :

hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye hi bye

Это весело…

Возможно, позже я написал более полную версию этого и опубликовал ее где -то, как открытый исходный код.

Оригинал: “https://dev.to/mak12776/write-lisp-in-python-42ph”