redshift 1.3.15
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.
- data/.gitignore +8 -0
- data/README +5 -0
- data/RELEASE-NOTES +455 -0
- data/TODO +431 -0
- data/bench/alg-state.rb +61 -0
- data/bench/bench +26 -0
- data/bench/bench.rb +10 -0
- data/bench/continuous.rb +76 -0
- data/bench/diff-bench +86 -0
- data/bench/discrete.rb +101 -0
- data/bench/euler.rb +50 -0
- data/bench/formula.rb +78 -0
- data/bench/half-strict.rb +103 -0
- data/bench/inertness.rb +116 -0
- data/bench/queue.rb +92 -0
- data/bench/run +66 -0
- data/bench/simple.rb +74 -0
- data/bench/strictness.rb +86 -0
- data/examples/ball-tkar.rb +72 -0
- data/examples/ball.rb +123 -0
- data/examples/collide.rb +70 -0
- data/examples/connect-parallel.rb +48 -0
- data/examples/connect.rb +109 -0
- data/examples/constants.rb +27 -0
- data/examples/delay.rb +80 -0
- data/examples/derivative.rb +77 -0
- data/examples/euler.rb +46 -0
- data/examples/external-lib.rb +33 -0
- data/examples/guard-debugger.rb +77 -0
- data/examples/lotka-volterra.rb +33 -0
- data/examples/persist-ball.rb +68 -0
- data/examples/pid.rb +87 -0
- data/examples/ports.rb +60 -0
- data/examples/queue.rb +56 -0
- data/examples/queue2.rb +98 -0
- data/examples/reset-with-event-val.rb +28 -0
- data/examples/scheduler.rb +104 -0
- data/examples/set-dest.rb +23 -0
- data/examples/simulink/README +1 -0
- data/examples/simulink/delay.mdl +827 -0
- data/examples/simulink/derivative.mdl +655 -0
- data/examples/step-discrete-profiler.rb +103 -0
- data/examples/subsystem.rb +109 -0
- data/examples/sync-deadlock.rb +32 -0
- data/examples/sync-queue.rb +91 -0
- data/examples/sync-retry.rb +20 -0
- data/examples/sync.rb +51 -0
- data/examples/thermostat.rb +53 -0
- data/examples/zeno.rb +53 -0
- data/lib/accessible-index.rb +47 -0
- data/lib/redshift.rb +1 -0
- data/lib/redshift/component.rb +412 -0
- data/lib/redshift/meta.rb +183 -0
- data/lib/redshift/mixins/zeno-debugger.rb +69 -0
- data/lib/redshift/port.rb +57 -0
- data/lib/redshift/queue.rb +104 -0
- data/lib/redshift/redshift.rb +111 -0
- data/lib/redshift/state.rb +31 -0
- data/lib/redshift/syntax.rb +558 -0
- data/lib/redshift/target/c.rb +37 -0
- data/lib/redshift/target/c/component-gen.rb +1303 -0
- data/lib/redshift/target/c/flow-gen.rb +325 -0
- data/lib/redshift/target/c/flow/algebraic.rb +85 -0
- data/lib/redshift/target/c/flow/buffer.rb +74 -0
- data/lib/redshift/target/c/flow/delay.rb +203 -0
- data/lib/redshift/target/c/flow/derivative.rb +101 -0
- data/lib/redshift/target/c/flow/euler.rb +67 -0
- data/lib/redshift/target/c/flow/expr.rb +113 -0
- data/lib/redshift/target/c/flow/rk4.rb +80 -0
- data/lib/redshift/target/c/library.rb +85 -0
- data/lib/redshift/target/c/world-gen.rb +1370 -0
- data/lib/redshift/target/spec.rb +34 -0
- data/lib/redshift/world.rb +300 -0
- data/rakefile +37 -0
- data/test/test.rb +52 -0
- data/test/test_buffer.rb +58 -0
- data/test/test_connect.rb +242 -0
- data/test/test_connect_parallel.rb +47 -0
- data/test/test_connect_strict.rb +135 -0
- data/test/test_constant.rb +74 -0
- data/test/test_delay.rb +145 -0
- data/test/test_derivative.rb +48 -0
- data/test/test_discrete.rb +592 -0
- data/test/test_discrete_isolated.rb +92 -0
- data/test/test_exit.rb +59 -0
- data/test/test_flow.rb +200 -0
- data/test/test_flow_link.rb +288 -0
- data/test/test_flow_sub.rb +100 -0
- data/test/test_flow_trans.rb +292 -0
- data/test/test_inherit.rb +127 -0
- data/test/test_inherit_event.rb +74 -0
- data/test/test_inherit_flow.rb +139 -0
- data/test/test_inherit_link.rb +65 -0
- data/test/test_inherit_setup.rb +56 -0
- data/test/test_inherit_state.rb +66 -0
- data/test/test_inherit_transition.rb +168 -0
- data/test/test_numerics.rb +34 -0
- data/test/test_queue.rb +90 -0
- data/test/test_queue_alone.rb +115 -0
- data/test/test_reset.rb +209 -0
- data/test/test_setup.rb +119 -0
- data/test/test_strict_continuity.rb +410 -0
- data/test/test_strict_reset_error.rb +30 -0
- data/test/test_strictness_error.rb +32 -0
- data/test/test_sync.rb +185 -0
- data/test/test_world.rb +328 -0
- metadata +204 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
module RedShift; class DelayFlow
|
2
|
+
def flow_wrapper cl, state
|
3
|
+
var_name = @var
|
4
|
+
flow = self
|
5
|
+
flow_name = "flow_#{CGenerator.make_c_name cl.name}_#{var_name}_#{state}"
|
6
|
+
delay_by = @delay_by
|
7
|
+
|
8
|
+
Component::FlowWrapper.make_subclass flow_name do
|
9
|
+
@inspect_str =
|
10
|
+
"#{cl.name}:#{state}: " +
|
11
|
+
"#{var_name} = #{flow.formula} [delay: #{delay_by}]"
|
12
|
+
|
13
|
+
ssn = cl.shadow_struct.name
|
14
|
+
cont_state_ssn = cl.cont_state_class.shadow_struct.name
|
15
|
+
|
16
|
+
require "redshift/target/c/flow/buffer"
|
17
|
+
RedShift.library.define_buffer
|
18
|
+
|
19
|
+
bufname = "#{var_name}_buffer_data"
|
20
|
+
offsetname = "#{var_name}_buffer_offset"
|
21
|
+
delayname = "#{var_name}_delay"
|
22
|
+
tsname = "#{var_name}_time_step"
|
23
|
+
|
24
|
+
cl.class_eval do
|
25
|
+
shadow_attr_accessor bufname => "Buffer #{bufname}"
|
26
|
+
shadow_attr_accessor offsetname => "long #{offsetname}"
|
27
|
+
shadow_attr_accessor delayname => "double #{delayname}"
|
28
|
+
# delay should be set only using the expr designated in :by => "expr"
|
29
|
+
shadow_attr tsname => "double #{tsname}"
|
30
|
+
|
31
|
+
after_commit do
|
32
|
+
alias_method "__#{bufname}=", "#{bufname}="
|
33
|
+
define_method "#{bufname}=" do |val|
|
34
|
+
send("__#{bufname}=", val)
|
35
|
+
d = world.time_step * (val.size / 4)
|
36
|
+
send("#{delayname}=", d) # keep cached delay consistent
|
37
|
+
end
|
38
|
+
end
|
39
|
+
private :"#{delayname}="
|
40
|
+
end
|
41
|
+
|
42
|
+
# We need the struct
|
43
|
+
shadow_library_source_file.include(cl.shadow_library_include_file)
|
44
|
+
|
45
|
+
shadow_library_source_file.define(flow_name).instance_eval do
|
46
|
+
arguments "ComponentShadow *comp_shdw"
|
47
|
+
declare :shadow => %{
|
48
|
+
struct #{ssn} *shadow;
|
49
|
+
struct #{cont_state_ssn} *cont_state;
|
50
|
+
|
51
|
+
ContVar *var;
|
52
|
+
double *ptr;
|
53
|
+
long i, len, offset, steps;
|
54
|
+
double delay, fill;
|
55
|
+
}
|
56
|
+
setup :shadow => %{
|
57
|
+
shadow = (#{ssn} *)comp_shdw;
|
58
|
+
cont_state = (#{cont_state_ssn} *)shadow->cont_state;
|
59
|
+
var = &cont_state->#{var_name};
|
60
|
+
}
|
61
|
+
setup :rk_level => %{
|
62
|
+
shadow->world->rk_level--;
|
63
|
+
} # has to happen before referenced alg flows are called in other setups
|
64
|
+
|
65
|
+
setup :delay =>
|
66
|
+
begin
|
67
|
+
"delay = #{Float(delay_by)}"
|
68
|
+
rescue ArgumentError
|
69
|
+
flow.translate(self, "delay", 0, cl, delay_by)
|
70
|
+
end
|
71
|
+
|
72
|
+
include World.shadow_library_include_file
|
73
|
+
|
74
|
+
# Note: cases 1,2 must proceed to allow alg deps to be computed,
|
75
|
+
# since their values are used later.
|
76
|
+
body %{
|
77
|
+
switch (shadow->world->rk_level) {
|
78
|
+
case 0:
|
79
|
+
ptr = shadow->#{bufname}.ptr;
|
80
|
+
offset = shadow->#{offsetname};
|
81
|
+
|
82
|
+
if (shadow->world->time_step != shadow->#{tsname}) {
|
83
|
+
if (shadow->#{tsname} == 0.0)
|
84
|
+
shadow->#{tsname} = shadow->world->time_step;
|
85
|
+
else
|
86
|
+
rs_raise(#{declare_class RedShiftError}, shadow->self,
|
87
|
+
"Delay flow doesn't support changing time_step yet"); // ##
|
88
|
+
}
|
89
|
+
|
90
|
+
if (ptr && delay == shadow->#{delayname}) {
|
91
|
+
len = shadow->#{bufname}.len;
|
92
|
+
if (offset < 0 || offset > len - 4) {
|
93
|
+
rs_raise(#{declare_class RedShiftError}, shadow->self,
|
94
|
+
"Offset out of bounds: %d not in 0..%d!", offset, len - 4);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
else {
|
98
|
+
steps = floor(delay / shadow->world->time_step + 0.5);
|
99
|
+
if (steps <= 0) {
|
100
|
+
rs_raise(#{declare_class RedShiftError}, shadow->self,
|
101
|
+
"Delay too small: %f.", delay);
|
102
|
+
}
|
103
|
+
len = steps*4;
|
104
|
+
|
105
|
+
if (!ptr) {
|
106
|
+
#{flow.translate(self, "fill", 0, cl).join("
|
107
|
+
")};
|
108
|
+
|
109
|
+
ptr = ALLOC_N(double, len);
|
110
|
+
shadow->#{bufname}.ptr = ptr;
|
111
|
+
shadow->#{bufname}.len = len;
|
112
|
+
shadow->#{offsetname} = 0;
|
113
|
+
shadow->#{delayname} = delay;
|
114
|
+
|
115
|
+
for (i=0; i<len; i++) {
|
116
|
+
ptr[i] = fill;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
else { // # delay != shadow->#{delayname}
|
120
|
+
long old_len = shadow->#{bufname}.len;
|
121
|
+
double *dst, *src;
|
122
|
+
|
123
|
+
if (delay < shadow->#{delayname}) {
|
124
|
+
if (offset < len) {
|
125
|
+
dst = ptr + offset;
|
126
|
+
src = ptr + offset + old_len - len;
|
127
|
+
}
|
128
|
+
else {
|
129
|
+
dst = ptr;
|
130
|
+
src = ptr + offset - len;
|
131
|
+
offset = 0;
|
132
|
+
}
|
133
|
+
memmove(dst, src, (len - offset) * sizeof(double));
|
134
|
+
REALLOC_N(ptr, double, len);
|
135
|
+
// ## maybe better: don't release space, just use less of it
|
136
|
+
}
|
137
|
+
else { // # delay > shadow->#{delayname}
|
138
|
+
REALLOC_N(ptr, double, len);
|
139
|
+
|
140
|
+
fill = ptr[offset];
|
141
|
+
dst = ptr + offset + len - old_len;
|
142
|
+
src = ptr + offset;
|
143
|
+
memmove(dst, src, (old_len - offset) * sizeof(double));
|
144
|
+
|
145
|
+
for (i = 0; i < len - old_len; i++) {
|
146
|
+
ptr[offset + i] = fill;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
shadow->#{bufname}.ptr = ptr;
|
151
|
+
shadow->#{bufname}.len = len;
|
152
|
+
shadow->#{offsetname} = offset;
|
153
|
+
shadow->#{delayname} = delay;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
offset = (offset + 4) % len;
|
158
|
+
shadow->#{offsetname} = offset;
|
159
|
+
|
160
|
+
var->value_0 = ptr[offset];
|
161
|
+
var->value_1 = ptr[offset + 1];
|
162
|
+
var->value_2 = ptr[offset + 2];
|
163
|
+
var->value_3 = ptr[offset + 3];
|
164
|
+
|
165
|
+
#{flow.translate(self, "ptr[offset]", 0, cl).join("
|
166
|
+
")};
|
167
|
+
break;
|
168
|
+
|
169
|
+
case 1:
|
170
|
+
case 2:
|
171
|
+
break;
|
172
|
+
|
173
|
+
case 3:
|
174
|
+
ptr = shadow->#{bufname}.ptr;
|
175
|
+
len = shadow->#{bufname}.len;
|
176
|
+
offset = shadow->#{offsetname};
|
177
|
+
|
178
|
+
#{flow.translate(self, "ptr[offset+1]", 1, cl).join("
|
179
|
+
")};
|
180
|
+
#{flow.translate(self, "ptr[offset+2]", 2, cl).join("
|
181
|
+
")};
|
182
|
+
#{flow.translate(self, "ptr[offset+3]", 3, cl).join("
|
183
|
+
")};
|
184
|
+
|
185
|
+
var->value_0 = ptr[(offset + 4) % len];
|
186
|
+
break;
|
187
|
+
|
188
|
+
default:
|
189
|
+
rb_raise(#{declare_class RuntimeError},
|
190
|
+
"Bad rk_level, %d!", shadow->world->rk_level);
|
191
|
+
}
|
192
|
+
|
193
|
+
shadow->world->rk_level++;
|
194
|
+
var->rk_level = shadow->world->rk_level;
|
195
|
+
}
|
196
|
+
end
|
197
|
+
|
198
|
+
define_c_method :calc_function_pointer do
|
199
|
+
body "shadow->flow = &#{flow_name}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end; end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module RedShift; class DerivativeFlow
|
2
|
+
def flow_wrapper cl, state
|
3
|
+
var_name = @var
|
4
|
+
flow = self
|
5
|
+
flow_name = "flow_#{CGenerator.make_c_name cl.name}_#{var_name}_#{state}"
|
6
|
+
feedback = @feedback
|
7
|
+
|
8
|
+
Component::FlowWrapper.make_subclass flow_name do
|
9
|
+
@inspect_str = "#{cl.name}:#{state}: #{var_name} = #{flow.formula}'"
|
10
|
+
|
11
|
+
ssn = cl.shadow_struct.name
|
12
|
+
cont_state_ssn = cl.cont_state_class.shadow_struct.name
|
13
|
+
|
14
|
+
# We need the struct
|
15
|
+
shadow_library_source_file.include(cl.shadow_library_include_file)
|
16
|
+
|
17
|
+
init_rhs_name = "#{var_name}_init_rhs"
|
18
|
+
cl.class_eval do
|
19
|
+
shadow_attr_accessor init_rhs_name => "double #{init_rhs_name}"
|
20
|
+
end
|
21
|
+
|
22
|
+
shadow_library_source_file.define(flow_name).instance_eval do
|
23
|
+
arguments "ComponentShadow *comp_shdw"
|
24
|
+
declare :shadow => %{
|
25
|
+
struct #{ssn} *shadow;
|
26
|
+
struct #{cont_state_ssn} *cont_state;
|
27
|
+
ContVar *var;
|
28
|
+
double antiddt, *scratch;
|
29
|
+
double time_step;
|
30
|
+
}
|
31
|
+
setup :shadow => %{
|
32
|
+
shadow = (#{ssn} *)comp_shdw;
|
33
|
+
cont_state = (#{cont_state_ssn} *)shadow->cont_state;
|
34
|
+
var = &cont_state->#{var_name};
|
35
|
+
scratch = &shadow->#{init_rhs_name};
|
36
|
+
time_step = shadow->world->time_step;
|
37
|
+
}
|
38
|
+
setup :rk_level => %{
|
39
|
+
shadow->world->rk_level--;
|
40
|
+
} # has to happen before referenced alg flows are called in other setups
|
41
|
+
if feedback ## possible to unite these cases somehow?
|
42
|
+
body %{
|
43
|
+
switch (shadow->world->rk_level) {
|
44
|
+
case 0:
|
45
|
+
#{flow.translate(self, "antiddt", 0, cl).join("
|
46
|
+
")};
|
47
|
+
var->value_0 = var->value_1 =
|
48
|
+
var->value_2 = var->value_3 =
|
49
|
+
(antiddt - *scratch) / time_step;
|
50
|
+
*scratch = antiddt;
|
51
|
+
}
|
52
|
+
shadow->world->rk_level++;
|
53
|
+
var->rk_level = shadow->world->rk_level;
|
54
|
+
}
|
55
|
+
else
|
56
|
+
body %{
|
57
|
+
switch (shadow->world->rk_level) {
|
58
|
+
case 0:
|
59
|
+
#{flow.translate(self, "antiddt", 0, cl).join("
|
60
|
+
")};
|
61
|
+
var->value_1 = var->value_0;
|
62
|
+
*scratch = antiddt;
|
63
|
+
break;
|
64
|
+
|
65
|
+
case 1:
|
66
|
+
#{flow.translate(self, "antiddt", 1, cl).join("
|
67
|
+
")};
|
68
|
+
var->value_2 = (antiddt - *scratch) / (time_step/2);
|
69
|
+
*scratch = antiddt;
|
70
|
+
break;
|
71
|
+
|
72
|
+
case 2:
|
73
|
+
#{flow.translate(self, "antiddt", 2, cl).join("
|
74
|
+
")};
|
75
|
+
var->value_3 = (antiddt - *scratch) / (time_step/2);
|
76
|
+
break;
|
77
|
+
|
78
|
+
case 3:
|
79
|
+
#{flow.translate(self, "antiddt", 3, cl).join("
|
80
|
+
")};
|
81
|
+
var->value_0 = (antiddt - *scratch) / (time_step/2);
|
82
|
+
break;
|
83
|
+
|
84
|
+
default:
|
85
|
+
rb_raise(#{declare_class RuntimeError},
|
86
|
+
"Bad rk_level, %d!", shadow->world->rk_level);
|
87
|
+
}
|
88
|
+
|
89
|
+
shadow->world->rk_level++;
|
90
|
+
var->rk_level = shadow->world->rk_level;
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
define_c_method :calc_function_pointer do
|
96
|
+
body "shadow->flow = &#{flow_name}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end; end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module RedShift; class EulerDifferentialFlow
|
2
|
+
def flow_wrapper cl, state
|
3
|
+
var_name = @var
|
4
|
+
flow = self
|
5
|
+
|
6
|
+
flow_name = "flow_#{CGenerator.make_c_name cl.name}_#{var_name}_#{state}"
|
7
|
+
|
8
|
+
Component::FlowWrapper.make_subclass flow_name do
|
9
|
+
@inspect_str = "#{cl.name}:#{state}: #{var_name} = #{flow.formula}"
|
10
|
+
|
11
|
+
ssn = cl.shadow_struct.name
|
12
|
+
cont_state_ssn = cl.cont_state_class.shadow_struct.name
|
13
|
+
|
14
|
+
# We need the struct
|
15
|
+
shadow_library_source_file.include(cl.shadow_library_include_file)
|
16
|
+
|
17
|
+
shadow_library_source_file.define(flow_name).instance_eval do
|
18
|
+
arguments "ComponentShadow *comp_shdw"
|
19
|
+
declare :shadow => %{
|
20
|
+
struct #{ssn} *shadow;
|
21
|
+
struct #{cont_state_ssn} *cont_state;
|
22
|
+
ContVar *var;
|
23
|
+
double ddt_#{var_name};
|
24
|
+
double time_step;
|
25
|
+
}
|
26
|
+
setup :first => %{
|
27
|
+
if (comp_shdw->world->rk_level == 2 ||
|
28
|
+
comp_shdw->world->rk_level == 3)
|
29
|
+
return;
|
30
|
+
} ## optimization: in rk_level==4 case, don't need to calc deps
|
31
|
+
setup :shadow => %{
|
32
|
+
shadow = (#{ssn} *)comp_shdw;
|
33
|
+
cont_state = (#{cont_state_ssn} *)shadow->cont_state;
|
34
|
+
var = &cont_state->#{var_name};
|
35
|
+
time_step = shadow->world->time_step;
|
36
|
+
} # return is necessary--else shadow, cont_state, var are uninitialized
|
37
|
+
setup :rk_level => %{
|
38
|
+
shadow->world->rk_level--;
|
39
|
+
} # has to happen before referenced alg flows are called in other setups
|
40
|
+
body %{
|
41
|
+
switch (shadow->world->rk_level) {
|
42
|
+
case 0:
|
43
|
+
#{flow.translate(self, "ddt_#{var_name}", 0, cl).join("
|
44
|
+
")};
|
45
|
+
|
46
|
+
var->value_1 = var->value_2 =
|
47
|
+
var->value_0 + ddt_#{var_name} * time_step/2;
|
48
|
+
var->value_3 =
|
49
|
+
var->value_0 + ddt_#{var_name} * time_step;
|
50
|
+
var->rk_level = 3;
|
51
|
+
break;
|
52
|
+
|
53
|
+
case 3:
|
54
|
+
var->value_0 = var->value_3;
|
55
|
+
var->rk_level = 4;
|
56
|
+
break;
|
57
|
+
}
|
58
|
+
|
59
|
+
shadow->world->rk_level++;
|
60
|
+
}
|
61
|
+
end
|
62
|
+
define_c_method :calc_function_pointer do
|
63
|
+
body "shadow->flow = &#{flow_name}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end; end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module RedShift; class CexprGuard
|
2
|
+
|
3
|
+
def initialize f
|
4
|
+
super nil, f
|
5
|
+
end
|
6
|
+
|
7
|
+
@@serial = 0
|
8
|
+
|
9
|
+
# +cl+ is the component class
|
10
|
+
## maybe all these methods should just be called wrapper?
|
11
|
+
def guard_wrapper cl
|
12
|
+
guard = self
|
13
|
+
cl_cname = CGenerator.make_c_name cl.name
|
14
|
+
g_cname = "Guard_#{@@serial}"; @@serial += 1
|
15
|
+
guard_name = "guard_#{cl_cname}_#{g_cname}"
|
16
|
+
|
17
|
+
Component::GuardWrapper.make_subclass guard_name do
|
18
|
+
@inspect_str = "#{cl.name}: #{guard.formula}"
|
19
|
+
|
20
|
+
ssn = cl.shadow_struct.name
|
21
|
+
cont_state_ssn = cl.cont_state_class.shadow_struct.name
|
22
|
+
|
23
|
+
# We need the struct
|
24
|
+
shadow_library_source_file.include(cl.shadow_library_include_file)
|
25
|
+
|
26
|
+
strict = false
|
27
|
+
|
28
|
+
shadow_library_source_file.define(guard_name).instance_eval do
|
29
|
+
arguments "ComponentShadow *comp_shdw"
|
30
|
+
return_type "int"
|
31
|
+
declare :shadow => %{
|
32
|
+
struct #{ssn} *shadow;
|
33
|
+
struct #{cont_state_ssn} *cont_state;
|
34
|
+
ContVar *var;
|
35
|
+
}
|
36
|
+
setup :shadow => %{
|
37
|
+
shadow = (#{ssn} *)comp_shdw;
|
38
|
+
cont_state = (#{cont_state_ssn} *)shadow->cont_state;
|
39
|
+
}
|
40
|
+
declare :result => "int result"
|
41
|
+
translation = guard.translate(self, "result", 0, cl) {|s| strict = s}
|
42
|
+
body %{
|
43
|
+
#{translation.join("
|
44
|
+
")};
|
45
|
+
return result;
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
@strict = strict
|
50
|
+
## should set guard.strict = strict too?
|
51
|
+
|
52
|
+
define_c_method :calc_function_pointer do
|
53
|
+
body "shadow->guard = &#{guard_name}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end; end
|
58
|
+
|
59
|
+
module RedShift; class Expr
|
60
|
+
attr_reader :type
|
61
|
+
|
62
|
+
def initialize f, type = "double"
|
63
|
+
super nil, f
|
64
|
+
@type = type
|
65
|
+
end
|
66
|
+
|
67
|
+
@@serial = 0
|
68
|
+
|
69
|
+
# +cl+ is the component class
|
70
|
+
def wrapper(cl)
|
71
|
+
expr = self
|
72
|
+
cl_cname = CGenerator.make_c_name cl.name
|
73
|
+
ex_cname = "Expr_#{@@serial}"; @@serial += 1
|
74
|
+
expr_name = "expr_#{cl_cname}_#{ex_cname}"
|
75
|
+
|
76
|
+
Component::ExprWrapper.make_subclass expr_name do
|
77
|
+
@inspect_str = "#{cl.name}: #{expr.formula}"
|
78
|
+
|
79
|
+
ssn = cl.shadow_struct.name
|
80
|
+
cont_state_ssn = cl.cont_state_class.shadow_struct.name
|
81
|
+
|
82
|
+
# We need the struct
|
83
|
+
shadow_library_source_file.include(cl.shadow_library_include_file)
|
84
|
+
|
85
|
+
shadow_library_source_file.define(expr_name).instance_eval do
|
86
|
+
arguments "ComponentShadow *comp_shdw"
|
87
|
+
return_type expr.type
|
88
|
+
declare :shadow => %{
|
89
|
+
struct #{ssn} *shadow;
|
90
|
+
struct #{cont_state_ssn} *cont_state;
|
91
|
+
ContVar *var;
|
92
|
+
}
|
93
|
+
setup :shadow => %{
|
94
|
+
shadow = (#{ssn} *)comp_shdw;
|
95
|
+
cont_state = (#{cont_state_ssn} *)shadow->cont_state;
|
96
|
+
}
|
97
|
+
declare :result => "#{expr.type} result"
|
98
|
+
translation = expr.translate(self, "result", 0, cl)
|
99
|
+
body %{
|
100
|
+
#{translation.join("
|
101
|
+
")};
|
102
|
+
return result;
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
define_c_method :calc_function_pointer do
|
107
|
+
body "shadow->expr = &#{expr_name}"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end; end
|
112
|
+
|
113
|
+
module RedShift; class ResetExpr < Expr; end; end
|