Approximately fully functional!

This commit is contained in:
etc404
2026-04-27 00:43:43 -06:00
parent 405f5f545a
commit 4ed01f8439
5 changed files with 187 additions and 13 deletions
+145 -3
View File
@@ -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)