Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ch4

  • Loading branch information...
commit 47d8d0416884f69d7092c9b9e248c9dbad3b5d9d 1 parent 5510e33
@flaming0 authored
View
27 ch4/interpreter-python/Environment.py
@@ -1,14 +1,33 @@
+class EnvironmentException(Exception): pass
+
class Environment:
def __init__(self, initialFrame, baseEnv = None):
self.frame = initialFrame
self.baseEnv = baseEnv
- def defineVariable(self, variable, value):
- pass
+ def define(self, variable, value):
+ self.frame[variable.raw[0]] = value
+ print("Environment after define var:val", self.frame)
- def setVariableValue(self, variable, value):
- pass
+ def set(self, variable, value):
+ if variable.raw[0] in self.frame.keys():
+ self.frame[variable.raw[0]] = value
+ else:
+ if self.baseEnv:
+ self.baseEnv.set(variable, value)
+ else:
+ raise EnvironmentException
+ print("Environment after setting var:val", self.frame)
+
+ def lookup(self, variable):
+ if variable.raw[0] in self.frame.keys():
+ return self.frame[variable.raw[0]]
+ else:
+ if self.baseEnv:
+ self.baseEnv.lookup(variable)
+ else:
+ raise EnvironmentException
globalEnvironment = Environment({ "+" : lambda x, y: x + y,
View
18 ch4/interpreter-python/EvalApply.py
@@ -1,6 +1,5 @@
-from io import StringIO
-from tokenize import generate_tokens
from Expression import *
+from Environment import *
def analyzeExpr(expr):
if len(expr.raw) == 1 and "(" not in expr.raw and ")" not in expr.raw:
@@ -15,7 +14,7 @@ def analyzeExpr(expr):
def schemeEval(expr, env):
exp = analyzeExpr(expr)
- exp.eval()
+ return exp.eval(env)
def schemeApply(proc, args):
@@ -23,14 +22,13 @@ def schemeApply(proc, args):
def Eval(exprString, env):
- lst = [token[1] for token
- in generate_tokens(StringIO(exprString).readline)
- if token[1]]
- schemeEval(Expression(lst), env)
+ ret = schemeEval(Expression.makeExpression(exprString), env)
+ if isinstance(ret, Expression):
+ ret.apply()
# debug
if __name__ == "__main__":
- #schemeEval("(define (square x) (* x x))", None)
- Eval("(define x 2)", None)
- Eval("(set x 15)", None)
+ Eval("(define (square x) (* x x))", globalEnvironment)
+ #Eval("(define x 2)", globalEnvironment)
+ #Eval("(set x 15)", globalEnvironment)
View
110 ch4/interpreter-python/Expression.py
@@ -1,18 +1,24 @@
-from Environment import Environment, globalEnvironment
+from io import StringIO
+from tokenize import generate_tokens
+from functools import *
+from Environment import Environment
class ExpressionException(Exception): pass
class BadExpression(ExpressionException): pass
class PureVirtualFunctionCall(ExpressionException): pass # lol, abstract methods
+
+# expr.raw is Python list, that represents Scheme list like
+# ['(', 'define', '(', 'square', 'x', ')', '(', '*', 'x', 'x', ')', ')']
class Expression:
def __init__(self, exprList):
self.raw = exprList
-
+
def car(self):
if not len(self.raw):
raise BadExpression
-
+
if self.raw[1] == "(":
return Expression(self.raw[1:self.raw.index(")") + 1])
else:
@@ -31,12 +37,36 @@ def cdr(self):
temp = self.raw[2:]
temp.insert(0, "(")
return Expression(temp)
-
- def eval(self):
+
+ @staticmethod
+ def cons(e1, e2):
+ raw1 = reduce(lambda a, b: a + " " + b, e1.raw)
+ raw2 = reduce(lambda a, b: a + " " + b, e2.raw)
+ return Expression.makeExpression(raw2[0:1] + raw1 + raw2[1:])
+
+ @staticmethod
+ def list(*arg):
+ lst = ""
+ for it in arg:
+ lst += " "
+ if isinstance(it, Expression):
+ lst += reduce(lambda a, b: a + " " + b, it.raw)
+ else:
+ lst += str(it)
+ return Expression.makeExpression("(" + lst + ")")
+
+ @staticmethod
+ def makeExpression(string):
+ lst = [token[1] for token
+ in generate_tokens(StringIO(string).readline)
+ if token[1]]
+ return Expression(lst)
+
+ def eval(self, env):
raise PureVirtualFunctionCall
- #pass
-
- # def __repr__ maybe I should use this function?
+
+ def apply(self):
+ pass
class AssignmentExpression(Expression):
@@ -50,19 +80,23 @@ def __assignmentVariable(self):
def __assignmentValue(self):
return Expression([self.cdr().cdr().car().raw])
- def eval(self):
+ def eval(self, env):
print("Eval assignment:", self.raw)
- globalEnvironment.setVariableValue(
+ env.set(
self.__assignmentVariable(),
- schemeEval(self.__assignmentValue(), globalEnvironment)
+ schemeEval(self.__assignmentValue(), env)
)
+ return "ok"
+
+ def apply(self):
+ pass
class DefinitionExpression(Expression):
def __init__(self, exprList):
super().__init__(exprList)
-
+
def __definitionVariable(self):
var = self.cdr().car().raw
if isinstance(var, str):
@@ -72,20 +106,26 @@ def __definitionVariable(self):
# suppose, it's `(` symbol
# define procedure
return VariableExpression([self.cdr().car().car().raw])
-
+
def __definitionValue(self):
var = self.cdr().car().raw
if isinstance(var, str):
return Expression([self.cdr().cdr().car().raw])
else:
- raise BadExpression # make lambda
-
- def eval(self):
+ return LambdaExpression.makeLambda(
+ Expression(self.cdr().car().cdr().raw),
+ Expression(self.cdr().cdr().raw))
+
+ def eval(self, env):
print("Eval definition:", self.raw)
- globalEnvironment.defineVariable(
+ env.define(
self.__definitionVariable(),
- schemeEval(self.__definitionValue(), globalEnvironment)
+ schemeEval(self.__definitionValue(), env)
)
+ return "ok"
+
+ def apply(self):
+ pass
class IfExpression(Expression):
@@ -93,7 +133,7 @@ class IfExpression(Expression):
def __init__(self, exprList):
super().__init__(exprList)
- def eval(self):
+ def eval(self, env):
print("Eval if:", self.raw)
pass
@@ -103,8 +143,24 @@ class LambdaExpression(Expression):
def __init__(self, exprList):
super().__init__(exprList)
- def eval(self):
+ def __params(self):
+ return Expression(self.cdr().car().raw)
+
+ def __body(self):
+ return Expression(self.cdr().cdr().raw)
+
+ @staticmethod
+ def makeLambda(params, body):
+ paramsBody = Expression.cons(params, body)
+ return Expression.cons(Expression.makeExpression("lambda"), paramsBody)
+
+ def eval(self, env):
print("Eval lambda:", self.raw)
+ compoundProc = Expression.list("procedure", self.__params(), self.__body())
+ compoundProc.raw.insert(-1, env)
+ return compoundProc
+
+ def apply(self):
pass
@@ -113,18 +169,24 @@ class NumberExpression(Expression):
def __init__(self, exprList):
super().__init__(exprList)
- def eval(self):
+ def eval(self, env):
print("Eval number:", self.raw)
+ return self.raw[0]
+
+ def apply(self):
pass
-
-
+
+
class VariableExpression(Expression):
def __init__(self, exprList):
super().__init__(exprList)
- def eval(self):
+ def eval(self, env):
print("Eval variable:", self.raw)
+ return env.lookup(self)
+
+ def apply(self):
pass
Please sign in to comment.
Something went wrong with that request. Please try again.