2006-10-01

About the Rule Compiler

I was working on the Rule Compiler this weekend and managed to come, at least, a little bit forward. Currently it can parse (which includes a syntax and a sanity check) and split a Python function into pieces which can be used to assemble a Rete Network.

>>> import pyRete
>>> @pyRete.Rule
... def foo(a = Type1, b = Type2):
... salience = 100
... if a.n > b.n:
... print a.n, "is larger than", b.n

>>> rc = Rulecompiler(None, None)
>>> rc.compile(foo)
>>> rc._rule # NOTE! The dict below is not complete!
{ 'name' = 'foo',
'variables' = [('a', Type1), ('b', Type2),],
'literal-condition' = [],
'conditional-element' = [((Type1, 'n'), '>', (Type2, 'n')),],
..., }
As I was writing the code to split everything up into pieces. It occured to me that each test is nicely encapsulated in a form that "easily" can be converted into a code object. Take for example the conditional-element 'a.n > b.n'. It's AST node looks like this:
Compare(Getattr(Name('a'), 'n'), [('>', Getattr(Name('b'), 'n'))])
The RuleCompiler (in it's current state) produces:
((Type1, 'n'), '>', (Type2, 'n'))
which is used to construct a BetaNode.

But what if I keep the AST as is and call the compiler.pycodegen module to get a code object?

In that case, the join could be performed by binding the names 'a' and 'b' to an object of the right Type in the execution context and just evaluate the code object.

The BetaNode would definitely be harder to understand because everything would be wrapped up in already byte-compiled code but it would definitely reduce the amount of work that has to be performed to deconstruct one structure (AST) and reconstruct it as another (Rete).

Node sharing could still be supported as long as the If statement is split up into several (if there are more than one) conditional elements and literal conditions.

I'll probably keep things as they are at the moment because it allows me to inspect nodes at runtime but I'd like to explore that thought in more detail somewhere down the road.

The one place where I probably *will* use this technique is in the action (or consequence) part of the Rule (not implemented yet). I allow almost any code to be executed and Python is just too big a language... I'll make sure to create references in the execution context for all variables used and useful things like the Working Memory but that's about it.

I've also started to use CLIPS a bit more seriously (trying out a few of the things we're using Drools for at work). I like it. I wish I had done that a long time ago. ;-)

Inga kommentarer: