bud 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MTY4MjlkMTY1NjZlYTZiOTVjNmYyMmIzYTliNDVlZDIwZjA0YjY4Yw==
5
+ data.tar.gz: !binary |-
6
+ MTE0ZGY3MDg5NzBmMTJkYTExNDNjYTcyNTFhOThmMzk0ZTM4YzgxOA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ OGJmYmMwZjU4Y2RlZWUyNDVkMGFkYTczZDhlNjk5MGQ5NmVlZDIyYzQyMjAz
10
+ NzEyZWI0YTI1MjVjM2VhZGRjMWE4ZDM4MGVlYzA4YzliYmJjNGUwZjEyY2I2
11
+ YjZhOTVjNzk5MGVjNWJkMTA0YWRmODk3MDAyYmVlOTM4MmVmYzA=
12
+ data.tar.gz: !binary |-
13
+ YjZkOTlkYzQwODJkZTI4YjU0YmFhMmY4MDY5Mjg3Y2ZjMzUyN2ZmZTAyOGI5
14
+ M2M3NWQ5OTgyM2U2ZjA3NGIzMjkwZjhjMTBhNWFmYzc3OTNiYmZjOWMzNmU3
15
+ MTkzZmI1MzJlODNkMmE2Y2E1NzU5ODYzNDlhM2Q3N2Q3MDk2Yzg=
data/History.txt CHANGED
@@ -1,8 +1,32 @@
1
+ == 0.9.6 / 2013-02-25
2
+
3
+ * Support syntax sugar for initializing lattices (#294). For example, rather
4
+ than writing "foo <= Bud::MaxLattice.new(2)", you can now just write "foo <=
5
+ 2". Note that, due to a bug in the superator gem, you cannot use this syntax
6
+ with the <+ operator.
7
+ * Allow nested lattice values to be sent over channels (#295, patch from Josh
8
+ Rosen). Lattice values could previously be sent as a field value in a tuple
9
+ delivered over a channel, but they could not be embedded arbitrarily deeply
10
+ within tuples (e.g., lattices nested within an array could not previously be
11
+ sent as a field value).
12
+ * Support "Comparable" for Bud::Lattice values
13
+ * Add support for lattices to rebl
14
+ * Reject attempts to insert into stdio via <+ (#288)
15
+ * Restore functionality of reading from stdio (i.e., stdin) with MRI 1.9
16
+ * Improve MRI 1.8 compatibility
17
+ * Require ruby_parser >= 3.1.0
18
+ * Fix bug in bootstrap blocks for lattice values
19
+ * Fix bug in rescan/invalidation for rules that reference lattice values and use
20
+ the <+ or <~ operators (#290)
21
+ * Fix bug in rescan logic for notin operator (#291)
22
+ * Fix bug in notin operators involving self joins (#298)
23
+ * Fix error when output from a notin operator was fed into a lattice
24
+
1
25
  == 0.9.5 / 2012-11-24
2
26
 
3
27
  * Lattice branch (Bloom^L) merged
4
28
  * Compatibility with recent versions of ruby_parser (3.0.2+) and ruby2ruby
5
- (2.0.1+) -- #. Older versions of these two gems are no longer supported
29
+ (2.0.1+). Older versions of these two gems are no longer supported
6
30
  * Add support for aggregate functions that take multiple input columns
7
31
  * Add built-in aggregate function accum_pair(x, y), which produces a Set of
8
32
  pairs (two-element arrays [x,y])
data/bin/budlabel CHANGED
File without changes
data/bin/budplot CHANGED
@@ -77,8 +77,8 @@ def process(mods)
77
77
  d = make_instance(mods)
78
78
 
79
79
  interfaces = {}
80
- d.t_provides.each do |name, is_input|
81
- interfaces[name] = is_input
80
+ d.t_provides.to_a.each do |prov|
81
+ interfaces[prov.interface] = prov.input
82
82
  end
83
83
 
84
84
  tabinf = {}
@@ -201,13 +201,18 @@ def get_trace_data
201
201
  end
202
202
 
203
203
  if ARGV.length < 2
204
- puts "Usage: budplot LIST_OF_FILES LIST_OF_MODULES_OR_CLASSES"
204
+ puts "Usage: budplot [-I PATH_TO_RUBY_INCLUDES] LIST_OF_FILES LIST_OF_MODULES_OR_CLASSES"
205
205
  exit
206
206
  end
207
207
 
208
- @opts = Getopt::Std.getopts("t:")
209
-
210
-
208
+ @opts = Getopt::Std.getopts("I:t:")
209
+ unless @opts["I"].nil?
210
+ if @opts["I"].class == Array
211
+ @opts["I"].each{|i| $:.unshift i}
212
+ else
213
+ $:.unshift @opts["I"]
214
+ end
215
+ end
211
216
 
212
217
  @data = get_trace_data
213
218
  `mkdir bud_doc`
data/bin/budtimelines CHANGED
@@ -10,7 +10,7 @@ include VizUtil
10
10
 
11
11
  module Depends
12
12
  state do
13
- table :depends, [:rid, :lhs, :op, :rhs, :nm, :in_body]
13
+ table :depends, [:bud_obj, :rid, :lhs, :op, :rhs, :nm, :in_body]
14
14
  end
15
15
  end
16
16
 
@@ -49,7 +49,7 @@ end
49
49
  module DeltaLogic
50
50
  include TPSchema
51
51
  bloom do
52
- zerod_cards <= cardinalities{|c| c + [c.bud_time-1]}
52
+ zerod_cards <= cardinalities{|c| c.to_a + [c.bud_time-1]}
53
53
  zerod_cards <= (times * depends).pairs do |t, d|
54
54
  unless cardinalities{|c| c[1] if c[0] == t.bud_time}.include? d[1]
55
55
  [t.bud_time, d[1], 0, t.bud_time - 1]
data/bin/budvis CHANGED
@@ -28,7 +28,13 @@ usage unless ARGV[0]
28
28
  usage if ARGV[0] == '--help'
29
29
 
30
30
  meta, data = get_meta2(BUD_DBM_DIR)
31
- vh = VizHelper.new(meta[:tabinf], meta[:cycle], meta[:depends], meta[:rules], ARGV[0], meta[:provides])
31
+
32
+ # prune outbufs from tabinf
33
+ tabinf = meta[:tabinf].find_all do |k|
34
+ !(k[1] == "Bud::BudChannel" and k[0] =~ /_snd\z/)
35
+ end
36
+
37
+ vh = VizHelper.new(tabinf, meta[:cycle], meta[:depends], meta[:rules], ARGV[0], meta[:provides])
32
38
  data.each do |d|
33
39
  vh.full_info << d
34
40
  end
data/docs/README.md CHANGED
@@ -20,14 +20,14 @@ try the following:
20
20
  `budplot` tools for visualizing Bloom program analyses.
21
21
  * [bfs.md][bfs]: A walkthrough of the Bloom distributed filesystem.
22
22
 
23
- [intro]: /bloom-lang/bud/blob/master/docs/intro.md
24
- [getstarted]: /bloom-lang/bud/blob/master/docs/getstarted.md
25
- [operational]: /bloom-lang/bud/blob/master/docs/operational.md
26
- [cheat]: /bloom-lang/bud/blob/master/docs/cheat.md
27
- [modules]: /bloom-lang/bud/blob/master/docs/modules.md
28
- [ruby_hooks]: /bloom-lang/bud/blob/master/docs/ruby_hooks.md
29
- [visualizations]: /bloom-lang/bud/blob/master/docs/visualizations.md
30
- [bfs]: /bloom-lang/bud/blob/master/docs/bfs.md
23
+ [intro]: /docs/intro.md
24
+ [getstarted]: /docs/getstarted.md
25
+ [operational]: /docs/operational.md
26
+ [cheat]: /docs/cheat.md
27
+ [modules]: /docs/modules.md
28
+ [ruby_hooks]: /docs/ruby_hooks.md
29
+ [visualizations]: /docs/visualizations.md
30
+ [bfs]: /docs/bfs.md
31
31
 
32
32
  In addition, the [bud-sandbox](http://github.com/bloom-lang/bud-sandbox) GitHub
33
33
  repository contains lots of useful libraries and example programs built using
data/docs/cheat.md CHANGED
@@ -224,14 +224,14 @@ Output the facts in `bc` that do not appear in `bc2`, as follows. First, we form
224
224
  :attr2`).
225
225
 
226
226
  2. If a code block is specified, invoke the block on every pair of matching
227
- tuples in the join result. Any matches for which the block returns `nil`
227
+ tuples in the join result. Any matches for which the block returns `false`
228
228
  are removed from `t`.
229
229
 
230
230
  Finally, we output every tuple of `bc` that does *not* appear in `t`.
231
231
 
232
232
  # output items from foo if (a) there is no matching key in bar, or
233
233
  # (b) all matching keys in bar have a smaller value
234
- stdio <~ foo.notin(bar, :key=>:key) {|f, b| true if f.val <= b.val}
234
+ stdio <~ foo.notin(bar, :key=>:key) {|f, b| f.val <= b.val}
235
235
 
236
236
 
237
237
  ## SQL-style grouping/aggregation (and then some) ##
data/lib/bud.rb CHANGED
@@ -265,7 +265,7 @@ module Bud
265
265
  mod_inst.t_rules.each do |imp_rule|
266
266
  qname = "#{local_name}.#{imp_rule.lhs}"
267
267
  self.t_rules << [imp_rule.bud_obj, imp_rule.rule_id, qname, imp_rule.op,
268
- imp_rule.src, imp_rule.orig_src, imp_rule.nm_funcs_called]
268
+ imp_rule.src, imp_rule.orig_src, imp_rule.unsafe_funcs_called]
269
269
  end
270
270
  mod_inst.t_depends.each do |imp_dep|
271
271
  qlname = "#{local_name}.#{imp_dep.lhs}"
@@ -326,7 +326,7 @@ module Bud
326
326
  # the user-defined tables and lattices. We start @app_tables off as a set,
327
327
  # then convert to an array later.
328
328
  @app_tables = (@tables.keys - @builtin_tables.keys).map {|t| @tables[t]}.to_set
329
- @app_tables += @lattices.values
329
+ @app_tables.merge(@lattices.values)
330
330
 
331
331
  # Check scan and merge_targets to see if any builtin_tables need to be added as well.
332
332
  @scanners.each do |scs|
@@ -346,7 +346,7 @@ module Bud
346
346
  seen = Set.new(working)
347
347
  sorted_elems = [] # sorted elements in this stratum
348
348
  while not working.empty?
349
- sorted_elems += working
349
+ sorted_elems.concat(working)
350
350
  wired_to = []
351
351
  working.each do |e|
352
352
  e.wirings.each do |out|
@@ -453,18 +453,19 @@ module Bud
453
453
 
454
454
  # By default, all tables are considered sources unless they appear on the
455
455
  # lhs. We only consider non-temporal rules because invalidation is only
456
- # about this tick. Also, we track (in nm_targets) those tables that are the
457
- # targets of user-defined code blocks that call non-monotonic functions
458
- # (such as budtime). Elements that feed these tables are forced to rescan
459
- # their contents, and thus forced to re-execute these code blocks.
460
- nm_targets = Set.new
456
+ # about this tick. Also, we track (in unsafe_targets) those tables that are
457
+ # the targets of user-defined code blocks that call "unsafe" functions that
458
+ # produce a different value in every tick (e.g., budtime). Elements that
459
+ # feed these tables are forced to rescan their contents, and thus forced to
460
+ # re-execute these code blocks.
461
+ unsafe_targets = Set.new
461
462
  t_rules.each do |rule|
462
463
  lhs = rule.lhs.to_sym
463
464
  if rule.op == "<="
464
465
  # Note that lattices cannot be sources
465
466
  @tables[lhs].is_source = false if @tables.has_key? lhs
466
467
  end
467
- nm_targets << lhs if rule.nm_funcs_called
468
+ unsafe_targets << lhs if rule.unsafe_funcs_called
468
469
  end
469
470
 
470
471
  # Compute a set of tables and elements that should be explicitly told to
@@ -477,7 +478,7 @@ module Bud
477
478
  @push_sorted_elems[stratum].each do |elem|
478
479
  rescan << elem if elem.rescan_at_tick
479
480
 
480
- if elem.outputs.any?{|tab| not(tab.class <= PushElement) and not(tab.class <= LatticePushElement) and nm_targets.member? tab.qualified_tabname.to_sym }
481
+ if elem.outputs.any?{|tab| not(tab.class <= PushElement) and not(tab.class <= LatticePushElement) and unsafe_targets.member? tab.qualified_tabname.to_sym }
481
482
  rescan.merge(elem.wired_by)
482
483
  end
483
484
  end
@@ -489,8 +490,11 @@ module Bud
489
490
  @default_rescan = rescan.to_a
490
491
  @default_invalidate = invalidate.to_a
491
492
 
492
- puts "Default rescan: #{rescan.inspect}" if $BUD_DEBUG
493
- puts "Default inval: #{invalidate.inspect}" if $BUD_DEBUG
493
+ if $BUD_DEBUG
494
+ puts "Default rescan: #{rescan.inspect}"
495
+ puts "Default inval: #{invalidate.inspect}"
496
+ puts "Unsafe targets: #{unsafe_targets.inspect}"
497
+ end
494
498
 
495
499
  # Now compute for each table that is to be scanned, the set of dependent
496
500
  # tables and elements that will be invalidated if that table were to be
@@ -518,27 +522,43 @@ module Bud
518
522
  end
519
523
  @reset_list = to_reset.to_a
520
524
 
521
- # For each lattice, find the set of tables that should be rescanned when
522
- # there is a new delta for the lattice. That is, if we have a rule like:
525
+ # For each lattice, find the collections that should be rescanned when there
526
+ # is a new delta for the lattice. That is, if we have a rule like:
523
527
  # "t2 <= t1 {|t| [t.key, lat_foo]}", whenever there is a delta on lat_foo we
524
528
  # should rescan t1 (to produce tuples with the updated lat_foo value).
529
+ #
525
530
  # TODO:
526
- # (1) support non-join ops to be rescanned (+ tests) + lambdas
527
- # (2) if t1 is fed by rules r1 and r2 but only r1 references lattice x,
531
+ # (1) if t1 is fed by rules r1 and r2 but only r1 references lattice x,
528
532
  # don't trigger rescan of r2 on deltas for x (hard)
529
533
  t_depends.each do |dep|
530
- src, dst = dep.body.to_sym, dep.lhs.to_sym
531
- if @lattices.has_key? src and @tables.has_key? dst and dep.in_body
534
+ src, target_name = dep.body.to_sym, dep.lhs.to_sym
535
+ if @lattices.has_key? src and dep.in_body
532
536
  src_lat = @lattices[src]
533
- dst_tbl = @tables[dst]
534
- dst_tbl.non_temporal_predecessors.each do |e|
535
- src_lat.rescan_on_merge << e
537
+ if @tables.has_key? target_name
538
+ target = @tables[target_name]
539
+ else
540
+ target = @lattices[target_name]
541
+ end
542
+
543
+ # Conservatively, we rescan all the elements that feed the lhs (target)
544
+ # collection via positive (non-deletion) rules; we then also need to
545
+ # potentially rescan ancestors of those elements as well (e.g., setting
546
+ # a stateless PushElement to rescan does nothing; we want to tell its
547
+ # ancestor ScannerElement to rescan).
548
+ #
549
+ # XXX: do we need to consider all transitively reachable nodes for
550
+ # rescan?
551
+ lat_rescan = target.positive_predecessors.to_set
552
+ lat_inval = Set.new
553
+ target.positive_predecessors.each do |e|
554
+ e.add_rescan_invalidate(lat_rescan, lat_inval)
536
555
  end
556
+ src_lat.rescan_on_delta.merge(lat_rescan)
537
557
  end
538
558
  end
539
559
  end
540
560
 
541
- # given rescan, invalidate sets, compute transitive closure
561
+ # Given rescan, invalidate sets, compute transitive closure
542
562
  def rescan_invalidate_tc(stratum, rescan, invalidate)
543
563
  rescan_len = rescan.size
544
564
  invalidate_len = invalidate.size
@@ -1139,14 +1159,14 @@ module Bud
1139
1159
  @periodics = table :periodics_tbl, [:pername] => [:period]
1140
1160
 
1141
1161
  # for BUD reflection
1142
- table :t_rules, [:bud_obj, :rule_id] => [:lhs, :op, :src, :orig_src, :nm_funcs_called]
1162
+ table :t_cycle, [:predicate, :via, :neg, :temporal]
1143
1163
  table :t_depends, [:bud_obj, :rule_id, :lhs, :op, :body] => [:nm, :in_body]
1144
1164
  table :t_provides, [:interface] => [:input]
1145
- table :t_underspecified, t_provides.schema
1165
+ table :t_rules, [:bud_obj, :rule_id] => [:lhs, :op, :src, :orig_src, :unsafe_funcs_called]
1146
1166
  table :t_stratum, [:predicate] => [:stratum]
1147
- table :t_cycle, [:predicate, :via, :neg, :temporal]
1148
1167
  table :t_table_info, [:tab_name, :tab_type]
1149
1168
  table :t_table_schema, [:tab_name, :col_name, :ord, :loc]
1169
+ table :t_underspecified, t_provides.schema
1150
1170
 
1151
1171
  # Identify builtin tables as such
1152
1172
  @builtin_tables = @tables.clone if toplevel
@@ -1186,7 +1206,7 @@ module Bud
1186
1206
  begin
1187
1207
  eval_rule(rule.bud_obj, rule.src)
1188
1208
  rescue Exception => e
1189
- err_msg = "** Exception while wiring rule: #{rule.src}\n ****** #{e}"
1209
+ err_msg = "** Exception while wiring rule: #{rule.orig_src}\n ****** #{e}"
1190
1210
  # Create a new exception for accomodating err_msg, but reuse original backtrace
1191
1211
  new_e = (e.class <= Bud::Error) ? e.class.new(err_msg) : Bud::Error.new(err_msg)
1192
1212
  new_e.set_backtrace(e.backtrace)
@@ -52,7 +52,7 @@ module Bud
52
52
  # user-specified schema.
53
53
  @cols.each do |s|
54
54
  if s.to_s.start_with? "@"
55
- raise Bud::Error, "illegal use of location specifier (@) in column #{s} of non-channel collection #{tabname}"
55
+ raise Bud::CompileError, "illegal use of location specifier (@) in column #{s} of non-channel collection #{tabname}"
56
56
  end
57
57
  end
58
58
 
@@ -284,7 +284,12 @@ module Bud
284
284
 
285
285
  public
286
286
  def non_temporal_predecessors
287
- @wired_by.select {|elem| elem.outputs.include? self}
287
+ @wired_by.select {|e| e.outputs.include? self}
288
+ end
289
+
290
+ public
291
+ def positive_predecessors
292
+ @wired_by.select {|e| e.outputs.include?(self) || e.pendings.include?(self)}
288
293
  end
289
294
 
290
295
  public
@@ -869,6 +874,8 @@ module Bud
869
874
  given_schema ||= [:@address, :val]
870
875
  @is_loopback = loopback
871
876
  @locspec_idx = nil
877
+ @wire_buf = StringIO.new
878
+ @packer = MessagePack::Packer.new(@wire_buf)
872
879
 
873
880
  # We're going to mutate the caller's given_schema (to remove the location
874
881
  # specifier), so make a deep copy first. We also save a ref to the
@@ -959,19 +966,40 @@ module Bud
959
966
  # particular, lattice values and Class instances), we first encode such
960
967
  # values using Marshal, and then encode the entire tuple with
961
968
  # MsgPack. Obviously, this is gross. The wire format also includes an
962
- # array of indices, indicating which fields hold Marshall'd objects.
969
+ # array of indices, indicating which fields hold Marshall'd values.
970
+ @packer.write_array_header(3)
971
+ @packer.write(qualified_tabname.to_s)
972
+ # The second element, wire_tuple, is an array. We will write it one
973
+ # element at a time:
974
+ @packer.write_array_header(t.length)
975
+ @packer.flush
963
976
  marshall_indexes = []
964
- wire_tuple = Array.new(t.length)
965
- t.each_with_index do |f, i|
977
+ t.each_with_index do |f,i|
978
+ # Performance optimization for cases where we know that we can't
979
+ # marshal the field using MsgPack:
966
980
  if [Bud::Lattice, Class].any?{|t| f.class <= t}
967
981
  marshall_indexes << i
968
- wire_tuple[i] = Marshal.dump(f)
982
+ @wire_buf << Marshal.dump(f).to_msgpack
969
983
  else
970
- wire_tuple[i] = f
984
+ begin
985
+ @wire_buf << f.to_msgpack
986
+ rescue NoMethodError
987
+ # If MsgPack can't marshal the field, fall back to Marshal.
988
+ # This handles fields that contain nested non-MsgPack-able
989
+ # objects (in these cases, the entire field is Marshal'd.)
990
+ marshall_indexes << i
991
+ @wire_buf << Marshal.dump(f).to_msgpack
992
+ end
971
993
  end
972
994
  end
973
- wire_str = [qualified_tabname.to_s, wire_tuple, marshall_indexes].to_msgpack
974
- toplevel.dsock.send_datagram(wire_str, the_locspec[0], the_locspec[1])
995
+ @packer.write(marshall_indexes)
996
+ @packer.flush
997
+ toplevel.dsock.send_datagram(@wire_buf.string,
998
+ the_locspec[0], the_locspec[1])
999
+
1000
+ # Reset output buffer
1001
+ @wire_buf.rewind
1002
+ @wire_buf.truncate(0)
975
1003
  end
976
1004
  @pending.clear
977
1005
  end
@@ -1015,45 +1043,28 @@ module Bud
1015
1043
  end
1016
1044
 
1017
1045
  superator "<+" do |o|
1018
- raise Bud::Error, "illegal use of <+ with channel '#{@tabname}' on left"
1046
+ raise Bud::CompileError, "illegal use of <+ with channel '#{@tabname}' on left"
1019
1047
  end
1020
1048
 
1021
1049
  undef merge
1022
1050
 
1023
1051
  def <=(o)
1024
- raise Bud::Error, "illegal use of <= with channel '#{@tabname}' on left"
1052
+ raise Bud::CompileError, "illegal use of <= with channel '#{@tabname}' on left"
1025
1053
  end
1026
1054
  end
1027
1055
 
1028
1056
  class BudTerminal < BudScratch # :nodoc: all
1029
- def initialize(name, given_schema, bud_instance, prompt=false) # :nodoc: all
1030
- super(name, bud_instance, given_schema)
1057
+ def initialize(name, bud_instance, prompt=false) # :nodoc: all
1058
+ super(name, bud_instance, [:line])
1031
1059
  @prompt = prompt
1032
1060
  end
1033
1061
 
1034
1062
  public
1035
1063
  def start_stdin_reader # :nodoc: all
1036
- # XXX: Ugly hack. Rather than sending terminal data to EM via UDP,
1037
- # we should add the terminal file descriptor to the EM event loop.
1038
- @reader = Thread.new do
1064
+ Thread.new do
1039
1065
  begin
1040
- toplevel = @bud_instance.toplevel
1041
1066
  while true
1042
- out_io = get_out_io
1043
- out_io.print("#{tabname} > ") if @prompt
1044
-
1045
- in_io = toplevel.options[:stdin]
1046
- s = in_io.gets
1047
- break if s.nil? # Hit EOF
1048
- s = s.chomp if s
1049
- tup = [s]
1050
-
1051
- ip = toplevel.ip
1052
- port = toplevel.port
1053
- EventMachine::schedule do
1054
- socket = EventMachine::open_datagram_socket("127.0.0.1", 0)
1055
- socket.send_datagram([tabname, tup, []].to_msgpack, ip, port)
1056
- end
1067
+ break unless read_line
1057
1068
  end
1058
1069
  rescue Exception
1059
1070
  puts "terminal reader thread failed: #{$!}"
@@ -1063,13 +1074,34 @@ module Bud
1063
1074
  end
1064
1075
  end
1065
1076
 
1077
+ # XXX: Ugly hack. Rather than sending terminal data to EM via UDP, we should
1078
+ # add the terminal file descriptor to the EM event loop.
1079
+ private
1080
+ def read_line
1081
+ toplevel = @bud_instance.toplevel
1082
+ if @prompt
1083
+ get_out_io.print("#{tabname} > ")
1084
+ end
1085
+
1086
+ in_io = toplevel.options[:stdin]
1087
+ input_str = in_io.gets
1088
+ return false if input_str.nil? # Hit EOF
1089
+ input_str.chomp!
1090
+
1091
+ EventMachine::schedule do
1092
+ socket = EventMachine::open_datagram_socket("127.0.0.1", 0)
1093
+ socket.send_datagram([tabname, [input_str], []].to_msgpack,
1094
+ toplevel.ip, toplevel.port)
1095
+ end
1096
+
1097
+ return true
1098
+ end
1099
+
1066
1100
  public
1067
1101
  def flush #:nodoc: all
1068
1102
  out_io = get_out_io
1069
- @pending.each_value do |p|
1070
- out_io.puts p[0]
1071
- out_io.flush
1072
- end
1103
+ @pending.each_value {|p| out_io.puts p[0]}
1104
+ out_io.flush
1073
1105
  @pending.clear
1074
1106
  end
1075
1107
 
@@ -1090,7 +1122,6 @@ module Bud
1090
1122
  @tick_delta.clear
1091
1123
  end
1092
1124
  @invalidated = true # channels and terminals are always invalidated.
1093
- raise Bud::Error, "orphaned pending tuples in terminal" unless @pending.empty?
1094
1125
  end
1095
1126
 
1096
1127
  public
@@ -1101,7 +1132,11 @@ module Bud
1101
1132
 
1102
1133
  public
1103
1134
  def <=(o) #:nodoc: all
1104
- raise Bud::Error, "illegal use of <= with terminal '#{@tabname}' on left"
1135
+ raise Bud::CompileError, "illegal use of <= with terminal '#{@tabname}' on left"
1136
+ end
1137
+
1138
+ superator "<+" do |o|
1139
+ raise Bud::CompileError, "illegal use of <+ with terminal '#{@tabname}' on left"
1105
1140
  end
1106
1141
 
1107
1142
  superator "<~" do |o|
@@ -1121,26 +1156,28 @@ module Bud
1121
1156
  def get_out_io
1122
1157
  rv = @bud_instance.toplevel.options[:stdout]
1123
1158
  rv ||= $stdout
1124
- raise Bud::Error, "attempting to write to terminal #{tabname} that was already closed" if rv.closed?
1159
+ if rv.closed?
1160
+ raise Bud::Error, "attempt to write to closed terminal '#{tabname}'"
1161
+ end
1125
1162
  rv
1126
1163
  end
1127
1164
  end
1128
1165
 
1129
1166
  class BudPeriodic < BudScratch # :nodoc: all
1130
1167
  def <=(o)
1131
- raise Bud::Error, "illegal use of <= with periodic '#{tabname}' on left"
1168
+ raise Bud::CompileError, "illegal use of <= with periodic '#{tabname}' on left"
1132
1169
  end
1133
1170
 
1134
1171
  superator "<~" do |o|
1135
- raise Bud::Error, "illegal use of <~ with periodic '#{tabname}' on left"
1172
+ raise Bud::CompileError, "illegal use of <~ with periodic '#{tabname}' on left"
1136
1173
  end
1137
1174
 
1138
1175
  superator "<-" do |o|
1139
- raise Bud::Error, "illegal use of <- with periodic '#{tabname}' on left"
1176
+ raise Bud::CompileError, "illegal use of <- with periodic '#{tabname}' on left"
1140
1177
  end
1141
1178
 
1142
1179
  superator "<+" do |o|
1143
- raise Bud::Error, "illegal use of <+ with periodic '#{tabname}' on left"
1180
+ raise Bud::CompileError, "illegal use of <+ with periodic '#{tabname}' on left"
1144
1181
  end
1145
1182
 
1146
1183
  def tick
@@ -1272,11 +1309,11 @@ module Bud
1272
1309
 
1273
1310
  class BudReadOnly < BudCollection # :nodoc: all
1274
1311
  superator "<+" do |o|
1275
- raise CompileError, "illegal use of <+ with read-only collection '#{@tabname}' on left"
1312
+ raise Bud::CompileError, "illegal use of <+ with read-only collection '#{@tabname}' on left"
1276
1313
  end
1277
1314
  public
1278
1315
  def merge(o) #:nodoc: all
1279
- raise CompileError, "illegal use of <= with read-only collection '#{@tabname}' on left"
1316
+ raise Bud::CompileError, "illegal use of <= with read-only collection '#{@tabname}' on left"
1280
1317
  end
1281
1318
  public
1282
1319
  def invalidate_cache