bud 0.1.0.pre1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ module Bud
17
17
  class BudCollection
18
18
  include Enumerable
19
19
 
20
- attr_accessor :bud_instance, :locspec_idx, :tabname # :nodoc: all
20
+ attr_accessor :bud_instance, :tabname # :nodoc: all
21
21
  attr_reader :cols, :key_cols # :nodoc: all
22
22
  attr_reader :struct
23
23
  attr_reader :storage, :delta, :new_delta, :pending, :tick_delta # :nodoc: all
@@ -25,6 +25,7 @@ module Bud
25
25
  attr_accessor :invalidated, :to_delete, :rescan
26
26
  attr_accessor :is_source
27
27
  attr_accessor :wired_by
28
+ attr_accessor :accumulate_tick_deltas # updated in bud.do_wiring
28
29
 
29
30
  def initialize(name, bud_instance, given_schema=nil, defer_schema=false) # :nodoc: all
30
31
  @tabname = name
@@ -32,6 +33,7 @@ module Bud
32
33
  @invalidated = true
33
34
  @is_source = true # unless it shows up on the lhs of some rule
34
35
  @wired_by = []
36
+ @accumulate_tick_deltas = false
35
37
  init_schema(given_schema) unless given_schema.nil? and defer_schema
36
38
  init_buffers
37
39
  end
@@ -46,8 +48,6 @@ module Bud
46
48
  public
47
49
  def init_schema(given_schema)
48
50
  given_schema ||= {[:key]=>[:val]}
49
-
50
-
51
51
  @given_schema = given_schema
52
52
  @cols, @key_cols = BudCollection.parse_schema(given_schema)
53
53
  # Check that no location specifiers appear in the schema. In the case of
@@ -91,7 +91,7 @@ module Bud
91
91
  cols = key_cols + val_cols
92
92
  cols.each do |c|
93
93
  if c.class != Symbol
94
- raise Bud::Error, "Invalid column name \"#{c}\", type \"#{c.class}\""
94
+ raise Bud::Error, "invalid column name \"#{c}\", type \"#{c.class}\""
95
95
  end
96
96
  end
97
97
  if cols.uniq.length < cols.length
@@ -105,11 +105,6 @@ module Bud
105
105
  "#{self.class}:#{self.object_id.to_s(16)} [#{qualified_tabname}]"
106
106
  end
107
107
 
108
- public
109
- def clone_empty #:nodoc: all
110
- self.class.new(tabname, bud_instance, @given_schema)
111
- end
112
-
113
108
  # produces the schema in a format that is useful as the schema specification for another table
114
109
  public
115
110
  def schema
@@ -140,24 +135,14 @@ module Bud
140
135
  # set up schema accessors, which are class methods
141
136
  @cols_access = Module.new do
142
137
  sc.each_with_index do |c, i|
143
- m = define_method c do
138
+ define_method c do
144
139
  [@tabname, i, c]
145
140
  end
146
141
  end
147
142
  end
148
143
  self.extend @cols_access
149
-
150
- # now set up a Module for tuple accessors, which are instance methods
151
- @tupaccess = Module.new do
152
- sc.each_with_index do |colname, offset|
153
- define_method colname do
154
- self[offset]
155
- end
156
- end
157
- end
158
144
  end
159
145
 
160
-
161
146
  private
162
147
  def name_reserved?(colname)
163
148
  reserved = eval "defined?(#{colname})"
@@ -174,12 +159,6 @@ module Bud
174
159
  return true
175
160
  end
176
161
 
177
- # define methods to access tuple attributes by column name
178
- public
179
- def tuple_accessors(tup)
180
- tup # XXX remove tuple_acessors everywhere.
181
- end
182
-
183
162
  # generate a tuple with the schema of this collection and nil values in each attribute
184
163
  public
185
164
  def null_tuple
@@ -208,7 +187,7 @@ module Bud
208
187
 
209
188
  # projection
210
189
  public
211
- def pro(the_name = tabname, the_schema = schema, &blk)
190
+ def pro(the_name=tabname, the_schema=schema, &blk)
212
191
  pusher = to_push_elem(the_name, the_schema)
213
192
  pusher_pro = pusher.pro(&blk)
214
193
  pusher_pro.elem_name = the_name
@@ -217,45 +196,46 @@ module Bud
217
196
  end
218
197
 
219
198
  public
220
- def each_with_index(the_name = tabname, the_schema = schema, &blk)
199
+ def each_with_index(the_name=tabname, the_schema=schema, &blk)
221
200
  toplevel = @bud_instance.toplevel
222
201
  if not toplevel.done_wiring
223
202
  proj = pro(the_name, the_schema)
224
- elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s, toplevel.this_rule_context, tabname)
203
+ elem = Bud::PushEachWithIndex.new('each_with_index' + object_id.to_s,
204
+ toplevel.this_rule_context, tabname)
225
205
  elem.set_block(&blk)
226
206
  proj.wire_to(elem)
227
- toplevel.push_elems[[self.object_id,:each,blk]] = elem
207
+ toplevel.push_elems[[self.object_id, :each, blk]] = elem
228
208
  elem
229
209
  else
230
210
  storage.each_with_index
231
211
  end
232
212
  end
233
213
 
234
-
235
- # ruby 1.9 defines flat_map to return "a new array with the concatenated results of running
236
- # <em>block</em> once for every element". So we wire the input to a pro(&blk), and wire the output
237
- # of that pro to a group that does accum.
214
+ # ruby 1.9 defines flat_map to return "a new array with the concatenated
215
+ # results of running <em>block</em> once for every element". So we wire the
216
+ # input to a pro(&blk), and wire the output of that pro to a group that does
217
+ # accum.
238
218
  public
239
219
  def flat_map(&blk)
240
220
  pusher = self.pro(&blk)
241
221
  toplevel = @bud_instance.toplevel
242
222
  elem = Bud::PushElement.new(tabname, toplevel.this_rule_context, tabname)
243
223
  pusher.wire_to(elem)
244
- f = Proc.new do |t|
245
- t.each do |i|
246
- elem.push_out(i,false)
224
+ f = Proc.new do |t|
225
+ t.each do |i|
226
+ elem.push_out(i, false)
247
227
  end
248
228
  nil
249
229
  end
250
230
  elem.set_block(&f)
251
- toplevel.push_elems[[self.object_id,:flatten]] = elem
231
+ toplevel.push_elems[[self.object_id, :flatten]] = elem
252
232
  return elem
253
233
  end
254
234
 
255
- public
235
+ public
256
236
  def sort(&blk)
257
237
  pusher = self.pro
258
- pusher.sort(@name, @bud_instance, @cols, &blk)
238
+ pusher.sort("sort#{object_id}", @bud_instance, @cols, &blk)
259
239
  end
260
240
 
261
241
  def rename(the_name, the_schema=nil)
@@ -300,7 +280,6 @@ module Bud
300
280
  rule_num = bud_instance.this_rule
301
281
  addr = nil
302
282
  addr = bud_instance.ip_port unless bud_instance.port.nil?
303
- rule_txt = nil
304
283
  bud_instance.metrics[:collections] ||= {}
305
284
  bud_instance.metrics[:collections][{:addr=>addr, :tabname=>qualified_tabname, :strat_num=>strat_num, :rule_num=>rule_num}] ||= 0
306
285
  bud_instance.metrics[:collections][{:addr=>addr, :tabname=>qualified_tabname, :strat_num=>strat_num, :rule_num=>rule_num}] += 1
@@ -311,7 +290,7 @@ module Bud
311
290
  bufs.each do |b|
312
291
  b.each_value do |v|
313
292
  tick_metrics if bud_instance and bud_instance.options[:metrics]
314
- yield tuple_accessors(v)
293
+ yield v
315
294
  end
316
295
  end
317
296
  end
@@ -365,7 +344,7 @@ module Bud
365
344
  # is this enforced in do_insert?
366
345
  check_enumerable(k)
367
346
  t = @storage[k]
368
- return t.nil? ? @delta[k] : tuple_accessors(t)
347
+ return t.nil? ? @delta[k] : t
369
348
  end
370
349
 
371
350
  # checks for +item+ in the collection
@@ -400,7 +379,7 @@ module Bud
400
379
  private
401
380
  def raise_pk_error(new_guy, old)
402
381
  key = get_key_vals(old)
403
- raise KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key = #{key.inspect}"
382
+ raise Bud::KeyConstraintError, "key conflict inserting #{new_guy.inspect} into \"#{tabname}\": existing tuple #{old.inspect}, key = #{key.inspect}"
404
383
  end
405
384
 
406
385
  private
@@ -408,24 +387,22 @@ module Bud
408
387
  return o if o.class == @struct
409
388
  if o.class == Array
410
389
  if @struct.nil?
411
- sch = (1 .. o.length).map{|i| ("c"+i.to_s).to_sym}
390
+ sch = (1 .. o.length).map{|i| "c#{i}".to_sym}
412
391
  init_schema(sch)
413
392
  end
414
- o = o.take(@structlen) if o.length > @structlen
415
393
  elsif o.kind_of? Struct
416
394
  init_schema(o.members.map{|m| m.to_sym}) if @struct.nil?
417
- o = o.take(@structlen)
418
395
  else
419
- raise TypeError, "Array or struct type expected in \"#{qualified_tabname}\": #{o.inspect}"
396
+ raise Bud::TypeError, "array or struct type expected in \"#{qualified_tabname}\": #{o.inspect}"
420
397
  end
398
+
399
+ o = o.take(@structlen) if o.length > @structlen
421
400
  return @struct.new(*o)
422
401
  end
423
402
 
424
403
  private
425
404
  def get_key_vals(t)
426
- @key_colnums.map do |i|
427
- t[i]
428
- end
405
+ @key_colnums.map {|i| t[i]}
429
406
  end
430
407
 
431
408
  public
@@ -445,7 +422,7 @@ module Bud
445
422
 
446
423
  old = store[key]
447
424
  if old.nil?
448
- store[key] = tuple_accessors(o)
425
+ store[key] = o
449
426
  else
450
427
  raise_pk_error(o, old) unless old == o
451
428
  end
@@ -465,7 +442,7 @@ module Bud
465
442
  private
466
443
  def check_enumerable(o)
467
444
  unless o.nil? or o.class < Enumerable or o.class <= Proc
468
- raise TypeError, "Collection #{qualified_tabname} expected Enumerable value, not #{o.inspect} (class = #{o.class})"
445
+ raise Bud::TypeError, "collection #{qualified_tabname} expected Enumerable value, not #{o.inspect} (class = #{o.class})"
469
446
  end
470
447
  end
471
448
 
@@ -502,34 +479,27 @@ module Bud
502
479
  init_schema((0..arity-1).map{|indx| ("c"+indx.to_s).to_sym})
503
480
  end
504
481
 
505
- private
506
- def include_any_buf?(t, key)
507
- bufs = [self, @delta, @new_delta]
508
- bufs.each do |b|
509
- old = b[key]
510
- next if old.nil?
511
- if old != t
512
- raise_pk_error(t, old)
513
- else
514
- return true
515
- end
482
+ protected
483
+ def add_merge_target
484
+ toplevel = @bud_instance.toplevel
485
+ if toplevel.done_bootstrap
486
+ toplevel.merge_targets[toplevel.this_stratum] << self
516
487
  end
517
- return false
518
488
  end
519
489
 
520
490
  public
521
491
  def merge(o, buf=@delta) # :nodoc: all
522
492
  toplevel = @bud_instance.toplevel
523
493
  if o.class <= Bud::PushElement
524
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
494
+ add_merge_target
525
495
  deduce_schema(o) if @cols.nil?
526
496
  o.wire_to self
527
497
  elsif o.class <= Bud::BudCollection
528
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
498
+ add_merge_target
529
499
  deduce_schema(o) if @cols.nil?
530
500
  o.pro.wire_to self
531
501
  elsif o.class <= Proc and toplevel.done_bootstrap and not toplevel.done_wiring and not o.nil?
532
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
502
+ add_merge_target
533
503
  tbl = register_coll_expr(o)
534
504
  tbl.pro.wire_to self
535
505
  else
@@ -543,17 +513,9 @@ module Bud
543
513
  return self
544
514
  end
545
515
 
546
- # def prep_coll_expr(o)
547
- # o = o.uniq.compact if o.respond_to?(:uniq)
548
- # check_enumerable(o)
549
- # establish_schema(o) if @cols.nil?
550
- # o
551
- # end
552
-
553
516
  def register_coll_expr(expr)
554
- # require 'ruby-debug'; debugger
555
- coll_name = ("expr_"+expr.object_id.to_s)
556
- cols = (1..@cols.length).map{|i| ("c"+i.to_s).to_sym} unless @cols.nil?
517
+ coll_name = "expr_#{expr.object_id}"
518
+ cols = (1..@cols.length).map{|i| "c#{i}".to_sym} unless @cols.nil?
557
519
  @bud_instance.coll_expr(coll_name.to_sym, expr, cols)
558
520
  coll = @bud_instance.send(coll_name)
559
521
  coll
@@ -570,13 +532,13 @@ module Bud
570
532
  def pending_merge(o) # :nodoc: all
571
533
  toplevel = @bud_instance.toplevel
572
534
  if o.class <= Bud::PushElement
573
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
535
+ add_merge_target
574
536
  o.wire_to_pending self
575
537
  elsif o.class <= Bud::BudCollection
576
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
538
+ add_merge_target
577
539
  o.pro.wire_to_pending self
578
540
  elsif o.class <= Proc and toplevel.done_bootstrap and not toplevel.done_wiring
579
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
541
+ add_merge_target
580
542
  tbl = register_coll_expr(o) unless o.nil?
581
543
  tbl.pro.wire_to_pending self
582
544
  else
@@ -599,7 +561,7 @@ module Bud
599
561
  end
600
562
 
601
563
  def tick
602
- raise "tick must be overriden in #{self.class}"
564
+ raise Bud::Error, "tick must be overriden in #{self.class}"
603
565
  end
604
566
 
605
567
  # move deltas to storage, and new_deltas to deltas.
@@ -609,12 +571,15 @@ module Bud
609
571
  unless @delta.empty?
610
572
  puts "#{qualified_tabname}.tick_delta delta --> storage (#{@delta.size} elems)" if $BUD_DEBUG
611
573
  @storage.merge!(@delta)
612
- @tick_delta += @delta.values
574
+ @tick_delta += @delta.values if accumulate_tick_deltas
613
575
  @delta.clear
614
576
  end
615
577
 
616
578
  unless @new_delta.empty?
617
579
  puts "#{qualified_tabname}.tick_delta new_delta --> delta (#{@new_delta.size} elems)" if $BUD_DEBUG
580
+
581
+ # XXX: what about multiple delta tuples produced in the same tick that
582
+ # conflict on the PK?
618
583
  @new_delta.each_pair do |k, v|
619
584
  sv = @storage[k]
620
585
  if sv.nil?
@@ -631,8 +596,9 @@ module Bud
631
596
 
632
597
  public
633
598
  def add_rescan_invalidate(rescan, invalidate)
634
- # No change. Most collections don't need to rescan on every tick (only do so on negate). Also, there's no cache
635
- # to invalidate by default. Scratches and PushElements override this method.
599
+ # No change. Most collections don't need to rescan on every tick (only do
600
+ # so on negate). Also, there's no cache to invalidate by default.
601
+ # Scratches and PushElements override this method.
636
602
  end
637
603
 
638
604
  def bootstrap
@@ -648,9 +614,9 @@ module Bud
648
614
  puts "#{qualified_tabname}.flush delta --> storage" unless @delta.empty?
649
615
  puts "#{qualified_tabname}.flush new_delta --> storage" unless @new_delta.empty?
650
616
  end
651
- unless (@delta.empty?)
617
+ unless @delta.empty?
652
618
  @storage.merge!(@delta)
653
- @tick_delta += @delta.values
619
+ @tick_delta += @delta.values if accumulate_tick_deltas
654
620
  @delta.clear
655
621
  end
656
622
  unless @new_delta.empty?
@@ -664,7 +630,6 @@ module Bud
664
630
  def to_push_elem(the_name=tabname, the_schema=schema)
665
631
  # if no push source yet, set one up
666
632
  toplevel = @bud_instance.toplevel
667
- #rule_context = toplevel.this_rule_context
668
633
  this_stratum = toplevel.this_stratum
669
634
  oid = self.object_id
670
635
  unless toplevel.scanners[this_stratum][[oid, the_name]]
@@ -674,17 +639,6 @@ module Bud
674
639
  return toplevel.scanners[this_stratum][[oid, the_name]]
675
640
  end
676
641
 
677
- private
678
- def method_missing(sym, *args, &block)
679
- begin
680
- @storage.send sym, *args, &block
681
- rescue Exception => e
682
- err = NoMethodError.new("no method :#{sym} in class #{self.class.name}")
683
- err.set_backtrace(e.backtrace)
684
- raise err
685
- end
686
- end
687
-
688
642
  ######## aggs
689
643
 
690
644
  private
@@ -699,16 +653,14 @@ module Bud
699
653
  end
700
654
  end
701
655
 
702
-
703
656
  # a generalization of argmin/argmax to arbitrary exemplary aggregates.
704
657
  # for each distinct value of the grouping key columns, return the items in that group
705
658
  # that have the value of the exemplary aggregate +aggname+
706
659
  public
707
660
  def argagg(aggname, gbkey_cols, collection)
708
661
  elem = to_push_elem
709
- elem.schema
710
662
  gbkey_cols = gbkey_cols.map{|k| canonicalize_col(k)} unless gbkey_cols.nil?
711
- retval = elem.argagg(aggname,gbkey_cols,canonicalize_col(collection))
663
+ retval = elem.argagg(aggname, gbkey_cols, canonicalize_col(collection))
712
664
  # PushElement inherits the schema accessors from this Collection
713
665
  retval.extend @cols_access
714
666
  retval
@@ -722,37 +674,21 @@ module Bud
722
674
  argagg(:min, gbkey_cols, col)
723
675
  end
724
676
 
725
- # for each distinct value of the grouping key columns, return the item in
726
- # that group that has the maximum value of the attribute +col+. Note that
677
+ # for each distinct value of the grouping key columns, return the items in
678
+ # that group that have the maximum value of the attribute +col+. Note that
727
679
  # multiple tuples might be returned.
728
680
  public
729
681
  def argmax(gbkey_cols, col)
730
682
  argagg(:max, gbkey_cols, col)
731
683
  end
732
684
 
733
- private
734
- def wrap_map(j, &blk)
735
- if blk.nil?
736
- return j
737
- else
738
- return j.map(&blk)
739
- end
740
- end
741
-
742
- # def join(collections, *preds, &blk)
743
- # # since joins are stateful, we want to allocate them once and store in this Bud instance
744
- # # we ID them on their tablenames, preds, and block
745
- # return wrap_map(BudJoin.new(collections, @bud_instance, preds), &blk)
746
- # end
747
-
748
685
  # form a collection containing all pairs of items in +self+ and items in
749
686
  # +collection+
750
687
  public
751
688
  def *(collection)
752
- elem1 = to_push_elem
689
+ elem1 = to_push_elem
753
690
  j = elem1.join(collection)
754
691
  return j
755
- # join([self, collection])
756
692
  end
757
693
 
758
694
  def group(key_cols, *aggpairs, &blk)
@@ -778,14 +714,14 @@ module Bud
778
714
  elem1 = to_push_elem
779
715
  red_elem = elem1.reduce(initial, &blk)
780
716
  return red_elem
781
- end
717
+ end
782
718
 
783
719
  public
784
720
  def pretty_print_instance_variables
785
721
  # list of attributes (in order) to print when pretty_print is called.
786
722
  important = ["@tabname", "@storage", "@delta", "@new_delta", "@pending"]
787
723
  # everything except bud_instance
788
- important + (self.instance_variables - important - ["@bud_instance"])
724
+ important + (self.instance_variables - important - ["@bud_instance"])
789
725
  end
790
726
 
791
727
  public
@@ -796,9 +732,12 @@ module Bud
796
732
  end
797
733
 
798
734
  class BudScratch < BudCollection # :nodoc: all
735
+ def accumulate_tick_deltas
736
+ false
737
+ end
738
+
799
739
  public
800
740
  def tick # :nodoc: all
801
- @tick_delta.clear
802
741
  @delta.clear
803
742
  if not @pending.empty?
804
743
  invalidate_cache
@@ -815,20 +754,19 @@ module Bud
815
754
  is_source # rescan always only if this scratch is a source.
816
755
  end
817
756
 
818
-
819
757
  public
820
758
  def add_rescan_invalidate(rescan, invalidate)
821
759
  srcs = non_temporal_predecessors
822
760
  if srcs.any? {|e| rescan.member? e}
823
761
  invalidate << self
824
- srcs.each{|e| rescan << e}
762
+ rescan += srcs
825
763
  end
826
764
  end
827
765
 
828
766
  public
829
767
  def invalidate_cache
830
768
  puts "#{qualified_tabname} invalidated" if $BUD_DEBUG
831
- #for scratches, storage is a cached value.
769
+ # for scratches, storage is a cached value
832
770
  @invalidated = true
833
771
  @storage.clear
834
772
  end
@@ -843,9 +781,10 @@ module Bud
843
781
  class BudTemp < BudScratch # :nodoc: all
844
782
  end
845
783
 
846
- # Channels are a different type of collection in that they represent two distinct collections, one each for
847
- # incoming and outgoing. The incoming side makes use of @storage and @delta, whereas the outgoing side only deals
848
- # with @pending. XXX Maybe we should be using aliases instead.
784
+ # Channels are a different type of collection in that they represent two
785
+ # distinct collections, one each for incoming and outgoing. The incoming side
786
+ # makes use of @storage and @delta, whereas the outgoing side only deals with
787
+ # @pending. XXX Maybe we should be using aliases instead.
849
788
  class BudChannel < BudCollection
850
789
  attr_reader :locspec_idx # :nodoc: all
851
790
 
@@ -908,15 +847,10 @@ module Bud
908
847
  lsplit[1] = lsplit[1].to_i
909
848
  return lsplit
910
849
  rescue Exception => e
911
- raise Bud::Error, "Illegal location specifier in tuple #{t.inspect} for channel \"#{qualified_tabname}\": #{e.to_s}"
850
+ raise Bud::Error, "illegal location specifier in tuple #{t.inspect} for channel \"#{qualified_tabname}\": #{e.to_s}"
912
851
  end
913
852
  end
914
853
 
915
- public
916
- def clone_empty
917
- self.class.new(tabname, bud_instance, @raw_schema, @is_loopback)
918
- end
919
-
920
854
  public
921
855
  def tick # :nodoc: all
922
856
  @storage.clear
@@ -968,7 +902,7 @@ module Bud
968
902
  end
969
903
 
970
904
  superator "<~" do |o|
971
- if o.class <= PushElement
905
+ if o.class <= Bud::PushElement
972
906
  o.wire_to_pending self
973
907
  else
974
908
  pending_merge(o)
@@ -1066,7 +1000,7 @@ module Bud
1066
1000
  end
1067
1001
 
1068
1002
  superator "<~" do |o|
1069
- if o.class <= PushElement
1003
+ if o.class <= Bud::PushElement
1070
1004
  o.wire_to_pending self
1071
1005
  else
1072
1006
  pending_merge(o)
@@ -1118,7 +1052,7 @@ module Bud
1118
1052
 
1119
1053
  public
1120
1054
  def invalidate_cache
1121
- raise "Abstract method not implemented by derived class #{self.class}"
1055
+ raise Bud::Error, "abstract method not implemented by derived class #{self.class}"
1122
1056
  end
1123
1057
  end
1124
1058
 
@@ -1149,13 +1083,13 @@ module Bud
1149
1083
  deleted ||= v
1150
1084
  end
1151
1085
 
1152
- @invalidated = (not deleted.nil?)
1086
+ @invalidated = (not deleted.nil?)
1153
1087
  puts "table #{qualified_tabname} invalidated" if $BUD_DEBUG and @invalidated
1154
1088
 
1155
1089
  @pending.each do |keycols, tuple|
1156
1090
  old = @storage[keycols]
1157
1091
  if old.nil?
1158
- @delta[keycols] = tuple #
1092
+ @delta[keycols] = tuple
1159
1093
  else
1160
1094
  raise_pk_error(tuple, old) unless tuple == old
1161
1095
  end
@@ -1166,19 +1100,19 @@ module Bud
1166
1100
  end
1167
1101
 
1168
1102
  def invalidated=(val)
1169
- raise "Internal error: nust not set invalidate on tables"
1103
+ raise "Internal error: must not set invalidate on tables"
1170
1104
  end
1171
1105
 
1172
1106
  def pending_delete(o)
1173
1107
  toplevel = @bud_instance.toplevel
1174
1108
  if o.class <= Bud::PushElement
1175
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
1109
+ add_merge_target
1176
1110
  o.wire_to_delete self
1177
1111
  elsif o.class <= Bud::BudCollection
1178
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
1112
+ add_merge_target
1179
1113
  o.pro.wire_to_delete self
1180
1114
  elsif o.class <= Proc and @bud_instance.toplevel.done_bootstrap and not toplevel.done_wiring
1181
- toplevel.merge_targets[toplevel.this_stratum][self] = true if toplevel.done_bootstrap
1115
+ add_merge_target
1182
1116
  tbl = register_coll_expr(o)
1183
1117
  tbl.pro.wire_to_delete self
1184
1118
  else
@@ -1217,8 +1151,9 @@ module Bud
1217
1151
 
1218
1152
  public
1219
1153
  def invalidate_cache
1220
- # no cache to invalidate. Also, tables do not invalidate dependents, because their own state is not considered
1221
- # invalidated; that happens only if there were pending deletes at the beginning of a tick (see tick())
1154
+ # No cache to invalidate. Also, tables do not invalidate dependents,
1155
+ # because their own state is not considered invalidated; that happens only
1156
+ # if there were pending deletes at the beginning of a tick (see tick())
1222
1157
  puts "******** invalidate_cache called on BudTable"
1223
1158
  end
1224
1159
 
@@ -1226,8 +1161,8 @@ module Bud
1226
1161
  superator "<+-" do |o|
1227
1162
  pending_delete_keys(o)
1228
1163
  self <+ o
1229
- end
1230
- public
1164
+ end
1165
+ public
1231
1166
  superator "<-+" do |o|
1232
1167
  self <+- o
1233
1168
  end
@@ -1251,20 +1186,6 @@ module Bud
1251
1186
  end
1252
1187
  end
1253
1188
 
1254
- class BudSignal < BudReadOnly
1255
- def invalidate_at_tick
1256
- true
1257
- end
1258
- def tick
1259
- @invalidated = true
1260
- @storage.clear
1261
- unless @pending.empty?
1262
- @delta = @pending
1263
- @pending = {}
1264
- end
1265
- end
1266
- end
1267
-
1268
1189
  class BudCollExpr < BudReadOnly # :nodoc: all
1269
1190
  def initialize(name, bud_instance, expr, given_schema=nil, defer_schema=false)
1270
1191
  super(name, bud_instance, given_schema, defer_schema)
@@ -1309,20 +1230,12 @@ module Bud
1309
1230
 
1310
1231
  public
1311
1232
  def each(&blk)
1312
- each_raw {|l| tuple_accessors(blk.call(l))}
1233
+ each_raw {|l| blk.call(l)}
1313
1234
  end
1314
1235
  end
1315
1236
  end
1316
1237
 
1317
1238
  module Enumerable
1318
- # public
1319
- # # monkeypatch to Enumerable to rename collections and their schemas
1320
- # def rename(new_tabname, new_schema=nil)
1321
- # scr = Bud::BudScratch.new(new_tabname.to_s, nil, new_schema)
1322
- # scr.merge(self, scr.storage)
1323
- # scr
1324
- # end
1325
-
1326
1239
  public
1327
1240
  # We rewrite "map" calls in Bloom blocks to invoke the "pro" method
1328
1241
  # instead. This is fine when applied to a BudCollection; when applied to a
data/lib/bud/errors.rb CHANGED
@@ -12,7 +12,11 @@ module Bud
12
12
  # Raised when the input program fails to compile (e.g., due to illegal
13
13
  # syntax).
14
14
  class CompileError < Error; end
15
+
16
+ # Raised when the program is given in an illegal location (e.g., presented as
17
+ # an eval block).
18
+ class IllegalSourceError < Error; end
15
19
 
16
- # Raised when evaluation halts with outstanding callbacks
20
+ # Raised when evaluation halts with outstanding callbacks.
17
21
  class ShutdownWithCallbacksError < Error; end
18
22
  end