AERA
All Classes Functions Pages
context.h
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 #ifndef ipgm_context_h
86 #define ipgm_context_h
87 
88 #include "../r_code/atom.h"
89 #include "../r_code/utils.h"
90 #include "object.h"
91 #include "_context.h"
92 #include "pgm_overlay.h"
93 #include "operator.h"
94 
95 
96 namespace r_exec {
97 
98 class InputLessPGMOverlay;
99 
100 // Evaluation context.
101 class dll_export IPGMContext :
102  public _Context {
103 private:
104  r_code::Code *object_; // the object the code belongs to; unchanged when the context is dereferenced to the overlay's value array.
105  View *view_; // the object's view, can be NULL when the context is dereferenced to a reference_set or a marker_set.
106 
107  bool is_cmd_with_cptr() const;
108 
109  static void addReference(r_code::Code *destination, uint16 write_index, r_code::Code *referenced_object) {
110 
111  for (uint16 i = 0; i < destination->references_size(); ++i)
112  if (referenced_object == destination->get_reference(i)) {
113 
114  destination->code(write_index) = Atom::RPointer(i);
115  return;
116  }
117 
118  destination->add_reference(referenced_object);
119  destination->code(write_index) = Atom::RPointer(destination->references_size() - 1);
120  }
121 
122  static void addReference(View *destination, uint16 write_index, r_code::Code *referenced_object) { // view references are set in order (index 0 then 1).
123 
124  uint16 r_ptr_index;
125  if (destination->references_[0]) // first ref already in place.
126  r_ptr_index = 1;
127  else
128  r_ptr_index = 0;
129  destination->references_[r_ptr_index] = referenced_object;
130  destination->code(write_index) = Atom::RPointer(r_ptr_index);
131  }
132 
133  template<class C> void copy_structure(C *destination,
134  uint16 write_index,
135  uint16 &extent_index,
136  bool dereference_cptr,
137  int32 pgm_index) const { // assumes the context is a structure; C: Object or View.
138 
139  if ((*this)[0].getDescriptor() == Atom::OPERATOR && Operator::Get((*this)[0].asOpcode()).is_syn()) { // (\ (expression ...)).
140 
141  IPGMContext c = get_child(1);
142  c.copy_member(destination, write_index, extent_index, dereference_cptr, pgm_index);
143  } else {
144 
145  destination->code(write_index++) = (*this)[0];
146 
147  uint16 atom_count = get_children_count();
148  extent_index = write_index + atom_count;
149 
150  switch ((*this)[0].getDescriptor()) {
151  case Atom::C_PTR: // copy members as is (no dereference).
152  if ((*this)[1].getDescriptor() == Atom::CODE_VL_PTR) {
153 
154  Atom a = code_[(*this)[1].asIndex()];
155  if (a.getDescriptor() == Atom::I_PTR)
156  a = code_[a.asIndex()];
157  switch (a.getDescriptor()) {
158  case Atom::OUT_OBJ_PTR:
159  destination->code(write_index++) = Atom::CodeVLPointer(code_[(*this)[1].asIndex()].asIndex());
160  break;
161  case Atom::IN_OBJ_PTR: // TMP: assumes destination is a mk.rdx.
162  destination->code(write_index++) = Atom::RPointer(1 + a.asInputIndex());
163  break;
164  default:
165  destination->code(write_index++) = (*this)[1];
166  break;
167  }
168  } else
169  destination->code(write_index++) = (*this)[1];
170  for (uint16 i = 2; i <= atom_count; ++i)
171  destination->code(write_index++) = (*this)[i];
172  break;
173  case Atom::TIMESTAMP: // copy members as is (no dereference).
174  for (uint16 i = 1; i <= atom_count; ++i)
175  destination->code(write_index++) = (*this)[i];
176  break;
177  case Atom::DURATION: // copy members as is (no dereference).
178  for (uint16 i = 1; i <= atom_count; ++i)
179  destination->code(write_index++) = (*this)[i];
180  break;
181  default:
182  if (is_cmd_with_cptr()) {
183 
184  for (uint16 i = 1; i <= atom_count; ++i) {
185 
186  IPGMContext c = get_child(i);
187  c.copy_member(destination, write_index++, extent_index, i != 2, pgm_index);
188  }
189  } else { // if a pgm is being copied, indicate the starting index of the pgm so that we can turn on code patching and know if a cptr is referencing code inside the pgm (in that case it will not be dereferenced).
190 
191  int32 _pgm_index;
192  if (pgm_index >= 0)
193  _pgm_index = pgm_index;
194  else if ((*this)[0].getDescriptor() == Atom::OBJECT && ((*this)[0].asOpcode() == Opcodes::Pgm || (*this)[0].asOpcode() == Opcodes::AntiPgm))
195  _pgm_index = index_;
196  else
197  _pgm_index = -1;
198 
199  for (uint16 i = 1; i <= atom_count; ++i) {
200 
201  IPGMContext c = get_child(i);
202  c.copy_member(destination, write_index++, extent_index, !(!dereference_cptr && i == 1), _pgm_index);
203  }
204  }
205  break;
206  }
207  }
208  }
209 
210  template<class C> void copy_member(C *destination,
211  uint16 write_index,
212  uint16 &extent_index,
213  bool dereference_cptr,
214  int32 pgm_index) const {
215 
216  switch ((*this)[0].getDescriptor()) {
217  case Atom::I_PTR:
218  case Atom::VALUE_PTR:
219  case Atom::IPGM_PTR: {
220 
221  if (data_ == REFERENCE && index_ == 0) { // points to an object, not to one of its members.
222 
223  addReference(destination, write_index, object_);
224  break;
225  }
226 
227  if (code_[(*this)[0].asIndex()].getDescriptor() == Atom::C_PTR) {
228 
229  if (!dereference_cptr || (pgm_index > 0 && code_[(*this)[0].asIndex() + 1].asIndex() > pgm_index)) { // the latter case occurs when a cptr references code inside a pgm being copied.
230 
231  IPGMContext c = IPGMContext(object_, view_, code_, (*this)[0].asIndex(), (InputLessPGMOverlay *)overlay_, data_);
232  destination->code(write_index) = Atom::IPointer(extent_index);
233  c.copy_structure(destination, extent_index, extent_index, dereference_cptr, pgm_index);
234  break;
235  }
236  }
237 
238  IPGMContext c = dereference();
239  if (c[0].isStructural()) {
240 
241  destination->code(write_index) = Atom::IPointer(extent_index);
242  if (pgm_index > 0 && index_ > pgm_index && data_ == STEM)
243  patch_code(index_, Atom::OutObjPointer(write_index));
244  c.copy_structure(destination, extent_index, extent_index, dereference_cptr, pgm_index);
245  } else
246  destination->code(write_index) = c[0];
247  break;
248  }
249  case Atom::CODE_VL_PTR:
250  switch (code_[(*this)[0].asIndex()].getDescriptor()) {
251  case Atom::PROD_PTR:
252  addReference(destination, write_index, ((InputLessPGMOverlay *)overlay_)->productions_[code_[(*this)[0].asIndex()].asIndex()]);
253  break;
254  case Atom::I_PTR:
255  if (code_[code_[(*this)[0].asIndex()].asIndex()].getDescriptor() == Atom::IN_OBJ_PTR)
256  addReference(destination, write_index, ((PGMOverlay *)overlay_)->getInputObject(code_[code_[(*this)[0].asIndex()].asIndex()].asInputIndex()));
257  else
258  dereference().copy_member(destination, write_index, extent_index, dereference_cptr, pgm_index);
259  break;
260  case Atom::OUT_OBJ_PTR:
261  destination->code(write_index) = Atom::CodeVLPointer(code_[(*this)[0].asIndex()].asIndex());
262  break;
263  case Atom::IN_OBJ_PTR:
264  case Atom::D_IN_OBJ_PTR: {
265 
266  IPGMContext c = dereference();
267  if (c.index_ == 0)
268  addReference(destination, write_index, c.object_);
269  else if (c[0].isStructural()) {
270 
271  destination->code(write_index++) = Atom::IPointer(extent_index);
272  c.copy_structure(destination, extent_index, extent_index, dereference_cptr, pgm_index);
273  } else
274  c.copy_member(destination, write_index, extent_index, dereference_cptr, pgm_index);
275  break;
276  }default:
277  dereference().copy_member(destination, write_index, extent_index, dereference_cptr, pgm_index);
278  break;
279  }
280  break;
281  case Atom::R_PTR:
282  addReference(destination, write_index, object_->get_reference((*this)[0].asIndex()));
283  break;
284  case Atom::PROD_PTR:
285  addReference(destination, write_index, ((InputLessPGMOverlay *)overlay_)->productions_[(*this)[0].asIndex()]);
286  break;
287  case Atom::IN_OBJ_PTR:
288  addReference(destination, write_index, ((PGMOverlay *)overlay_)->getInputObject((*this)[0].asIndex()));
289  break;
290  case Atom::D_IN_OBJ_PTR: {
291  IPGMContext c = dereference();
292  addReference(destination, write_index, c.object_);
293  break;
294  }case Atom::OPERATOR:
295  case Atom::OBJECT:
296  case Atom::MARKER:
297  case Atom::INSTANTIATED_PROGRAM:
298  case Atom::INSTANTIATED_CPP_PROGRAM:
299  case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
300  case Atom::INSTANTIATED_ANTI_PROGRAM:
301  case Atom::COMPOSITE_STATE:
302  case Atom::MODEL:
303  case Atom::GROUP:
304  case Atom::SET:
305  case Atom::S_SET:
306  case Atom::TIMESTAMP:
307  case Atom::DURATION:
308  case Atom::STRING:
309  destination->code(write_index) = Atom::IPointer(extent_index);
310  if (pgm_index > 0 && index_ > pgm_index && data_ == STEM)
311  patch_code(index_, Atom::OutObjPointer(write_index));
312  copy_structure(destination, extent_index, extent_index, dereference_cptr, pgm_index);
313  break;
314  case Atom::T_WILDCARD:
315  destination->code(write_index) = (*this)[0];
316  break;
317  default:
318  destination->code(write_index) = (*this)[0];
319  if (pgm_index > 0 && index_ > pgm_index && data_ == STEM)
320  patch_code(index_, Atom::OutObjPointer(write_index));
321  break;
322  }
323  }
324 
325  void copy_structure_to_value_array(bool prefix, uint16 write_index, uint16 &extent_index, bool dereference_cptr);
326  void copy_member_to_value_array(uint16 child_index, bool prefix, uint16 write_index, uint16 &extent_index, bool dereference_cptr);
327 public:
328  static IPGMContext GetContextFromInput(View *input, InputLessPGMOverlay *overlay) { return IPGMContext(input->object_, input, &input->object_->code(0), 0, overlay, REFERENCE); }
329 
330  IPGMContext() : _Context(NULL, 0, NULL, UNDEFINED), object_(NULL), view_(NULL) {} // undefined context (happens when accessing the view of an object when it has not been provided).
331  IPGMContext(r_code::Code *object, View *view, Atom *code, uint16 index, InputLessPGMOverlay *const overlay, Data data = STEM) : _Context(code, index, overlay, data), object_(object), view_(view) {}
332  IPGMContext(r_code::Code *object, uint16 index) : _Context(&object->code(0), index, NULL, REFERENCE), object_(object), view_(NULL) {}
333  IPGMContext(r_code::Code *object, Data data) : _Context(&object->code(0), index_, NULL, data), object_(object), view_(NULL) {}
334 
335  // _Context implementation.
336  _Context *clone() override { return new IPGMContext(*this); }
337 
338  bool equal(const _Context *c) const override { return *this == *(IPGMContext *)c; }
339 
340  Atom &get_atom(uint16 i) const override { return this->operator [](i); }
341 
342  uint16 get_object_code_size() const override { return object_->code_size(); }
343 
344  uint16 get_children_count() const override {
345 
346  uint16 c;
347  switch (data_) {
348  case MKS:
349  object_->acq_markers();
350  c = object_->markers_.size();
351  object_->rel_markers();
352  return c;
353  case VWS:
354  object_->acq_views();
355  c = object_->views_.size();
356  object_->rel_views();
357  return c;
358  default:
359  return code_[index_].getAtomCount();
360  }
361  }
362 
366  _Context *get_child_new(uint16 index) const override {
367 
368  IPGMContext *_c = new IPGMContext(get_child(index));
369  return _c;
370  }
371 
375  _Context *dereference_new() const override {
376 
377  IPGMContext *_c = new IPGMContext(dereference());
378  return _c;
379  }
380 
381  // IPGM specifics.
382  bool evaluate() const;
383  bool evaluate_no_dereference() const;
384 
385  IPGMContext &operator =(const IPGMContext &c) {
386 
387  object_ = c.object_;
388  view_ = c.view_;
389  code_ = c.code_;
390  index_ = c.index_;
391  data_ = c.data_;
392  return *this;
393  }
394 
395  bool operator ==(const IPGMContext &c) const;
396  bool operator !=(const IPGMContext &c) const;
397 
398  IPGMContext get_child(uint16 index) const {
399 
400  switch (data_) {
401  case STEM:
402  return IPGMContext(object_, view_, code_, index_ + index, (InputLessPGMOverlay *)overlay_, STEM);
403  case REFERENCE:
404  return IPGMContext(object_, view_, code_, index_ + index, (InputLessPGMOverlay *)overlay_, REFERENCE);
405  case VIEW:
406  return IPGMContext(object_, view_, code_, index_ + index, NULL, VIEW);
407  case MKS: {
408 
409  uint16 i = 0;
411  object_->acq_markers();
412  for (m = object_->markers_.begin(); i < index - 1; ++i, ++m) {
413 
414  if (m == object_->markers_.end()) { // happens when the list has changed after the call to get_children_count.
415 
416  object_->rel_markers();
417  return IPGMContext();
418  }
419  }
420  object_->rel_markers();
421  return IPGMContext(*m, 0);
422  }case VWS: {
423 
424  uint16 i = 0;
425  std::unordered_set<r_code::_View *, r_code::_View::Hash, r_code::_View::Equal>::const_iterator v;
426  object_->acq_views();
427  for (v = object_->views_.begin(); i < index - 1; ++i, ++v) {
428 
429  if (v == object_->views_.end()) { // happens when the list has changed after the call to get_children_count.
430 
431  object_->rel_views();
432  return IPGMContext();
433  }
434  }
435  object_->rel_views();
436  return IPGMContext(object_, (r_exec::View*)*v, &(*v)->code(0), index_ + index, NULL, VIEW);
437  }case VALUE_ARRAY:
438  return IPGMContext(object_, view_, code_, index_ + index, (InputLessPGMOverlay *)overlay_, VALUE_ARRAY);
439  default: // undefined context.
440  return IPGMContext();
441  }
442  }
443 
447  IPGMContext get_child_deref(uint16 index) const {
448  return get_child(index).dereference();
449  }
450 
451  Atom &operator [](uint16 i) const { return code_[index_ + i]; }
452  r_code::Code *get_object() const { return object_; }
453  uint16 getIndex() const { return index_; }
454 
455  IPGMContext dereference() const;
456  void dereference_once();
457 
458  bool is_reference() const { return data_ == REFERENCE; }
459  bool is_undefined() const { return data_ == UNDEFINED; }
460 
461  void patch_input_code(uint16 pgm_code_index, uint16 input_index) const { ((InputLessPGMOverlay *)overlay_)->patch_input_code(pgm_code_index, input_index, 0); }
462 
463  uint16 addProduction(r_code::Code *object, bool check_for_existence) const; // if check_for_existence==false, the object is assumed not to be new.
464 
465  template<class C> void copy(C *destination, uint16 write_index) const {
466 
467  uint16 extent_index = 0;
468  copy_structure(destination, write_index, extent_index, true, -1);
469  }
470 
471  template<class C> void copy(C *destination, uint16 write_index, uint16 &extent_index) const {
472 
473  copy_structure(destination, write_index, extent_index, true, -1);
474  }
475 
476  void copy_to_value_array(uint16 &position);
477 
478  typedef enum {
479  TYPE_OBJECT = 0,
480  TYPE_VIEW = 1,
481  TYPE_GROUP = 2,
482  TYPE_UNDEFINED = 3
483  }ObjectType;
484 
485  // To retrieve objects, groups and views in mod/set expressions; views are copied.
486  void getMember(void *&object, uint32 &view_oid, ObjectType &object_type, int16 &member_index) const;
487 
488  // 'this' is a context on a pattern skeleton.
489  bool match(const IPGMContext &input) const;
490 
491  // called by operators.
492  r_code::Code *build_object(Atom head) const { return overlay_->build_object(head); }
493 
494  // Implementation of executive-dependent operators.
495  static bool Ins(const IPGMContext &context);
496  static bool Fvw(const IPGMContext &context);
497  static bool Red(const IPGMContext &context);
498 };
499 }
500 
501 
502 #endif
r_code::list::const_iterator
Definition: list.h:266
r_exec::IPGMContext
Definition: context.h:102
r_exec::IPGMContext::get_child_deref
IPGMContext get_child_deref(uint16 index) const
Definition: context.h:447
r_code::Atom
Definition: atom.h:104
r_exec::IPGMContext::get_child_new
_Context * get_child_new(uint16 index) const override
Definition: context.h:366
r_code::Code
Definition: r_code/object.h:224
r_exec::IPGMContext::dereference_new
_Context * dereference_new() const override
Definition: context.h:375
r_exec::View
Definition: view.h:102
r_exec::PGMOverlay
Definition: pgm_overlay.h:136
r_exec::_Context
Definition: _context.h:96
r_exec::InputLessPGMOverlay
Definition: pgm_overlay.h:100