AERA
guard_builder.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2025 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2025 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2025 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel
12 //_/_/ Center for Analysis and Design of Intelligent Agents
13 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
14 //_/_/ http://cadia.ru.is
15 //_/_/
16 //_/_/ Part of this software was developed by Eric Nivel
17 //_/_/ in the HUMANOBS EU research project, which included
18 //_/_/ the following parties:
19 //_/_/
20 //_/_/ Autonomous Systems Laboratory
21 //_/_/ Technical University of Madrid, Spain
22 //_/_/ http://www.aslab.org/
23 //_/_/
24 //_/_/ Communicative Machines
25 //_/_/ Edinburgh, United Kingdom
26 //_/_/ http://www.cmlabs.com/
27 //_/_/
28 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
29 //_/_/ University of Lugano and SUPSI, Switzerland
30 //_/_/ http://www.idsia.ch/
31 //_/_/
32 //_/_/ Institute of Cognitive Sciences and Technologies
33 //_/_/ Consiglio Nazionale delle Ricerche, Italy
34 //_/_/ http://www.istc.cnr.it/
35 //_/_/
36 //_/_/ Dipartimento di Ingegneria Informatica
37 //_/_/ University of Palermo, Italy
38 //_/_/ http://diid.unipa.it/roboticslab/
39 //_/_/
40 //_/_/
41 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
42 //_/_/
43 //_/_/ Redistribution and use in source and binary forms, with or without
44 //_/_/ modification, is permitted provided that the following conditions
45 //_/_/ are met:
46 //_/_/ - Redistributions of source code must retain the above copyright
47 //_/_/ and collaboration notice, this list of conditions and the
48 //_/_/ following disclaimer.
49 //_/_/ - Redistributions in binary form must reproduce the above copyright
50 //_/_/ notice, this list of conditions and the following disclaimer
51 //_/_/ in the documentation and/or other materials provided with
52 //_/_/ the distribution.
53 //_/_/
54 //_/_/ - Neither the name of its copyright holders nor the names of its
55 //_/_/ contributors may be used to endorse or promote products
56 //_/_/ derived from this software without specific prior
57 //_/_/ written permission.
58 //_/_/
59 //_/_/ - CADIA Clause: The license granted in and to the software
60 //_/_/ under this agreement is a limited-use license.
61 //_/_/ The software may not be used in furtherance of:
62 //_/_/ (i) intentionally causing bodily injury or severe emotional
63 //_/_/ distress to any person;
64 //_/_/ (ii) invading the personal privacy or violating the human
65 //_/_/ rights of any person; or
66 //_/_/ (iii) committing or preparing for any act of war.
67 //_/_/
68 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
69 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
70 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
71 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
72 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
73 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
74 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
75 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
76 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
77 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
78 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
79 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
81 //_/_/ OF SUCH DAMAGE.
82 //_/_/
83 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
84 
85 #include "guard_builder.h"
86 
87 using namespace std::chrono;
88 using namespace r_code;
89 
90 namespace r_exec {
91 
92 GuardBuilder::GuardBuilder() : _Object() {
93 }
94 
95 GuardBuilder::~GuardBuilder() {
96 }
97 
98 void GuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
99 
100  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
101  mdl->code(write_index) = Atom::Set(0);
102 
103  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
104  mdl->code(write_index) = Atom::Set(0);
105 }
106 
108 
109 TimingGuardBuilder::TimingGuardBuilder(microseconds period) : GuardBuilder(), period_(period) {
110 }
111 
112 TimingGuardBuilder::~TimingGuardBuilder() {
113 }
114 
115 void TimingGuardBuilder::write_guard(Code *mdl, uint16 l, uint16 r, uint16 opcode, microseconds offset, uint16 &write_index, uint16 &extent_index) const {
116 
117  mdl->code(++write_index) = Atom::AssignmentPointer(l, ++extent_index);
118  mdl->code(extent_index) = Atom::Operator(opcode, 2); // l:(opcode r offset)
119  mdl->code(++extent_index) = Atom::VLPointer(r);
120  uint16 index = extent_index + 2;
121  mdl->code(++extent_index) = Atom::IPointer(index);
122  Utils::SetDurationStruct(mdl, ++extent_index, offset);
123  extent_index += 2;
124 }
125 
126 void TimingGuardBuilder::_build(Code *mdl, uint16 t0, uint16 t1, uint16 &write_index) const {
127 
128  Code *rhs_val = mdl->get_reference(1);
129  uint16 t2 = rhs_val->code(FACT_AFTER).asIndex();
130  uint16 t3 = rhs_val->code(FACT_BEFORE).asIndex();
131 
132  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
133  mdl->code(write_index) = Atom::Set(2);
134 
135  uint16 extent_index = write_index + 2;
136 
137  write_guard(mdl, t2, t0, Opcodes::Add, period_, write_index, extent_index);
138  write_guard(mdl, t3, t1, Opcodes::Add, period_, write_index, extent_index);
139 
140  write_index = extent_index;
141  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
142  mdl->code(write_index) = Atom::Set(2);
143 
144  extent_index = write_index + 2;
145 
146  write_guard(mdl, t0, t2, Opcodes::Sub, period_, write_index, extent_index);
147  write_guard(mdl, t1, t3, Opcodes::Sub, period_, write_index, extent_index);
148 
149  write_index = extent_index;
150 }
151 
152 void TimingGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
153 
154  uint16 t0;
155  uint16 t1;
156  uint16 tpl_arg_set_index = mdl->code(MDL_TPL_ARGS).asIndex();
157  if (mdl->code(tpl_arg_set_index).getAtomCount() == 0) {
158 
159  Code *lhs_val = mdl->get_reference(0);
160  t0 = lhs_val->code(FACT_AFTER).asIndex();
161  t1 = lhs_val->code(FACT_BEFORE).asIndex();
162  } else { // use the tpl args.
163 
164  t0 = 1;
165  t1 = 2;
166  }
167 
168  _build(mdl, t0, t1, write_index);
169 }
170 
172 
173 SGuardBuilder::SGuardBuilder(microseconds period, microseconds offset) : TimingGuardBuilder(period), offset_(offset) {
174 }
175 
176 SGuardBuilder::~SGuardBuilder() {
177 }
178 
179 void SGuardBuilder::_build(Code *mdl, uint16 q0, uint16 t0, uint16 t1, uint16 &write_index) const {
180 
181  Code *rhs = mdl->get_reference(1);
182  uint16 t2 = rhs->code(FACT_AFTER).asIndex();
183  uint16 t3 = rhs->code(FACT_BEFORE).asIndex();
184  uint16 q1 = rhs->get_reference(0)->code(MK_VAL_VALUE).asIndex();
185 
186  Code *lhs = mdl->get_reference(0);
187  uint16 speed_t0 = lhs->code(FACT_AFTER).asIndex();
188  uint16 speed_t1 = lhs->code(FACT_BEFORE).asIndex();
189  uint16 speed_value = lhs->get_reference(0)->code(MK_VAL_VALUE).asIndex();
190 
191  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
192  mdl->code(write_index) = Atom::Set(3);
193 
194  uint16 extent_index = write_index + 3;
195 
196  write_guard(mdl, t2, t0, Opcodes::Add, period_, write_index, extent_index);
197  write_guard(mdl, t3, t1, Opcodes::Add, period_, write_index, extent_index);
198 
199  mdl->code(++write_index) = Atom::AssignmentPointer(q1, ++extent_index);
200  mdl->code(extent_index) = Atom::Operator(Opcodes::Add, 2); // q1:(+ q0 (* s period))
201  mdl->code(++extent_index) = Atom::VLPointer(q0);
202  uint16 index = extent_index + 2;
203  mdl->code(++extent_index) = Atom::IPointer(index);
204  mdl->code(++extent_index) = Atom::Operator(Opcodes::Mul, 2);
205  mdl->code(++extent_index) = Atom::VLPointer(speed_value);
206  index = extent_index + 2;
207  mdl->code(++extent_index) = Atom::IPointer(index);
208  Utils::SetDurationStruct(mdl, ++extent_index, period_);
209  extent_index += 2;
210 
211  write_index = extent_index;
212  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
213  mdl->code(write_index) = Atom::Set(5);
214 
215  extent_index = write_index + 5;
216 
217  write_guard(mdl, t0, t2, Opcodes::Sub, period_, write_index, extent_index);
218  write_guard(mdl, t1, t3, Opcodes::Sub, period_, write_index, extent_index);
219 
220  write_guard(mdl, speed_t0, t2, Opcodes::Sub, offset_, write_index, extent_index);
221  write_guard(mdl, speed_t1, t3, Opcodes::Sub, period_, write_index, extent_index);
222 
223  mdl->code(++write_index) = Atom::AssignmentPointer(speed_value, ++extent_index);
224  mdl->code(extent_index) = Atom::Operator(Opcodes::Div, 2); // s:(/ (- q1 q0) period)
225  index = extent_index + 3;
226  mdl->code(++extent_index) = Atom::IPointer(index);
227  index = extent_index + 5;
228  mdl->code(++extent_index) = Atom::IPointer(index);
229  mdl->code(++extent_index) = Atom::Operator(Opcodes::Sub, 2);
230  mdl->code(++extent_index) = Atom::VLPointer(q1);
231  mdl->code(++extent_index) = Atom::VLPointer(q0);
232  Utils::SetDurationStruct(mdl, ++extent_index, period_);
233  extent_index += 2;
234 
235  write_index = extent_index;
236 }
237 
238 void SGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
239 
240  uint16 q0;
241  uint16 t0;
242  uint16 t1;
243  uint16 tpl_arg_set_index = mdl->code(MDL_TPL_ARGS).asIndex();
244  if (mdl->code(tpl_arg_set_index).getAtomCount() == 0) {
245 
246  q0 = premise_pattern->get_reference(0)->code(MK_VAL_VALUE).asIndex();
247  t0 = premise_pattern->code(FACT_AFTER).asIndex();
248  t1 = premise_pattern->code(FACT_BEFORE).asIndex();
249  } else { // use the tpl args.
250 
251  q0 = 0;
252  t0 = 1;
253  t1 = 2;
254  }
255 
256  _build(mdl, q0, t0, t1, write_index);
257 }
258 
260 
261 NoArgCmdGuardBuilder::NoArgCmdGuardBuilder(microseconds period, microseconds offset, microseconds cmd_duration)
262 : TimingGuardBuilder(period), offset_(offset), cmd_duration_(cmd_duration) {
263 }
264 
265 NoArgCmdGuardBuilder::~NoArgCmdGuardBuilder() {
266 }
267 
268 void NoArgCmdGuardBuilder::_build(Code *mdl, uint16 q0, uint16 t0, uint16 t1, uint16 &write_index) const {
269 
270  Code *rhs = mdl->get_reference(1);
271  uint16 t2 = rhs->code(FACT_AFTER).asIndex();
272  uint16 t3 = rhs->code(FACT_BEFORE).asIndex();
273 
274  Code *lhs = mdl->get_reference(0);
275  uint16 cmd_t0 = lhs->code(FACT_AFTER).asIndex();
276  uint16 cmd_t1 = lhs->code(FACT_BEFORE).asIndex();
277 
278  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
279  mdl->code(write_index) = Atom::Set(2);
280 
281  uint16 extent_index = write_index + 2;
282 
283  write_guard(mdl, t2, t0, Opcodes::Add, period_, write_index, extent_index);
284  write_guard(mdl, t3, t1, Opcodes::Add, period_, write_index, extent_index);
285 
286  write_index = extent_index;
287  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
288 
289  mdl->code(write_index) = Atom::Set(4);
290  extent_index = write_index + 4;
291 
292  write_guard(mdl, t0, t2, Opcodes::Sub, period_, write_index, extent_index);
293  write_guard(mdl, t1, t3, Opcodes::Sub, period_, write_index, extent_index);
294 
295  write_guard(mdl, cmd_t0, t2, Opcodes::Sub, offset_, write_index, extent_index);
296  write_guard(mdl, cmd_t1, t3, Opcodes::Sub, period_, write_index, extent_index);
297 
298  write_index = extent_index;
299 }
300 
301 void NoArgCmdGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
302 
303  uint16 q0;
304  uint16 t0;
305  uint16 t1;
306  uint16 tpl_arg_set_index = mdl->code(MDL_TPL_ARGS).asIndex();
307  if (mdl->code(tpl_arg_set_index).getAtomCount() == 0) {
308 
309  q0 = premise_pattern->get_reference(0)->code(MK_VAL_VALUE).asIndex();
310  t0 = premise_pattern->code(FACT_AFTER).asIndex();
311  t1 = premise_pattern->code(FACT_BEFORE).asIndex();
312  } else { // use the tpl args.
313 
314  q0 = 0;
315  t0 = 1;
316  t1 = 2;
317  }
318 
319  _build(mdl, q0, t0, t1, write_index);
320 }
321 
323 
324 CmdGuardBuilder::CmdGuardBuilder(microseconds period, microseconds offset, uint16 cmd_arg_index) : TimingGuardBuilder(period), offset_(offset), cmd_arg_index_(cmd_arg_index) {
325 }
326 
327 CmdGuardBuilder::~CmdGuardBuilder() {
328 }
329 
330 void CmdGuardBuilder::_build(Code *mdl, uint16 fwd_opcode, uint16 bwd_opcode, uint16 q0, uint16 t0, uint16 t1, uint16 &write_index) const {
331 
332  Code *rhs = mdl->get_reference(1);
333  uint16 t2 = rhs->code(FACT_AFTER).asIndex();
334  uint16 t3 = rhs->code(FACT_BEFORE).asIndex();
335  uint16 q1 = rhs->get_reference(0)->code(MK_VAL_VALUE).asIndex();
336 
337  Code *lhs = mdl->get_reference(0);
338  uint16 cmd_t0 = lhs->code(FACT_AFTER).asIndex();
339  uint16 cmd_t1 = lhs->code(FACT_BEFORE).asIndex();
340  uint16 cmd_arg = lhs->get_reference(0)->code(cmd_arg_index_).asIndex();
341 
342  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
343  mdl->code(write_index) = Atom::Set(3);
344 
345  uint16 extent_index = write_index + 3;
346 
347  write_guard(mdl, t2, t0, Opcodes::Add, period_, write_index, extent_index);
348  write_guard(mdl, t3, t1, Opcodes::Add, period_, write_index, extent_index);
349 
350  mdl->code(++write_index) = Atom::AssignmentPointer(q1, ++extent_index);
351  mdl->code(extent_index) = Atom::Operator(fwd_opcode, 2); // q1:(fwd_opcode q0 cmd_arg)
352  mdl->code(++extent_index) = Atom::VLPointer(q0);
353  mdl->code(++extent_index) = Atom::VLPointer(cmd_arg);
354  extent_index += 1;
355 
356  write_index = extent_index;
357  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
358  mdl->code(write_index) = Atom::Set(5);
359 
360  extent_index = write_index + 5;
361 
362  write_guard(mdl, t0, t2, Opcodes::Sub, period_, write_index, extent_index);
363  write_guard(mdl, t1, t3, Opcodes::Sub, period_, write_index, extent_index);
364 
365  write_guard(mdl, cmd_t0, t2, Opcodes::Sub, offset_, write_index, extent_index);
366  write_guard(mdl, cmd_t1, t3, Opcodes::Sub, period_, write_index, extent_index);
367 
368  mdl->code(++write_index) = Atom::AssignmentPointer(cmd_arg, ++extent_index);
369  mdl->code(extent_index) = Atom::Operator(bwd_opcode, 2); // cmd_arg:(bwd_opcode q1 q0)
370  mdl->code(++extent_index) = Atom::VLPointer(q1);
371  mdl->code(++extent_index) = Atom::VLPointer(q0);
372  extent_index += 1;
373 
374  write_index = extent_index;
375 }
376 
377 void CmdGuardBuilder::_build(Code *mdl, uint16 fwd_opcode, uint16 bwd_opcode, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
378 
379  uint16 q0;
380  uint16 t0;
381  uint16 t1;
382  uint16 tpl_arg_set_index = mdl->code(MDL_TPL_ARGS).asIndex();
383  if (mdl->code(tpl_arg_set_index).getAtomCount() == 0) {
384 
385  q0 = premise_pattern->get_reference(0)->code(MK_VAL_VALUE).asIndex();
386  t0 = premise_pattern->code(FACT_AFTER).asIndex();
387  t1 = premise_pattern->code(FACT_BEFORE).asIndex();
388  } else { // use the tpl args.
389 
390  q0 = 0;
391  t0 = 1;
392  t1 = 2;
393  }
394 
395  _build(mdl, fwd_opcode, bwd_opcode, q0, t0, t1, write_index);
396 }
397 
399 
400 MCGuardBuilder::MCGuardBuilder(microseconds period, microseconds offset, float32 cmd_arg_index) : CmdGuardBuilder(period, offset, cmd_arg_index) {
401 }
402 
403 MCGuardBuilder::~MCGuardBuilder() {
404 }
405 
406 void MCGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
407 
408  _build(mdl, Opcodes::Mul, Opcodes::Div, premise_pattern, cause_pattern, write_index);
409 }
410 
412 
413 ACGuardBuilder::ACGuardBuilder(microseconds period, microseconds offset, uint16 cmd_arg_index) : CmdGuardBuilder(period, offset, cmd_arg_index) {
414 }
415 
416 ACGuardBuilder::~ACGuardBuilder() {
417 }
418 
419 void ACGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
420 
421  _build(mdl, Opcodes::Add, Opcodes::Sub, premise_pattern, cause_pattern, write_index);
422 }
423 
425 
426 ConstGuardBuilder::ConstGuardBuilder(microseconds period, float32 constant, microseconds offset) : TimingGuardBuilder(period), constant_(constant), offset_(offset) {
427 }
428 
429 ConstGuardBuilder::~ConstGuardBuilder() {
430 }
431 
432 void ConstGuardBuilder::_build(Code *mdl, uint16 fwd_opcode, uint16 bwd_opcode, uint16 q0, uint16 t0, uint16 t1, uint16 &write_index) const {
433 
434  Code *rhs = mdl->get_reference(1);
435  uint16 t2 = rhs->code(FACT_AFTER).asIndex();
436  uint16 t3 = rhs->code(FACT_BEFORE).asIndex();
437  uint16 q1 = rhs->get_reference(0)->code(MK_VAL_VALUE).asIndex();
438 
439  Code *lhs = mdl->get_reference(1);
440  uint16 t4 = lhs->code(FACT_AFTER).asIndex();
441  uint16 t5 = lhs->code(FACT_BEFORE).asIndex();
442 
443  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
444  mdl->code(write_index) = Atom::Set(3);
445 
446  uint16 extent_index = write_index + 3;
447 
448  write_guard(mdl, t2, t0, Opcodes::Add, period_, write_index, extent_index);
449  write_guard(mdl, t3, t1, Opcodes::Add, period_, write_index, extent_index);
450 
451  mdl->code(++write_index) = Atom::AssignmentPointer(q1, ++extent_index);
452  mdl->code(extent_index) = Atom::Operator(fwd_opcode, 2); // q1:(fwd_opcode q0 constant)
453  mdl->code(++extent_index) = Atom::VLPointer(q0);
454  mdl->code(++extent_index) = Atom::Float(constant_);
455  extent_index += 1;
456 
457  write_index = extent_index;
458  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
459  mdl->code(write_index) = Atom::Set(5);
460 
461  extent_index = write_index + 5;
462 
463  write_guard(mdl, t0, t2, Opcodes::Sub, period_, write_index, extent_index);
464  write_guard(mdl, t1, t3, Opcodes::Sub, period_, write_index, extent_index);
465 
466  write_guard(mdl, t4, t2, Opcodes::Sub, offset_, write_index, extent_index);
467  write_guard(mdl, t5, t3, Opcodes::Sub, period_, write_index, extent_index);
468 
469  mdl->code(++write_index) = Atom::AssignmentPointer(q0, ++extent_index);
470  mdl->code(extent_index) = Atom::Operator(bwd_opcode, 2); // q0:(bwd_opcode q1 constant)
471  mdl->code(++extent_index) = Atom::VLPointer(q1);
472  mdl->code(++extent_index) = Atom::Float(constant_);
473  extent_index += 1;
474 
475  write_index = extent_index;
476 }
477 
478 void ConstGuardBuilder::_build(Code *mdl, uint16 fwd_opcode, uint16 bwd_opcode, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
479 
480  uint16 q0;
481  uint16 t0;
482  uint16 t1;
483  uint16 tpl_arg_set_index = mdl->code(MDL_TPL_ARGS).asIndex();
484  if (mdl->code(tpl_arg_set_index).getAtomCount() == 0) {
485 
486  q0 = premise_pattern->get_reference(0)->code(MK_VAL_VALUE).asIndex();
487  t0 = premise_pattern->code(FACT_AFTER).asIndex();
488  t1 = premise_pattern->code(FACT_BEFORE).asIndex();
489  } else { // use the tpl args.
490 
491  q0 = 0;
492  t0 = 1;
493  t1 = 2;
494  }
495 
496  _build(mdl, fwd_opcode, bwd_opcode, q0, t0, t1, write_index);
497 }
498 
500 
501 MGuardBuilder::MGuardBuilder(microseconds period, float32 constant, microseconds offset) : ConstGuardBuilder(period, constant, offset) {
502 }
503 
504 MGuardBuilder::~MGuardBuilder() {
505 }
506 
507 void MGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
508 
509  _build(mdl, Opcodes::Mul, Opcodes::Div, premise_pattern, cause_pattern, write_index);
510 }
511 
513 
514 AGuardBuilder::AGuardBuilder(microseconds period, float32 constant, microseconds offset) : ConstGuardBuilder(period, constant, offset) {
515 }
516 
517 AGuardBuilder::~AGuardBuilder() {
518 }
519 
520 void AGuardBuilder::build(Code *mdl, _Fact *premise_pattern, _Fact *cause_pattern, uint16 &write_index) const {
521 
522  _build(mdl, Opcodes::Add, Opcodes::Sub, premise_pattern, cause_pattern, write_index);
523 }
524 
526 
527 ConstBwdArgCmdGuardBuilder::ConstBwdArgCmdGuardBuilder(microseconds period, microseconds offset, uint16 cmd_arg_index, _Fact* cause) : TimingGuardBuilder(period), offset_(offset), cmd_arg_index_(cmd_arg_index), cause_(cause) {
528 }
529 
530 ConstBwdArgCmdGuardBuilder::~ConstBwdArgCmdGuardBuilder() {
531 }
532 
533 void ConstBwdArgCmdGuardBuilder::build(Code* mdl, _Fact* premise_pattern, _Fact* cause_pattern, uint16& write_index) const {
534  // use the tpl args.
535  uint16 t0 = 1;
536  uint16 t1 = 2;
537 
538  Code* rhs = mdl->get_reference(1);
539  uint16 t2 = rhs->code(FACT_AFTER).asIndex();
540  uint16 t3 = rhs->code(FACT_BEFORE).asIndex();
541 
542  Code* lhs = mdl->get_reference(0);
543  uint16 cmd_t0 = lhs->code(FACT_AFTER).asIndex();
544  uint16 cmd_t1 = lhs->code(FACT_BEFORE).asIndex();
545  uint16 cmd_arg = lhs->get_reference(0)->code(cmd_arg_index_).asIndex();
546 
547  mdl->code(MDL_FWD_GUARDS) = Atom::IPointer(++write_index);
548  mdl->code(write_index) = Atom::Set(2);
549 
550  uint16 extent_index = write_index + 2;
551 
552  write_guard(mdl, t2, t0, Opcodes::Add, period_, write_index, extent_index);
553  write_guard(mdl, t3, t1, Opcodes::Add, period_, write_index, extent_index);
554 
555  write_index = extent_index;
556  mdl->code(MDL_BWD_GUARDS) = Atom::IPointer(++write_index);
557  mdl->code(write_index) = Atom::Set(5);
558 
559  extent_index = write_index + 5;
560 
561  write_guard(mdl, t0, t2, Opcodes::Sub, period_, write_index, extent_index);
562  write_guard(mdl, t1, t3, Opcodes::Sub, period_, write_index, extent_index);
563 
564  write_guard(mdl, cmd_t0, t2, Opcodes::Sub, offset_, write_index, extent_index);
565  write_guard(mdl, cmd_t1, t3, Opcodes::Sub, period_, write_index, extent_index);
566 
567  // Assign the specific value from the cause.
568  Atom cmd_arg_value = cause_->get_reference(0)->code(cmd_arg_index_);
569  mdl->code(++write_index) = Atom::AssignmentPointer(cmd_arg, ++extent_index);
570  if (cmd_arg_value.getDescriptor() == Atom::I_PTR &&
571  cause_->get_reference(0)->code(cmd_arg_value.asIndex()).getDescriptor() == Atom::OBJECT)
572  // Copy the object.
574  mdl, extent_index, &cause_->get_reference(0)->code(0), cmd_arg_value.asIndex());
575  else if (cmd_arg_value.isFloat()) {
576  // We can't put the float value in the AssignmentPointer, so point to the identity operator.
577  mdl->code(extent_index) = Atom::Operator(Opcodes::Id, 1);
578  mdl->code(++extent_index) = cmd_arg_value;
579  extent_index += 1;
580  }
581 
582  write_index = extent_index;
583 }
584 
585 }
r_exec::StructureValue::copy_structure
static void copy_structure(r_code::Code *destination, uint16 &extent_index, const Atom *source, uint16 source_index)
Definition: binding_map.cpp:242
r_code::Atom
Definition: atom.h:104
r_code::Code
Definition: r_code/object.h:224
r_exec::TimingGuardBuilder
Definition: guard_builder.h:105
core::_Object
Definition: base.h:131
r_exec::NoArgCmdGuardBuilder::NoArgCmdGuardBuilder
NoArgCmdGuardBuilder(std::chrono::microseconds period, std::chrono::microseconds offset, std::chrono::microseconds cmd_duration)
Definition: guard_builder.cpp:261