Mercurial > code > home > repos > light9
view light9/effecteval/effect.py @ 1113:780e91cc21cc
dead code from the prototype
Ignore-this: 4b9f45d89e1571fc8fc305cf00a1729e
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Thu, 12 Jun 2014 08:59:52 +0000 |
parents | 4b542d321c8f |
children | 57eb333e6a4c |
line wrap: on
line source
import re, logging import toposort from rdflib import URIRef from light9.namespaces import L9, RDF from light9.curvecalc.curve import CurveResource from light9 import Submaster, Effects log = logging.getLogger('effect') # consider http://waxeye.org/ for a parser that can be used in py and js class CodeLine(object): """code string is immutable""" def __init__(self, graph, code): self.graph, self.code = graph, code self.outName, self.inExpr, self.expr, self.resources = self._asPython() self.pyResources = self._resourcesAsPython(self.resources) self.possibleVars = self.findVars(self.inExpr) def _asPython(self): """ out = sub(<uri1>, intensity=<curveuri2>) becomes 'out', 'sub(_u1, intensity=curve(_u2, t))', {'_u1': URIRef('uri1'), '_u2': URIRef('uri2')} """ lname, expr = [s.strip() for s in self.code.split('=', 1)] self.uriCounter = 0 resources = {} def alreadyInCurveFunc(s, i): prefix = 'curve(' return i >= len(prefix) and s[i-len(prefix):i] == prefix def repl(m): v = '_res%s' % self.uriCounter self.uriCounter += 1 r = resources[v] = URIRef(m.group(1)) if self._uriIsCurve(r): if not alreadyInCurveFunc(m.string, m.start()): return 'curve(%s, t)' % v return v outExpr = re.sub(r'<(http\S*?)>', repl, expr) return lname, expr, outExpr, resources def findVars(self, expr): """may return some more strings than just the vars""" withoutUris = re.sub(r'<(http\S*?)>', 'None', expr) tokens = set(re.findall(r'\b([a-zA-Z_]\w*)\b', withoutUris)) tokens.discard('None') return tokens def _uriIsCurve(self, uri): # this result could vary with graph changes (rare) return self.graph.contains((uri, RDF.type, L9['Curve'])) def _resourcesAsPython(self, resources): """ mapping of the local names for uris in the code to high-level objects (Submaster, Curve) """ out = {} subs = Submaster.get_global_submasters(self.graph) for localVar, uri in resources.items(): for rdfClass in self.graph.objects(uri, RDF.type): if rdfClass == L9['Curve']: cr = CurveResource(self.graph, uri) cr.loadCurve() out[localVar] = cr.curve elif rdfClass == L9['Submaster']: out[localVar] = subs.get_sub_by_uri(uri) else: out[localVar] = uri return out class EffectNode(object): def __init__(self, graph, uri): self.graph, self.uri = graph, uri # this is not expiring at the right time, when an effect goes away self.graph.addHandler(self.prepare) def prepare(self): log.info("prepare effect %s", self.uri) # maybe there can be multiple lines of code as multiple # objects here, and we sort them by dependencies codeStrs = list(self.graph.objects(self.uri, L9['code'])) if not codeStrs: raise ValueError("effect %s has no code" % self.uri) self.codes = [CodeLine(self.graph, s) for s in codeStrs] self.sortCodes() self.otherFuncs = Effects.configExprGlobals() def sortCodes(self): """put self.codes in a working evaluation order""" codeFromOutput = dict((c.outName, c) for c in self.codes) deps = {} for c in self.codes: outName = c.outName inNames = c.possibleVars.intersection(codeFromOutput.keys()) inNames.discard(outName) deps[outName] = inNames self.codes = [codeFromOutput[n] for n in toposort.toposort_flatten(deps)] def eval(self, songTime): ns = {'t': songTime} ns.update(self.otherFuncs) ns.update(dict( curve=lambda c, t: c.eval(t), )) for c in self.codes: codeNs = ns.copy() codeNs.update(c.pyResources) lineOut = eval(c.expr, codeNs) ns[c.outName] = lineOut if 'out' not in ns: log.error("ran code for %s, didn't make an 'out' value", self.uri) return ns['out']