On Sat, Jun 13, 2009 at 3:54 AM, Simon Forman<[email protected]> wrote: > Hello, > > I spent most of the last week reading the pdfs from the vpri.org site > and I am bowled over. It's amazing what you're accomplishing. > Congratulations. > > I am trying to understand the COLA architecture by way of building a > model of it in the python language. I think I've got the basic object > model down okay, but I'm having trouble grokking the eval/transform > system. I suspect there's an elegant twist there I'm just missing. > > The attached files are: > co.py - a python version of the basic object model. > la.py - an attempt at making the transformation engine. > rootbeer.py - a "port" of la.py to the co.py object model. > > Could someone take a look at those, or just fill in some detail about > section 5 "Behaviour: symbolic expressions and transformations" from > http://www.vpri.org/pdf/rn2006001a_colaswp.pdf "Accessible > Language-Based Environments of Recursive Theories"? I think I'm > missing something about how the transformation engine is supposed to > work. I dug through the Jolt(?) code but I could locate the magic. > > Thank you in advance, and thank you all for doing such incredible > work. The object model alone is breathtaking. >
I think I've managed to create a simple version of a COLA in python, following the descriptions in the pdfs on vpri.org. I was a little confused over the description of how the transform function was supposed to work with the symbols and contexts, but I think I made it work sufficiently like the paper(s) describe. In any event the simple COLA certainly works. Again, the COLA architecture is just breathtaking. I am so moved by the idea that a page or two of code can be so powerful and general. I'm trying now to create a very simple "bridge" between the COLA and Pepsi. I implemented a very simple Forth-like system using the COLA structures and on top of that I am writing a very simple parser (based on "A BNF Parser in Forth" http://www.bradrodriguez.com/papers/bnfparse.htm) which I hope then to use to parse pepsi source. My general idea is to write just enough code to be able to turn any basic COLA into a pepsi compiler, and thence into a full-fledged Coke/OMeta system capable of all the great and powerful magics. Is there a grammar for Pepsi? I've read http://piumarta.com/software/cola/pepsi.html and could figure it out from that document but I'd rather just work with a formal grammar. Warm regards, ~Simon -- "The history of mankind for the last four centuries is rather like that of an imprisoned sleeper, stirring clumsily and uneasily while the prison that restrains and shelters him catches fire, not waking but incorporating the crackling and warmth of the fire with ancient and incongruous dreams, than like that of a man consciously awake to danger and opportunity." --H. P. Wells, "A Short History of the World"
''' A simple model of an Object Model as per: "Open Reusable Object Models", Ian Piumarta, Alessandro Warth http://www.vpri.org/pdf/tr2006003a_objmod.pdf This departs in several ways from the OM described in that paper. It's meant mainly as a rough sketch done to better understand the ideas. There is no specific symbol type, we just use strings. The vtable also has no specific type, it's just an Object. Last, I lean on the python dict type to act as the vtable's storage. ''' class Object: ''' Root of the whole system, has a vtable and some data. ''' def __init__(self, vtable): self.vtable = vtable self.data = None def send(obj, name, *args, **keyword_args): method = bind(obj, name) return method(obj, *args, **keyword_args) def bind(obj, name): if obj.vtable is obj and name == 'lookup': return lookup(obj, name) return send(obj.vtable, 'lookup', name) def addMethod(vtable, name, implementation): vtable.data[name] = implementation def lookup(vtable, name): try: return vtable.data[name] except KeyError: if vtable.parent is not None: return send(vtable.parent, 'lookup', name) raise Exception("lookup failed for %r" % name) def delegated(vtable): vt = None if vtable is None else vtable.vtable child = Object(vt) # allocate() from the paper. child.parent = vtable child.data = {} # Map names to methods. return child def bootstrap(): # Create the VTable's VTable. vtvt = delegated(None) # VTable is its own VTable. vtvt.vtable = vtvt # Create a VTable for Objects. (Use delegated(None) so it has no # parent. In other words Object, not VTable, is the root of the # system.) object_vt = delegated(None) # Manually tell it it's a VTable. object_vt.vtable = vtvt # VTable is a kind of Object. Thus its VTable's parent is Object's # VTable and since it's its own VTable we just set its parent here. vtvt.parent = object_vt # Give VTable a lookup method by directly calling addMethod(). addMethod(vtvt, 'lookup', lookup) # Now the send() and bind() machinery will work. assert lookup is send(vtvt, 'lookup', 'lookup') # Add addMethod() to the VTable. addMethod(vtvt, 'addMethod', addMethod) # We can add the rest using send(). send(vtvt, 'addMethod', 'allocate', Object) # Use class as allocate(). send(vtvt, 'addMethod', 'delegated', delegated) # We're done. return object_vt, vtvt
#!/usr/bin/env python ''' Playing with integrating la.py and co.py So this is basically an attempt to understand: "Accessible Language-Based Environments of Recursive Theories", Ian Piumarta - http://www.vpri.org/pdf/rn2006001a_colaswp.pdf by implementing [part of] it in python. The co module implements the object model as simply and directly as I could, and the la module tries to implement the transformation engine using that object module. I'm not quite getting it. This works, but I think there's a much more elegant system just out of sight and the secret's in the way you dispatch the transform method to objects vs symbols. I'm not sure though. This is a somewhat more elegant take on rootbeer.py, I'm still not quite getting it though. The following classes/methods are constructed. Object.eval Object.transform Object.typeOf Symbol.transform Symbol.setName / Symbol.getName Symbol.setSymbol AST.init ''' from co import send def Eval(tree, context): symbol = send(tree, 'typeOf') if symbol is None: return method = send(symbol, 'transform', context) assert method is not None new_tree = method(tree, context) if new_tree is None: return return send(new_tree, 'eval', context) def setName(symbol, name): symbol.name = name def getName(symbol): return symbol.name def setSymbol(symbol, thing): thing.symbol = symbol def transform(symbol, context): name = send(symbol, 'getName') method = send(context, 'lookup', name) assert method is not None return method def typeOf(obj): try: return obj.symbol except AttributeError: pass def init_ast(ast, symbol, *values): ast.data = list(values) send(symbol, 'setSymbol', ast) # At this point the basic eval/transform widgetry is done. It still needs # some cruft to work though: ASTs and symbols to attach to the ASTs. def setUpTransformEngine(object_vt, vtvt): # Create a Symbol object type. symbol_vt = send(vtvt, 'delegated') # Create ast object type. ast_vt = send(object_vt, 'delegated') send(object_vt, 'addMethod', 'eval', Eval) send(object_vt, 'addMethod', 'transform', Eval) send(object_vt, 'addMethod', 'typeOf', typeOf) send(symbol_vt, 'addMethod', 'setName', setName) send(symbol_vt, 'addMethod', 'getName', getName) send(symbol_vt, 'addMethod', 'setSymbol', setSymbol) send(symbol_vt, 'addMethod', 'transform', transform) send(ast_vt, 'addMethod', 'init', init_ast) return symbol_vt, ast_vt
_______________________________________________ fonc mailing list [email protected] http://vpri.org/mailman/listinfo/fonc
