redshift 1.3.24 → 1.3.30

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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +49 -0
  3. data/RELEASE-NOTES +34 -3
  4. data/Rakefile +81 -0
  5. data/bench/bench +1 -1
  6. data/bench/formula.rb +2 -3
  7. data/examples/pid.rb +6 -6
  8. data/examples/robots/lib/shell-world.rb +1 -1
  9. data/examples/scheduler.rb +6 -1
  10. data/ext/redshift/dvector-float/dvector-float.c +184 -0
  11. data/ext/redshift/dvector-float/dvector-float.h +36 -0
  12. data/ext/redshift/dvector-float/dvector-float.rb +33 -0
  13. data/ext/redshift/dvector-float/extconf.rb +2 -0
  14. data/lib/redshift/redshift.rb +5 -5
  15. data/lib/redshift/target/c/component-gen.rb +1 -1
  16. data/lib/redshift/target/c/flow-gen.rb +1 -1
  17. data/lib/redshift/target/c/flow/delay.rb +1 -1
  18. data/lib/redshift/target/c/world-gen.rb +101 -101
  19. data/lib/redshift/util/isaac.rb +2 -2
  20. data/lib/redshift/util/tkar-driver.rb +1 -1
  21. data/test/test.rb +1 -1
  22. data/test/test_buffer.rb +2 -2
  23. data/test/test_connect.rb +2 -2
  24. data/test/test_connect_parallel.rb +2 -2
  25. data/test/test_connect_strict.rb +4 -5
  26. data/test/test_constant.rb +2 -4
  27. data/test/test_delay.rb +2 -2
  28. data/test/test_derivative.rb +2 -2
  29. data/test/test_discrete.rb +2 -4
  30. data/test/test_discrete_isolated.rb +2 -4
  31. data/test/test_dvector-float.rb +110 -0
  32. data/test/test_dvector.rb +15 -17
  33. data/test/test_exit.rb +2 -4
  34. data/test/test_flow.rb +2 -4
  35. data/test/test_flow_link.rb +2 -4
  36. data/test/test_flow_sub.rb +2 -4
  37. data/test/test_flow_trans.rb +23 -25
  38. data/test/test_inherit.rb +2 -4
  39. data/test/test_inherit_event.rb +2 -4
  40. data/test/test_inherit_flow.rb +2 -4
  41. data/test/test_inherit_link.rb +2 -4
  42. data/test/test_inherit_setup.rb +2 -4
  43. data/test/test_inherit_state.rb +2 -4
  44. data/test/test_inherit_transition.rb +2 -4
  45. data/test/test_numerics.rb +2 -4
  46. data/test/test_queue.rb +3 -3
  47. data/test/test_queue_alone.rb +2 -2
  48. data/test/test_reset.rb +2 -4
  49. data/test/test_setup.rb +2 -4
  50. data/test/test_strict_continuity.rb +2 -4
  51. data/test/test_strict_reset_error.rb +2 -4
  52. data/test/test_strictness_error.rb +2 -4
  53. data/test/test_sync.rb +2 -2
  54. data/test/test_world.rb +2 -4
  55. metadata +80 -106
  56. data/.bnsignore +0 -27
  57. data/.gitignore +0 -9
  58. data/README +0 -25
  59. data/TODO +0 -431
  60. data/bench/aug17-ruby19.bench +0 -86
  61. data/bench/aug17.bench +0 -86
  62. data/bench/aug7.bench +0 -86
  63. data/bench/prof.html +0 -0
  64. data/examples/robots/README +0 -49
  65. data/ext/redshift/util/isaac/extconf.rb +0 -2
  66. data/ext/redshift/util/isaac/isaac.c +0 -129
  67. data/ext/redshift/util/isaac/rand.c +0 -140
  68. data/ext/redshift/util/isaac/rand.h +0 -61
  69. data/rakefile +0 -50
@@ -0,0 +1,36 @@
1
+ #ifndef dvector_float_h
2
+ #define dvector_float_h
3
+
4
+ #include <ruby.h>
5
+
6
+ typedef struct {
7
+ long len;
8
+ long capa;
9
+ float *ptr;
10
+ } RS_DVectorFloat;
11
+
12
+ extern void rs_dvf_grow(RS_DVectorFloat *dvf);
13
+ extern void rs_dvf_shrink(RS_DVectorFloat *dvf);
14
+
15
+ inline static RS_DVectorFloat *rs_dvf(VALUE obj)
16
+ {
17
+ return (RS_DVectorFloat *)DATA_PTR(obj);
18
+ }
19
+
20
+ inline static void rs_dvf_push(RS_DVectorFloat *dvf, float val)
21
+ {
22
+ if (dvf->len == dvf->capa) {
23
+ rs_dvf_grow(dvf);
24
+ }
25
+ dvf->ptr[dvf->len++] = val;
26
+ }
27
+
28
+ inline static float rs_dvf_pop(RS_DVectorFloat *dvf)
29
+ {
30
+ if (dvf->len == 0) {
31
+ return 0;
32
+ }
33
+ return dvf->ptr[--dvf->len];
34
+ }
35
+
36
+ #endif
@@ -0,0 +1,33 @@
1
+ module RedShift; end
2
+
3
+ # A linear collection of single-precision floats.
4
+ #
5
+ # Intended primarily for access from C code, using the inline
6
+ # rs_dvf_push() and rs_dvf_pop() functions.
7
+ #
8
+ # Implements some of the same methods as Array, but not all.
9
+ #
10
+ # Like an Array, a DVector grows implicitly as elements are
11
+ # pushed. But unlike an Array, a DVector shrinks only explicitly.
12
+ # This is to minimize realloc() calls when a DVector rapidly
13
+ # grows and shrinks.
14
+
15
+ class RedShift::DVectorFloat
16
+ include Enumerable
17
+ require 'redshift/dvector-float/dvector_float.so'
18
+
19
+ def self.[](*elts)
20
+ new elts
21
+ end
22
+
23
+ def initialize(elts=nil)
24
+ push(*elts) if elts
25
+ end
26
+
27
+ def inspect; to_a.inspect; end
28
+ def to_s; to_a.to_s; end
29
+
30
+ def dup
31
+ self.class.new to_a
32
+ end
33
+ end
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'dvector_float'
@@ -69,8 +69,8 @@ end
69
69
 
70
70
  module RedShift
71
71
  include Math
72
-
73
- VERSION = '1.3.24'
72
+
73
+ VERSION = '1.3.30'
74
74
 
75
75
  Infinity = Math::Infinity
76
76
 
@@ -87,7 +87,7 @@ module RedShift
87
87
  $REDSHIFT_DEBUG = setting
88
88
  end
89
89
  end
90
-
90
+
91
91
  # Returns a list of all worlds (instances of RedShift::World and subclasses),
92
92
  # or just those descending from +world_class+.
93
93
  # Not very efficient, since it uses <tt>ObjectSpace.each_object</tt>, but
@@ -99,7 +99,7 @@ module RedShift
99
99
  end
100
100
 
101
101
  # class Warning < Exception; end
102
- #
102
+ #
103
103
  # # Warn with string str and skipping n stack frames.
104
104
  # def warn str, n = 0
105
105
  # warning = sprintf "\nWarning: #{str}\n\t#{caller(n).join("\n\t")}\n"
@@ -112,7 +112,7 @@ module RedShift
112
112
  # module_function :warn
113
113
 
114
114
  @library_calls = []
115
-
115
+
116
116
  # Defer a block until just after the library ruby code is loaded, but before
117
117
  # commit. Necessary for defining inline C functions or shadow_attrs. Note that
118
118
  # a whole require statement could be placed inside the with_library block.
@@ -1207,7 +1207,7 @@ module RedShift
1207
1207
  int flags;
1208
1208
  }.tabto(0)
1209
1209
 
1210
- include("dvector/dvector.h")
1210
+ library.include("dvector/dvector.h")
1211
1211
 
1212
1212
  body %{
1213
1213
  var_count = shadow->var_count;
@@ -173,7 +173,7 @@ module RedShift; class Flow
173
173
  raise(NameError, "No such link, #{link}") unless link_type
174
174
  strict = (link_strictness == :strict)
175
175
 
176
- flow_fn.include link_type.shadow_library_include_file
176
+ flow_fn.file.include link_type.shadow_library_include_file
177
177
 
178
178
  link_cname = "link_#{link}"
179
179
  get_var_cname = "get_#{link}__#{var}"
@@ -73,7 +73,7 @@ module RedShift; class DelayFlow
73
73
  flow.translate(self, "delay", cl, 0, delay_by)
74
74
  end
75
75
 
76
- include World.shadow_library_include_file
76
+ source_file.include World.shadow_library_include_file
77
77
 
78
78
  # Note: cases 1,2 must proceed to allow alg deps to be computed,
79
79
  # since their values are used later.
@@ -20,7 +20,6 @@ class World
20
20
  1); \\
21
21
  list_i--)
22
22
 
23
- int dummy;
24
23
  '.tabto(0)
25
24
  # Note: EACH_COMP_DO(lc) block may use move_comp and remove_comp
26
25
  # but it should (re)move none or all. Must have declarations for comp
@@ -32,30 +31,30 @@ class World
32
31
  double value;
33
32
  } CVCacheEntry;
34
33
  }
35
-
34
+
36
35
  shadow_library_include_file.declare :link_cache_entry => %{
37
36
  typedef struct {
38
37
  ComponentShadow **link_ptr;
39
38
  VALUE value;
40
39
  } LinkCacheEntry;
41
40
  }
42
-
41
+
43
42
  shadow_library_include_file.declare :port_cache_entry => %{
44
43
  typedef struct {
45
44
  VALUE input_port;
46
45
  VALUE other_port;
47
46
  } PortCacheEntry;
48
47
  }
49
-
48
+
50
49
  # Initial size for the constant value cache.
51
50
  CV_CACHE_SIZE = 64
52
51
 
53
52
  # Initial size for the link cache.
54
53
  LINK_CACHE_SIZE = 64
55
-
54
+
56
55
  # Initial size for the port cache.
57
56
  PORT_CACHE_SIZE = 64
58
-
57
+
59
58
  World.subclasses.each do |sub|
60
59
  file_name = CGenerator.make_c_name(sub.name).to_s
61
60
  sub.shadow_library_file file_name
@@ -80,7 +79,7 @@ class World
80
79
  :active_E=, :prev_active_E=, :awake=,
81
80
  :strict_sleep=, :inert=, :diff_list=,
82
81
  :queue_sleep=
83
-
82
+
84
83
  shadow_attr_reader :time_step => "double time_step"
85
84
  shadow_attr_accessor :zeno_limit => "long zeno_limit"
86
85
  shadow_attr_accessor :step_count => "long step_count"
@@ -95,7 +94,7 @@ class World
95
94
  "long input_depth_limit"
96
95
  shadow_attr_accessor :alg_depth_limit =>
97
96
  "long alg_depth_limit"
98
-
97
+
99
98
  shadow_attr_accessor :base_clock => "double base_clock"
100
99
  shadow_attr_accessor :base_step_count =>
101
100
  "long base_step_count"
@@ -118,7 +117,7 @@ class World
118
117
  shadow->cv_cache_used = 0;
119
118
  }
120
119
  free_function.free "free(shadow->constant_value_cache)"
121
-
120
+
122
121
  shadow_struct.declare :link_cache => %{
123
122
  LinkCacheEntry *link_cache;
124
123
  int link_cache_size;
@@ -131,7 +130,7 @@ class World
131
130
  shadow->link_cache_used = 0;
132
131
  }
133
132
  free_function.free "free(shadow->link_cache)"
134
-
133
+
135
134
  shadow_struct.declare :port_cache => %{
136
135
  PortCacheEntry *port_cache;
137
136
  int port_cache_size;
@@ -143,15 +142,15 @@ class World
143
142
  shadow->port_cache_used = 0;
144
143
  }
145
144
  free_function.free "free(shadow->port_cache)"
146
-
145
+
147
146
  class << self
148
147
  # Redefines World#new so that a library commit happens first.
149
148
  def new(*args, &block)
150
- commit # redefines World.new
149
+ commit # redefines World.new
151
150
  new(*args, &block) # which is what this line calls
152
151
  end
153
152
  end
154
-
153
+
155
154
  define_c_method :time_step= do
156
155
  arguments :time_step
157
156
  body %{
@@ -163,7 +162,7 @@ class World
163
162
  }
164
163
  returns "shadow->time_step" ## needed?
165
164
  end
166
-
165
+
167
166
  define_c_method :clock do
168
167
  returns %{
169
168
  rb_float_new(
@@ -171,8 +170,8 @@ class World
171
170
  (shadow->step_count - shadow->base_step_count) * shadow->time_step)
172
171
  }
173
172
  end
174
-
175
- # This is for when Component#world is nonpersistent
173
+
174
+ # This is for when Component#world is nonpersistent
176
175
  # _load_data_method.post_code %{
177
176
  # rb_funcall(shadow->self, #{shadow_library_include_file.declare_symbol "__restore__world__refs"}, 0);
178
177
  # }
@@ -180,7 +179,7 @@ class World
180
179
  define_c_method :bump_d_tick do
181
180
  body "shadow->d_tick++"
182
181
  end
183
-
182
+
184
183
  slif = shadow_library_include_file
185
184
  slif.declare :get_shadow => %{
186
185
  inline static ComponentShadow *get_shadow(VALUE comp)
@@ -220,13 +219,13 @@ class World
220
219
  }
221
220
  }
222
221
  }
223
-
222
+
224
223
  for (shadow->rk_level = 1; shadow->rk_level <= 3; shadow->rk_level++) {
225
224
  len = rs_dv(shadow->diff_list)->len;
226
225
  comp_ary = rs_dv(shadow->diff_list)->ptr;
227
226
  for (ci = 0; ci < len; ci++) {
228
227
  Data_Get_Struct(comp_ary[ci], ComponentShadow, comp_shdw);
229
-
228
+
230
229
  if (shadow->rk_level == 1 && !comp_shdw->has_diff) {
231
230
  if (ci < len-1) {
232
231
  comp_ary[ci] = comp_ary[len-1];
@@ -250,7 +249,7 @@ class World
250
249
  }
251
250
  }
252
251
  }
253
-
252
+
254
253
  shadow->rk_level = 4;
255
254
  for (li = 0; li < 2; li++) {
256
255
  len = rs_dv(comp_dvector[li])->len;
@@ -266,7 +265,7 @@ class World
266
265
  var->rk_level < shadow->rk_level &&
267
266
  !var->algebraic)
268
267
  (*var->flow)((ComponentShadow *)comp_shdw);
269
-
268
+
270
269
  if (var->rk_level == 4)
271
270
  var->d_tick = 1; //# var will be current in discrete_step
272
271
  else
@@ -289,14 +288,14 @@ class World
289
288
  # scope :static
290
289
  # returns "rb_obj_instance_eval(0, 0, comp)"
291
290
  # end
292
- #
291
+ #
293
292
  # shadow_library_source_file.define(:call_block).instance_eval do
294
293
  # arguments "VALUE arg1", "VALUE block"
295
294
  # return_type "VALUE"
296
295
  # scope :static
297
296
  # returns "rb_funcall(block, #{declare_symbol :call}, 0)"
298
297
  # end
299
-
298
+
300
299
  discrete_step_definer = proc do
301
300
  parent.declare :static_locals => %{
302
301
  static VALUE ExitState, GuardWrapperClass, ExprWrapperClass;
@@ -304,7 +303,7 @@ class World
304
303
  static VALUE QMatchClass, ConnectClass;
305
304
  static VALUE PostClass, DynamicEventClass, SyncClass;
306
305
  }.tabto(0)
307
-
306
+
308
307
  declare :locals => %{
309
308
  VALUE comp;
310
309
  ComponentShadow *comp_shdw;
@@ -315,11 +314,11 @@ class World
315
314
  int list_i;
316
315
  int did_reset;
317
316
  }.tabto(0)
318
-
317
+
319
318
  insteval_proc = declare_symbol :insteval_proc
320
319
  epi = Component::EventPhaseItem
321
320
  spi = Component::SyncPhaseItem
322
-
321
+
323
322
  parent.declare :step_discrete_subs => %{
324
323
  inline static VALUE cur_syncs(ComponentShadow *comp_shdw)
325
324
  {
@@ -468,7 +467,7 @@ class World
468
467
  }
469
468
  return 1;
470
469
  }
471
-
470
+
472
471
  inline static int comp_can_sync(ComponentShadow *comp_shdw,
473
472
  #{World.shadow_struct_name} *shadow)
474
473
  {
@@ -476,7 +475,7 @@ class World
476
475
  int can_sync = 1;
477
476
  VALUE syncs = cur_syncs(comp_shdw);
478
477
  assert(RTEST(syncs));
479
-
478
+
480
479
  for (i = RARRAY_LEN(syncs) - 1; i >= 0; i--) {
481
480
  VALUE sync = RARRAY_PTR(syncs)[i];
482
481
  assert(RARRAY_LEN(sync) == 3);
@@ -484,18 +483,18 @@ class World
484
483
  VALUE event = RARRAY_PTR(sync)[#{spi::EVENT_IDX}];
485
484
  ComponentShadow *link_shdw =
486
485
  *(ComponentShadow **)(((char *)comp_shdw) + link_offset);
487
-
486
+
488
487
  if (!link_shdw || !RTEST(link_shdw->trans)) {
489
488
  can_sync = 0;
490
489
  break;
491
490
  }
492
-
491
+
493
492
  int found = 0;
494
493
  VALUE link_events = cur_events(link_shdw);
495
494
  if (RTEST(link_events)) {
496
495
  VALUE *ptr = RARRAY_PTR(link_events);
497
496
  long len = RARRAY_LEN(link_events);
498
-
497
+
499
498
  for (j = len; j > 0; j--, ptr++) {
500
499
  VALUE link_event = RARRAY_PTR(*ptr)[#{epi::E_IDX}];
501
500
  if (link_event == event) {
@@ -504,23 +503,23 @@ class World
504
503
  }
505
504
  }
506
505
  }
507
-
506
+
508
507
  if (!found) {
509
508
  can_sync = 0;
510
509
  break;
511
510
  }
512
511
  }
513
-
512
+
514
513
  //%% hook_can_sync(comp_shdw->self, INT2BOOL(can_sync));
515
514
  return can_sync;
516
515
  }
517
-
516
+
518
517
  inline static int eval_events(ComponentShadow *comp_shdw,
519
518
  #{World.shadow_struct_name} *shadow)
520
519
  {
521
520
  VALUE events = cur_events(comp_shdw);
522
521
  int has_events = RTEST(events);
523
-
522
+
524
523
  if (has_events) {
525
524
  VALUE *ptr = RARRAY_PTR(events);
526
525
  long len = RARRAY_LEN(events);
@@ -547,13 +546,13 @@ class World
547
546
 
548
547
  return has_events;
549
548
  }
550
-
549
+
551
550
  inline static void cache_new_constant_value(
552
551
  double *dbl_ptr, double value,
553
552
  #{World.shadow_struct_name} *shadow)
554
553
  {
555
554
  CVCacheEntry *entry;
556
-
555
+
557
556
  if (!shadow->constant_value_cache) {
558
557
  int n = #{CV_CACHE_SIZE};
559
558
  shadow->constant_value_cache = malloc(n*sizeof(CVCacheEntry));
@@ -577,7 +576,7 @@ class World
577
576
  entry->value = value;
578
577
  shadow->cv_cache_used += 1;
579
578
  }
580
-
579
+
581
580
  inline static int assign_new_constant_values(
582
581
  #{World.shadow_struct_name} *shadow)
583
582
  {
@@ -593,16 +592,16 @@ class World
593
592
  }
594
593
  shadow->cv_cache_used = 0;
595
594
  }
596
-
595
+
597
596
  return did_reset;
598
597
  }
599
-
598
+
600
599
  inline static void cache_new_link(
601
600
  ComponentShadow **link_ptr, VALUE value,
602
601
  #{World.shadow_struct_name} *shadow)
603
602
  {
604
603
  LinkCacheEntry *entry;
605
-
604
+
606
605
  if (!shadow->link_cache) {
607
606
  int n = #{LINK_CACHE_SIZE};
608
607
  shadow->link_cache = malloc(n*sizeof(LinkCacheEntry));
@@ -625,12 +624,12 @@ class World
625
624
  entry->value = value;
626
625
  shadow->link_cache_used += 1;
627
626
  }
628
-
627
+
629
628
  inline static int assign_new_links(
630
629
  #{World.shadow_struct_name} *shadow)
631
630
  {
632
631
  int did_reset = shadow->link_cache_used;
633
-
632
+
634
633
  if (shadow->link_cache_used) {
635
634
  int i;
636
635
  LinkCacheEntry *entry;
@@ -646,15 +645,15 @@ class World
646
645
  }
647
646
  shadow->link_cache_used = 0;
648
647
  }
649
-
648
+
650
649
  return did_reset;
651
650
  }
652
-
651
+
653
652
  inline static void cache_new_port(VALUE input_port, VALUE other_port,
654
653
  #{World.shadow_struct_name} *shadow)
655
654
  {
656
655
  PortCacheEntry *entry;
657
-
656
+
658
657
  if (!shadow->port_cache) {
659
658
  int n = #{PORT_CACHE_SIZE};
660
659
  shadow->port_cache = malloc(n*sizeof(PortCacheEntry));
@@ -677,12 +676,12 @@ class World
677
676
  entry->other_port = other_port;
678
677
  shadow->port_cache_used += 1;
679
678
  }
680
-
679
+
681
680
  inline static int assign_new_ports(
682
681
  #{World.shadow_struct_name} *shadow)
683
682
  {
684
683
  int did_reset = shadow->port_cache_used;
685
-
684
+
686
685
  if (shadow->port_cache_used) {
687
686
  int i;
688
687
  PortCacheEntry *entry;
@@ -694,10 +693,10 @@ class World
694
693
  }
695
694
  shadow->port_cache_used = 0;
696
695
  }
697
-
696
+
698
697
  return did_reset;
699
698
  }
700
-
699
+
701
700
  inline static int eval_continuous_resets(ComponentShadow *comp_shdw,
702
701
  #{World.shadow_struct_name} *shadow)
703
702
  {
@@ -769,7 +768,7 @@ class World
769
768
  }
770
769
  }
771
770
  }
772
-
771
+
773
772
  return has_cont_resets;
774
773
  }
775
774
 
@@ -822,11 +821,11 @@ class World
822
821
  new_value, shadow);
823
822
  }
824
823
  }
825
-
824
+
826
825
  if (has_link_resets) {
827
826
  VALUE *ptr = RARRAY_PTR(link_resets);
828
827
  long len = RARRAY_LEN(link_resets);
829
-
828
+
830
829
  for (i = 0; i < len; i++) {
831
830
  VALUE pair = ptr[i];
832
831
  int offset = NUM2INT(RARRAY_PTR(pair)[0]);
@@ -872,10 +871,10 @@ class World
872
871
  new_value, shadow);
873
872
  }
874
873
  }
875
-
874
+
876
875
  return has_const_resets || has_link_resets;
877
876
  }
878
-
877
+
879
878
  inline static int eval_port_connects(ComponentShadow *comp_shdw,
880
879
  #{World.shadow_struct_name} *shadow)
881
880
  {
@@ -895,7 +894,7 @@ class World
895
894
  VALUE connect_spec = RARRAY_PTR(pair)[1];
896
895
  VALUE input_port;
897
896
  VALUE other_port;
898
-
897
+
899
898
  input_port = rb_funcall(comp, #{declare_symbol :port}, 1, input_var);
900
899
  if (connect_spec == Qnil) {
901
900
  other_port = Qnil;
@@ -914,7 +913,7 @@ class World
914
913
  return 1;
915
914
  }
916
915
  }
917
-
916
+
918
917
  inline static int assign_new_cont_values(ComponentShadow *comp_shdw)
919
918
  {
920
919
  VALUE resets = cur_resets(comp_shdw);
@@ -947,7 +946,7 @@ class World
947
946
  {
948
947
  long i;
949
948
  VALUE comp = comp_shdw->self;
950
-
949
+
951
950
  assert(RTEST(actions));
952
951
 
953
952
  for (i = 0; i < RARRAY_LEN(actions); i++) {
@@ -981,7 +980,7 @@ class World
981
980
  }
982
981
  }
983
982
  }
984
-
983
+
985
984
  inline static void start_trans(ComponentShadow *comp_shdw,
986
985
  #{World.shadow_struct_name} *shadow,
987
986
  VALUE trans, VALUE dest)
@@ -990,7 +989,7 @@ class World
990
989
  comp_shdw->dest = dest;
991
990
  //%% hook_start_transition(comp_shdw->self, trans, dest);
992
991
  }
993
-
992
+
994
993
  inline static void finish_trans(ComponentShadow *comp_shdw,
995
994
  #{World.shadow_struct_name} *shadow)
996
995
  { //%% hook_finish_transition(comp_shdw->self, comp_shdw->trans,
@@ -1004,19 +1003,19 @@ class World
1004
1003
  comp_shdw->trans = Qnil;
1005
1004
  comp_shdw->dest = Qnil;
1006
1005
  }
1007
-
1006
+
1008
1007
  inline static void abort_trans(ComponentShadow *comp_shdw)
1009
1008
  {
1010
1009
  comp_shdw->trans = Qnil;
1011
1010
  comp_shdw->dest = Qnil;
1012
1011
  }
1013
-
1012
+
1014
1013
  inline static void check_strict(ComponentShadow *comp_shdw)
1015
1014
  {
1016
1015
  ContVar *vars = (ContVar *)&FIRST_CONT_VAR(comp_shdw);
1017
1016
  long count = comp_shdw->var_count;
1018
1017
  long i;
1019
-
1018
+
1020
1019
  for(i = 0; i < count; i++) {
1021
1020
  ContVar *var = &vars[i];
1022
1021
  if (var->ck_strict) {
@@ -1030,7 +1029,7 @@ class World
1030
1029
  }
1031
1030
  }
1032
1031
  }
1033
-
1032
+
1034
1033
  inline static void check_guards(#{World.shadow_struct_name} *shadow,
1035
1034
  int sync_retry)
1036
1035
  {
@@ -1040,13 +1039,13 @@ class World
1040
1039
  int list_i;
1041
1040
  VALUE *ptr;
1042
1041
  long len, cur;
1043
-
1042
+
1044
1043
  EACH_COMP_DO(shadow->prev_awake) {
1045
1044
  int enabled = 0;
1046
-
1045
+
1047
1046
  if (shadow->discrete_step == 0)
1048
1047
  comp_shdw->checked = 0;
1049
-
1048
+
1050
1049
  len = RARRAY_LEN(comp_shdw->outgoing) - 1; //# last is flags
1051
1050
  cur = len;
1052
1051
 
@@ -1060,20 +1059,20 @@ class World
1060
1059
  cur -= 4 * comp_shdw->tmp.trans.idx;
1061
1060
  else
1062
1061
  comp_shdw->tmp.trans.idx = 0;
1063
-
1062
+
1064
1063
  while (cur >= 4) {
1065
1064
  VALUE trans, dest, guard, strict;
1066
-
1065
+
1067
1066
  strict = ptr[--cur];
1068
1067
  guard = ptr[--cur];
1069
-
1068
+
1070
1069
  enabled = !RTEST(guard) ||
1071
1070
  ((comp_shdw->checked && RTEST(strict)) ? 0 :
1072
1071
  guard_enabled(comp, guard, shadow->discrete_step));
1073
-
1072
+
1074
1073
  //%% hook_eval_guard(comp, guard, INT2BOOL(enabled),
1075
1074
  //%% ptr[cur-2], ptr[cur-1]);
1076
-
1075
+
1077
1076
  if (enabled) {
1078
1077
  dest = ptr[--cur];
1079
1078
  trans = ptr[--cur];
@@ -1089,7 +1088,7 @@ class World
1089
1088
  else
1090
1089
  cur -= 2;
1091
1090
  }
1092
-
1091
+
1093
1092
  if (!enabled) {
1094
1093
  VALUE qrc;
1095
1094
  if (comp_shdw->strict)
@@ -1106,7 +1105,7 @@ class World
1106
1105
  }
1107
1106
  assert(rs_dv(shadow->prev_awake)->len == 0);
1108
1107
  }
1109
-
1108
+
1110
1109
  inline static void do_sync_phase(#{World.shadow_struct_name} *shadow)
1111
1110
  {
1112
1111
  VALUE comp;
@@ -1114,7 +1113,7 @@ class World
1114
1113
  RS_DVector *list;
1115
1114
  int list_i;
1116
1115
  int changed;
1117
-
1116
+
1118
1117
  do {
1119
1118
  changed = 0;
1120
1119
  EACH_COMP_DO(shadow->curr_S) {
@@ -1127,17 +1126,17 @@ class World
1127
1126
  move_comp(comp, shadow->curr_S, shadow->prev_awake);
1128
1127
  }
1129
1128
  }
1130
-
1129
+
1131
1130
  assert(rs_dv(shadow->curr_S)->len == 0);
1132
1131
  SWAP_VALUE(shadow->curr_S, shadow->next_S);
1133
1132
  //%% hook_sync_step(shadow->curr_S, INT2BOOL(changed));
1134
1133
  } while (changed);
1135
-
1134
+
1136
1135
  move_all_comps(shadow->curr_S, shadow->curr_T);
1137
1136
  }
1138
-
1137
+
1139
1138
  }.tabto(0)
1140
-
1139
+
1141
1140
  comp_id = declare_class RedShift::Component
1142
1141
  get_const = proc {|k| "rb_const_get(#{comp_id}, #{declare_symbol k})"}
1143
1142
  init %{
@@ -1154,7 +1153,7 @@ class World
1154
1153
  ExprWrapperClass = #{get_const[:ExprWrapper]};
1155
1154
  DynamicEventClass = #{get_const[:DynamicEventValue]};
1156
1155
  }
1157
-
1156
+
1158
1157
  body %{
1159
1158
  //%% hook_begin();
1160
1159
  shadow->zeno_counter = 0;
@@ -1162,9 +1161,9 @@ class World
1162
1161
  for (shadow->discrete_step = 0 ;; shadow->discrete_step++) {
1163
1162
  //%% hook_begin_step();
1164
1163
  int sync_retry = 0;
1165
-
1164
+
1166
1165
  SWAP_VALUE(shadow->prev_awake, shadow->awake);
1167
-
1166
+
1168
1167
  while (rs_dv(shadow->prev_awake)->len) {
1169
1168
  //%% hook_enter_guard_phase();
1170
1169
  check_guards(shadow, sync_retry);
@@ -1175,7 +1174,7 @@ class World
1175
1174
  //%% hook_leave_sync_phase();
1176
1175
  sync_retry = 1;
1177
1176
  }
1178
-
1177
+
1179
1178
  if (!rs_dv(shadow->curr_T)->len) {
1180
1179
  //%% hook_end_step();
1181
1180
  break; //# out of main loop
@@ -1187,7 +1186,7 @@ class World
1187
1186
  rs_dv_push(rs_dv(shadow->active_E), comp);
1188
1187
  //%% hook_end_eval_events(comp);
1189
1188
  }
1190
-
1189
+
1191
1190
  //# Export new event values.
1192
1191
  EACH_COMP_DO(shadow->active_E) {
1193
1192
  SWAP_VALUE(comp_shdw->event_values, comp_shdw->next_event_values);
@@ -1195,7 +1194,7 @@ class World
1195
1194
  }
1196
1195
  SWAP_VALUE(shadow->active_E, shadow->prev_active_E);
1197
1196
  assert(rs_dv(shadow->active_E)->len == 0);
1198
-
1197
+
1199
1198
  //%% hook_enter_eval_phase();
1200
1199
  EACH_COMP_DO(shadow->curr_T) {
1201
1200
  //%% hook_begin_eval_resets(comp);
@@ -1204,10 +1203,10 @@ class World
1204
1203
  eval_constant_resets(comp_shdw, shadow);
1205
1204
  eval_port_connects(comp_shdw, shadow);
1206
1205
  //%% hook_end_eval_resets(comp);
1207
-
1206
+
1208
1207
  if (RTEST(cur_actions(comp_shdw)))
1209
1208
  rs_dv_push(rs_dv(shadow->curr_A), comp);
1210
-
1209
+
1211
1210
  if (RTEST(cur_posts(comp_shdw)))
1212
1211
  rs_dv_push(rs_dv(shadow->curr_P), comp);
1213
1212
  }
@@ -1237,7 +1236,7 @@ class World
1237
1236
  }
1238
1237
  rs_dv(shadow->curr_P)->len = 0;
1239
1238
  //%% hook_leave_post_phase();
1240
-
1239
+
1241
1240
  EACH_COMP_DO(shadow->curr_T) {
1242
1241
  finish_trans(comp_shdw, shadow);
1243
1242
  }
@@ -1246,20 +1245,20 @@ class World
1246
1245
  shadow->d_tick++;
1247
1246
  //## replace "1" with "some comp entered new
1248
1247
  //## state with new alg. eqs"
1249
-
1248
+
1250
1249
  EACH_COMP_DO(shadow->curr_T) {
1251
1250
  check_strict(comp_shdw);
1252
1251
  //## optimize: only keep comps with var->ck_strict on this list
1253
1252
  //## option to skip this check
1254
1253
  }
1255
-
1254
+
1256
1255
  //# Check for zeno problem.
1257
1256
  if (shadow->zeno_limit >= 0) {
1258
1257
  shadow->zeno_counter++;
1259
1258
  if (shadow->zeno_counter > shadow->zeno_limit)
1260
1259
  rb_funcall(shadow->self, #{declare_symbol :step_zeno}, 0);
1261
1260
  }
1262
-
1261
+
1263
1262
  EACH_COMP_DO(shadow->curr_T) {
1264
1263
  if (comp_shdw->state == ExitState)
1265
1264
  remove_comp(comp, shadow->curr_T, shadow);
@@ -1275,17 +1274,17 @@ class World
1275
1274
  RARRAY_LEN(comp_shdw->event_values));
1276
1275
  }
1277
1276
  rs_dv(shadow->prev_active_E)->len = 0;
1278
-
1277
+
1279
1278
  //%% hook_end_step();
1280
1279
  }
1281
-
1280
+
1282
1281
  move_all_comps(shadow->strict_sleep, shadow->awake);
1283
1282
 
1284
1283
  //%% hook_end();
1285
1284
  shadow->discrete_step = 0;
1286
1285
  shadow->zeno_counter = 0;
1287
1286
  }
1288
-
1287
+
1289
1288
  # only call this when all defs have been added
1290
1289
  def parent.to_s
1291
1290
  @cached_output ||= super
@@ -1294,30 +1293,31 @@ class World
1294
1293
 
1295
1294
  hook = /\bhook_\w+/
1296
1295
  world_classes = World.subclasses + [World]
1297
- hooks = Hash.new {|h,cl| h[cl] = cl.instance_methods(true).grep(hook).sort}
1296
+ hooks = Hash.new {|h,cl| h[cl] =
1297
+ cl.instance_methods(true).grep(hook).sort.map{|s|s.to_sym} }
1298
1298
  hooks[World.superclass] = nil
1299
1299
  known_hooks = nil
1300
-
1300
+
1301
1301
  world_classes.each do |cl|
1302
1302
  cl_hooks = hooks[cl]
1303
1303
  next if hooks[cl.superclass] == hooks[cl]
1304
-
1304
+
1305
1305
  cl.class_eval do
1306
1306
  shadow_library_source_file.include(Component.shadow_library_include_file)
1307
1307
  shadow_library_source_file.include("dvector/dvector.h")
1308
-
1308
+
1309
1309
  if (instance_methods(false) + protected_instance_methods(false) +
1310
1310
  private_instance_methods(false)).grep(/^step_discrete$/).size > 0
1311
1311
  warn "Redefining step_discrete in #{self}"
1312
1312
  end
1313
-
1313
+
1314
1314
  meth = define_c_method(:step_discrete, &discrete_step_definer)
1315
1315
  private :step_discrete
1316
-
1316
+
1317
1317
  before_commit do
1318
1318
  # at this point, we know the file is complete
1319
1319
  file_str = meth.parent.to_s
1320
-
1320
+
1321
1321
  known_hooks ||= file_str.scan(hook).map {|s|s.to_sym}
1322
1322
  unknown_hooks = cl_hooks - known_hooks
1323
1323