AERA
binding_map.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 "mem.h"
86 #include "binding_map.h"
87 #include "factory.h"
88 
89 using namespace std::chrono;
90 using namespace r_code;
91 
92 namespace r_exec {
93 
94 Value::Value(BindingMap *map) : _Object(), map_(map) {
95 }
96 
98 
99 BoundValue::BoundValue(BindingMap *map) : Value(map) {
100 }
101 
103 
104 UnboundValue::UnboundValue(BindingMap *map, uint8 index) : Value(map), index_(index) {
105 
106  ++map->unbound_values_;
107 }
108 
109 UnboundValue::~UnboundValue() {
110 
111  --map_->unbound_values_;
112 }
113 
114 Value *UnboundValue::copy(BindingMap *map) const {
115 
116  return new UnboundValue(map, index_);
117 }
118 
119 void UnboundValue::valuate(Code *destination, uint16 write_index, uint16& /* extent_index */) const {
120 
121  destination->code(write_index) = Atom::VLPointer(index_);
122 }
123 
124 bool UnboundValue::match(const Code *object, uint16 index) {
125 
126  Atom o_atom = object->code(index);
127  switch (o_atom.getDescriptor()) {
128  case Atom::I_PTR:
129  map_->bind_variable(new StructureValue(map_, object, o_atom.asIndex()), index_);
130  break;
131  case Atom::R_PTR:
132  map_->bind_variable(new ObjectValue(map_, object->get_reference(o_atom.asIndex())), index_);
133  break;
134  case Atom::WILDCARD:
135  break;
136  default:
137  map_->bind_variable(new AtomValue(map_, o_atom), index_);
138  break;
139  }
140 
141  return true;
142 }
143 
144 Atom *UnboundValue::get_code() {
145 
146  return NULL;
147 }
148 
149 Code *UnboundValue::get_object() {
150 
151  return NULL;
152 }
153 
154 uint16 UnboundValue::get_code_size() {
155 
156  return 0;
157 }
158 
160 
161 AtomValue::AtomValue(BindingMap *map, Atom atom) : BoundValue(map), atom_(atom) {
162 }
163 
164 Value *AtomValue::copy(BindingMap *map) const {
165 
166  return new AtomValue(map, atom_);
167 }
168 
169 void AtomValue::valuate(Code *destination, uint16 write_index, uint16& /* extent_index */) const {
170 
171  destination->code(write_index) = atom_;
172 }
173 
174 bool AtomValue::match(const Code *object, uint16 index) {
175 
176  return map_->match_atom(object->code(index), atom_);
177 }
178 
179 Atom *AtomValue::get_code() {
180 
181  return &atom_;
182 }
183 
184 Code *AtomValue::get_object() {
185 
186  return NULL;
187 }
188 
189 uint16 AtomValue::get_code_size() {
190 
191  return 1;
192 }
193 
194 bool AtomValue::intersect(const Value *v) const {
195 
196  return v->_intersect(this);
197 }
198 
199 bool AtomValue::_intersect(const AtomValue *v) const {
200 
201  return contains(v->atom_);
202 }
203 
204 bool AtomValue::contains(const Atom a) const {
205 
206  if (atom_ == a)
207  return true;
208 
209  if (atom_.isFloat() && a.isFloat())
210  return Utils::Equal(atom_.asFloat(), a.asFloat());
211 
212  return false;
213 }
214 
216 
217 StructureValue::StructureValue(BindingMap *map, const Atom *source, uint16 structure_index) : BoundValue(map) {
218 
219  structure_ = new LocalObject();
220  uint16 extent_index = 0;
221  copy_structure(structure_, extent_index, source, structure_index);
222 }
223 
224 StructureValue::StructureValue(BindingMap *map, Timestamp time) : BoundValue(map) {
225 
226  structure_ = new LocalObject();
227  structure_->resize_code(3);
228  Utils::SetTimestamp(&structure_->code(0), time);
229 }
230 
231 StructureValue::StructureValue(BindingMap *map, microseconds duration) : BoundValue(map) {
232  structure_ = new LocalObject();
233  structure_->resize_code(3);
234  Utils::SetDuration(&structure_->code(0), duration);
235 }
236 
237 Value *StructureValue::copy(BindingMap *map) const {
238 
239  return new StructureValue(map, structure_);
240 }
241 
242 void StructureValue::copy_structure(
243  Code *destination, uint16 &extent_index, const Atom* source, uint16 source_index) {
244 
245  uint16 extent_start = extent_index;
246  uint8 atom_count = source[source_index].getAtomCount();
247  // Increment extent_index now in case we need to write more after the structure.
248  extent_index += (1 + atom_count);
249  for (uint16 i = 0; i <= atom_count; ++i) {
250  Atom a = source[source_index + i];
251  if (a.getDescriptor() == Atom::I_PTR) {
252  // Write an I_PTR and recurse to copy the the sub-structure.
253  destination->code(extent_start + i) = Atom::IPointer(extent_index);
254  copy_structure(destination, extent_index, source, a.asIndex());
255  continue;
256  }
257  destination->code(extent_start + i) = a;
258  }
259 }
260 
261 bool StructureValue::match(const Code *object, uint16 index) {
262 
263  if (object->code(index).getDescriptor() != Atom::I_PTR)
264  return false;
265  return map_->match_structure(object, object->code(index).asIndex(), 0, structure_, 0);
266 }
267 
268 Atom *StructureValue::get_code() {
269 
270  return &structure_->code(0);
271 }
272 
273 Code *StructureValue::get_object() {
274 
275  return NULL;
276 }
277 
278 uint16 StructureValue::get_code_size() {
279 
280  return structure_->code_size();
281 }
282 
283 bool StructureValue::intersect(const Value *v) const {
284 
285  return v->_intersect(this);
286 }
287 
288 bool StructureValue::_intersect(const StructureValue *v) const {
289 
290  return contains(&v->structure_->code(0));
291 }
292 
293 bool StructureValue::contains(const Atom *s) const {
294 
295  if (structure_->code(0) != s[0])
296  return false;
297  if (structure_->code(0).getDescriptor() == Atom::TIMESTAMP)
298  return Utils::Synchronous(Utils::GetTimestamp(&structure_->code(0)), Utils::GetTimestamp(s));
299  for (uint16 i = 1; i < structure_->code_size(); ++i) {
300 
301  Atom a = structure_->code(i);
302  Atom _a = s[i];
303  if (a == _a)
304  continue;
305 
306  if (a.isFloat() && _a.isFloat())
307  if (Utils::Equal(a.asFloat(), _a.asFloat()))
308  continue;
309 
310  return false;
311  }
312 
313  return true;
314 }
315 
317 
318 ObjectValue::ObjectValue(BindingMap *map, Code *object) : BoundValue(map), object_(object) {
319 }
320 
321 Value *ObjectValue::copy(BindingMap *map) const {
322 
323  return new ObjectValue(map, object_);
324 }
325 
326 void ObjectValue::valuate(Code *destination, uint16 write_index, uint16& /* extent_index */) const {
327 
328  destination->code(write_index) = Atom::RPointer(destination->references_size());
329  destination->add_reference(object_);
330 }
331 
332 bool ObjectValue::match(const Code *object, uint16 index) {
333 
334  return map_->match_object(object->get_reference(object->code(index).asIndex()), object_);
335 }
336 
337 Atom *ObjectValue::get_code() {
338 
339  return &object_->code(0);
340 }
341 
342 Code *ObjectValue::get_object() {
343 
344  return object_;
345 }
346 
347 uint16 ObjectValue::get_code_size() {
348 
349  return object_->code_size();
350 }
351 
352 bool ObjectValue::intersect(const Value *v) const {
353 
354  return v->_intersect(this);
355 }
356 
357 bool ObjectValue::_intersect(const ObjectValue *v) const {
358 
359  return contains(v->object_);
360 }
361 
362 bool ObjectValue::contains(const Code *o) const {
363 
364  return object_ == o;
365 }
366 
368 
369 _Fact *BindingMap::abstract_f_ihlp(const _Fact *f_ihlp) { // bindings are set already (coming from a mk.rdx caught by auto-focus).
370 
371  uint16 opcode;
372  Code *ihlp = f_ihlp->get_reference(0);
373  if (ihlp->code(0).asOpcode() == Opcodes::ICst)
374  opcode = Opcodes::ICst;
375  else
376  opcode = Opcodes::IMdl;
377 
378  _Fact *_f_ihlp = new Fact();
379  for (uint16 i = 0; i < f_ihlp->code_size(); ++i)
380  _f_ihlp->code(i) = f_ihlp->code(i);
381 
382  Code *_ihlp = _Mem::Get()->build_object(Atom::Object(opcode, I_HLP_ARITY));
383  _ihlp->code(I_HLP_OBJ) = Atom::RPointer(0);
384 
385  uint16 extent_index = I_HLP_ARITY + 1;
386 
387  uint32 map_index = 0;
388 
389  uint16 tpl_arg_set_index = ihlp->code(I_HLP_TPL_ARGS).asIndex();
390  uint16 tpl_arg_count = ihlp->code(tpl_arg_set_index).getAtomCount();
391 
392  _ihlp->code(I_HLP_TPL_ARGS) = Atom::IPointer(extent_index);
393  _ihlp->code(extent_index) = Atom::Set(tpl_arg_count);
394  for (uint16 i = 1; i <= tpl_arg_count; ++i)
395  _ihlp->code(extent_index + i) = Atom::VLPointer(map_index++);
396  extent_index += 1 + tpl_arg_count;
397 
398  uint16 arg_set_index = ihlp->code(I_HLP_EXPOSED_ARGS).asIndex();
399  uint16 arg_count = ihlp->code(arg_set_index).getAtomCount();
400  _ihlp->code(I_HLP_EXPOSED_ARGS) = Atom::IPointer(extent_index);
401  _ihlp->code(extent_index) = Atom::Set(arg_count);
402  for (uint16 i = 1; i <= arg_count; ++i)
403  _ihlp->code(extent_index + i) = Atom::VLPointer(map_index++);
404 
405  _ihlp->code(I_HLP_WEAK_REQUIREMENT_ENABLED) = ihlp->code(I_HLP_WEAK_REQUIREMENT_ENABLED);
406  _ihlp->code(I_HLP_ARITY) = ihlp->code(I_HLP_ARITY);
407 
408  _ihlp->add_reference(ihlp->get_reference(ihlp->code(I_HLP_OBJ).asIndex()));
409 
410  _f_ihlp->add_reference(_ihlp);
411  return _f_ihlp;
412 }
413 
414 _Fact *BindingMap::abstract_fact(_Fact *fact, const _Fact *original, bool force_sync, int timing_vars_first_search_index) { // abstract values as they are encountered.
415 
416  if (fwd_after_index_ == -1)
417  first_index_ = map_.size();
418 
419  uint16 extent_index = FACT_ARITY + 1;
420  abstract_member(original, FACT_OBJ, fact, FACT_OBJ, extent_index, timing_vars_first_search_index);
421  if (fwd_after_index_ != -1 && force_sync) {
422 
423  fact->code(FACT_AFTER) = Atom::VLPointer(fwd_after_index_);
424  fact->code(FACT_BEFORE) = Atom::VLPointer(fwd_before_index_);
425  } else {
426 
427  abstract_member(original, FACT_AFTER, fact, FACT_AFTER, extent_index, timing_vars_first_search_index);
428  abstract_member(original, FACT_BEFORE, fact, FACT_BEFORE, extent_index, timing_vars_first_search_index);
429  }
430  fact->code(FACT_CFD) = Atom::Wildcard();
431  fact->code(FACT_ARITY) = Atom::Wildcard();
432 
433  if (fwd_after_index_ == -1) {
434 
435  // Get the indexes that were put into the fact by abstract_member().
436  fwd_after_index_ = fact->code(FACT_AFTER).asIndex();
437  fwd_before_index_ = fact->code(FACT_BEFORE).asIndex();
438  }
439 
440  return fact;
441 }
442 
443 Code *BindingMap::abstract_object(Code *object, bool force_sync, int timing_vars_first_search_index) { // abstract values as they are encountered.
444 
445  Code *abstracted_object = NULL;
446 
447  uint16 opcode = object->code(0).asOpcode();
448  if (opcode == Opcodes::Fact)
449  return abstract_fact(new Fact(), (_Fact *)object, force_sync, timing_vars_first_search_index);
450  else if (opcode == Opcodes::AntiFact)
451  return abstract_fact(new AntiFact(), (_Fact *)object, force_sync, timing_vars_first_search_index);
452  else if (opcode == Opcodes::Cmd) {
453 
454  uint16 extent_index = CMD_ARITY + 1;
455  abstracted_object = _Mem::Get()->build_object(object->code(0));
456  abstracted_object->code(CMD_FUNCTION) = object->code(CMD_FUNCTION);
457  abstract_member(object, CMD_ARGS, abstracted_object, CMD_ARGS, extent_index);
458  abstracted_object->code(CMD_ARITY) = Atom::Wildcard();
459  } else if (opcode == Opcodes::MkVal) {
460 
461  uint16 extent_index = MK_VAL_ARITY + 1;
462  abstracted_object = _Mem::Get()->build_object(object->code(0));
463  abstract_member(object, MK_VAL_OBJ, abstracted_object, MK_VAL_OBJ, extent_index);
464  abstract_member(object, MK_VAL_ATTR, abstracted_object, MK_VAL_ATTR, extent_index);
465  abstract_member(object, MK_VAL_VALUE, abstracted_object, MK_VAL_VALUE, extent_index);
466  abstracted_object->code(MK_VAL_ARITY) = Atom::Wildcard();
467  } else if (opcode == Opcodes::IMdl || opcode == Opcodes::ICst) {
468 
469  uint16 extent_index = I_HLP_ARITY + 1;
470  abstracted_object = _Mem::Get()->build_object(object->code(0));
471  abstract_member(object, I_HLP_OBJ, abstracted_object, I_HLP_OBJ, extent_index);
472  // Set first_search_index to allow search to match with the model template args.
473  abstract_member(object, I_HLP_TPL_ARGS, abstracted_object, I_HLP_TPL_ARGS, extent_index, 0);
474  // Set first_search_index to not search because exposed args are "output values" which can't be assume to be the same as other values.
475  abstract_member(object, I_HLP_EXPOSED_ARGS, abstracted_object, I_HLP_EXPOSED_ARGS, extent_index, -1);
476  abstracted_object->code(I_HLP_WEAK_REQUIREMENT_ENABLED) = Atom::Wildcard();
477  abstracted_object->code(I_HLP_ARITY) = Atom::Wildcard();
478  } else
479  return object;
480  return abstracted_object;
481 }
482 
484  if (!(ihlp->code(0).asOpcode() != Opcodes::IMdl || ihlp->code(0).asOpcode() != Opcodes::ICst))
485  // We don't expect this to happen.
486  return 0;
487 
488  uint16 template_args_index = ihlp->code(I_HLP_TPL_ARGS).asIndex();
489  // The abstracted exposed args will start right after the template args.
490  return template_args_index + 1 + ihlp->code(template_args_index).getAtomCount();
491 }
492 
493 void BindingMap::abstract_member(const Code *object, uint16 index, Code *abstracted_object, uint16 write_index, uint16 &extent_index, int first_search_index) {
494 
495  Atom a = object->code(index);
496  uint16 ai = a.asIndex();
497  switch (a.getDescriptor()) {
498  case Atom::R_PTR: {
499  Code *reference = object->get_reference(ai);
500  if (reference->code(0).asOpcode() == Opcodes::Ont) { // ontologies resist abstraction.
501 
502  abstracted_object->code(write_index) = Atom::RPointer(abstracted_object->references_size());
503  abstracted_object->add_reference(reference);
504  } else if (reference->code(0).asOpcode() == Opcodes::Ent) // entities are always abstracted.
505  abstracted_object->code(write_index) = get_object_variable(reference);
506  else { // abstract the reference.
507 
508  abstracted_object->code(write_index) = Atom::RPointer(abstracted_object->references_size());
509  abstracted_object->add_reference(abstract_object(reference, false, first_search_index));
510  }
511  break;
512  }case Atom::I_PTR:
513  // If there is a SET or an OBJECT, then we use its structure.
514  if (hasUserDefinedOperators(object->code(ai).asOpcode()))
515  abstracted_object->code(write_index) = get_structure_variable(object, ai);
516  else if (object->code(ai).getDescriptor() == Atom::SET || object->code(ai).getDescriptor() == Atom::OBJECT) {
517 
518  abstracted_object->code(write_index) = Atom::IPointer(extent_index);
519 
520  uint16 element_count = object->code(ai).getAtomCount();
521  abstracted_object->code(extent_index) = object->code(ai);
522  uint16 _write_index = extent_index;
523  extent_index += element_count + 1;
524  for (uint16 i = 1; i <= element_count; ++i)
525  abstract_member(object, ai + i, abstracted_object, _write_index + i, extent_index, first_search_index);
526  } else
527  abstracted_object->code(write_index) = get_structure_variable(object, ai, first_search_index);
528  break;
529  default:
530  abstracted_object->code(write_index) = get_atom_variable(a);
531  break;
532  }
533 }
534 
535 void BindingMap::init(const Code *object, uint16 index) {
536 
537  Atom a = object->code(index);
538  switch (a.getDescriptor()) {
539  case Atom::R_PTR:
540  get_object_variable(object->get_reference(a.asIndex()));
541  break;
542  case Atom::I_PTR:
543  if (object->code(a.asIndex()).getDescriptor() == Atom::SET &&
544  object->code(a.asIndex()).getAtomCount() == 1)
545  // Special case: Treat a singleton set as just its one member (without recursion). To generalize, we may
546  // need a Value class which can hold other Value classes, and maybe restrict recursion.
547  return init(object, a.asIndex() + 1);
548 
549  get_structure_variable(object, a.asIndex());
550  break;
551  default:
552  get_atom_variable(a);
553  break;
554  }
555 }
556 
557 Atom BindingMap::get_atom_variable(Atom a) {
558 
559  for (uint32 i = 0; i < map_.size(); ++i) {
560 
561  if (map_[i]->contains(a))
562  return Atom::VLPointer(i);
563  }
564 
565  uint32 size = map_.size();
566  map_.push_back(new AtomValue(this, a));
567  return Atom::VLPointer(size);
568 }
569 
570 Atom BindingMap::get_structure_variable(const Code *object, uint16 index, int first_search_index) {
571 
572  if (first_search_index >= 0 && map_.size() > 0) {
573  if (first_search_index > map_.size())
574  first_search_index = map_.size() - 1;
575 
576  for (uint32 i = first_search_index; true;) {
577 
578  if (map_[i]->contains(&object->code(index)))
579  return Atom::VLPointer(i);
580 
581  ++i;
582  if (i >= map_.size())
583  // Wrap around.
584  i = 0;
585  if (i == first_search_index)
586  // We reached the starting point.
587  break;
588  }
589  }
590 
591  uint32 size = map_.size();
592  map_.push_back(new StructureValue(this, &object->code(0), index));
593  return Atom::VLPointer(size);
594 }
595 
596 Atom BindingMap::get_object_variable(Code *object) {
597 
598  for (uint32 i = 0; i < map_.size(); ++i) {
599 
600  if (map_[i]->contains(object))
601  return Atom::VLPointer(i);
602  }
603 
604  uint32 size = map_.size();
605  map_.push_back(new ObjectValue(this, object));
606  return Atom::VLPointer(size);
607 }
608 
609 BindingMap::BindingMap() : _Object(), first_index_(-1), fwd_after_index_(-1), fwd_before_index_(-1), unbound_values_(0) {
610 }
611 
612 BindingMap::BindingMap(const BindingMap *source) : _Object() {
613 
614  *this = *source;
615 }
616 
617 BindingMap::BindingMap(const BindingMap &source) : _Object() {
618 
619  *this = source;
620 }
621 
622 BindingMap::~BindingMap() {
623 }
624 
625 void BindingMap::clear() {
626 
627  map_.clear();
628  fwd_after_index_ = fwd_before_index_ = -1;
629 }
630 
631 BindingMap &BindingMap::operator =(const BindingMap &source) {
632 
633  clear();
634  for (uint8 i = 0; i < source.map_.size(); ++i)
635  map_.push_back(source.map_[i]->copy(this));
636  first_index_ = source.first_index_;
637  fwd_after_index_ = source.fwd_after_index_;
638  fwd_before_index_ = source.fwd_before_index_;
639  unbound_values_ = source.unbound_values_;
640  return *this;
641 }
642 
643 void BindingMap::load(const BindingMap *source) {
644 
645  *this = *source;
646 }
647 
648 void BindingMap::add_unbound_value(uint8 id) {
649 
650  if (id >= map_.size())
651  map_.resize(id + 1);
652  map_[id] = new UnboundValue(this, id);
653 }
654 
655 bool BindingMap::match(const Code *object, uint16 o_base_index, uint16 o_index, const Code *pattern, uint16 p_index, uint16 o_arity) {
656 
657  uint16 o_full_index = o_base_index + o_index;
658  Atom o_atom = object->code(o_full_index);
659  Atom p_atom = pattern->code(p_index);
660  switch (o_atom.getDescriptor()) {
661  case Atom::T_WILDCARD:
662  case Atom::WILDCARD:
663  case Atom::VL_PTR:
664  break;
665  case Atom::I_PTR:
666  switch (p_atom.getDescriptor()) {
667  case Atom::VL_PTR:
668  if (!map_[p_atom.asIndex()]->match(object, o_full_index))
669  return false;
670  break;
671  case Atom::I_PTR:
672  if (!match_structure(object, o_atom.asIndex(), 0, pattern, p_atom.asIndex()))
673  return false;
674  break;
675  case Atom::T_WILDCARD:
676  case Atom::WILDCARD:
677  break;
678  default:
679  return false;
680  }
681  break;
682  case Atom::R_PTR:
683  switch (p_atom.getDescriptor()) {
684  case Atom::VL_PTR:
685  if (!map_[p_atom.asIndex()]->match(object, o_full_index))
686  return false;
687  break;
688  case Atom::R_PTR:
689  if (!match_object(object->get_reference(o_atom.asIndex()), pattern->get_reference(p_atom.asIndex())))
690  return false;
691  break;
692  case Atom::T_WILDCARD:
693  case Atom::WILDCARD:
694  break;
695  default:
696  return false;
697  }
698  break;
699  default:
700  switch (p_atom.getDescriptor()) {
701  case Atom::VL_PTR:
702  if (!map_[p_atom.asIndex()]->match(object, o_full_index))
703  return false;
704  break;
705  case Atom::T_WILDCARD:
706  case Atom::WILDCARD:
707  break;
708  default:
709  if (!match_atom(o_atom, p_atom))
710  return false;
711  break;
712  }
713  break;
714  }
715 
716  if (o_index == o_arity)
717  return true;
718  return match(object, o_base_index, o_index + 1, pattern, p_index + 1, o_arity);
719 }
720 
721 bool BindingMap::match_atom(Atom o_atom, Atom p_atom) {
722 
723  if (p_atom == o_atom)
724  return true;
725 
726  if (p_atom.isFloat() && o_atom.isFloat())
727  return Utils::Equal(o_atom.asFloat(), p_atom.asFloat());
728 
729  return false;
730 }
731 
732 bool BindingMap::match_structure(const Code *object, uint16 o_base_index, uint16 o_index, const Code *pattern, uint16 p_index) {
733 
734  uint16 o_full_index = o_base_index + o_index;
735  Atom o_atom = object->code(o_full_index);
736  Atom p_atom = pattern->code(p_index);
737  if (o_atom != p_atom)
738  return false;
739  uint16 arity = o_atom.getAtomCount();
740  if (arity == 0) // empty sets.
741  return true;
742  if (o_atom.getDescriptor() == Atom::TIMESTAMP)
743  return Utils::Synchronous(Utils::GetTimestamp(&object->code(o_full_index)), Utils::GetTimestamp(&pattern->code(p_index)));
744  if (p_atom == Atom::Object(Opcodes::TI, 2)) {
745  // This is a (ti : :). Check the args.
746  Atom after_atom = pattern->code(p_index + 1);
747  Atom before_atom = pattern->code(p_index + 2);
748  if (after_atom.getDescriptor() == Atom::VL_PTR && before_atom.getDescriptor() == Atom::VL_PTR &&
749  map_[after_atom.asIndex()]->get_code() != NULL && map_[before_atom.asIndex()]->get_code() != NULL) {
750  // Both args are variables pointing to a value.
751  if (Utils::HasTimestamp<Code>(object, o_full_index + 1) &&
752  Utils::HasTimestamp<Code>(object, o_full_index + 2))
753  // The object to match has timestamp values in its (ti After Before). Use the same "smart" match_timings
754  // method that match_fwd_timings, etc. use to match the time intervals of two facts.
755  return match_timings(
756  Utils::GetTimestamp<Code>(object, o_full_index + 1),
757  Utils::GetTimestamp<Code>(object, o_full_index + 2), after_atom.asIndex(), before_atom.asIndex());
758  }
759  }
760  return match(object, o_base_index, o_index + 1, pattern, p_index + 1, arity);
761 }
762 
763 void BindingMap::reset_fwd_timings(_Fact *reference_fact) { // valuate at after_index and after_index+1 from the timings of the reference object.
764 
765  if (fwd_after_index_ >= 0 && fwd_after_index_ < map_.size())
766  map_[fwd_after_index_] = new StructureValue(this, reference_fact, reference_fact->code(FACT_AFTER).asIndex());
767  if (fwd_before_index_ >= 0 && fwd_before_index_ < map_.size())
768  map_[fwd_before_index_] = new StructureValue(this, reference_fact, reference_fact->code(FACT_BEFORE).asIndex());
769 }
770 
771 bool BindingMap::match_timings(Timestamp after, Timestamp before, uint32 after_index, uint32 before_index) {
772 
773  Atom* after_code = map_[after_index]->get_code();
774  Atom* before_code = map_[before_index]->get_code();
775  if (after_code[0].getDescriptor() != Atom::TIMESTAMP ||
776  before_code[0].getDescriptor() != Atom::TIMESTAMP)
777  return false;
778  Timestamp stored_after = Utils::GetTimestamp(after_code);
779  Timestamp stored_before = Utils::GetTimestamp(before_code);
780 
781  if (stored_after <= after) {
782 
783  if (stored_before >= before) { // sa a b sb
784 
785  Utils::SetTimestamp(after_code, after);
786  Utils::SetTimestamp(before_code, before);
787  return true;
788  } else {
789 
790  if (stored_before > after) { // sa a sb b
791 
792  Utils::SetTimestamp(after_code, after);
793  return true;
794  }
795  return false;
796  }
797  } else {
798 
799  if (stored_before <= before) // a sa sb b
800  return true;
801  else if (stored_after < before) { // a sa b sb
802 
803  Utils::SetTimestamp(before_code, before);
804  return true;
805  }
806  return false;
807  }
808 }
809 
810 bool BindingMap::match_fwd_timings(const _Fact *f_object) {
811 
812  return match_fwd_timings(f_object->get_after(), f_object->get_before());
813 }
814 
815 bool BindingMap::match_fwd_strict(const _Fact *f_object, const _Fact *f_pattern) {
816 
817  if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
818 
819  if (f_object->code(0) != f_pattern->code(0))
820  return false;
821 
822  return match_fwd_timings(f_object);
823  } else
824  return false;
825 }
826 
827 MatchResult BindingMap::match_fwd_lenient(const _Fact *f_object, const _Fact *f_pattern) {
828 
829  if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
830 
831  MatchResult r;
832  if (f_pattern->code(0) == f_object->code(0))
833  r = MATCH_SUCCESS_POSITIVE;
834  else
835  r = MATCH_SUCCESS_NEGATIVE;
836 
837  if (match_fwd_timings(f_object))
838  return r;
839  return MATCH_FAILURE;
840  } else
841  return MATCH_FAILURE;
842 }
843 
844 Timestamp BindingMap::get_fwd_after() const {
845 
846  return Utils::GetTimestamp(map_[fwd_after_index_]->get_code());
847 }
848 
849 Timestamp BindingMap::get_fwd_before() const {
850 
851  return Utils::GetTimestamp(map_[fwd_before_index_]->get_code());
852 }
853 
854 bool BindingMap::match_object(const Code *object, const Code *pattern) {
855 
856  if (object->code(0) != pattern->code(0))
857  return false;
858  uint16 pattern_opcode = pattern->code(0).asOpcode();
859  if (pattern_opcode == Opcodes::Ent ||
860  pattern_opcode == Opcodes::Ont ||
861  pattern_opcode == Opcodes::Mdl ||
862  pattern_opcode == Opcodes::Cst)
863  return object == pattern;
864  return match(object, 0, 1, pattern, 1, object->code(0).getAtomCount());
865 }
866 
867 void BindingMap::bind_variable(BoundValue *value, uint8 id) {
868 
869  map_[id] = value;
870 }
871 
872 void BindingMap::bind_variable(Atom *code, uint8 id, uint16 value_index, Atom *intermediate_results) { // assigment.
873 
874  Atom v_atom = code[value_index];
875  if (v_atom.isFloat())
876  bind_variable(new AtomValue(this, v_atom), id);
877  else switch (v_atom.getDescriptor()) {
878  case Atom::OBJECT:
879  // Assume this is an object literal like (vec3 -0.5 0 0).
880  bind_variable(new StructureValue(this, code, value_index), id);
881  break;
882  case Atom::VALUE_PTR:
883  bind_variable(new StructureValue(this, intermediate_results, v_atom.asIndex()), id);
884  break;
885  }
886 }
887 
888 Atom *BindingMap::get_value_code(uint16 id) const {
889 
890  return map_[id]->get_code();
891 }
892 
893 uint16 BindingMap::get_value_code_size(uint16 id) const {
894 
895  return map_[id]->get_code_size();
896 }
897 
898 bool BindingMap::scan_variable(uint16 id) const {
899 
900  if (id < first_index_)
901  return true;
902  return (map_[id]->get_code() != NULL);
903 }
904 
905 bool BindingMap::intersect(const BindingMap *bm) const {
906 
907  for (uint32 i = 0; i < map_.size();) {
908 
909  if (i == fwd_after_index_) { // ignore fact timings.
910 
911  i += 2;
912  continue;
913  }
914 
915  for (uint32 j = 0; j < bm->map_.size();) {
916 
917  if (j == bm->fwd_after_index_) { // ignore fact timings.
918 
919  j += 2;
920  continue;
921  }
922 
923  if (map_[i]->intersect(bm->map_[j]))
924  return true;
925 
926  ++j;
927  }
928 
929  ++i;
930  }
931 
932  return false;
933 }
934 
935 bool BindingMap::is_fully_specified() const {
936 
937  return unbound_values_ == 0;
938 }
939 
941 
942 HLPBindingMap::HLPBindingMap() : BindingMap(), bwd_after_index_(-1), bwd_before_index_(-1) {
943 }
944 
945 HLPBindingMap::HLPBindingMap(const HLPBindingMap *source) : BindingMap() {
946 
947  *this = *source;
948 }
949 
950 HLPBindingMap::HLPBindingMap(const HLPBindingMap &source) : BindingMap() {
951 
952  *this = source;
953 }
954 
955 HLPBindingMap::~HLPBindingMap() {
956 }
957 
958 void HLPBindingMap::clear() {
959 
960  BindingMap::clear();
961  bwd_after_index_ = bwd_before_index_ = -1;
962 }
963 
964 HLPBindingMap &HLPBindingMap::operator =(const HLPBindingMap &source) {
965 
966  clear();
967  for (uint8 i = 0; i < source.map_.size(); ++i)
968  map_.push_back(source.map_[i]->copy(this));
969  first_index_ = source.first_index_;
970  fwd_after_index_ = source.fwd_after_index_;
971  fwd_before_index_ = source.fwd_before_index_;
972  bwd_after_index_ = source.bwd_after_index_;
973  bwd_before_index_ = source.bwd_before_index_;
974  unbound_values_ = source.unbound_values_;
975  return *this;
976 }
977 
978 void HLPBindingMap::load(const HLPBindingMap *source) {
979 
980  *this = *source;
981 }
982 
983 void HLPBindingMap::add_unbound_values(const Code* hlp, uint16 structure_index) {
984  uint16 arg_count = hlp->code(structure_index).getAtomCount();
985  for (uint16 i = 1; i <= arg_count; ++i) {
986 
987  Atom a = hlp->code(structure_index + i);
988  if (a.getDescriptor() == Atom::VL_PTR)
989  add_unbound_value(a.asIndex());
990  else if (a.getDescriptor() == Atom::I_PTR)
991  // Recurse into the structure.
992  add_unbound_values(hlp, hlp->code(structure_index + i).asIndex());
993  }
994 }
995 
996 void HLPBindingMap::init_from_hlp(const Code* hlp, const Code* packed_hlp) { // hlp is cst or mdl.
997 
998  add_unbound_values(hlp, hlp->code(HLP_TPL_ARGS).asIndex());
999 
1000  first_index_ = map_.size();
1001 
1002  uint16 obj_set_index = hlp->code(HLP_OBJS).asIndex();
1003  uint16 obj_count = hlp->code(obj_set_index).getAtomCount();
1004  if (obj_count >= 1)
1005  init_timing_indexes(hlp->get_reference(hlp->code(obj_set_index + 1).asIndex()),
1006  fwd_after_index_, fwd_before_index_);
1007  if (obj_count >= 2)
1008  init_timing_indexes(hlp->get_reference(hlp->code(obj_set_index + 2).asIndex()),
1009  bwd_after_index_, bwd_before_index_);
1010 
1011  // Use the packed hlp without recursion which has exactly the vars we need for the binding map.
1012  // NOTE: If the hlp contains a string literal where a char looks like a VL_PTR, this won't work.
1013  for (uint16 i = 1; i < packed_hlp->code_size(); ++i) {
1014  Atom s = packed_hlp->code(i);
1015  if (s.getDescriptor() == Atom::VL_PTR)
1016  add_unbound_value(s.asIndex());
1017  }
1018 }
1019 
1020 void HLPBindingMap::init_from_ihlp_args(
1021  const Code* hlp, uint16 hlp_args_index, const Code* ihlp, uint16 ihlp_args_index) {
1022  if (hlp->code(hlp_args_index) != ihlp->code(ihlp_args_index))
1023  // The type of structure or the arity doesn't match.
1024  return;
1025 
1026  uint16 count = ihlp->code(ihlp_args_index).getAtomCount();
1027  // valuate args.
1028  for (uint16 i = 0; i < count; ++i) {
1029 
1030  Atom hlp_atom = hlp->code(hlp_args_index + 1 + i);
1031  Atom ihlp_atom = ihlp->code(ihlp_args_index + 1 + i);
1032 
1033  if (hlp_atom.getDescriptor() == Atom::I_PTR) {
1034  if (ihlp_atom.getDescriptor() != Atom::I_PTR)
1035  // Can't get values from the ihlp
1036  continue;
1037  // Recurse into the structure.
1038  init_from_ihlp_args(hlp, hlp_atom.asIndex(), ihlp, ihlp_atom.asIndex());
1039  continue;
1040  }
1041  if (hlp_atom.getDescriptor() != Atom::VL_PTR)
1042  // No variable to set.
1043  continue;
1044 
1045  switch (ihlp_atom.getDescriptor()) {
1046  case Atom::R_PTR:
1047  map_[hlp_atom.asIndex()] = new ObjectValue(this, ihlp->get_reference(ihlp_atom.asIndex()));
1048  break;
1049  case Atom::I_PTR:
1050  map_[hlp_atom.asIndex()] = new StructureValue(this, ihlp, ihlp_atom.asIndex());
1051  break;
1052  default:
1053  map_[hlp_atom.asIndex()] = new AtomValue(this, ihlp_atom);
1054  break;
1055  }
1056  }
1057 }
1058 
1059 void HLPBindingMap::init_from_f_ihlp(const _Fact *f_ihlp) { // source is f->icst or f->imdl; map already initialized with values from hlp.
1060 
1061  Code *ihlp = f_ihlp->get_reference(0);
1062 
1063  Code* hlp = ihlp->get_reference(0);
1064  init_from_ihlp_args(hlp, hlp->code(HLP_TPL_ARGS).asIndex(), ihlp, ihlp->code(I_HLP_TPL_ARGS).asIndex());
1065 
1066  uint16 val_set_index = ihlp->code(I_HLP_EXPOSED_ARGS).asIndex() + 1;
1067  uint32 i = 0;
1068  for (uint32 j = first_index_; j < map_.size(); ++j) { // valuate args.
1069 
1070  if (j == fwd_after_index_ || j == fwd_before_index_)
1071  // The forward timestamps don't appear in the args set, so skip.
1072  continue;
1073 
1074  Atom atom = ihlp->code(val_set_index + i);
1075  switch (atom.getDescriptor()) {
1076  case Atom::R_PTR:
1077  map_[j] = new ObjectValue(this, ihlp->get_reference(atom.asIndex()));
1078  break;
1079  case Atom::I_PTR:
1080  map_[j] = new StructureValue(this, ihlp, atom.asIndex());
1081  break;
1082  case Atom::WILDCARD:
1083  case Atom::T_WILDCARD:
1084  case Atom::VL_PTR:
1085  break;
1086  default:
1087  map_[j] = new AtomValue(this, atom);
1088  break;
1089  }
1090 
1091  // Increment to look at the next value in the args set in the ihlp.
1092  ++i;
1093  }
1094 
1095  // Valuate timings; fwd_after_index is already known. We know that time stamps are I_PTR to the time stamp structure.
1096  map_[fwd_after_index_] = new StructureValue(this, f_ihlp, f_ihlp->code(FACT_AFTER).asIndex());
1097  map_[fwd_before_index_] = new StructureValue(this, f_ihlp, f_ihlp->code(FACT_BEFORE).asIndex());
1098 }
1099 
1100 void HLPBindingMap::build_ihlp_structure(
1101  const Code* hlp, uint16 hlp_structure_index, Code* ihlp, uint16& extent_index) const
1102 {
1103  uint16 count = hlp->code(hlp_structure_index).getAtomCount();
1104  ihlp->code(extent_index) = hlp->code(hlp_structure_index);
1105  uint16 write_index = extent_index + 1;
1106  extent_index = write_index + count;
1107  bool is_ti = (hlp->code(hlp_structure_index) == Atom::Object(Opcodes::TI, 2));
1108 
1109  // Copy from the HLP structure, valuating each VL_PTR.
1110  for (uint16 i = 0; i < count; ++i) {
1111  Atom a = hlp->code(hlp_structure_index + 1 + i);
1112  // Leave the args of (ti After: Before:) as variables so that Match can "narrow" them.
1113  if (a.getDescriptor() == Atom::VL_PTR && !is_ti)
1114  // Valuate the arg.
1115  map_[a.asIndex()]->valuate(ihlp, write_index, extent_index);
1116  else if (a.getDescriptor() == Atom::I_PTR) {
1117  ihlp->code(write_index) = Atom::IPointer(extent_index);
1118  // Recurse into the structure.
1119  build_ihlp_structure(hlp, a.asIndex(), ihlp, extent_index);
1120  }
1121  else
1122  ihlp->code(write_index) = a;
1123 
1124  ++write_index;
1125  }
1126 }
1127 
1128 Fact *HLPBindingMap::build_f_ihlp(Code *hlp, uint16 opcode, bool wr_enabled) const {
1129 
1130  Code *ihlp = _Mem::Get()->build_object(Atom::Object(opcode, I_HLP_ARITY));
1131  ihlp->code(I_HLP_OBJ) = Atom::RPointer(0);
1132  ihlp->add_reference(hlp);
1133 
1134  uint16 tpl_arg_index = I_HLP_ARITY + 1;
1135  ihlp->code(I_HLP_TPL_ARGS) = Atom::IPointer(tpl_arg_index);
1136  uint16 extent_index = tpl_arg_index;
1137  build_ihlp_structure(hlp, hlp->code(HLP_TPL_ARGS).asIndex(), ihlp, extent_index);
1138 
1139  ihlp->code(I_HLP_EXPOSED_ARGS) = Atom::IPointer(extent_index);
1140  uint16 exposed_arg_start = first_index_;
1141  uint16 exposed_arg_count = map_.size() - exposed_arg_start - 2; // -2: do not expose the first after/before timestamps.
1142  ihlp->code(extent_index) = Atom::Set(exposed_arg_count);
1143 
1144  uint16 write_index = extent_index + 1;
1145  extent_index = write_index + exposed_arg_count;
1146  for (uint16 i = exposed_arg_start; i < map_.size(); ++i) { // valuate args.
1147 
1148  if (i == fwd_after_index_)
1149  continue;
1150  if (i == fwd_before_index_)
1151  continue;
1152  map_[i]->valuate(ihlp, write_index, extent_index);
1153  ++write_index;
1154  }
1155 
1156  ihlp->code(I_HLP_WEAK_REQUIREMENT_ENABLED) = Atom::Boolean(wr_enabled);
1157  ihlp->code(I_HLP_ARITY) = Atom::Float(1); // psln_thr.
1158 
1159  Fact *f_ihlp = new Fact(ihlp, Timestamp(seconds(0)), Timestamp(seconds(0)), 1, 1);
1160  extent_index = FACT_ARITY + 1;
1161  map_[fwd_after_index_]->valuate(f_ihlp, FACT_AFTER, extent_index);
1162  map_[fwd_before_index_]->valuate(f_ihlp, FACT_BEFORE, extent_index);
1163  return f_ihlp;
1164 }
1165 
1167  // Use the same logic as build_f_ihlp.
1168  uint16 exposed_arg_start = first_index_;
1169  if (index == fwd_after_index_ || index == fwd_before_index_ ||
1170  index < exposed_arg_start || index >= map_.size())
1171  return -1;
1172 
1173  uint16 exposed_arg_count = map_.size() - exposed_arg_start - 2; // -2: do not expose the first after/before timestamps.
1174  uint16 position = 0;
1175  for (uint16 i = exposed_arg_start; i < map_.size(); ++i) {
1176  if (i == fwd_after_index_ || i == fwd_before_index_)
1177  continue;
1178 
1179  if (i == index)
1180  return position;
1181  ++position;
1182  }
1183 
1184  return -1;
1185 }
1186 
1187 
1188 Code *HLPBindingMap::bind_pattern(Code *pattern) const {
1189 
1190  if (!need_binding(pattern))
1191  return pattern;
1192 
1193  Code *bound_pattern = _Mem::Get()->build_object(pattern->code(0));
1194 
1195  for (uint16 i = 0; i < pattern->references_size(); ++i) { // bind references when needed; must be done before binding the code as this may add references.
1196 
1197  Code *reference = pattern->get_reference(i);
1198  if (need_binding(reference))
1199  bound_pattern->set_reference(i, bind_pattern(reference));
1200  else
1201  bound_pattern->set_reference(i, reference);
1202  }
1203 
1204  uint16 extent_index = pattern->code_size();
1205  for (uint16 i = 1; i < pattern->code_size(); ++i) { // transform code containing variables into actual values when they exist: objects -> r_ptr, structures -> i_ptr, atoms -> atoms.
1206 
1207  Atom p_atom = pattern->code(i);
1208  switch (p_atom.getDescriptor()) {
1209  case Atom::VL_PTR:
1210  map_[p_atom.asIndex()]->valuate(bound_pattern, i, extent_index);
1211  break;
1212  case Atom::TIMESTAMP:
1213  case Atom::DURATION:
1214  case Atom::STRING: { // avoid misinterpreting raw data that could be lead by descriptors.
1215  bound_pattern->code(i) = p_atom;
1216  uint16 atom_count = p_atom.getAtomCount();
1217  for (uint16 j = i + 1; j <= i + atom_count; ++j)
1218  bound_pattern->code(j) = pattern->code(j);
1219  i += atom_count;
1220  break;
1221  }default:
1222  bound_pattern->code(i) = p_atom;
1223  break;
1224  }
1225  }
1226 
1227  return bound_pattern;
1228 }
1229 
1230 bool HLPBindingMap::need_binding(Code *pattern) const {
1231 
1232  if (pattern->code(0).asOpcode() == Opcodes::Ont ||
1233  pattern->code(0).asOpcode() == Opcodes::Ent ||
1234  pattern->code(0).asOpcode() == Opcodes::Mdl ||
1235  pattern->code(0).asOpcode() == Opcodes::Cst)
1236  return false;
1237 
1238  for (uint16 i = 0; i < pattern->references_size(); ++i) {
1239 
1240  if (need_binding(pattern->get_reference(i)))
1241  return true;
1242  }
1243 
1244  for (uint16 i = 1; i < pattern->code_size(); ++i) {
1245 
1246  Atom p_atom = pattern->code(i);
1247  switch (p_atom.getDescriptor()) {
1248  case Atom::VL_PTR:
1249  return true;
1250  case Atom::TIMESTAMP:
1251  case Atom::DURATION:
1252  case Atom::STRING:
1253  i += p_atom.getAtomCount();
1254  break;
1255  default:
1256  break;
1257  }
1258  }
1259 
1260  return false;
1261 }
1262 
1263 void HLPBindingMap::reset_bwd_timings(_Fact *reference_fact) { // valuate at after_index and after_index+1 from the timings of the reference fact.
1264 
1265  if (bwd_after_index_ >= 0 && bwd_after_index_ < map_.size())
1266  map_[bwd_after_index_] = new StructureValue(this, reference_fact, reference_fact->code(FACT_AFTER).asIndex());
1267  if (bwd_before_index_ >= 0 && bwd_before_index_ < map_.size())
1268  map_[bwd_before_index_] = new StructureValue(this, reference_fact, reference_fact->code(FACT_BEFORE).asIndex());
1269 }
1270 
1271 bool HLPBindingMap::match_bwd_timings(const _Fact *f_object, const _Fact *f_pattern) {
1272 
1273  return match_timings(f_object->get_after(), f_object->get_before(), bwd_after_index_, bwd_before_index_);
1274 }
1275 
1276 bool HLPBindingMap::match_bwd_strict(const _Fact *f_object, const _Fact *f_pattern) {
1277 
1278  if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
1279 
1280  if (f_object->code(0) != f_pattern->code(0))
1281  return false;
1282 
1283  return match_bwd_timings(f_object, f_pattern);
1284  } else
1285  return false;
1286 }
1287 
1288 MatchResult HLPBindingMap::match_bwd_lenient(const _Fact *f_object, const _Fact *f_pattern) {
1289 
1290  if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
1291 
1292  MatchResult r;
1293  if (f_pattern->code(0) == f_object->code(0))
1294  r = MATCH_SUCCESS_POSITIVE;
1295  else
1296  r = MATCH_SUCCESS_NEGATIVE;
1297 
1298  if (match_bwd_timings(f_object, f_pattern))
1299  return r;
1300  return MATCH_FAILURE;
1301  } else
1302  return MATCH_FAILURE;
1303 }
1304 
1305 Timestamp HLPBindingMap::get_bwd_after() const {
1306 
1307  return Utils::GetTimestamp(map_[bwd_after_index_]->get_code());
1308 }
1309 
1310 Timestamp HLPBindingMap::get_bwd_before() const {
1311 
1312  return Utils::GetTimestamp(map_[bwd_before_index_]->get_code());
1313 }
1314 }
r_exec::BindingMap::get_structure_variable
Atom get_structure_variable(const r_code::Code *object, uint16 index, int first_search_index=0)
Definition: binding_map.cpp:570
r_exec::BindingMap::get_abstracted_ihlp_exposed_args_index
static uint16 get_abstracted_ihlp_exposed_args_index(const r_code::Code *ihlp)
Definition: binding_map.cpp:483
r_exec::AntiFact
Definition: factory.h:371
r_exec::HLPBindingMap::get_ihlp_exposed_args_position
int16 get_ihlp_exposed_args_position(int16 index) const
Definition: binding_map.cpp:1166
r_exec::BindingMap
Definition: binding_map.h:248
r_code::Atom
Definition: atom.h:104
r_exec::_Fact
Definition: factory.h:155
r_code::Code
Definition: r_code/object.h:224
core::_Object
Definition: base.h:131
r_exec::BindingMap::abstract_fact
_Fact * abstract_fact(_Fact *fact, const _Fact *original, bool force_sync, int timing_vars_first_search_index=0)
Definition: binding_map.cpp:414
r_code::LocalObject
Definition: r_code/object.h:377
r_exec::StructureValue
Definition: binding_map.h:178
r_exec::BindingMap::intersect
bool intersect(const BindingMap *bm) const
Definition: binding_map.cpp:905
r_exec::BindingMap::match_timings
bool match_timings(Timestamp after, Timestamp before, uint32 after_index, uint32 before_index)
Definition: binding_map.cpp:771
r_exec::Fact
Definition: factory.h:360