-
Notifications
You must be signed in to change notification settings - Fork 5
/
py2lisp.py
41 lines (33 loc) · 1.37 KB
/
py2lisp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!python
"""
This module translates Python source into Lisp forms.
The generated Lisp is little more than a Python-heavy DSL which depends on a
Lisp runtime for all the macro/function definitions.
"""
import ast
def translate(node_or_literal):
"Convert an AST node or Python literal into a Lisp form (recursively)."
if isinstance(node_or_literal, ast.AST):
symbol = "|py-%s|" % node_or_literal.__class__.__name__
if not node_or_literal._fields: # this is a leaf node
return "(%s)" % symbol
args = " ".join(translate(sub_nl)
for _, sub_nl in ast.iter_fields(node_or_literal))
return "(%s %s)" % (symbol, args)
return translate_literal(node_or_literal)
def translate_literal(literal):
"Translate a Python literal into a Lisp literal."
if isinstance(literal, str):
return translate_literal(literal.encode("utf-32-be"))
elif isinstance(literal, bytes):
return "#(%s)" % " ".join(map(str, literal))
elif literal is None:
return "|None|"
elif isinstance(literal, bool):
return "t" if literal else "nil"
elif isinstance(literal, list):
return "(%s)" % " ".join(map(translate, literal))
elif isinstance(literal, complex):
return "#C(%r %r)" % (literal.real, literal.imag)
else: # Should be an integer or float
return repr(literal)