AERA
atom.cpp
1 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
2 //_/_/
3 //_/_/ AERA
4 //_/_/ Autocatalytic Endogenous Reflective Architecture
5 //_/_/
6 //_/_/ Copyright (c) 2018-2023 Jeff Thompson
7 //_/_/ Copyright (c) 2018-2023 Kristinn R. Thorisson
8 //_/_/ Copyright (c) 2018-2023 Icelandic Institute for Intelligent Machines
9 //_/_/ http://www.iiim.is
10 //_/_/
11 //_/_/ Copyright (c) 2010-2012 Eric Nivel
12 //_/_/ Copyright (c) 2010 Nathaniel Thurston
13 //_/_/ Center for Analysis and Design of Intelligent Agents
14 //_/_/ Reykjavik University, Menntavegur 1, 102 Reykjavik, Iceland
15 //_/_/ http://cadia.ru.is
16 //_/_/
17 //_/_/ Part of this software was developed by Eric Nivel
18 //_/_/ in the HUMANOBS EU research project, which included
19 //_/_/ the following parties:
20 //_/_/
21 //_/_/ Autonomous Systems Laboratory
22 //_/_/ Technical University of Madrid, Spain
23 //_/_/ http://www.aslab.org/
24 //_/_/
25 //_/_/ Communicative Machines
26 //_/_/ Edinburgh, United Kingdom
27 //_/_/ http://www.cmlabs.com/
28 //_/_/
29 //_/_/ Istituto Dalle Molle di Studi sull'Intelligenza Artificiale
30 //_/_/ University of Lugano and SUPSI, Switzerland
31 //_/_/ http://www.idsia.ch/
32 //_/_/
33 //_/_/ Institute of Cognitive Sciences and Technologies
34 //_/_/ Consiglio Nazionale delle Ricerche, Italy
35 //_/_/ http://www.istc.cnr.it/
36 //_/_/
37 //_/_/ Dipartimento di Ingegneria Informatica
38 //_/_/ University of Palermo, Italy
39 //_/_/ http://diid.unipa.it/roboticslab/
40 //_/_/
41 //_/_/
42 //_/_/ --- HUMANOBS Open-Source BSD License, with CADIA Clause v 1.0 ---
43 //_/_/
44 //_/_/ Redistribution and use in source and binary forms, with or without
45 //_/_/ modification, is permitted provided that the following conditions
46 //_/_/ are met:
47 //_/_/ - Redistributions of source code must retain the above copyright
48 //_/_/ and collaboration notice, this list of conditions and the
49 //_/_/ following disclaimer.
50 //_/_/ - Redistributions in binary form must reproduce the above copyright
51 //_/_/ notice, this list of conditions and the following disclaimer
52 //_/_/ in the documentation and/or other materials provided with
53 //_/_/ the distribution.
54 //_/_/
55 //_/_/ - Neither the name of its copyright holders nor the names of its
56 //_/_/ contributors may be used to endorse or promote products
57 //_/_/ derived from this software without specific prior
58 //_/_/ written permission.
59 //_/_/
60 //_/_/ - CADIA Clause: The license granted in and to the software
61 //_/_/ under this agreement is a limited-use license.
62 //_/_/ The software may not be used in furtherance of:
63 //_/_/ (i) intentionally causing bodily injury or severe emotional
64 //_/_/ distress to any person;
65 //_/_/ (ii) invading the personal privacy or violating the human
66 //_/_/ rights of any person; or
67 //_/_/ (iii) committing or preparing for any act of war.
68 //_/_/
69 //_/_/ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
70 //_/_/ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
71 //_/_/ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
72 //_/_/ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
73 //_/_/ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
74 //_/_/ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
75 //_/_/ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
76 //_/_/ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
77 //_/_/ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 //_/_/ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
79 //_/_/ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
80 //_/_/ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
81 //_/_/ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
82 //_/_/ OF SUCH DAMAGE.
83 //_/_/
84 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
85 
86 #include "utils.h"
87 #include "atom.h"
88 
89 #include <iostream>
90 
91 using namespace std;
92 using namespace std::chrono;
93 
94 namespace r_code {
95 
96 Atom::TraceContext::TraceContext() {
97  members_to_go_ = 0;
98  timestamp_data_ = 0;
99  duration_data_ = 0;
100  string_data_ = 0;
101  char_count_ = 0;
102 }
103 
104 void Atom::trace(TraceContext& context, std::ostream& out) const {
105 
106  context.write_indents(out);
107  if (context.timestamp_data_) {
108  // Output the timestamp value now. Otherwise, it could be interpreted
109  // as an op code, etc.
110  --context.timestamp_data_;
111  out << atom_;
112 
113  if (context.timestamp_data_ == 1)
114  // Save for the next step.
115  context.int64_high_ = atom_;
116  else {
117  // Imitate Utils::GetTimestamp.
118  auto timestamp = core::Timestamp(microseconds(context.int64_high_ << 32 | atom_));
119  out << " " << Utils::RelativeTime(timestamp);
120  }
121  return;
122  }
123  if (context.duration_data_) {
124  // Output the duration value now. Otherwise, it could be interpreted as an op code, etc.
125  --context.duration_data_;
126  out << atom_;
127 
128  if (context.duration_data_ == 1)
129  // Save for the next step.
130  context.int64_high_ = atom_;
131  else {
132  // Imitate Utils::GetDuration.
133  auto duration = microseconds(context.int64_high_ << 32 | atom_);
134  out << " " << Utils::ToString_us(duration);
135  }
136  return;
137  }
138 
139  switch (getDescriptor()) {
140  case NIL: out << "nil"; return;
141  case BOOLEAN_: out << "bl: " << std::boolalpha << asBoolean(); return;
142  case WILDCARD: out << ":"; return;
143  case T_WILDCARD: out << "::"; return;
144  case I_PTR: out << "iptr: " << std::dec << asIndex(); return;
145  case VL_PTR: out << "vlptr: " << std::dec << asIndex(); return;
146  case R_PTR: out << "rptr: " << std::dec << asIndex(); return;
147  case IPGM_PTR: out << "ipgm_ptr: " << std::dec << asIndex(); return;
148  case IN_OBJ_PTR: out << "in_obj_ptr: " << std::dec << (uint32)asInputIndex() << " " << asIndex(); return;
149  case D_IN_OBJ_PTR: out << "d_in_obj_ptr: " << std::dec << (uint32)asRelativeIndex() << " " << asIndex(); return;
150  case OUT_OBJ_PTR: out << "out_obj_ptr: " << std::dec << asIndex(); return;
151  case VALUE_PTR: out << "value_ptr: " << std::dec << asIndex(); return;
152  case PROD_PTR: out << "prod_ptr: " << std::dec << asIndex(); return;
153  case ASSIGN_PTR: out << "assign_ptr: " << std::dec << (uint16)asAssignmentIndex() << " " << asIndex(); return;
154  case CODE_VL_PTR: out << "code_vlptr: " << std::dec << asIndex(); return;
155  case THIS: out << "this"; return;
156  case VIEW: out << "view"; return;
157  case MKS: out << "mks"; return;
158  case VWS: out << "vws"; return;
159  case NODE: out << "nid: " << std::dec << (uint32)getNodeID(); return;
160  case DEVICE: out << "did: " << std::dec << (uint32)getNodeID() << " " << (uint32)getClassID() << " " << (uint32)getDeviceID(); return;
161  case DEVICE_FUNCTION: out << "fid: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ")"; return;
162  case C_PTR: out << "cptr: " << std::dec << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
163  case SET: out << "set: " << std::dec << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
164  case OBJECT: out << "obj: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
165  case S_SET: out << "s_set: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
166  case MARKER: out << "mk: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
167  case OPERATOR: out << "op: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
168  case STRING: out << "st: " << std::dec << (uint16)getAtomCount() << " " << (atom_ & 0x000000FF); context.members_to_go_ = context.string_data_ = getAtomCount(); context.char_count_ = (atom_ & 0x000000FF); return;
169  case TIMESTAMP: out << "ts"; context.members_to_go_ = context.timestamp_data_ = 2; return;
170  case DURATION: out << "us"; context.members_to_go_ = context.duration_data_ = 2; return;
171  case GROUP: out << "grp: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
172  case INSTANTIATED_PROGRAM:
173  case INSTANTIATED_ANTI_PROGRAM:
174  case INSTANTIATED_INPUT_LESS_PROGRAM:
175  out << "ipgm: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
176  case COMPOSITE_STATE: out << "cst: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
177  case MODEL: out << "mdl: " << std::dec << asOpcode() << " (" << GetOpcodeName(asOpcode()).c_str() << ") " << (uint16)getAtomCount(); context.members_to_go_ = getAtomCount(); return;
178  case NULL_PROGRAM: out << "null pgm " << takesPastInputs() ? "all inputs" : "new inputs"; return;
179  default:
180  if (context.string_data_) {
181 
182  --context.string_data_;
183  std::string s;
184  char *content = (char *)&atom_;
185  for (uint8 i = 0; i < 4; ++i) {
186 
187  if (context.char_count_-- > 0)
188  s += content[i];
189  else
190  break;
191  }
192  out << s.c_str();
193  } else if (isFloat()) {
194 
195  out << "nb: " << std::scientific << asFloat() << std::defaultfloat;
196  } else
197  out << "undef";
198  return;
199  }
200 }
201 
202 void Atom::TraceContext::write_indents(std::ostream& out) {
203 
204  if (members_to_go_) {
205 
206  out << " ";
207  --members_to_go_;
208  }
209 }
210 
211 // These are filled by r_exec::Init().
212 unordered_map<uint16, set<string>> OpcodeNames;
213 
214 string GetOpcodeName(uint16 opcode) {
215  unordered_map<uint16, set<string>>::iterator names =
216  OpcodeNames.find(opcode);
217  if (names == OpcodeNames.end())
218  return "unknown";
219 
220  string result;
221  for (set<string>::iterator it = names->second.begin();
222  it != names->second.end(); ++it) {
223  if (result.size() != 0)
224  result += "/";
225  result += *it;
226  }
227 
228  return result;
229 }
230 
231 bool SetOpcodeNames(const std::unordered_map<uint16, std::set<std::string>>& opcode_names) {
232  if (OpcodeNames.size() > 0)
233  // GetOpcodeName has already been using a set of opcodes. The new codes could be inconsistent. Fail.
234  return false;
235 
236  OpcodeNames = opcode_names;
237  return true;
238 }
239 
240 }