Documentation and report.
This commit is contained in:
@@ -1,20 +1,11 @@
|
||||
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)
|
||||
|
||||
### LISP.PY
|
||||
### Autumn Wolf
|
||||
### 04/26/26
|
||||
### CSE3024
|
||||
# This file (and contained class) handles lisp interpreter details, environment management, and expression evaluation.
|
||||
|
||||
class Function:
|
||||
def __init__(self, parameters, expression):
|
||||
@@ -28,11 +19,15 @@ class Lisp:
|
||||
else:
|
||||
self.env = env
|
||||
|
||||
# Recursively evaluate an expression
|
||||
def evaluate(self, expression):
|
||||
# Handle literals
|
||||
if type(expression) is not list:
|
||||
if expression in self.env.keys():
|
||||
return self.env[expression]
|
||||
return expression
|
||||
|
||||
# Handling of some special operations
|
||||
operation = expression[0]
|
||||
if type(operation) is list:
|
||||
operation = self.evaluate(operation)
|
||||
@@ -41,7 +36,7 @@ class Lisp:
|
||||
if operation == "QUOTE":
|
||||
return expression[1:][0]
|
||||
if operation != "DEFUN":
|
||||
arguments = [self.evaluate(x) for x in expression[1:]]
|
||||
arguments = [self.evaluate(x) for x in expression[1:]] # Don't evaluate for defun or quote!
|
||||
else:
|
||||
arguments = expression[1:]
|
||||
match operation:
|
||||
@@ -53,6 +48,7 @@ class Lisp:
|
||||
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")
|
||||
@@ -68,6 +64,7 @@ class Lisp:
|
||||
return [arguments[0]]+arguments[1]
|
||||
else:
|
||||
return [arguments[0]]+arguments[1]
|
||||
|
||||
case "SQRT":
|
||||
if len(arguments) != 1:
|
||||
raise ValueError("Expected 1 argument")
|
||||
@@ -76,6 +73,7 @@ class Lisp:
|
||||
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")
|
||||
@@ -111,9 +109,11 @@ class Lisp:
|
||||
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")
|
||||
@@ -132,6 +132,7 @@ class Lisp:
|
||||
else:
|
||||
raise ValueError("Undefined variable: " + str(arguments[0]))
|
||||
return arguments[0]
|
||||
|
||||
case "MAPCAR":
|
||||
if len(arguments) != 3:
|
||||
raise ValueError("Expected 3 arguments")
|
||||
@@ -140,14 +141,14 @@ class Lisp:
|
||||
result.append(self.evaluate([arguments[0], arguments[1][i], arguments[2][i]]))
|
||||
return result
|
||||
case _:
|
||||
if operation in self.env.keys():
|
||||
if operation in self.env.keys(): # Check for user-defined functions
|
||||
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]
|
||||
functionrunner.env[func.parameters[i]] = arguments[i] # Populate sub-interpreter environment
|
||||
return functionrunner.evaluate(self.env[operation].expression)
|
||||
else:
|
||||
raise TypeError("This value is not a valid function: " + operation)
|
||||
|
||||
Reference in New Issue
Block a user