redshift 1.3.24 → 1.3.30

Sign up to get free protection for your applications and to get access to all the features.
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