rules(&t(X,Y)) := needs(&t(X,Y)), &r(X, sym(Y)).
rules(&t(X,Y,Z)) := needs(&t(X,Y,Z)), needs(Z), &r(X, sym(Y), sym(Z)).
+:- dispos &t(&).
+:- dispos &t(&,&).
+:- dispos &t(&,&,&).
+
% count the number of words in a subtree
+:- backchain numwords/1.
numwords(X) := 1.
numwords(t(X,Y)) := numwords(Y).
numwords(t(X,Y,Z)) := numwords(Y) + numwords(Z).
% extract word and it's position in tree
+:- backchain word/2.
word(0, X) := X.
word(I, t(X,Y)) := word(I, Y).
word(I, t(X,Y,Z)) := I < numwords(Y), word(I, Y).
word(I, t(X,Y,Z)) := I >= numwords(Y), word(I-numwords(Y), Z).
+%senword(S, I) := word(I, sentence(S)), between(0,I,numwords(S)).
+
% unnormalized
c(X,Y) += r(X,Y) is rules(&t(X1,Y1)), 1.
c(X,Y,Z) += r(X,Y,Z) is rules(&t(X1,Y1,Z1)), 1.
vcat
[ pretty (o^.mv_var)
<+> equals
- <+> "gbc" <> brackets (pfas f m)
- <> tupled (map (pretty . _mv_var) m)
+ <+> "gbc"
+ <> tupled (pfas f m : map (pretty . _mv_var) m)
, "if" <+> pretty (o^.mv_var) <+> "is not None" <> colon
]
-pdope_ bc (OPIter o m f _ Nothing) =
+pdope_ bc (OPIter o m f _ Nothing) =
assert (not $ (f,length m) `S.member` bc) $ do
i <- incState
return $ let mo = m ++ [o] in
hPutStrLn fh "\"\"\""
hPutStrLn fh ""
+ hPutStrLn fh $ "queries = []"
hPutStrLn fh $ "agg_decl = {}"
hPutStrLn fh $ "updaters = []"
hPutStrLn fh $ "initializers = []"
self.idx = idx
self.init = None
self.updaters = []
+ self.query = None
@property
def span(self):
- return parse_attrs(self.init)['Span']
+ return parse_attrs(self.init or self.query)['Span']
@property
def src(self):
- return parse_attrs(self.init)['rule']
+ return parse_attrs(self.init or self.query)['rule']
def __repr__(self):
return 'Rule(%s, %r)' % (self.idx, self.src)
# declarations
self.agg_name = defaultdict(none)
self.updaters = defaultdict(list)
+ self._gbc = defaultdict(list)
+
# data structures
self.agenda = prioritydict()
self.parser_state = ''
rule.updaters.append(handler)
handler.rule = rule
+
+ def gbc(self, fn, *args):
+ # TODO: need to distinguish `unknown` from `null`
+
+ head = self.build(fn, *args)
+
+ if head.value is not None:
+ return head.value
+
+ head.aggregator.clear()
+
+ def _emit(item, val, ruleix, variables):
+ assert item is head, [item, head]
+ head.aggregator.inc(val, ruleix, variables)
+
+ for h in self._gbc[fn]:
+ h(*args, emit=_emit)
+
+ head.value = head.aggregator.fold()
+ return head.value
+
+ def new_query(self, fn, ruleix, handler):
+ self._gbc[fn].append(handler)
+ rule = self.rules[ruleix]
+ assert rule.query is None
+ rule.query = handler
+ handler.rule = rule
+
def new_initializer(self, ruleix, init):
rule = self.rules[ruleix]
assert rule.init is None
for k,v in [('chart', self.chart),
('build', self.build),
+ ('gbc', self.gbc),
('peel', peel),
('uniform', uniform), ('log', log), ('exp', exp), ('sqrt', sqrt),
('pycall', pycall)]:
for k, v in env.agg_decl.items():
self.new_fn(k, v)
+ for fn, r, h in env.queries:
+ self.new_query(fn, r, h)
+
try:
if initialize:
# only run new initializers
# - maybe transaction isn't want I mean. Maybe all I want (for now
# is to avoid ^C.
- # add new updaters
for fn, r, h in env.updaters:
self.new_updater(fn, r, h)
- # add new initializers
for r, h in env.initializers:
self.new_initializer(r, h)
+
# accept the new parser state
self.parser_state = env.parser_state
# process emits
if args.plan:
plan = args.source
else:
- plan = dotdynadir / 'tmp' / args.source.read_hexhash('sha1') + '.plan.py'
+# plan = dotdynadir / 'tmp' / args.source.read_hexhash('sha1') + '.plan.py'
+ plan = args.source + '.plan.py'
dynac(args.source, plan)
if args.profile: