Skip to content

Instantly share code, notes, and snippets.

@ytaki0801
Last active February 22, 2022 10:40
Show Gist options
  • Save ytaki0801/58d7e71f7b43b0800ec87799dd44a5ca to your computer and use it in GitHub Desktop.
Save ytaki0801/58d7e71f7b43b0800ec87799dd44a5ca to your computer and use it in GitHub Desktop.
A Pure LISP Interpreter in Pseudocode-style Python 3
####
#### ev.py: A Pure LISP Interpreter
#### in Pseudocode-style Python 3
####
#### (C) 2022 TAKIZAWA Yozo
#### This code is licensed under CC0.
#### https://creativecommons.org/publicdomain/zero/1.0/
####
#### <examples>
####
#### S> (((lambda (u) (u u)) (lambda (u) (lambda (a b) (if (eq a (quote ())) b ((u u) (cdr a) (cons (car a) b)))))) (quote (a b c d e)) (quote ()))
#### (e d c b a)
#### S> (((lambda (u) (u u)) (lambda (u) (lambda (a b) (if (eq a (quote ())) b (cons (car a) ((u u) (cdr a) b)))))) (quote (a b c)) (quote (x y z)))
#### (a b c x y z)
def cons(x, y):
return [x] + y
def car(x):
return x[0]
def cdr(x):
return x[1:]
def atom(x):
c = isinstance(x, str)
return c or x == []
def eq(x, y):
if atom(x) and atom(y):
return x == y
else:
return False
builtins = {'cons': cons,
'car' : car,
'cdr' : cdr,
'atom': atom,
'eq' : eq}
def slex(s):
global tokens
s = s.replace('(', ' ( ')
s = s.replace(')', ' ) ')
s = s.split(' ')
tokens = []
while s:
if car(s) != '':
tokens = tokens + [car(s)]
s = cdr(s)
def get_token():
global tp
tp = tp + 1
return tokens[tp - 1]
def slist():
t = get_token()
if t == ')':
return []
elif t == '(':
h = slist()
return cons(h, slist())
else:
return cons(t, slist())
def sread():
t = get_token()
if t == '(':
return slist()
else:
return t
def swrite(s):
if atom(s):
print(s, end='')
else:
print('(', end='')
swrite(car(s))
s = cdr(s)
while s:
print(' ', end='')
swrite(car(s))
s = cdr(s)
print(')', end='')
def quote_syntax(s):
return s[1]
def if_syntax(s, e):
if ev(s[1], e):
return ev(s[2], e)
else:
return ev(s[3], e)
def lambda_syntax(s, e):
return s + [e]
def apply_function(s, e):
f = ev(car(s), e)
a = []
s = cdr(s)
while s:
a = a + [ev(car(s), e)]
s = cdr(s)
if callable(f):
return f(*a)
else:
va = dict(zip(f[1], a))
e1 = dict(**f[3], **va)
return ev(f[2], e1)
def ev(s, e):
if atom(s):
if s in builtins:
return builtins[s]
else:
return e[s]
elif car(s) == 'quote':
return quote_syntax(s)
elif car(s) == 'if':
return if_syntax(s, e)
elif car(s) == 'lambda':
return lambda_syntax(s, e)
else:
return apply_function(s, e)
while True:
tokens, tp = [], 0
print('S> ', end='')
s = input().rstrip()
if s == 'exit':
break
else:
slex(s)
swrite(ev(sread(), {}))
print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment