redshift 1.3.29 → 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.
- checksums.yaml +5 -5
- data/README.md +2 -0
- data/lib/redshift/redshift.rb +1 -1
- data/lib/redshift/target/c/world-gen.rb +99 -100
- data/test/test_flow_trans.rb +21 -21
- metadata +3 -6
- data/examples/robots/README +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0e70ddb9e9f05b61a7b15acd4a9a59ad94f8fb43771aa0619f0d69400f691ba2
|
4
|
+
data.tar.gz: 0a2087fa620759313761ddcfc788dc44fcc204f5b0d2d8ceb5e73681102c2f75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '059c869b96c8e837ebdd1762e28859f5fdf6d4f4f76afa6a955149a93013b11d262d849b30e472523ce9ca9d09f0b255efc6ae64bcf9488703a0431e6af5cbe5'
|
7
|
+
data.tar.gz: 25438a65be067f8b8a5df3dbd9f276722e2de0468bfa06273041fd7dc3e56f79677a1382c75633783c4d46c436845df1873ec34b72c89d83beb87be1638c814a
|
data/README.md
CHANGED
@@ -6,6 +6,8 @@ RedShift is for simulating digital devices operating in an analog world. It's al
|
|
6
6
|
|
7
7
|
There's not much [documentation](doc) yet, but plenty of [examples](examples). Some of the original SHIFT papers are available: [Shift: A Formalism and a Programming Language for Dynamic Networks of Hybrid Automata]( http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.32.5913&rep=rep1&type=pdf).
|
8
8
|
|
9
|
+
My [2009 rubyconf talk](http://confreaks.com/videos/165-rubyconf2009-dsls-code-generation-and-new-domains-for-ruby) discusses RedShift.
|
10
|
+
|
9
11
|
## Requirements ##
|
10
12
|
|
11
13
|
RedShift needs ruby (1.8, 1.9, 2.0, 2.1) and a compatible C compiler. If you can build native gems, you're all set.
|
data/lib/redshift/redshift.rb
CHANGED
@@ -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
|
@@ -1298,27 +1297,27 @@ class World
|
|
1298
1297
|
cl.instance_methods(true).grep(hook).sort.map{|s|s.to_sym} }
|
1299
1298
|
hooks[World.superclass] = nil
|
1300
1299
|
known_hooks = nil
|
1301
|
-
|
1300
|
+
|
1302
1301
|
world_classes.each do |cl|
|
1303
1302
|
cl_hooks = hooks[cl]
|
1304
1303
|
next if hooks[cl.superclass] == hooks[cl]
|
1305
|
-
|
1304
|
+
|
1306
1305
|
cl.class_eval do
|
1307
1306
|
shadow_library_source_file.include(Component.shadow_library_include_file)
|
1308
1307
|
shadow_library_source_file.include("dvector/dvector.h")
|
1309
|
-
|
1308
|
+
|
1310
1309
|
if (instance_methods(false) + protected_instance_methods(false) +
|
1311
1310
|
private_instance_methods(false)).grep(/^step_discrete$/).size > 0
|
1312
1311
|
warn "Redefining step_discrete in #{self}"
|
1313
1312
|
end
|
1314
|
-
|
1313
|
+
|
1315
1314
|
meth = define_c_method(:step_discrete, &discrete_step_definer)
|
1316
1315
|
private :step_discrete
|
1317
|
-
|
1316
|
+
|
1318
1317
|
before_commit do
|
1319
1318
|
# at this point, we know the file is complete
|
1320
1319
|
file_str = meth.parent.to_s
|
1321
|
-
|
1320
|
+
|
1322
1321
|
known_hooks ||= file_str.scan(hook).map {|s|s.to_sym}
|
1323
1322
|
unknown_hooks = cl_hooks - known_hooks
|
1324
1323
|
|
data/test/test_flow_trans.rb
CHANGED
@@ -19,7 +19,7 @@ class Flow_Transition_Alg_To_Other < FlowTestComponent
|
|
19
19
|
alg "x=42"
|
20
20
|
end
|
21
21
|
transition A => B
|
22
|
-
|
22
|
+
|
23
23
|
def assert_consistent test
|
24
24
|
if state == B
|
25
25
|
test.assert_equal(42, x)
|
@@ -31,23 +31,23 @@ end
|
|
31
31
|
|
32
32
|
class Flow_Transition < FlowTestComponent
|
33
33
|
state :Alg, :Diff, :Euler, :Empty, :Switch
|
34
|
-
|
34
|
+
|
35
35
|
flow Alg, Diff, Euler, Empty do
|
36
36
|
diff "t' = 1"
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
flow Alg do
|
40
40
|
alg "x = 10*t"
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
flow Diff do
|
44
44
|
diff "x' = 10"
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
flow Euler do
|
48
48
|
euler "x' = 10"
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
setup do
|
52
52
|
self.x = 0
|
53
53
|
@alarm_time = 0
|
@@ -71,7 +71,7 @@ class Flow_Transition < FlowTestComponent
|
|
71
71
|
puts " alarm seed = #{@alarm_seq.generator.seeds rescue @alarm_seq.generator.seed}"
|
72
72
|
puts " state seed = #{@state_seq.generator.seeds rescue @state_seq.generator.seed}"
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
transition Enter => Switch,
|
76
76
|
Alg => Switch, Diff => Switch,
|
77
77
|
Euler => Switch, Empty => Switch do
|
@@ -89,7 +89,7 @@ class Flow_Transition < FlowTestComponent
|
|
89
89
|
end
|
90
90
|
}
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
transition Switch => Alg do
|
94
94
|
guard { @current == Alg }
|
95
95
|
end
|
@@ -102,7 +102,7 @@ class Flow_Transition < FlowTestComponent
|
|
102
102
|
transition Switch => Empty do
|
103
103
|
guard { @current == Empty }
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
transition Empty => Empty do
|
107
107
|
guard { t > (@last_empty_t || 0) }
|
108
108
|
action {
|
@@ -110,7 +110,7 @@ class Flow_Transition < FlowTestComponent
|
|
110
110
|
self.x = 10 * t # manually update x
|
111
111
|
}
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
def assert_consistent test
|
115
115
|
# In the alg case, calling the accessor invokes the update method. We want
|
116
116
|
# to test that alg flows work even if the update method isn't called.
|
@@ -122,7 +122,7 @@ class Flow_Transition < FlowTestComponent
|
|
122
122
|
"in #{state.name} after #{t} sec,\n")
|
123
123
|
end
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
def finish test
|
127
127
|
# puts "At finish: t = #{t}, alarm_time = #{@alarm_time}"
|
128
128
|
end
|
@@ -191,9 +191,9 @@ class Flow_AlgebraicAction < FlowTestComponent
|
|
191
191
|
constant :k
|
192
192
|
link :other => self
|
193
193
|
flow {alg " x = other.y + k "}
|
194
|
-
|
194
|
+
|
195
195
|
@@first = true
|
196
|
-
|
196
|
+
|
197
197
|
setup do
|
198
198
|
self.other = self
|
199
199
|
if @@first
|
@@ -201,21 +201,21 @@ class Flow_AlgebraicAction < FlowTestComponent
|
|
201
201
|
@other = create(Flow_AlgebraicAction) {|c| c.y = 5}
|
202
202
|
end
|
203
203
|
end
|
204
|
-
|
204
|
+
|
205
205
|
transition Enter => Exit do
|
206
206
|
action do
|
207
207
|
next unless @other
|
208
|
-
|
208
|
+
|
209
209
|
@x_values = []
|
210
210
|
@x_values << x
|
211
211
|
other.y = 1
|
212
212
|
@x_values << x
|
213
213
|
other.y = 2
|
214
214
|
@x_values << x
|
215
|
-
|
215
|
+
|
216
216
|
self.other = @other
|
217
217
|
@x_values << x
|
218
|
-
|
218
|
+
|
219
219
|
self.k = 10
|
220
220
|
@x_values << x
|
221
221
|
end
|
@@ -232,17 +232,17 @@ end
|
|
232
232
|
require 'minitest/autorun'
|
233
233
|
|
234
234
|
class TestFlow < Minitest::Test
|
235
|
-
|
235
|
+
|
236
236
|
def setup
|
237
237
|
@world = World.new
|
238
238
|
@world.time_step = 0.01
|
239
239
|
@world.zeno_limit = 100
|
240
240
|
end
|
241
|
-
|
241
|
+
|
242
242
|
def teardown
|
243
243
|
@world = nil
|
244
244
|
end
|
245
|
-
|
245
|
+
|
246
246
|
def test_flow
|
247
247
|
testers = []
|
248
248
|
ObjectSpace.each_object(Class) do |cl|
|
@@ -251,7 +251,7 @@ class TestFlow < Minitest::Test
|
|
251
251
|
testers << @world.create(cl)
|
252
252
|
end
|
253
253
|
end
|
254
|
-
|
254
|
+
|
255
255
|
testers.each { |t| t.assert_consistent self }
|
256
256
|
@world.run 1000 do
|
257
257
|
testers.each { |t| t.assert_consistent self }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redshift
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.30
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel VanderWerf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cgen
|
@@ -104,7 +104,6 @@ files:
|
|
104
104
|
- examples/queue.rb
|
105
105
|
- examples/queue2.rb
|
106
106
|
- examples/reset-with-event-val.rb
|
107
|
-
- examples/robots/README
|
108
107
|
- examples/robots/lib/base.rb
|
109
108
|
- examples/robots/lib/explosion.rb
|
110
109
|
- examples/robots/lib/missile.rb
|
@@ -240,10 +239,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
239
|
- !ruby/object:Gem::Version
|
241
240
|
version: '0'
|
242
241
|
requirements: []
|
243
|
-
|
244
|
-
rubygems_version: 2.4.1
|
242
|
+
rubygems_version: 3.1.4
|
245
243
|
signing_key:
|
246
244
|
specification_version: 4
|
247
245
|
summary: Simulation of hybrid automata
|
248
246
|
test_files: []
|
249
|
-
has_rdoc:
|
data/examples/robots/README
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
= Robots
|
2
|
-
|
3
|
-
An example covering some of the basic language features plus some techniques for interactive simulation and for animating simulation output.
|
4
|
-
|
5
|
-
To run the example:
|
6
|
-
|
7
|
-
ruby robots.rb
|
8
|
-
|
9
|
-
Press ^C to break into a command shell, and then ^D to continue the simulation run. The "help" command in the shell shows you the commands beyond the basic irb.
|
10
|
-
|
11
|
-
Use -h from the command line to see the switches.
|
12
|
-
|
13
|
-
To change the setup of the world, edit robots.rb. You can add and move robots and missles.
|
14
|
-
|
15
|
-
You can also move the objects interactively in the Tk visualization.
|
16
|
-
|
17
|
-
Currently, the robots move around and the missles track and hit them.
|
18
|
-
|
19
|
-
= To do
|
20
|
-
|
21
|
-
== robots physics
|
22
|
-
|
23
|
-
- collision detection and effect on robot health
|
24
|
-
|
25
|
-
- walls and obstacles
|
26
|
-
|
27
|
-
== robot control
|
28
|
-
|
29
|
-
- command language to evade attackers and launch missiles based on radar
|
30
|
-
|
31
|
-
- maybe similar to RoboTalk (from RoboWar)
|
32
|
-
|
33
|
-
- multirobot coordination using comm channels
|
34
|
-
|
35
|
-
== game mechanics
|
36
|
-
|
37
|
-
- robot shop
|
38
|
-
|
39
|
-
- tournaments
|
40
|
-
|
41
|
-
== dev tools
|
42
|
-
|
43
|
-
- debugger
|
44
|
-
|
45
|
-
- plotter
|
46
|
-
|
47
|
-
== visualization
|
48
|
-
|
49
|
-
- for each sensor, show nearest robot by drawing arrow
|