Skip to content

Instantly share code, notes, and snippets.

@jolod
Last active November 2, 2019 22:54
Show Gist options
  • Select an option

  • Save jolod/982f66beb423bd9f998d05c5c5f2fbc0 to your computer and use it in GitHub Desktop.

Select an option

Save jolod/982f66beb423bd9f998d05c5c5f2fbc0 to your computer and use it in GitHub Desktop.
# I rewrote the code so that you can keep the os calls unchanged and only add yield before it.
# The interpreter is now represented by a class with static methods instead. The class only
# serves as a dictionary of functions.
import collections
import os
import types
Op = collections.namedtuple('Op', ['op', 'args', 'kwargs'])
class Ops:
def __getattribute__(self, attr):
return lambda *args, **kwargs: Op(attr, args, kwargs)
def count_chars_of_file(fn):
os = Ops()
fd = yield os.open(fn)
text = yield os.read(fd)
n = len(text)
yield os.close(fd)
return n
class Os:
@staticmethod
def open(filename):
fd = os.open(filename, os.O_RDONLY)
return fd
@staticmethod
def read(fh):
text = os.read(fh, 10000)
return text
@staticmethod
def close(fh):
os.close(fh)
return None
def runProgram(prog):
ops = Os()
def runOp(op):
return ops.__getattribute__(op.op)(*op.args, **op.kwargs)
try:
op = prog.send(None)
while True:
if isinstance(op, Op):
r = runOp(op)
op = prog.send(r)
elif isinstance(op, types.GeneratorType):
r = runProgram(op)
op = prog.send(r)
except StopIteration as e:
return e.value
if __name__ == '__main__':
import sys
filename = sys.argv[0]
program = count_chars_of_file(filename)
output = runProgram(program)
print(output)
# Added namespacing, so the full name of the action is 'os.open'.
# The namespace is passed to the action object, and the interpreter
# is now represented by a dictionary of objects, where the keys are
# the namespaces.
import collections
import os
import types
Op = collections.namedtuple('Op', ['qual', 'op', 'args', 'kwargs'])
class Ops:
def __init__(self, namespace):
self.__namespace = namespace
def __getattribute__(self, attr):
cls = type(self)
if attr.startswith('_' + cls.__name__ + '__'):
return super(cls, self).__getattribute__(attr)
else:
return lambda *args, **kwargs: Op(self.__namespace, attr, args, kwargs)
def count_chars_of_file(fn):
os = Ops('os')
fd = yield os.open(fn)
text = yield os.read(fd)
n = len(text)
yield os.close(fd)
return n
class Os:
@staticmethod
def open(filename):
fd = os.open(filename, os.O_RDONLY)
return fd
@staticmethod
def read(fh):
text = os.read(fh, 10000)
return text
@staticmethod
def close(fh):
os.close(fh)
return None
def runProgram(prog):
ops = dict(os = Os())
def runOp(op):
base = ops.get(op.qual, None)
if not base:
raise Exception("No handlers for qualifier: " + op.qual)
opname = op.op
try:
f = base.__getattribute__(opname)
except:
raise Exception("No handler for {!s}.{!s}".format(op.qual, opname))
return f(*op.args, **op.kwargs)
try:
op = prog.send(None)
while True:
if isinstance(op, Op):
r = runOp(op)
op = prog.send(r)
elif isinstance(op, types.GeneratorType):
r = runProgram(op)
op = prog.send(r)
else:
raise Exception(op)
except StopIteration as e:
return e.value
if __name__ == '__main__':
import sys
filename = sys.argv[0]
program = count_chars_of_file(filename)
output = runProgram(program)
print(output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment