Skip to content

Instantly share code, notes, and snippets.

@daeken
Last active December 15, 2015 10:09
Show Gist options
  • Select an option

  • Save daeken/5243257 to your computer and use it in GitHub Desktop.

Select an option

Save daeken/5243257 to your computer and use it in GitHub Desktop.
from funcpy import *
class Chord(object):
_chord_active = None
def __init__(self):
self._chord_queue = []
methods = {}
for method in self.chord_methods.split(' '):
methods[method] = rename_func(decorate(lambda name, *args: self._chord(name, args))(method), method)
setattr(self, method, methods[method])
self._chord_handler = None
for name in dir(self):
obj = getattr(self, name)
if hasattr(obj, '_chord_handler'):
self._chord_handler = obj
break
assert self._chord_handler != None
inner = inner_func(self._chord_handler)
inner.func_globals.update(methods)
self._chord_unexpected = None
self._chord_activate()
self._chord_handler = self._chord_handler()
self._chord_expect = self._chord_handler.next()
self._chord_deactivate()
self._chord_terminated = False
def _chord(self, name, args):
if self._chord_terminated:
return
type = getattr(self, name)
self._chord_activate()
while self._chord_expect == Chord.peek:
try:
self._chord_expect = self._chord_handler.send((type, args))
except StopIteration:
self._chord_terminated = True
self._chord_deactivate()
return
if self._chord_expect == Chord.pop:
try:
self._chord_expect = self._chord_handler.send((type, args))
except StopIteration:
self._chord_terminated = True
self._chord_deactivate()
return
expect = self._chord_expect.func_name
if name == expect:
try:
self._chord_expect = self._chord_handler.send(args[0] if len(args) == 1 else (args if len(args) else None))
except StopIteration:
self._chord_terminated = True
elif not self._chord_unexpected or not self._chord_unexpected(type, args):
self._chord_terminated = True
self._chord_deactivate()
def _chord_activate(self):
self._chord_oldactive = Chord._chord_active
Chord._chord_active = self
def _chord_deactivate(self):
Chord._chord_active = self._chord_oldactive
@staticmethod
def handler(func):
func._chord_handler = True
return func
@staticmethod
def unexpected(func):
Chord._chord_active._chord_unexpected = func
return func
@staticmethod
def ignore_unexpected():
Chord._chord_active._chord_unexpected = clambda(True)
@staticmethod
def peek():
pass
@staticmethod
def pop():
pass
@decorate
def chorded_class(methods, func, base=None, bases=None):
if base:
bases = [base]
if not bases:
bases = []
return type(func.func_name, tuple([Chord] + bases), dict(chord_methods=methods, __chord_method=Chord.handler(impartial(func, 1))))
chorded_object = wrap_inner(chorded_class, lambda x, f: x(f)())
if __name__=='__main__':
from xml import sax
@chorded_object('startElement endElement characters', base=sax.handler.ContentHandler)
def handler():
yield startElement
while True:
if (yield Chord.peek)[0] == endElement:
break
name, attrs = yield startElement
print 'start', name
print `(yield characters)`
print 'end', (yield endElement)
sax.parseString('<?xml version="1.0"?><test><hi>HI!</hi><bye>bye</bye></test>', handler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment