bud 0.1.0.pre1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,6 @@
1
- require "set"
1
+ require 'set'
2
2
  require 'bud/collections'
3
+
3
4
  ELEMENT_BUFSIZE = 1
4
5
 
5
6
  module Bud
@@ -14,8 +15,8 @@ module Bud
14
15
  class PushElement < BudCollection
15
16
  attr_accessor :elem_name
16
17
  attr_accessor :rescan, :invalidated
17
- attr_reader :arity, :inputs, :found_delta, :refcount, :wired_by, :outputs
18
-
18
+ attr_reader :inputs, :found_delta, :refcount, :wired_by, :outputs
19
+
19
20
  def initialize(name_in, bud_instance, collection_name=nil, given_schema=nil, defer_schema=false, &blk)
20
21
  super(name_in, bud_instance, given_schema, defer_schema)
21
22
  @blk = blk
@@ -27,7 +28,6 @@ module Bud
27
28
  @elem_name = name_in
28
29
  @found_delta = false
29
30
  @refcount = 1
30
- @each_index = 0
31
31
  @collection_name = collection_name
32
32
  @invalidated = true
33
33
  @rescan = true
@@ -42,7 +42,7 @@ module Bud
42
42
  end
43
43
 
44
44
  public
45
- def print_wiring(depth=0, accum = "")
45
+ def print_wiring(depth=0, accum="")
46
46
  depth.times {print " "}
47
47
  puts "#{accum} #{(self.object_id*2).to_s(16)}: #{qualified_tabname} (#{self.class})"
48
48
 
@@ -54,11 +54,11 @@ module Bud
54
54
  next_accum = "+> "
55
55
  when @deletes.object_id, @delete_keys.object_id
56
56
  next_accum = "-> "
57
- end
58
-
57
+ end
58
+
59
59
  kind.each do |o|
60
- if o.respond_to?(:print_wiring)
61
- o.print_wiring(depth+1, next_accum)
60
+ if o.respond_to?(:print_wiring)
61
+ o.print_wiring(depth+1, next_accum)
62
62
  else
63
63
  (depth+1).times {print " "}
64
64
  print "#{next_accum} "
@@ -74,16 +74,16 @@ module Bud
74
74
 
75
75
  def check_wiring
76
76
  if @blk.nil? and @outputs.empty? and @pendings.empty? and @deletes.empty? and @delete_keys.empty?
77
- raise "no output specified for PushElement #{@qualified_tabname}"
77
+ raise Bud::Error, "no output specified for PushElement #{@qualified_tabname}"
78
78
  end
79
79
  end
80
-
80
+
81
81
  def set_block(&blk)
82
82
  @blk = blk
83
83
  end
84
84
  def wire_to(element)
85
- unless element.methods.include? :insert or element.methods.include? "insert"
86
- raise Bud::Error, "attempt to wire_to element without insert method"
85
+ unless element.respond_to? :insert
86
+ raise Bud::Error, "attempt to wire_to element without insert method"
87
87
  end
88
88
  # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
89
89
  # puts "wiring #{self.elem_name} to #{elem_name}"
@@ -91,22 +91,28 @@ module Bud
91
91
  element.wired_by << self if element.respond_to? :wired_by
92
92
  end
93
93
  def wire_to_pending(element)
94
- raise Bud::Error, "attempt to wire_to_pending element without pending_merge method" unless element.methods.include? "pending_merge" or element.methods.include? :pending_merge
95
- elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
94
+ unless element.respond_to? :pending_merge
95
+ raise Bud::Error, "attempt to wire_to_pending element without pending_merge method"
96
+ end
97
+ # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
96
98
  # puts "wiring #{self.elem_name} to #{elem_name}(pending)"
97
99
  @pendings << element
98
100
  element.wired_by << self if element.respond_to? :wired_by
99
101
  end
100
102
  def wire_to_delete(element)
101
- raise Bud::Error, "attempt to wire_to_delete element without pending_delete method" unless element.methods.include? "pending_delete" or element.methods.include? :pending_delete
102
- elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
103
+ unless element.respond_to? :pending_delete
104
+ raise Bud::Error, "attempt to wire_to_delete element without pending_delete method"
105
+ end
106
+ # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
103
107
  # puts "wiring #{self.elem_name} to #{elem_name}(delete)"
104
108
  @deletes << element
105
109
  element.wired_by << self if element.respond_to? :wired_by
106
110
  end
107
111
  def wire_to_delete_by_key(element)
108
- raise Bud::Error, "attempt to wire_to_delete_by_key element without pending_delete_keys method" unless element.methods.include? "pending_delete_keys" or element.methods.include? :pending_delete_keys
109
- elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
112
+ unless element.respond_to? :pending_delete_keys
113
+ raise Bud::Error, "attempt to wire_to_delete_by_key element without pending_delete_keys method"
114
+ end
115
+ # elem_name = element.respond_to?(:tabname) ? element.tabname : element.elem_name
110
116
  # puts "wiring #{self.elem_name} to #{elem_name}(delete)"
111
117
  @delete_keys << element
112
118
  element.wired_by << self if element.respond_to? :wired_by
@@ -116,7 +122,6 @@ module Bud
116
122
  false
117
123
  end
118
124
 
119
-
120
125
  def insert(item, source=nil)
121
126
  push_out(item)
122
127
  end
@@ -131,36 +136,34 @@ module Bud
131
136
 
132
137
  def push_out(item, do_block=true)
133
138
  if item
134
- blk = @blk if do_block
135
- if blk
136
- item = item.to_a if blk.arity > 1
137
- begin
138
- item = blk.call item
139
- rescue Exception
140
- raise
141
- end
139
+ if do_block && @blk
140
+ item = item.to_a if @blk.arity > 1
141
+ item = @blk.call item
142
142
  end
143
- @outputs.each do |ou|
144
- if ou.class <= Bud::PushElement
145
- #the_name = ou.elem_name
146
- # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
147
- ou.insert(item,self)
148
- elsif ou.class <= Bud::BudCollection
149
- # the_name = ou.tabname
150
- # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
151
- ou.do_insert(item,ou.new_delta)
152
- else
153
- raise "Expected either a PushElement or a BudCollection"
143
+
144
+ unless item.nil?
145
+ @outputs.each do |ou|
146
+ if ou.class <= Bud::PushElement
147
+ #the_name = ou.elem_name
148
+ # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
149
+ ou.insert(item, self)
150
+ elsif ou.class <= Bud::BudCollection
151
+ # the_name = ou.tabname
152
+ # puts "#{self.object_id%10000} (#{elem_name}) -> #{ou.object_id%10000} (#{the_name}): #{item.inspect}"
153
+ ou.do_insert(item, ou.new_delta)
154
+ else
155
+ raise Bud::Error, "expected either a PushElement or a BudCollection"
156
+ end
154
157
  end
155
- end unless item.nil?
156
- # for all the following, o is a BudCollection
157
- @deletes.each{|o| o.pending_delete([item])} unless item.nil?
158
- @delete_keys.each{|o| o.pending_delete_keys([item])} unless item.nil?
159
- @pendings.each{|o| o.pending_merge([item])} unless item.nil?
158
+
159
+ # for all the following, o is a BudCollection
160
+ @deletes.each{|o| o.pending_delete([item])}
161
+ @delete_keys.each{|o| o.pending_delete_keys([item])}
162
+ @pendings.each{|o| o.pending_merge([item])}
163
+ end
160
164
  end
161
165
  end
162
166
 
163
-
164
167
  # default for stateless elements
165
168
  public
166
169
  def add_rescan_invalidate(rescan, invalidate)
@@ -170,23 +173,25 @@ module Bud
170
173
  rescan << self
171
174
  end
172
175
 
173
- # pass the current state to the non-element outputs, and see if they end up marking this node for rescan
176
+ # pass the current state to the non-element outputs, and see if they end
177
+ # up marking this node for rescan
174
178
  invalidate_tables(rescan, invalidate)
175
179
 
176
- # finally, if this node is in rescan, pass the request on to all source elements
180
+ # finally, if this node is in rescan, pass the request on to all source
181
+ # elements
177
182
  if rescan.member? self
178
- srcs.each{|e| rescan << e} # propagate a rescan request to all sources.
183
+ rescan += srcs
179
184
  end
180
185
  end
181
186
 
182
187
  def invalidate_tables(rescan, invalidate)
183
- # exchange rescan and invalidate information with tables. If this node is in rescan, it may invalidate a target
184
- # table (if it is a scratch). And if the target node is invalidated, this node marks itself for rescan to
188
+ # exchange rescan and invalidate information with tables. If this node is
189
+ # in rescan, it may invalidate a target table (if it is a scratch). And if
190
+ # the target node is invalidated, this node marks itself for rescan to
185
191
  # enable a refill of that table at run-time
186
-
187
192
  @outputs.each do |o|
188
193
  unless o.class <= PushElement
189
- o.add_rescan_invalidate(rescan, invalidate) unless o.class <= PushElement
194
+ o.add_rescan_invalidate(rescan, invalidate)
190
195
  rescan << self if invalidate.member? o
191
196
  end
192
197
  end
@@ -211,45 +216,48 @@ module Bud
211
216
  # setup_accessors
212
217
  #end
213
218
 
214
-
219
+
215
220
  ####
216
221
  # and now, the Bloom-facing methods
217
222
  public
218
- def pro(the_name = @elem_name, the_schema = schema, &blk)
223
+ def pro(the_name=@elem_name, the_schema=schema, &blk)
219
224
  toplevel = @bud_instance.toplevel
220
- elem = Bud::PushElement.new('project' + object_id.to_s, toplevel.this_rule_context, @collection_name, the_schema)
221
- #elem.init_schema(the_schema) unless the_schema.nil?
225
+ elem = Bud::PushElement.new('project' + object_id.to_s,
226
+ toplevel.this_rule_context,
227
+ @collection_name, the_schema)
222
228
  self.wire_to(elem)
223
229
  elem.set_block(&blk)
224
- toplevel.push_elems[[self.object_id,:pro,blk]] = elem
230
+ toplevel.push_elems[[self.object_id, :pro, blk]] = elem
225
231
  return elem
226
232
  end
227
-
233
+
228
234
  alias each pro
229
-
235
+
230
236
  public
231
- def each_with_index(the_name = elem_name, the_schema = schema, &blk)
237
+ def each_with_index(the_name=elem_name, the_schema=schema, &blk)
232
238
  toplevel = @bud_instance.toplevel
233
- elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s, toplevel.this_rule_context, @collection_name)
239
+ elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s,
240
+ toplevel.this_rule_context,
241
+ @collection_name)
234
242
  elem.set_block(&blk)
235
243
  self.wire_to(elem)
236
- toplevel.push_elems[[self.object_id,:each,blk]] = elem
244
+ toplevel.push_elems[[self.object_id, :each, blk]] = elem
237
245
  end
238
-
246
+
239
247
  def join(elem2, &blk)
240
248
  # cached = @bud_instance.push_elems[[self.object_id,:join,[self,elem2], @bud_instance, blk]]
241
249
  # if cached.nil?
242
250
  elem2 = elem2.to_push_elem unless elem2.class <= PushElement
243
251
  toplevel = @bud_instance.toplevel
244
- join = Bud::PushSHJoin.new([self,elem2], toplevel.this_rule_context, [])
252
+ join = Bud::PushSHJoin.new([self, elem2], toplevel.this_rule_context, [])
245
253
  self.wire_to(join)
246
254
  elem2.wire_to(join)
247
- toplevel.push_elems[[self.object_id,:join,[self,elem2], toplevel, blk]] = join
255
+ toplevel.push_elems[[self.object_id, :join, [self, elem2], toplevel, blk]] = join
248
256
  toplevel.push_joins[toplevel.this_stratum] << join
249
257
  # else
250
258
  # cached.refcount += 1
251
259
  # end
252
- return toplevel.push_elems[[self.object_id,:join,[self,elem2], toplevel, blk]]
260
+ return toplevel.push_elems[[self.object_id, :join, [self, elem2], toplevel, blk]]
253
261
  end
254
262
  def *(elem2, &blk)
255
263
  join(elem2, &blk)
@@ -260,7 +268,7 @@ module Bud
260
268
  notin_elem = Bud::PushNotIn.new([self, elem2], toplevel.this_rule_context, preds, &blk)
261
269
  self.wire_to(notin_elem)
262
270
  elem2.wire_to(notin_elem)
263
- toplevel.push_elems[[self.object_id, :notin, collection, toplevel, blk]] == notin_elem
271
+ toplevel.push_elems[[self.object_id, :notin, collection, toplevel, blk]] = notin_elem
264
272
  return notin_elem
265
273
  end
266
274
 
@@ -268,20 +276,20 @@ module Bud
268
276
  if source.class <= PushElement and wiring?
269
277
  source.wire_to(self)
270
278
  else
271
- source.each{|i| self << i}
279
+ source.each {|i| self << i}
272
280
  end
273
281
  end
274
282
  alias <= merge
275
283
  superator "<~" do |o|
276
- raise Bud::Error, "Illegal use of <~ with pusher '#{tabname}' on left"
284
+ raise Bud::Error, "illegal use of <~ with pusher '#{tabname}' on left"
277
285
  end
278
286
 
279
287
  superator "<-" do |o|
280
- raise Bud::Error, "Illegal use of <- with pusher '#{tabname}' on left"
288
+ raise Bud::Error, "illegal use of <- with pusher '#{tabname}' on left"
281
289
  end
282
290
 
283
291
  superator "<+" do |o|
284
- raise Bud::Error, "Illegal use of <+ with pusher '#{tabname}' on left"
292
+ raise Bud::Error, "illegal use of <+ with pusher '#{tabname}' on left"
285
293
  end
286
294
 
287
295
  def group(keycols, *aggpairs, &blk)
@@ -293,13 +301,13 @@ module Bud
293
301
  aggcols = []
294
302
  aggcolsdups.each_with_index do |n, i|
295
303
  aggcols << "#{n.downcase}_#{i}".to_sym
296
- end
304
+ end
297
305
  if aggcols.empty?
298
306
  the_schema = keynames
299
307
  else
300
308
  the_schema = { keynames => aggcols }
301
309
  end
302
-
310
+
303
311
  aggpairs = aggpairs.map{|ap| ap[1].nil? ? [ap[0]] : [ap[0], canonicalize_col(ap[1])]}
304
312
  toplevel = @bud_instance.toplevel
305
313
  # if @bud_instance.push_elems[[self.object_id, :group, keycols, aggpairs, blk]].nil?
@@ -325,7 +333,7 @@ module Bud
325
333
  k[2]
326
334
  end
327
335
  end
328
- aggpairs = [[agg,collection]]
336
+ aggpairs = [[agg, collection]]
329
337
  # if toplevel.push_elems[[self.object_id,:argagg, gbkey_cols, aggpairs, blk]].nil?
330
338
  aa = Bud::PushArgAgg.new('argagg'+Time.new.tv_usec.to_s, toplevel.this_rule_context, @collection_name, gbkey_cols, aggpairs, schema, &blk)
331
339
  self.wire_to(aa)
@@ -345,8 +353,10 @@ module Bud
345
353
  wire_to(elem)
346
354
  elem
347
355
  end
348
- def push_predicate(pred_symbol, name=nil, bud_instance=nil, the_schema=nil, &blk)
349
- elem = Bud::PushPredicate.new(pred_symbol, name, bud_instance, the_schema, &blk)
356
+ def push_predicate(pred_symbol, name=nil, bud_instance=nil,
357
+ the_schema=nil, &blk)
358
+ elem = Bud::PushPredicate.new(pred_symbol, name, bud_instance,
359
+ the_schema, &blk)
350
360
  wire_to(elem)
351
361
  elem
352
362
  end
@@ -368,44 +378,45 @@ module Bud
368
378
  def one?(name=nil, bud_instance=nil, the_schema=nil, &blk)
369
379
  push_predicate(:one?, name, bud_instance, the_schema, &blk)
370
380
  end
371
-
381
+
372
382
  def reduce(initial, &blk)
373
383
  @memo = initial
374
- retval = Bud::PushReduce.new('reduce'+Time.new.tv_usec.to_s, @bud_instance, @collection_name, schema, initial, &blk)
384
+ retval = Bud::PushReduce.new("reduce#{Time.new.tv_usec}",
385
+ @bud_instance, @collection_name,
386
+ schema, initial, &blk)
375
387
  self.wire_to(retval)
376
388
  retval
377
389
  end
378
-
390
+
379
391
  alias on_exists? pro
380
392
  def on_include?(item, &blk)
381
393
  toplevel = @bud_instance.toplevel
382
- if toplevel.push_elems[[self.object_id,:on_include?, item, blk]].nil?
394
+ if toplevel.push_elems[[self.object_id, :on_include?, item, blk]].nil?
383
395
  inc = pro{|i| blk.call(item) if i == item and not blk.nil?}
384
396
  wire_to(inc)
385
- toplevel.push_elems[[self.object_id,:on_include?, item, blk]] = inc
397
+ toplevel.push_elems[[self.object_id, :on_include?, item, blk]] = inc
386
398
  end
387
- toplevel.push_elems[[self.object_id,:on_include?, item, blk]]
399
+ toplevel.push_elems[[self.object_id, :on_include?, item, blk]]
388
400
  end
389
401
  def inspected
390
402
  toplevel = @bud_instance.toplevel
391
- if toplevel.push_elems[[self.object_id,:inspected]].nil?
403
+ if toplevel.push_elems[[self.object_id, :inspected]].nil?
392
404
  ins = pro{|i| [i.inspect]}
393
405
  self.wire_to(ins)
394
- toplevel.push_elems[[self.object_id,:inspected]] = ins
406
+ toplevel.push_elems[[self.object_id, :inspected]] = ins
395
407
  end
396
- toplevel.push_elems[[self.object_id,:inspected]]
408
+ toplevel.push_elems[[self.object_id, :inspected]]
397
409
  end
398
-
410
+
399
411
  def to_enum
400
- # scr = @bud_instance.scratch(("scratch_" + Process.pid.to_s + "_" + object_id.to_s + "_" + rand(10000).to_s).to_sym, schema)
401
- scr = []
402
- self.wire_to(scr)
403
- scr
412
+ # scr = @bud_instance.scratch(("scratch_" + Process.pid.to_s + "_" + object_id.to_s + "_" + rand(10000).to_s).to_sym, schema)
413
+ scr = []
414
+ self.wire_to(scr)
415
+ scr
404
416
  end
405
- end
417
+ end
406
418
 
407
419
  class PushStatefulElement < PushElement
408
-
409
420
  def rescan_at_tick
410
421
  true
411
422
  end
@@ -415,10 +426,9 @@ module Bud
415
426
  end
416
427
 
417
428
  def add_rescan_invalidate(rescan, invalidate)
418
- # If an upstream node is set to rescan, a stateful node invalidates its cache
419
- # In addition, a stateful node always rescans its own contents (doesn't need to pass a rescan request to its
420
- # its source nodes
421
-
429
+ # If an upstream node is set to rescan, a stateful node invalidates its
430
+ # cache. In addition, a stateful node always rescans its own contents
431
+ # (doesn't need to pass a rescan request to its its source nodes).
422
432
  rescan << self
423
433
  srcs = non_temporal_predecessors
424
434
  if srcs.any? {|p| rescan.member? p}
@@ -435,7 +445,7 @@ module Bud
435
445
  @in_buf = []
436
446
  super(elem_name, bud_instance, collection_name, schema_in, &blk)
437
447
  end
438
-
448
+
439
449
  def insert(item, source)
440
450
  @in_buf << item
441
451
  end
@@ -450,13 +460,14 @@ module Bud
450
460
  @in_buf.clear
451
461
  end
452
462
  end
453
-
463
+
454
464
  class PushSort < PushStatefulElement
455
- def initialize(elem_name=nil, bud_instance=nil, collection_name=nil, schema_in=nil, &blk)
465
+ def initialize(elem_name=nil, bud_instance=nil, collection_name=nil,
466
+ schema_in=nil, &blk)
456
467
  @sortbuf = []
457
468
  super(elem_name, bud_instance, collection_name, schema_in, &blk)
458
469
  end
459
-
470
+
460
471
  def insert(item, source)
461
472
  @sortbuf << item
462
473
  end
@@ -476,12 +487,13 @@ module Bud
476
487
  @sortbuf = []
477
488
  end
478
489
  end
479
-
490
+
480
491
  class ScannerElement < PushElement
481
492
  attr_reader :collection
482
493
  attr_reader :rescan_set, :invalidate_set
483
- def initialize(elem_name, bud_instance, collection_in, the_schema=collection_in.schema, &blk)
484
- # puts self.class
494
+
495
+ def initialize(elem_name, bud_instance, collection_in,
496
+ the_schema=collection_in.schema, &blk)
485
497
  super(elem_name, bud_instance, collection_in.qualified_tabname, the_schema)
486
498
  @collection = collection_in
487
499
  @rescan_set = []
@@ -496,8 +508,9 @@ module Bud
496
508
  @collection.invalidate_at_tick # need to scan afresh if collection invalidated.
497
509
  end
498
510
 
511
+ # collection of others to rescan/invalidate if this scanner's collection
512
+ # were to be invalidated.
499
513
  def invalidate_at_tick(rescan, invalidate)
500
- # collection of others to rescan/invalidate if this scanner's collection were to be invalidated.
501
514
  @rescan_set = rescan
502
515
  @invalidate_set = invalidate
503
516
  end
@@ -507,19 +520,19 @@ module Bud
507
520
  # scanner elements are never directly connected to tables.
508
521
  rescan << self if invalidate.member? @collection
509
522
 
510
- # Note also that this node can be nominated for rescan by a target node; in other words, a scanner element
511
- # can be set to rescan even if the collection is not invalidated.
523
+ # Note also that this node can be nominated for rescan by a target node;
524
+ # in other words, a scanner element can be set to rescan even if the
525
+ # collection is not invalidated.
512
526
  end
513
527
 
514
528
  def scan(first_iter)
515
- if (first_iter)
529
+ if first_iter
516
530
  if rescan
517
- # scan entire storage
518
- @collection.each_raw {|item|
519
- push_out(item)
520
- }
531
+ # Scan entire storage
532
+ @collection.each_raw {|item| push_out(item)}
521
533
  else
522
- # In the first iteration, tick_delta would be non-null IFF the collection has grown in an earlier stratum
534
+ # In the first iteration, tick_delta would be non-null IFF the
535
+ # collection has grown in an earlier stratum
523
536
  @collection.tick_delta.each {|item| push_out(item)}
524
537
  end
525
538
  end
@@ -530,14 +543,15 @@ module Bud
530
543
  end
531
544
 
532
545
  class PushReduce < PushStatefulElement
533
- def initialize(elem_name, bud_instance, collection_name, schema_in, initial, &blk)
546
+ def initialize(elem_name, bud_instance, collection_name,
547
+ schema_in, initial, &blk)
534
548
  @memo = initial
535
549
  @blk = blk
536
550
  super(elem_name, bud_instance, collection_name, schema)
537
551
  end
538
552
 
539
553
  def insert(i, source=nil)
540
- @memo = @blk.call(@memo,i)
554
+ @memo = @blk.call(@memo, i)
541
555
  end
542
556
 
543
557
  def invalidate_cache
@@ -567,11 +581,12 @@ module Bud
567
581
 
568
582
  invalidate_tables(rescan, invalidate)
569
583
 
570
- # This node has some state (@each_index), but not the tuples. If it is in rescan mode, then it must ask its
571
- # sources to rescan, and restart its index.
584
+ # This node has some state (@each_index), but not the tuples. If it is in
585
+ # rescan mode, then it must ask its sources to rescan, and restart its
586
+ # index.
572
587
  if rescan.member? self
573
588
  invalidate << self
574
- srcs.each {|e| rescan << e}
589
+ rescan += srcs
575
590
  end
576
591
  end
577
592
 
@@ -585,7 +600,7 @@ module Bud
585
600
 
586
601
  def insert(item, source=nil)
587
602
  ix = @each_index
588
- @each_index = ix + 1
603
+ @each_index += 1
589
604
  push_out([item, ix])
590
605
  end
591
606
  end
@@ -5,7 +5,7 @@ module Bud
5
5
  def initialize(elem_name, bud_instance, collection_name, keys_in, aggpairs_in, schema_in, &blk)
6
6
  @groups = {}
7
7
  if keys_in.nil?
8
- @keys = []
8
+ @keys = []
9
9
  else
10
10
  @keys = keys_in.map{|k| k[1]}
11
11
  end
@@ -13,9 +13,9 @@ module Bud
13
13
  @aggpairs = aggpairs_in.map{|ap| ap[1].nil? ? [ap[0]] : [ap[0], ap[1][1]]}
14
14
  super(elem_name, bud_instance, collection_name, schema_in, &blk)
15
15
  end
16
-
16
+
17
17
  def insert(item, source)
18
- key = @keys.map{|k| item[k]}
18
+ key = @keys.map{|k| item[k]}
19
19
  @aggpairs.each_with_index do |ap, agg_ix|
20
20
  agg_input = ap[1].nil? ? item : item[ap[1]]
21
21
  agg = (@groups[key].nil? or @groups[key][agg_ix].nil?) ? ap[0].send(:init, agg_input) : ap[0].send(:trans, @groups[key][agg_ix], agg_input)[0]
@@ -43,7 +43,7 @@ module Bud
43
43
  #@groups = {}
44
44
  end
45
45
  end
46
-
46
+
47
47
  class PushArgAgg < PushGroup
48
48
  def initialize(elem_name, bud_instance, collection_name, keys_in, aggpairs_in, schema_in, &blk)
49
49
  raise "Multiple aggpairs #{aggpairs_in.map{|a| a.class.name}} in ArgAgg; only one allowed" if aggpairs_in.length > 1
@@ -63,7 +63,7 @@ module Bud
63
63
  def insert(item, source)
64
64
  key = @keys.map{|k| item[k]}
65
65
  @aggpairs.each_with_index do |ap, agg_ix|
66
- agg_input = item[ap[1]]
66
+ agg_input = item[ap[1]]
67
67
  if @groups[key].nil?
68
68
  agg = ap[0].send(:init, agg_input)
69
69
  @winners[key] = [item]
@@ -88,7 +88,7 @@ module Bud
88
88
  @groups[key] ||= Array.new(@aggpairs.length)
89
89
  @groups[key][agg_ix] = agg
90
90
  #push_out(nil)
91
- end
91
+ end
92
92
  end
93
93
 
94
94
  def flush