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