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