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.
@@ -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