Approximately fully functional!
This commit is contained in:
@@ -1,6 +1,148 @@
|
||||
import atom
|
||||
import reader
|
||||
import math
|
||||
import string
|
||||
from functools import reduce
|
||||
|
||||
def prettyprint(expression) -> str:
|
||||
if type(expression) is list:
|
||||
retvalue = "("
|
||||
for x in expression:
|
||||
retvalue += prettyprint(x) + " "
|
||||
return retvalue.rstrip() + ")"
|
||||
elif type(expression) is bool:
|
||||
return "T" if expression else "NIL"
|
||||
elif str():
|
||||
return expression.upper()
|
||||
else:
|
||||
return str(expression)
|
||||
|
||||
|
||||
class Function:
|
||||
def __init__(self, parameters, expression):
|
||||
self.parameters = parameters
|
||||
self.expression = expression
|
||||
|
||||
class Lisp:
|
||||
def __init__(self, env=None):
|
||||
if env is None:
|
||||
self.env = {}
|
||||
else:
|
||||
self.env = env
|
||||
|
||||
def evaluate(self, expression):
|
||||
print(expression)
|
||||
if type(expression) is not list:
|
||||
if expression in self.env.keys():
|
||||
return self.env[expression]
|
||||
return expression
|
||||
operation = expression[0]
|
||||
if type(operation) is list:
|
||||
operation = self.evaluate(operation)
|
||||
if type(operation) is list:
|
||||
raise TypeError("This value is not a valid operation: " + str(operation))
|
||||
if operation == "QUOTE":
|
||||
return expression[1:][0]
|
||||
if operation != "DEFUN":
|
||||
arguments = [self.evaluate(x) for x in expression[1:]]
|
||||
else:
|
||||
arguments = expression[1:]
|
||||
match operation:
|
||||
case "+":
|
||||
return sum(arguments)
|
||||
case "-":
|
||||
return arguments[0] - sum(arguments[1:])
|
||||
case "*":
|
||||
return reduce(lambda x,y: x*y, arguments)
|
||||
case "/":
|
||||
return reduce(lambda x,y: x/y, arguments)
|
||||
case "CAR":
|
||||
if len(arguments) != 1:
|
||||
raise ValueError("Expected 1 argument")
|
||||
return arguments[0][0]
|
||||
case "CDR":
|
||||
if len(arguments) != 1:
|
||||
raise ValueError("Expected 1 argument")
|
||||
return arguments[0][1:]
|
||||
case "CONS":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
if type(arguments[0]) == list:
|
||||
return [arguments[0]]+arguments[1]
|
||||
else:
|
||||
return [arguments[0]]+arguments[1]
|
||||
case "SQRT":
|
||||
if len(arguments) != 1:
|
||||
raise ValueError("Expected 1 argument")
|
||||
return math.sqrt(arguments[0])
|
||||
case "POW":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return pow(arguments[0], arguments[1])
|
||||
case "IF":
|
||||
if len(arguments) != 3:
|
||||
raise ValueError("Expected 3 arguments")
|
||||
if arguments[0]:
|
||||
return arguments[1]
|
||||
else:
|
||||
return arguments[2]
|
||||
case ">":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return arguments[0] > arguments[1]
|
||||
case "<":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return arguments[0] < arguments[1]
|
||||
case "=":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return arguments[0] == arguments[1]
|
||||
case "!=":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return arguments[0] != arguments[1]
|
||||
case "AND":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return arguments[0] and arguments[1]
|
||||
case "OR":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
return arguments[0] or arguments[1]
|
||||
case "NOT":
|
||||
if len(arguments) != 1:
|
||||
raise ValueError("Expected 1 argument")
|
||||
return not arguments[0]
|
||||
case "QUIT":
|
||||
print(">> bye")
|
||||
raise SystemExit
|
||||
case "DEFINE":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
self.env[arguments[0]] = arguments[1]
|
||||
return arguments[0]
|
||||
case "DEFUN":
|
||||
if len(arguments) != 3:
|
||||
raise ValueError("Expected 3 arguments")
|
||||
self.env[arguments[0]] = Function(arguments[1], arguments[2])
|
||||
return arguments[0]
|
||||
case "SET!":
|
||||
if len(arguments) != 2:
|
||||
raise ValueError("Expected 2 arguments")
|
||||
if arguments[0] in self.env:
|
||||
self.env[arguments[0]] = arguments[1]
|
||||
else:
|
||||
raise ValueError("Undefined variable: " + str(arguments[0]))
|
||||
return arguments[0]
|
||||
case _:
|
||||
if operation in self.env.keys():
|
||||
if type(self.env[operation]) == Function:
|
||||
func = self.env[operation]
|
||||
functionrunner = Lisp(self.env)
|
||||
if len(arguments) != len(func.parameters):
|
||||
raise ValueError("Expected " + str(len(func.parameters)) + " arguments")
|
||||
for i in range(0, len(arguments)):
|
||||
functionrunner.env[func.parameters[i]] = arguments[i]
|
||||
return functionrunner.evaluate(self.env[operation].expression)
|
||||
else:
|
||||
raise TypeError("This value is not a valid function: " + operation)
|
||||
else:
|
||||
raise ValueError("Undefined operation: " + operation)
|
||||
Reference in New Issue
Block a user