Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

282 lines (209 sloc) 7.729 kB
"""This syntax tree implements the general evaluation model for the
scripts.
"""
from scope import Scope
from urllib import urlopen
class Thunk(object):
def __init__(self, a, scope):
self.a = a
self.scope = scope
self.thunked = False
def __call__(self):
if not self.thunked:
self.v = self.a(self.scope)
self.thunked = True
return self.v
def export(f, count=None):
"""Expose a function in to the language.
based on http://refactormycode.com/codes/127-currying-decorator
"""
if count is None:
count = len(inspect.getargspec(f)[0])
def curhelp(n, args):
if n==0:
return f(*args)
else:
return lambda arg, scope: curhelp(n-1, args+[Thunk(arg, scope)])
curried = curhelp(count, [])
return lambda: curried
# statement nodes
class BlockNode(object):
def __init__(self, statements):
""""""
self.statements = statements
def __call__(self, scope):
r = None
for s in self.statements:
r = s(scope)
return r
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.statements)
class LetNode(object):
"""A binding node.
let binds a name to a value when it is evaluated
"""
def __init__(self, pairs):
self.pairs = pairs
def __call__(self, scope):
for name, value in self.pairs:
scope[name] = (lambda v: lambda: (v(scope)))(value)
return value
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.pairs)
class LetInNode(object):
"""A binding node,
Binds the name for only the expression provided.
"""
def __init__(self, pairs, child):
self.pairs = pairs
self.child = child
def __call__(self, scope):
scope = Scope(scope)
for name, value in self.pairs:
scope[name] = (lambda v: lambda: (v(scope)))(value)
return self.child(scope)
def __repr__(self):
return "%s(%r, %r)" % (self.__class__.__name__, self.pairs,
self.child)
class FileNode(object):
def __init__(self, filename):
self.filename = filename
def __call__(self, scope):
return self.filename
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.filename)
def __hash__(self):
return hash(self.filename)
class PlayNode(object):
def __init__(self, sound_server, resource):
self.sound_server = sound_server
self.resource = resource
def __call__(self, scope):
r = self.resource(scope)
self.sound_server.play(r)
return self
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.resource)
class WaitNode(object):
def __init__(self, sound_server, seconds, child):
self.sound_server = sound_server
self.wait_for = seconds
self.child = child
def __call__(self, scope):
print "Waiting %s, then %r" % (self.wait_for(scope), self.child)
self.sound_server.wait(self.wait_for(scope), lambda:self.child(scope))
return self
def __repr__(self):
return "%s(%r, %r)" % (self.__class__.__name__, self.wait_for
, self.child)
class LoadNode(object):
def __init__(self, resource, parser):
self.parser = parser
self.resource = resource
def __call__(self, scope):
print "Loading %s"% self.resource(scope)
text = urlopen(self.resource(scope)).read()
nodes = self.parser.parse_text(text, scope)
return nodes
def __repr__(self):
return "%s(%r, %r)" % (self.__class__.__name__, self.resource
, self.parser)
class CatalogNode(object):
"""docstring for CatalogNode"""
def __call__(self, scope):
return 'Bound names:\n' + u', '.join("%s" % name for name, val in scope.iteritems())
def __repr__(self):
return "%s()" % self.__class__.__name__
class FunctionDefNode(object):
def __init__(self, arg_names, body):
self.arg_names = arg_names
self.body = body
self.memos = {}
def __call__(self, scope):
def call(*args):
new_scope = Scope(scope)
for k, v in zip(self.arg_names, args):
new_scope[k] = v
return self.body(new_scope)
return export(call, len(self.arg_names))()
def __repr__(self):
return "%s(%r, %r)" % (self.__class__.__name__, self.arg_names
, self.body)
# infix syntax
class ValueNode(object):
"""This is a leaf node for single numeric values.
Evaluates to itself, has maximum precedence
"""
def __init__(self, value):
self.left = value
self.precedence = 1000
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.left)
def __call__(self, scope):
return self.left
def __hash__(self):
return hash(self.left)
def flatten(self):
return self
class LookupNode(object):
"""docstring for EvaluateNode"""
def __init__(self, name):
self.name = name
self.precedence = 1000
def __call__(self, scope):
return scope[self.name]()
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self.name)
def flatten(self):
return self
class FunctionCallNode(object):
"""docstring for EvaluateNode"""
def __init__(self, fun_exp, arg_exp):
self.fun_exp = fun_exp.flatten()
self.arg_exp = arg_exp.flatten()
self.precedence = 1000
def __call__(self, scope):
return self.fun_exp(scope)(self.arg_exp, scope)
def __repr__(self):
return "%s(%r, %r)" % (self.__class__.__name__,
self.fun_exp,
self.arg_exp)
def flatten(self):
return self
class ParentheticalNode(object):
"""This node encapsulates a child node.
This node will be merged into BinaryNodes as if it were a single
value; This protects parenthesized trees from having order adjusted.
"""
def __init__(self, child):
self.child = child
self.precedence = 1000
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__, self.child)
def __call__(self, scope):
return self.child(scope)
def flatten(self):
return self.child
class BinaryNode(object):
def __init__(self, op, left):
self.left = left
self.op = op
self.right = None
self.precedence = op.precedence
def flatten(self):
return self
def merge(self, right):
if self.precedence >= right.precedence:
self.right = right.left.flatten()
right.left = self
return right
else:
self.right = right.flatten()
self.left = self.left.flatten()
return self
def __repr__(self):
return "%s(%r, %r, %r)" % (self.__class__.__name__, self.op,
self.left,
self.right)
def __call__(self, scope):
return self.op(self.left, self.right, scope)
Jump to Line
Something went wrong with that request. Please try again.