AERA
compiler.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 //_/_/ 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 "compiler.h"
87 #include <string.h>
88 
89 using namespace std;
90 using namespace r_code;
91 
92 namespace r_comp {
93 
94 static bool Output = true;
95 
96 static inline bool is_decimal(char c) { return c >= '0' && c <= '9'; }
97 
98 Compiler::Compiler(bool allow_variables_and_wildcards_outside_pattern_skeleton)
99 : out_stream_(NULL), current_object_(NULL), error_(std::string("")),
100  allow_variables_and_wildcards_outside_pattern_skeleton_(allow_variables_and_wildcards_outside_pattern_skeleton)
101 {
102 }
103 
104 Compiler::~Compiler() {
105 
106  if (out_stream_)
107  delete out_stream_;
108 }
109 
110 Compiler::State Compiler::save_state() {
111 
112  State s(this);
113  return s;
114 }
115 
116 void Compiler::restore_state(State s) {
117 
118  in_stream_->seekg(s.stream_ptr);
119  state_ = s;
120 }
121 
122 void Compiler::set_error(const std::string &s) {
123 
124  if (!err_ && Output) {
125 
126  err_ = true;
127  error_ = s;
128  }
129 }
130 
131 void Compiler::set_arity_error(uint16 expected, uint16 got) {
132 
133  set_error("error: got " + std::to_string(got) + " elements, expected " +
134  std::to_string(expected));
135 }
136 
138 
139 bool Compiler::compile(std::istream *stream, r_comp::Image *image, r_comp::Metadata *metadata, std::string &error, bool trace) {
140 
141  in_stream_ = stream;
142  err_ = false;
143  trace_ = trace;
144 
145  image_ = image;
146  metadata_ = metadata;
147  current_object_index_ = image->object_map_.objects_.size();
148  while (!in_stream_->eof()) {
149 
150  switch (in_stream_->peek()) {
151  case '!':
152  set_error("error: found preprocessor directive");
153  error = error_;
154  return false;
155  default:
156  if (in_stream_->eof())
157  return true;
158  if (!read_sys_object()) {
159 
160  error = error_;
161  return false;
162  }
163  current_object_index_++;
164  break;
165  }
166  char c = (char)in_stream_->get();
167  if (c != -1)
168  in_stream_->putback(c);
169  }
170 
171  return true;
172 }
173 
174 bool Compiler::read_sys_object() {
175 
176  local_references_.clear();
177  hlp_references_.clear();
178  bool indented = false;
179  bool lbl = false;
180 
181  current_view_index_ = -1;
182 
183  std::string l;
184  while (indent(false));
185  char c = (char)in_stream_->get();
186  if (c != -1)
187  in_stream_->putback(c);
188  else
189  return true;
190 
191  in_hlp_ = false;
192 
193  if (label(l))
194  lbl = true;
195  if (!expression_begin(indented)) {
196 
197  if (lbl)
198  set_error("error: label not followed by an expression");
199  else
200  set_error("syntax error: missing expression opening");
201  return false;
202  }
203  indent(false);
204 
205  if (!sys_object(current_class_)) {
206 
207  set_error("error: unknown class");
208  return false;
209  } else {
210 
211  if (current_class_.str_opcode == "mdl" || current_class_.str_opcode == "cst")
212  in_hlp_ = true;
213  current_object_ = new SysObject();
214  if (lbl) {
215  if (global_references_.find(l) != global_references_.end()) {
216  set_error("error: redefinition of label `" + l + "`");
217  return false;
218  }
219  global_references_[l] = Reference(image_->code_segment_.objects_.size(), current_class_, Class());
220  }
221  }
222 
223  current_object_->code_[0] = current_class_.atom_;
224  if (current_class_.atom_.getAtomCount()) {
225 
226  if (!right_indent(true)) {
227 
228  if (!separator(false)) {
229 
230  set_error("syntax error: missing separator/right_indent after head");
231  return false;
232  }
233  }
234  uint16 extent_index = current_class_.atom_.getAtomCount() + 1;
235  if (!expression_tail(indented, current_class_, 1, extent_index, true))
236  return false;
237  }
238 
239  SysObject *sys_object = (SysObject *)current_object_; // current_object_ will point to views_, if any.
240 
241  // compile view set
242  // input format:
243  // []
244  // [view-data]
245  // ...
246  // [view-data]
247  // or:
248  // |[]
249 
250  while (indent(false));
251  std::streampos i = in_stream_->tellg();
252  if (!match_symbol("|[]", false)) {
253 
254  in_stream_->seekg(i);
255  if (!set_begin(indented)) {
256 
257  set_error(" error: expected a view set");
258  return false;
259  }
260 
261  indent(false);
262 
263  if (current_class_.str_opcode == "grp")
264  current_class_ = metadata_->classes_.find("grp_view")->second;
265  else if (current_class_.str_opcode == "ipgm" ||
266  current_class_.str_opcode == "icpp_pgm" ||
267  current_class_.str_opcode == "mdl" ||
268  current_class_.str_opcode == "cst")
269  current_class_ = metadata_->classes_.find("pgm_view")->second;
270  else
271  current_class_ = metadata_->classes_.find("view")->second;
272  current_class_.use_as = StructureMember::I_CLASS;
273 
274  uint16 count = 0;
275  bool _indented = false;
276  while (!in_stream_->eof()) {
277 
278  current_object_ = new SysView();
279  current_view_index_ = count;
280  uint16 extent_index = 0;
281 
282  if (set_end(indented)) {
283 
284  if (!count) {
285 
286  set_error(" syntax error: use |[] for empty sets");
287  delete current_object_;
288  return false;
289  } else {
290 
291  delete current_object_;
292  break;
293  }
294  }
295  if (count) {
296 
297  if (!_indented) {
298 
299  if (!right_indent(true)) {
300 
301  if (!separator(false)) {
302 
303  set_error("syntax error: missing separator between 2 elements");
304  delete current_object_;
305  return false;
306  }
307  }
308  } else
309  _indented = false;
310  }
311  if (!read_set(_indented, true, &current_class_, 0, extent_index, true)) {
312 
313  set_error(" error: illegal element in set");
314  delete current_object_;
315  return false;
316  }
317  count++;
318  sys_object->views_.push_back((SysView *)current_object_);
319  }
320  }
321 
322  if (trace_)
323  sys_object->trace();
324 
325  image_->add_sys_object(sys_object, l);
326  return true;
327 }
328 
329 bool Compiler::read(const StructureMember &m, bool &indented, bool enforce, uint16 write_index, uint16 &extent_index, bool write) {
330 
331  if (Class *p = m.get_class(metadata_)) {
332 
333  p->use_as = m.getIteration();
334  return (this->*m.read())(indented, enforce, p, write_index, extent_index, write);
335  }
336  return (this->*m.read())(indented, enforce, NULL, write_index, extent_index, write);
337 }
338 
339 bool Compiler::getGlobalReferenceIndex(const std::string reference_name, const ReturnType t, ImageObject *object, uint16 &index, Class *&_class) {
340 
341  unordered_map<std::string, Reference>::iterator it = global_references_.find(reference_name);
342  if (it != global_references_.end() && (t == ANY || (t != ANY && it->second.class_.type == t))) {
343 
344  _class = &it->second.class_;
345  for (uint16 j = 0; j < object->references_.size(); ++j)
346  if (object->references_[j] == it->second.index_) { // the object has already been referenced.
347 
348  index = j; // rptr points to object->reference_set[j], which in turn points to it->second.index.
349  return true;
350  }
351  object->references_.push_back(it->second.index_); // add new reference to the object.
352  index = object->references_.size() - 1; // rptr points to the last element of object->reference_set, which in turn points to it->second.index.
353  return true;
354  }
355  return false;
356 }
357 
358 void Compiler::addLocalReference(const std::string reference_name, const uint16 index, const Class &p) {
359 
360  // cast detection.
361  size_t pos = reference_name.find('#');
362  if (pos != string::npos) {
363 
364  std::string class_name = reference_name.substr(pos + 1);
365  std::string ref_name = reference_name.substr(0, pos);
366 
367  unordered_map<std::string, Class>::iterator it = metadata_->classes_.find(class_name);
368  if (it != metadata_->classes_.end())
369  local_references_[ref_name] = Reference(index, p, it->second);
370  else
371  set_error(" error: cast to " + class_name + ": unknown class");
372  } else
373  local_references_[reference_name] = Reference(index, p, Class());
374 }
375 
376 uint8 Compiler::add_hlp_reference(std::string reference_name) {
377 
378  for (uint8 i = 0; i < hlp_references_.size(); ++i)
379  if (reference_name == hlp_references_[i])
380  return i;
381  hlp_references_.push_back(reference_name);
382  return hlp_references_.size() - 1;
383 }
384 
385 uint8 Compiler::get_hlp_reference(std::string reference_name) {
386 
387  for (uint8 i = 0; i < hlp_references_.size(); ++i)
388  if (reference_name == hlp_references_[i])
389  return i;
390  return 0xFF;
391 }
392 
394 
395 bool Compiler::comment() {
396 
397  std::streampos i = in_stream_->tellg();
398  bool started = false;
399  bool continuation = false; // continuation mark detected
400  bool period = false; // to detect 2 subsequent '.'
401  while (!in_stream_->eof()) {
402 
403  switch (char c = (char)in_stream_->get()) {
404  case ';':
405  if (!started)
406  started = true;
407  break;
408  case '.':
409  if (!started)
410  goto return_false;
411  if (continuation) {
412 
413  set_error(" syntax error: ...");
414  goto return_false;
415  }
416  if (period)
417  continuation = true;
418  period = true;
419  break;
420  case NEWLINE:
421  if (!continuation) {
422 
423  in_stream_->putback(c);
424  return true;
425  }
426  continuation = period = false;
427  break;
428  default:
429  if (!started)
430  goto return_false;
431  period = false;
432  break;
433  }
434  }
435 return_false:
436  in_stream_->seekg(i);
437  in_stream_->clear();
438  return false;
439 }
440 
441 bool Compiler::indent(bool pushback) {
442 
443  comment();
444  std::string s;
445  s += NEWLINE;
446  for (uint16 j = 0; j < 3 * state_.indents; j++)
447  s += ' ';
448  return match_symbol(s.c_str(), pushback);
449 }
450 
451 bool Compiler::right_indent(bool pushback) { // no look ahead when pushback==true
452 
453  comment();
454  if (pushback) {
455 
456  if (state_.right_indents_ahead)
457  return true;
458  std::string s;
459  s += NEWLINE;
460  for (uint16 j = 0; j < 3 * (state_.indents + 1); j++)
461  s += ' ';
462  return match_symbol(s.c_str(), true);
463  }
464  if (state_.right_indents_ahead) {
465 
466  state_.indents++;
467  state_.right_indents_ahead--;
468  return true;
469  }
470  std::string s;
471  s += NEWLINE;
472  for (uint16 j = 0; j < 3 * (state_.indents + 1); j++)
473  s += ' ';
474  if (!match_symbol(s.c_str(), false))
475  return false;
476  state_.indents++;
477  s = " ";
478  while (match_symbol(s.c_str(), false)) // look ahead for more indents
479  state_.right_indents_ahead++;
480  return true;
481 }
482 
483 bool Compiler::left_indent(bool pushback) { // no look ahead when pushback==true
484 
485  comment();
486  if (indent(true))
487  return false;
488  if (pushback) {
489 
490  if (state_.left_indents_ahead)
491  return true;
492  std::string s;
493  s += NEWLINE;
494  for (uint16 j = 0; j < 3 * (state_.indents - 1); j++)
495  s += ' ';
496  return match_symbol(s.c_str(), true);
497  }
498  if (state_.left_indents_ahead) {
499 
500  if (state_.indents)
501  state_.indents--;
502  state_.left_indents_ahead--;
503  return true;
504  }
505  std::string s;
506  s += NEWLINE;
507  if (!match_symbol(s.c_str(), false))
508  return false;
509  uint16 expected = state_.indents - 1;
510  if (expected <= 0) {
511 
512  if (state_.indents)
513  state_.indents--;
514  return true;
515  }
516  state_.left_indents_ahead = expected; // look ahead for more indents
517  s = " ";
518  for (uint16 j = 0; j < expected; j++) {
519 
520  if (match_symbol(s.c_str(), false))
521  state_.left_indents_ahead--;
522  }
523  if (state_.indents)
524  state_.indents--;
525  return true;
526 }
527 
528 bool Compiler::separator(bool pushback) {
529 
530  if (indent(pushback))
531  return true;
532  char c = (char)in_stream_->get();
533  if (c == ' ') {
534 
535  if (pushback)
536  in_stream_->putback(c);
537  return true;
538  }
539  in_stream_->clear();
540  in_stream_->putback(c);
541  return false;
542 }
543 
544 bool Compiler::symbol_expr(std::string &s) {
545 
546  std::streampos i = in_stream_->tellg();
547  uint16 count = 0;
548  while (!in_stream_->eof()) {
549 
550  switch (char c = (char)in_stream_->get()) {
551  case ':':
552  case ' ':
553  case NEWLINE:
554  case ';':
555  case ')':
556  if (count) {
557 
558  in_stream_->putback(c);
559  return true;
560  }
561  case '(':
562  case '[':
563  case ']':
564  case '\"':
565  case '.':
566  if (s == "mk") {
567 
568  s += '.';
569  break;
570  }
571  in_stream_->seekg(i);
572  return false;
573  default:
574  count++;
575  s += c;
576  break;
577  }
578  }
579  in_stream_->clear();
580  in_stream_->seekg(i);
581  return false;
582 }
583 
584 bool Compiler::symbol_expr_set(std::string &s) {
585 
586  std::streampos i = in_stream_->tellg();
587  uint16 count = 0;
588  while (!in_stream_->eof()) {
589 
590  switch (char c = (char)in_stream_->get()) {
591  case ' ':
592  case NEWLINE:
593  case ';':
594  case ')':
595  case ']':
596  if (count) {
597 
598  in_stream_->putback(c);
599  return true;
600  }
601  case '(':
602  case '[':
603  case '.':
604  case ':':
605  in_stream_->seekg(i);
606  return false;
607  default:
608  count++;
609  s += c;
610  break;
611  }
612  }
613  in_stream_->clear();
614  in_stream_->seekg(i);
615  return false;
616 }
617 
618 bool Compiler::match_symbol_separator(const char *symbol, bool pushback) {
619 
620  if (match_symbol(symbol, pushback)) {
621 
622  if (separator(true) || right_indent(true) || left_indent(true))
623  return true;
624  char c = (char)in_stream_->peek();
625  if (c == ')' || c == ']')
626  return true;
627  }
628  return false;
629 }
630 
631 bool Compiler::match_symbol(const char *symbol, bool pushback) {
632 
633  std::streampos i = in_stream_->tellg();
634  for (uint32 j = 0; j < strlen(symbol); j++) {
635 
636  if (in_stream_->eof() || ((char)in_stream_->get()) != symbol[j]) {
637 
638  in_stream_->clear();
639  in_stream_->seekg(i);
640  return false;
641  }
642  }
643  if (pushback)
644  in_stream_->seekg(i);
645  return true;
646 }
647 
648 bool Compiler::member(std::string &s) {
649 
650  std::streampos i = in_stream_->tellg();
651  s = "";
652  uint16 count = 0;
653  while (!in_stream_->eof()) {
654 
655  switch (char c = (char)in_stream_->get()) {
656  case ' ':
657  case NEWLINE:
658  case ';':
659  case ')':
660  case ']':
661  case '.':
662  if (count) {
663 
664  in_stream_->putback(c);
665  return true;
666  }
667  case '(':
668  case '[':
669  case ':':
670  in_stream_->seekg(i);
671  return false;
672  default:
673  count++;
674  s += c;
675  break;
676  }
677  }
678  in_stream_->clear();
679  in_stream_->seekg(i);
680  return false;
681 }
682 
683 bool Compiler::expression_begin(bool &indented) {
684 
685  if (right_indent(false)) {
686 
687  indented = true;
688  return true;
689  }
690  std::streampos i = in_stream_->tellg();
691  if (indent(false)) {
692 
693  char c = (char)in_stream_->get();
694  if (c == '(')
695  return true;
696  in_stream_->clear();
697  }
698  in_stream_->seekg(i);
699  char c = (char)in_stream_->get();
700  if (c == '(')
701  return true;
702  in_stream_->clear();
703  in_stream_->putback(c);
704  return false;
705 }
706 
707 bool Compiler::expression_end(bool indented) {
708 
709  if (indented)
710  return left_indent(false);
711  std::streampos i = in_stream_->tellg();
712  if (indent(false)) {
713 
714  char c = (char)in_stream_->get();
715  if (c == ')')
716  return true;
717  in_stream_->clear();
718  }
719  in_stream_->seekg(i);
720  char c = (char)in_stream_->get();
721  if (c == ')')
722  return true;
723  in_stream_->clear();
724  in_stream_->putback(c);
725  return false;
726 }
727 
728 bool Compiler::set_begin(bool &indented) {
729 
730  std::streampos i = in_stream_->tellg();
731  if (match_symbol("[]", false)) {
732 
733  if (right_indent(false)) {
734 
735  indented = true;
736  return true;
737  } else {
738 
739  set_error(" syntax error: [] not followed by indent");
740  return false;
741  }
742  }
743  in_stream_->seekg(i);
744  if (indent(false)) {
745 
746  char c = (char)in_stream_->get();
747  if (c == '[')
748  return true;
749  in_stream_->clear();
750  }
751  in_stream_->seekg(i);
752  char c = (char)in_stream_->get();
753  if (c == '[')
754  return true;
755  in_stream_->clear();
756  in_stream_->putback(c);
757  return false;
758 }
759 
760 bool Compiler::set_end(bool indented) {
761 
762  if (indented)
763  return left_indent(false);
764  std::streampos i = in_stream_->tellg();
765  if (indent(false)) {
766 
767  char c = (char)in_stream_->get();
768  if (c == ']')
769  return true;
770  in_stream_->clear();
771  }
772  in_stream_->seekg(i);
773  char c = (char)in_stream_->get();
774  if (c == ']')
775  return true;
776  in_stream_->clear();
777  in_stream_->putback(c);
778  return false;
779 }
780 
782 
783 bool Compiler::nil() {
784 
785  std::streampos i = in_stream_->tellg();
786  if (match_symbol_separator("nil", false))
787  return true;
788  in_stream_->clear();
789  in_stream_->seekg(i);
790  return false;
791 }
792 
793 bool Compiler::nil_nb() {
794 
795  std::streampos i = in_stream_->tellg();
796  if (match_symbol_separator("|nb", false))
797  return true;
798  in_stream_->clear();
799  in_stream_->seekg(i);
800  return false;
801 }
802 
803 bool Compiler::nil_ts() {
804 
805  std::streampos i = in_stream_->tellg();
806  if (match_symbol_separator("|ts", false))
807  return true;
808  in_stream_->clear();
809  in_stream_->seekg(i);
810  return false;
811 }
812 
813 bool Compiler::forever() {
814 
815  std::streampos i = in_stream_->tellg();
816  if (match_symbol_separator("forever", false))
817  return true;
818  in_stream_->clear();
819  in_stream_->seekg(i);
820  return false;
821 }
822 
823 bool Compiler::nil_nid() {
824 
825  std::streampos i = in_stream_->tellg();
826  if (match_symbol_separator("|nid", false))
827  return true;
828  in_stream_->clear();
829  in_stream_->seekg(i);
830  return false;
831 }
832 
833 bool Compiler::nil_did() {
834 
835  std::streampos i = in_stream_->tellg();
836  if (match_symbol_separator("|did", false))
837  return true;
838  in_stream_->clear();
839  in_stream_->seekg(i);
840  return false;
841 }
842 
843 bool Compiler::nil_fid() {
844 
845  std::streampos i = in_stream_->tellg();
846  if (match_symbol_separator("|fid", false))
847  return true;
848  in_stream_->clear();
849  in_stream_->seekg(i);
850  return false;
851 }
852 
853 bool Compiler::nil_bl() {
854 
855  std::streampos i = in_stream_->tellg();
856  if (match_symbol_separator("|bl", false))
857  return true;
858  in_stream_->clear();
859  in_stream_->seekg(i);
860  return false;
861 }
862 
863 bool Compiler::nil_st() {
864 
865  std::streampos i = in_stream_->tellg();
866  if (match_symbol_separator("|st", false))
867  return true;
868  in_stream_->clear();
869  in_stream_->seekg(i);
870  return false;
871 }
872 
873 bool Compiler::label(std::string &l) {
874 
875  std::streampos i = in_stream_->tellg();
876  if (symbol_expr(l) && l[0] != '-' && !is_decimal(l[0]) && (char)in_stream_->get() == ':')
877  return true;
878  in_stream_->clear();
879  in_stream_->seekg(i);
880  return false;
881 }
882 
883 bool Compiler::variable(std::string &l) {
884 
885  std::streampos i = in_stream_->tellg();
886  if (symbol_expr(l) && !is_decimal(l[0]) && (char)in_stream_->get() == ':') {
887 
888  in_stream_->seekg(i);
889  std::string _l = l + ':';
890  if (match_symbol_separator(_l.c_str(), false))
891  return true;
892  }
893  in_stream_->clear();
894  in_stream_->seekg(i);
895  return false;
896 }
897 
898 bool Compiler::this_() {
899 
900  std::streampos i = in_stream_->tellg();
901  if (match_symbol_separator("this", false))
902  return true;
903  in_stream_->clear();
904  in_stream_->seekg(i);
905  return false;
906 }
907 
908 bool Compiler::local_reference(uint16 &index, const ReturnType t) {
909 
910  std::streampos i = in_stream_->tellg();
911  std::string r;
912  if (symbol_expr_set(r)) {
913 
914  unordered_map<std::string, Reference>::iterator it = local_references_.find(r);
915  if (it != local_references_.end() && (t == ANY || it->second.class_.type == ANY || (t != ANY && it->second.class_.type == t))) {
916 
917  index = it->second.index_;
918  return true;
919  }
920  }
921  in_stream_->clear();
922  in_stream_->seekg(i);
923  return false;
924 }
925 
926 bool Compiler::global_reference(uint16 &index, const ReturnType t) {
927 
928  std::streampos i = in_stream_->tellg();
929  std::string r;
930  if (symbol_expr_set(r)) {
931 
932  Class *unused;
933  if (getGlobalReferenceIndex(r, t, current_object_, index, unused))
934  return true;
935  }
936  in_stream_->clear();
937  in_stream_->seekg(i);
938  return false;
939 }
940 
941 bool Compiler::hlp_reference(uint16 &index) {
942 
943  std::string r;
944  std::streampos i = in_stream_->tellg();
945  if (label(r)) {
946 
947  in_stream_->clear();
948  in_stream_->seekg(i);
949  return false;
950  }
951  r = "";
952  if (symbol_expr(r)) {
953 
954  for (uint8 i = 0; i < hlp_references_.size(); ++i)
955  if (r == hlp_references_[i]) {
956 
957  index = i;
958  return true;
959  }
960  }
961  in_stream_->clear();
962  in_stream_->seekg(i);
963  return false;
964 }
965 
966 bool Compiler::this_indirection(vector<int16> &v, const ReturnType t) {
967 
968  std::streampos i = in_stream_->tellg();
969  if (match_symbol("this.", false)) {
970 
971  Class *p; // in general, p starts as the current_class_; exception: in pgm, this refers to the instantiated program.
972  if (current_class_.str_opcode == "pgm")
973  p = &metadata_->sys_classes_["ipgm"];
974  Class *_p;
975  std::string m;
976  uint16 index;
977  ReturnType type;
978  while (member(m)) {
979 
980  if (m == "vw") {
981 
982  _p = &metadata_->classes_.find("pgm_view")->second;
983  type = ANY;
984  v.push_back(-1);
985  } else if (m == "mks") {
986 
987  _p = NULL;
988  type = SET;
989  v.push_back(-2);
990  } else if (m == "vws") {
991 
992  _p = NULL;
993  type = SET;
994  v.push_back(-3);
995  } else if (!p->get_member_index(metadata_, m, index, _p)) {
996 
997  set_error(" error: " + m + " is not a member of " + p->str_opcode);
998  break;
999  } else {
1000 
1001  type = p->get_member_type(index);
1002  v.push_back(index);
1003  }
1004 
1005  char c = (char)in_stream_->get();
1006  if (c == '.') {
1007 
1008  if (!_p) {
1009 
1010  set_error(" error: " + m + " is not a structure");
1011  break;
1012  }
1013  p = _p;
1014  } else {
1015 
1016  if (t == ANY || (t != ANY && type == t)) {
1017 
1018  in_stream_->putback(c);
1019  return true;
1020  }
1021  break;
1022  }
1023  }
1024  }
1025  in_stream_->clear();
1026  in_stream_->seekg(i);
1027  return false;
1028 }
1029 
1030 bool Compiler::local_indirection(vector<int16> &v, const ReturnType t, uint16 &cast_opcode) {
1031 
1032  std::streampos i = in_stream_->tellg();
1033  std::string m;
1034  std::string path = "";
1035  Class *p;
1036  if (member(m) && (char)in_stream_->get() == '.') { // first m is a reference to a label or a variable
1037 
1038  uint16 index;
1039  ReturnType type;
1040  unordered_map<std::string, Reference>::iterator it = local_references_.find(m);
1041  if (it != local_references_.end()) {
1042 
1043  index = it->second.index_;
1044  v.push_back(index);
1045  if (it->second.cast_class_.str_opcode == "undefined") { // find out if there was a cast for this reference.
1046 
1047  p = &it->second.class_;
1048  cast_opcode = 0x0FFF;
1049  } else {
1050 
1051  p = &it->second.cast_class_;
1052  cast_opcode = p->atom_.asOpcode();
1053  }
1054  Class *_p;
1055  while (member(m)) {
1056 
1057  if (m == "vw") {
1058 
1059  _p = &metadata_->classes_.find("pgm_view")->second;
1060  type = ANY;
1061  v.push_back(-1);
1062  } else if (m == "mks") {
1063 
1064  _p = NULL;
1065  type = SET;
1066  v.push_back(-2);
1067  } else if (m == "vws") {
1068 
1069  _p = NULL;
1070  type = SET;
1071  v.push_back(-3);
1072  } else if (!p->get_member_index(metadata_, m, index, _p)) {
1073 
1074  set_error(" error: " + m + " is not a member of " + p->str_opcode);
1075  break;
1076  } else {
1077 
1078  type = p->get_member_type(index);
1079  v.push_back(index);
1080  }
1081 
1082  path += '.';
1083  path += m;
1084  char c = (char)in_stream_->get();
1085  if (c == '.') {
1086 
1087  if (!_p) {
1088 
1089  set_error(" error: " + path + " is not an addressable structure");
1090  break;
1091  }
1092  p = _p;
1093  } else {
1094 
1095  if (t == ANY || (t != ANY && type == t)) {
1096 
1097  in_stream_->putback(c);
1098  return true;
1099  }
1100  break;
1101  }
1102  }
1103  }
1104  }
1105  in_stream_->clear();
1106  in_stream_->seekg(i);
1107  return false;
1108 }
1109 
1110 bool Compiler::global_indirection(vector<int16> &v, const ReturnType t) {
1111 
1112  std::streampos i = in_stream_->tellg();
1113  std::string m;
1114  Class *p;
1115  if (member(m) && (char)in_stream_->get() == '.') { // first m is a reference
1116 
1117  uint16 index;
1118  ReturnType type;
1119  if (getGlobalReferenceIndex(m, ANY, current_object_, index, p)) {
1120 
1121  v.push_back(index);
1122  Class *_p;
1123  bool first_member = true;
1124  while (member(m)) {
1125 
1126  if (m == "vw") {
1127 
1128  set_error(" error: vw is not accessible on global references");
1129  break;
1130  } else if (m == "mks") {
1131 
1132  _p = NULL;
1133  type = SET;
1134  v.push_back(-2);
1135  } else if (m == "vws") {
1136 
1137  _p = NULL;
1138  type = SET;
1139  v.push_back(-3);
1140  } else if (!p->get_member_index(metadata_, m, index, _p)) {
1141 
1142  set_error(" error: " + m + " is not a member of " + p->str_opcode);
1143  break;
1144  } else {
1145 
1146  type = p->get_member_type(index);
1147  if (first_member && index == 0) // indicates the first member; store in the RObject, after the leading atom, hence index=1.
1148  index = 1;
1149  v.push_back(index);
1150  }
1151 
1152  first_member = false;
1153 
1154  char c = (char)in_stream_->get();
1155  if (c == '.') {
1156 
1157  if (!_p) {
1158 
1159  set_error(" error: " + m + " is not a structure");
1160  break;
1161  }
1162  p = _p;
1163  } else {
1164 
1165  if (t == ANY || (t != ANY && type == t)) {
1166 
1167  in_stream_->putback(c);
1168  return true;
1169  }
1170  break;
1171  }
1172  }
1173  }
1174  }
1175  in_stream_->clear();
1176  in_stream_->seekg(i);
1177  return false;
1178 }
1179 
1180 bool Compiler::wildcard() {
1181 
1182  std::streampos i = in_stream_->tellg();
1183  if (match_symbol_separator(":", false))
1184  return true;
1185  in_stream_->clear();
1186  in_stream_->seekg(i);
1187  return false;
1188 }
1189 
1190 bool Compiler::tail_wildcard() {
1191 
1192  std::streampos i = in_stream_->tellg();
1193  if (match_symbol("::", false)) {
1194 
1195  if (left_indent(true)) {
1196 
1197  state_.no_arity_check = true;
1198  return true;
1199  }
1200  char c = (char)in_stream_->peek();
1201  if (c == ')' || c == ']') {
1202 
1203  state_.no_arity_check = true;
1204  return true;
1205  }
1206  }
1207  in_stream_->clear();
1208  in_stream_->seekg(i);
1209  return false;
1210 }
1211 
1212 bool Compiler::number(float32 &n) {
1213 
1214  std::streampos i = in_stream_->tellg();
1215  if (match_symbol("0x", true)) {
1216 
1217  in_stream_->clear();
1218  in_stream_->seekg(i);
1219  return false;
1220  }
1221  *in_stream_ >> std::dec >> n;
1222  if (in_stream_->fail() || in_stream_->eof()) {
1223 
1224  in_stream_->clear();
1225  in_stream_->seekg(i);
1226  return false;
1227  }
1228  if (match_symbol("us", true) ||
1229  match_symbol("ms", true) ||
1230  match_symbol("s", true)) {
1231  // Assume this is a timestamp or duration, not a number.
1232  in_stream_->clear();
1233  in_stream_->seekg(i);
1234  return false;
1235  }
1236  return true;
1237 }
1238 
1239 bool Compiler::hex(uint32 &h) {
1240 
1241  std::streampos i = in_stream_->tellg();
1242  if (!match_symbol("0x", false)) {
1243 
1244  in_stream_->clear();
1245  in_stream_->seekg(i);
1246  return false;
1247  }
1248  *in_stream_ >> std::hex >> h;
1249  if (in_stream_->fail() || in_stream_->eof()) {
1250 
1251  in_stream_->clear();
1252  in_stream_->seekg(i);
1253  return false;
1254  }
1255  return true;
1256 }
1257 
1258 bool Compiler::boolean(bool &b) {
1259 
1260  std::streampos i = in_stream_->tellg();
1261  if (match_symbol_separator("true", false)) {
1262 
1263  b = true;
1264  return true;
1265  }
1266  if (match_symbol_separator("false", false)) {
1267 
1268  b = false;
1269  return true;
1270  }
1271  in_stream_->clear();
1272  in_stream_->seekg(i);
1273  return false;
1274 }
1275 
1276 bool Compiler::duration(int64 &result) {
1277 
1278  std::streampos i = in_stream_->tellg();
1279  if (match_symbol("0x", true)) {
1280 
1281  in_stream_->clear();
1282  in_stream_->seekg(i);
1283  return false;
1284  }
1285  *in_stream_ >> std::dec >> result;
1286  if (in_stream_->fail() || in_stream_->eof()) {
1287 
1288  in_stream_->clear();
1289  in_stream_->seekg(i);
1290  return false;
1291  }
1292  if (match_symbol("us", false))
1293  return true;
1294  else if (match_symbol("ms", false)) {
1295  result *= 1000;
1296  return true;
1297  }
1298  else if (match_symbol("s", false)) {
1299  // Make sure this is not for timestamp_s_ms_us.
1300  if (!match_symbol(":", true)) {
1301  result *= 1000000;
1302  return true;
1303  }
1304  }
1305 
1306  in_stream_->clear();
1307  in_stream_->seekg(i);
1308  return false;
1309 }
1310 
1311 bool Compiler::timestamp_s_ms_us(int64 &ts) {
1312 
1313  std::streampos i = in_stream_->tellg();
1314  if (match_symbol("0x", true)) {
1315  in_stream_->clear();
1316  in_stream_->seekg(i);
1317  return false;
1318  }
1319 
1320  bool negative = match_symbol("-", false);
1321  uint64 s;
1322  *in_stream_ >> std::dec >> s;
1323  if (in_stream_->fail() || in_stream_->eof()) {
1324  in_stream_->clear();
1325  in_stream_->seekg(i);
1326  return false;
1327  }
1328  if (!match_symbol("s:", false)) {
1329  in_stream_->clear();
1330  in_stream_->seekg(i);
1331  return false;
1332  }
1333 
1334  uint64 ms;
1335  *in_stream_ >> std::dec >> ms;
1336  if (in_stream_->fail() || in_stream_->eof()) {
1337  in_stream_->clear();
1338  in_stream_->seekg(i);
1339  return false;
1340  }
1341  if (!match_symbol("ms:", false)) {
1342  in_stream_->clear();
1343  in_stream_->seekg(i);
1344  return false;
1345  }
1346 
1347  uint64 us;
1348  *in_stream_ >> std::dec >> us;
1349  if (in_stream_->fail() || in_stream_->eof()) {
1350  in_stream_->clear();
1351  in_stream_->seekg(i);
1352  return false;
1353  }
1354  if (!match_symbol("us", false)) {
1355  in_stream_->clear();
1356  in_stream_->seekg(i);
1357  return false;
1358  }
1359 
1360  ts = s * 1000000 + ms * 1000 + us;
1361  if (negative)
1362  ts = -ts;
1363  return true;
1364 }
1365 
1366 bool Compiler::str(std::string &s) {
1367 
1368  std::streampos i = in_stream_->tellg();
1369  uint16 count = 0;
1370  bool started = false;
1371  while (!in_stream_->eof()) {
1372 
1373  switch (char c = (char)in_stream_->get()) {
1374  case '"':
1375  if (!started) {
1376 
1377  started = true;
1378  break;
1379  }
1380  return true;
1381  default:
1382  if (!started) {
1383 
1384  in_stream_->clear();
1385  in_stream_->seekg(i);
1386  return false;
1387  }
1388  count++;
1389  s += c;
1390  break;
1391  }
1392  }
1393  in_stream_->clear();
1394  in_stream_->seekg(i);
1395  return false;
1396 }
1397 
1398 bool Compiler::object(Class &p) {
1399 
1400  if (sys_object(p))
1401  return true;
1402  std::streampos i = in_stream_->tellg();
1403  std::string s;
1404  if (!symbol_expr(s)) {
1405 
1406  in_stream_->seekg(i);
1407  s = "";
1408  if (!symbol_expr_set(s)) {
1409 
1410  in_stream_->seekg(i);
1411  return false;
1412  }
1413  }
1414  unordered_map<std::string, Class>::const_iterator it = metadata_->classes_.find(s);
1415  if (it == metadata_->classes_.end()) {
1416 
1417  in_stream_->seekg(i);
1418  return false;
1419  }
1420  p = it->second;
1421  return true;
1422 }
1423 
1424 bool Compiler::object(const Class &p) {
1425 
1426  if (sys_object(p))
1427  return true;
1428  std::streampos i = in_stream_->tellg();
1429  if (!match_symbol_separator(p.str_opcode.c_str(), false)) {
1430 
1431  in_stream_->seekg(i);
1432  return false;
1433  }
1434  return true;
1435 }
1436 
1437 bool Compiler::sys_object(Class &p) {
1438 
1439  std::streampos i = in_stream_->tellg();
1440  std::string s;
1441  if (!symbol_expr(s)) {
1442 
1443  in_stream_->seekg(i);
1444  s = "";
1445  if (!symbol_expr_set(s)) {
1446 
1447  in_stream_->seekg(i);
1448  return false;
1449  }
1450  }
1451  unordered_map<std::string, Class>::const_iterator it = metadata_->sys_classes_.find(s);
1452  if (it == metadata_->sys_classes_.end()) {
1453 
1454  in_stream_->seekg(i);
1455  return false;
1456  }
1457  p = it->second;
1458  return true;
1459 }
1460 
1461 bool Compiler::sys_object(const Class &p) {
1462 
1463  std::streampos i = in_stream_->tellg();
1464  if (!match_symbol_separator(p.str_opcode.c_str(), false)) {
1465 
1466  in_stream_->seekg(i);
1467  return false;
1468  }
1469  return true;
1470 }
1471 
1472 bool Compiler::marker(Class &p) {
1473 
1474  std::streampos i = in_stream_->tellg();
1475  if (!match_symbol("mk.", false)) {
1476 
1477  in_stream_->seekg(i);
1478  return false;
1479  }
1480  std::streampos j = in_stream_->tellg();
1481  std::string s;
1482  if (!symbol_expr(s)) {
1483 
1484  in_stream_->seekg(j);
1485  s = "";
1486  if (!symbol_expr_set(s)) {
1487 
1488  in_stream_->seekg(i);
1489  return false;
1490  }
1491  }
1492  unordered_map<std::string, Class>::const_iterator it = metadata_->sys_classes_.find("mk." + s);
1493  if (it == metadata_->sys_classes_.end()) {
1494 
1495  in_stream_->seekg(i);
1496  return false;
1497  }
1498  p = it->second;
1499  return true;
1500 }
1501 
1502 bool Compiler::op(Class &p, const ReturnType t) { // return true if type matches t or ANY
1503 
1504  std::streampos i = in_stream_->tellg();
1505  std::string s;
1506  if (!symbol_expr(s)) {
1507 
1508  in_stream_->seekg(i);
1509  return false;
1510  }
1511  unordered_map<std::string, Class>::const_iterator it = metadata_->classes_.find(s);
1512  if (it == metadata_->classes_.end() || (t != ANY && it->second.type != ANY && it->second.type != t)) {
1513 
1514  in_stream_->seekg(i);
1515  return false;
1516  }
1517  p = it->second;
1518  return true;
1519 }
1520 
1521 bool Compiler::op(const Class &p) {
1522 
1523  std::streampos i = in_stream_->tellg();
1524  if (!match_symbol_separator(p.str_opcode.c_str(), false)) {
1525 
1526  in_stream_->seekg(i);
1527  return false;
1528  }
1529  return true;
1530 }
1531 
1532 bool Compiler::function(Class &p) {
1533 
1534  std::streampos i = in_stream_->tellg();
1535  std::string s;
1536  if (!symbol_expr(s)) {
1537 
1538  in_stream_->seekg(i);
1539  return false;
1540  }
1541  unordered_map<std::string, Class>::const_iterator it = metadata_->classes_.find(s);
1542  if (it == metadata_->classes_.end()) {
1543 
1544  in_stream_->seekg(i);
1545  return false;
1546  }
1547  p = it->second;
1548  return true;
1549 }
1550 
1551 bool Compiler::expression_head(Class &p, const ReturnType t) {
1552 
1553  indent(false);
1554  if (t == ANY) {
1555 
1556  if (!object(p))
1557  if (!marker(p))
1558  if (!op(p, ANY))
1559  return false;
1560  } else if (!op(p, t))
1561  return false;
1562  if (p.atom_.getAtomCount()) {
1563 
1564  if (!right_indent(true)) {
1565 
1566  if (!separator(false)) {
1567 
1568  set_error("syntax error: missing separator/right_indent after head");
1569  return false;
1570  }
1571  }
1572  }
1573  return true;
1574 }
1575 
1576 bool Compiler::expression_head(const Class &p) {
1577 
1578  indent(false);
1579  if (!object(p))
1580  if (!op(p))
1581  return false;
1582  if (p.atom_.getAtomCount()) {
1583 
1584  if (!right_indent(true)) {
1585 
1586  if (!separator(false)) {
1587 
1588  set_error("syntax error: missing separator/right_indent after head");
1589  return false;
1590  }
1591  }
1592  }
1593  return true;
1594 }
1595 
1596 bool Compiler::expression_tail(bool indented, const Class &p, uint16 write_index, uint16 &extent_index, bool write) { // arity>0.
1597 
1598  uint16 count = 0;
1599  bool _indented = false;
1600  bool entered_pattern;
1601  uint16 pattern_end_index;
1602  if (in_hlp_) {
1603 
1604  entered_pattern = true;//p.is_fact(metadata_);
1605  pattern_end_index = p.atom_.getAtomCount() - 1;
1606  } else {
1607 
1608  entered_pattern = p.is_pattern(metadata_);
1609  pattern_end_index = 0;
1610  }
1611  if (write && state_.pattern_lvl) // fill up with wildcards that will be overwritten up to ::.
1612  for (uint16 j = write_index; j < write_index + p.atom_.getAtomCount(); ++j)
1613  current_object_->code_[j] = Atom::Wildcard();
1614  std::streampos i = in_stream_->tellg();
1615  while (!in_stream_->eof()) {
1616 
1617  if (expression_end(indented)) {
1618 
1619  if (state_.no_arity_check) {
1620 
1621  state_.no_arity_check = false;
1622  if (entered_pattern && pattern_end_index > 0 && count - 1 < pattern_end_index)
1623  // state_.pattern_lvl was incremented below, but the tail wildcard prevented decrementing it. Do it here.
1624  --state_.pattern_lvl;
1625  return true;
1626  }
1627  if (count == p.atom_.getAtomCount())
1628  return true;
1629  set_arity_error(p.atom_.getAtomCount(), count);
1630  return false;
1631  }
1632  if (count >= p.atom_.getAtomCount()) {
1633 
1634  set_arity_error(p.atom_.getAtomCount(), count + 1);
1635  return false;
1636  }
1637  if (count) {
1638 
1639  if (!_indented) {
1640 
1641  if (!right_indent(true)) {
1642 
1643  if (!separator(false)) {
1644 
1645  set_error("syntax error: missing separator between 2 elements");
1646  return false;
1647  }
1648  }
1649  } else
1650  _indented = false;
1651  }
1652  if (entered_pattern && count == 0) // pattern begin.
1653  ++state_.pattern_lvl;
1654  if (!read(p.things_to_read[count], _indented, true, write_index + count, extent_index, write)) {
1655 
1656  set_error(" error: parsing element in expression");
1657  return false;
1658  }
1659  if (entered_pattern && count == pattern_end_index) // pattern end.
1660  --state_.pattern_lvl;
1661  ++count;
1662  }
1663  return false;
1664 }
1665 
1667 
1668 bool Compiler::expression(bool &indented, const ReturnType t, uint16 write_index, uint16 &extent_index, bool write) {
1669 
1670  bool lbl = false;
1671  std::streampos i = in_stream_->tellg();
1672  std::string l;
1673  if (label(l))
1674  lbl = true;
1675  if (!expression_begin(indented)) {
1676 
1677  if (lbl)
1678  set_error(" error: label not followed by an expression");
1679  return false;
1680  }
1681  Class p;
1682  if (!expression_head(p, t)) {
1683 
1684  in_stream_->seekg(i);
1685  return false;
1686  }
1687  if (lbl && !in_hlp_)
1688  addLocalReference(l, write_index, p);
1689  uint16 tail_write_index = 0;
1690  if (write) {
1691 
1692  if (lbl && in_hlp_) {
1693 
1694  uint8 variable_index = get_hlp_reference(l);
1695  if (variable_index == 0xFF) {
1696 
1697  set_error(" error: undeclared variable");
1698  return false;
1699  }
1700  current_object_->code_[write_index] = Atom::AssignmentPointer(variable_index, extent_index);
1701  } else
1702  current_object_->code_[write_index] = Atom::IPointer(extent_index);
1703  current_object_->code_[extent_index++] = p.atom_;
1704  tail_write_index = extent_index;
1705  extent_index += p.atom_.getAtomCount();
1706  }
1707  if (!expression_tail(indented, p, tail_write_index, extent_index, write))
1708  return false;
1709  return true;
1710 }
1711 
1712 bool Compiler::expression(bool &indented, const Class &p, uint16 write_index, uint16 &extent_index, bool write) {
1713 
1714  bool lbl = false;
1715  std::streampos i = in_stream_->tellg();
1716  std::string l;
1717  if (label(l))
1718  lbl = true;
1719  if (!expression_begin(indented)) {
1720 
1721  if (lbl)
1722  set_error(" error: label not followed by an expression");
1723  return false;
1724  }
1725  if (!expression_head(p)) {
1726 
1727  in_stream_->seekg(i);
1728  return false;
1729  }
1730  if (lbl)
1731  addLocalReference(l, write_index, p);
1732  uint16 tail_write_index = 0;
1733  if (write) {
1734 
1735  if (lbl && in_hlp_) {
1736 
1737  uint8 variable_index = get_hlp_reference(l);
1738  if (variable_index == 0xFF) {
1739 
1740  set_error(" error: undeclared variable");
1741  return false;
1742  }
1743  current_object_->code_[write_index] = Atom::AssignmentPointer(variable_index, extent_index);
1744  } else
1745  current_object_->code_[write_index] = Atom::IPointer(extent_index);
1746  current_object_->code_[extent_index++] = p.atom_;
1747  tail_write_index = extent_index;
1748  extent_index += p.atom_.getAtomCount();
1749  }
1750  if (!expression_tail(indented, p, tail_write_index, extent_index, write))
1751  return false;
1752  return true;
1753 }
1754 
1755 bool Compiler::set(bool &indented, uint16 write_index, uint16 &extent_index, bool write) { // [ ] is illegal; use |[] instead, or [nil].
1756 
1757  std::streampos i = in_stream_->tellg();
1758  bool lbl = false;
1759  std::string l;
1760  if (label(l))
1761  lbl = true;
1762  if (!set_begin(indented)) {
1763 
1764  if (lbl)
1765  set_error(" error: label not followed by a structure");
1766  return false;
1767  }
1768  if (lbl)
1769  addLocalReference(l, write_index, Class(SET));
1770  indent(false);
1771  uint16 content_write_index = 0;
1772  if (write) {
1773 
1774  current_object_->code_[write_index] = Atom::IPointer(extent_index);
1775  uint8 element_count = set_element_count(indented);
1776  current_object_->code_[extent_index++] = Atom::Set(element_count);
1777  content_write_index = extent_index;
1778  extent_index += element_count;
1779  }
1780  uint16 count = 0;
1781  bool _indented = false;
1782  while (!in_stream_->eof()) {
1783 
1784  if (set_end(indented)) {
1785 
1786  if (!count) {
1787 
1788  set_error(" syntax error: use |[] for empty sets");
1789  return false;
1790  }
1791  return true;
1792  }
1793  if (count) {
1794 
1795  if (!_indented) {
1796 
1797  if (!right_indent(true)) {
1798 
1799  if (!separator(false)) {
1800 
1801  set_error("syntax error: missing separator between 2 elements");
1802  return false;
1803  }
1804  }
1805  } else
1806  _indented = false;
1807  }
1808  if (!read_any(_indented, false, NULL, content_write_index + count, extent_index, write)) {
1809 
1810  set_error(" error: illegal element in set");
1811  return false;
1812  }
1813  count++;
1814  }
1815  in_stream_->clear();
1816  in_stream_->seekg(i);
1817  return false;
1818 }
1819 
1820 bool Compiler::set(bool &indented, const Class &p, uint16 write_index, uint16 &extent_index, bool write) { // for class defs like member-name:[member-list] or !class (name[] member-list).
1821 
1822  std::streampos i = in_stream_->tellg();
1823  bool lbl = false;
1824  std::string l;
1825  if (label(l))
1826  lbl = true;
1827  if (!set_begin(indented)) {
1828 
1829  if (lbl)
1830  set_error(" error: label not followed by a structure");
1831  return false;
1832  }
1833  if (lbl)
1834  addLocalReference(l, write_index, p);
1835  indent(false);
1836  uint16 content_write_index = 0;
1837  if (write) {
1838 
1839  current_object_->code_[write_index] = Atom::IPointer(extent_index);
1840  uint8 element_count;
1841  if (p.atom_.getDescriptor() == Atom::S_SET && p.use_as != StructureMember::I_SET) {
1842 
1843  element_count = p.atom_.getAtomCount();
1844  current_object_->code_[extent_index++] = p.atom_;
1845  } else {
1846 
1847  element_count = set_element_count(indented);
1848  current_object_->code_[extent_index++] = Atom::Set(element_count);
1849  }
1850  content_write_index = extent_index;
1851  extent_index += element_count;
1852  }
1853  uint16 count = 0;
1854  bool _indented = false;
1855  uint16 arity = 0xFFFF;
1856  if (p.use_as == StructureMember::I_CLASS) { // undefined arity for unstructured sets.
1857 
1858  arity = p.atom_.getAtomCount();
1859  if (write) // fill up with wildcards that will be overwritten up to ::.
1860  for (uint16 j = content_write_index; j < content_write_index + arity; ++j)
1861  current_object_->code_[j] = Atom::Wildcard();
1862  }
1863  while (!in_stream_->eof()) {
1864 
1865  if (set_end(indented)) {
1866 
1867  if (!count) {
1868 
1869  set_error(" syntax error: use |[] for empty sets");
1870  return false;
1871  }
1872  if (count == arity || arity == 0xFFFF)
1873  return true;
1874  if (state_.no_arity_check) {
1875 
1876  state_.no_arity_check = false;
1877  return true;
1878  }
1879  set_arity_error(arity, count);
1880  return false;
1881  }
1882  if (count >= arity) {
1883 
1884  set_arity_error(arity, count + 1);
1885  return false;
1886  }
1887  if (count) {
1888 
1889  if (!_indented) {
1890 
1891  if (!right_indent(true)) {
1892 
1893  if (!separator(false)) {
1894 
1895  set_error("syntax error: missing separator between 2 elements");
1896  return false;
1897  }
1898  }
1899  } else
1900  _indented = false;
1901  }
1902  bool r;
1903  switch (p.use_as) {
1904  case StructureMember::I_EXPRESSION:
1905  r = read_expression(_indented, true, &p, content_write_index + count, extent_index, write);
1906  break;
1907  case StructureMember::I_SET:
1908  {
1909  Class _p = p;
1910  _p.use_as = StructureMember::I_CLASS;
1911  r = read_set(_indented, true, &_p, content_write_index + count, extent_index, write);
1912  break;
1913  }
1914  case StructureMember::I_CLASS:
1915  r = read(p.things_to_read[count], _indented, true, content_write_index + count, extent_index, write);
1916  break;
1917  case StructureMember::I_DCLASS:
1918  r = read_class(_indented, true, NULL, content_write_index + count, extent_index, write);
1919  break;
1920  }
1921  if (!r) {
1922 
1923  set_error(" error: illegal element in set");
1924  return false;
1925  }
1926  count++;
1927  }
1928  in_stream_->clear();
1929  in_stream_->seekg(i);
1930  return false;
1931 }
1932 
1933 uint8 Compiler::set_element_count(bool indented) { // error checking is done in set(). This is a naive implementation: basically it parses the whole set depth-first. That's very slow and shall be replaced by a more clever design (avoiding deliving in the depths of the elements of the set).
1934 
1935  Output = false;
1936  uint8 count = 0;
1937  State s = save_state();
1938  indent(false);
1939  bool _indented = false;
1940  uint16 unused_index = 0;
1941  while (!in_stream_->eof()) {
1942 
1943  if (set_end(indented))
1944  break;
1945  if (count) {
1946 
1947  if (!_indented) {
1948 
1949  if (!right_indent(true)) {
1950 
1951  if (!separator(false))
1952  break;
1953  }
1954  } else
1955  _indented = false;
1956  }
1957  if (!read_any(_indented, false, NULL, 0, unused_index, false))
1958  break;
1959  count++;
1960  }
1961  in_stream_->clear();
1962  restore_state(s);
1963  Output = true;
1964  return count;
1965 }
1966 
1968 
1969 bool Compiler::read_any(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // enforce always false, p always NULL.
1970 
1971  indented = false;
1972  if (read_number(indented, false, NULL, write_index, extent_index, write))
1973  return true;
1974  if (err_)
1975  return false;
1976  if (read_timestamp(indented, false, NULL, write_index, extent_index, write))
1977  return true;
1978  if (read_duration(indented, false, NULL, write_index, extent_index, write))
1979  return true;
1980  if (err_)
1981  return false;
1982  if (read_string(indented, false, NULL, write_index, extent_index, write))
1983  return true;
1984  if (err_)
1985  return false;
1986  if (read_boolean(indented, false, NULL, write_index, extent_index, write))
1987  return true;
1988  if (err_)
1989  return false;
1990  if (read_function(indented, false, NULL, write_index, extent_index, write))
1991  return true;
1992  if (err_)
1993  return false;
1994  if (read_node(indented, false, NULL, write_index, extent_index, write))
1995  return true;
1996  if (err_)
1997  return false;
1998  if (read_device(indented, false, NULL, write_index, extent_index, write))
1999  return true;
2000  if (read_class(indented, false, NULL, write_index, extent_index, write))
2001  return true;
2002  if (err_)
2003  return false;
2004  if (read_expression(indented, false, NULL, write_index, extent_index, write))
2005  return true;
2006  if (err_)
2007  return false;
2008  if (read_set(indented, false, NULL, write_index, extent_index, write))
2009  return true;
2010  if (write)
2011  set_error(" error: expecting more elements");
2012  return false;
2013 }
2014 
2015 bool Compiler::read_number(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL
2016 
2017  if (read_nil_nb(write_index, extent_index, write))
2018  return true;
2019  if (read_forever_nb(write_index, extent_index, write))
2020  return true;
2021  if (read_variable(write_index, extent_index, write, NUMBER))
2022  return true;
2023  if (read_reference(write_index, extent_index, write, NUMBER))
2024  return true;
2025  if (read_wildcard(write_index, extent_index, write))
2026  return true;
2027  if (read_tail_wildcard(write_index, extent_index, write))
2028  return true;
2029 
2030  float32 n;
2031  if (number(n)) {
2032 
2033  if (write)
2034  current_object_->code_[write_index] = Atom::Float(n);
2035  return true;
2036  }
2037  State s = save_state();
2038  if (expression(indented, NUMBER, write_index, extent_index, write))
2039  return true;
2040  restore_state(s);
2041  if (enforce) {
2042 
2043  set_error(" error: expected a number or an expr evaluating to a number");
2044  return false;
2045  }
2046  return false;
2047 }
2048 
2049 bool Compiler::read_boolean(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL
2050 
2051  if (read_nil_bl(write_index, extent_index, write))
2052  return true;
2053  if (read_variable(write_index, extent_index, write, BOOLEAN))
2054  return true;
2055  if (read_reference(write_index, extent_index, write, BOOLEAN))
2056  return true;
2057  if (read_wildcard(write_index, extent_index, write))
2058  return true;
2059  if (read_tail_wildcard(write_index, extent_index, write))
2060  return true;
2061 
2062  bool b;
2063  if (boolean(b)) {
2064 
2065  if (write)
2066  current_object_->code_[write_index] = Atom::Boolean(b);
2067  return true;
2068  }
2069  State s = save_state();
2070  if (expression(indented, BOOLEAN, write_index, extent_index, write))
2071  return true;
2072  restore_state(s);
2073  if (enforce) {
2074 
2075  set_error(" error: expected a Boolean or an expr evaluating to a Boolean");
2076  return false;
2077  }
2078  return false;
2079 }
2080 
2081 bool Compiler::read_timestamp(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL
2082 
2083  if (read_nil_ts(write_index, extent_index, write))
2084  return true;
2085  if (read_variable(write_index, extent_index, write, TIMESTAMP))
2086  return true;
2087  if (read_reference(write_index, extent_index, write, TIMESTAMP))
2088  return true;
2089  if (read_wildcard(write_index, extent_index, write))
2090  return true;
2091  if (read_tail_wildcard(write_index, extent_index, write))
2092  return true;
2093 
2094  int64 ts;
2095  if (timestamp_s_ms_us(ts)) {
2096  if (write) {
2097 
2098  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2099  current_object_->code_[extent_index++] = Atom::Timestamp();
2100  current_object_->code_[extent_index + 1] = 0;
2101  Utils::SetInt64(&current_object_->code_[0], extent_index, ts);
2102  extent_index += 2;
2103  }
2104  return true;
2105  }
2106 
2107  State s = save_state();
2108  if (expression(indented, TIMESTAMP, write_index, extent_index, write))
2109  return true;
2110  restore_state(s);
2111  if (enforce) {
2112 
2113  set_error(" error: expected a timestamp or an expr evaluating to a timestamp");
2114  return false;
2115  }
2116  return false;
2117 }
2118 
2119 // p is always NULL.
2120 bool Compiler::read_duration(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) {
2121 
2122  if (read_variable(write_index, extent_index, write, DURATION))
2123  return true;
2124  if (read_reference(write_index, extent_index, write, DURATION))
2125  return true;
2126  if (read_wildcard(write_index, extent_index, write))
2127  return true;
2128  if (read_tail_wildcard(write_index, extent_index, write))
2129  return true;
2130 
2131  int64 d;
2132  if (duration(d)) {
2133 
2134  if (write) {
2135 
2136  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2137  current_object_->code_[extent_index++] = Atom::Duration();
2138  current_object_->code_[extent_index + 1] = 0;
2139  Utils::SetInt64(&current_object_->code_[0], extent_index, d);
2140  extent_index += 2;
2141  }
2142  return true;
2143  }
2144 
2145  State s = save_state();
2146  if (expression(indented, DURATION, write_index, extent_index, write))
2147  return true;
2148  restore_state(s);
2149  if (enforce) {
2150 
2151  set_error(" error: expected a duration or an expr evaluating to a duration");
2152  return false;
2153  }
2154  return false;
2155 }
2156 
2157 bool Compiler::read_string(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL
2158 
2159  if (read_nil_st(write_index, extent_index, write))
2160  return true;
2161  if (read_variable(write_index, extent_index, write, STRING))
2162  return true;
2163  if (read_reference(write_index, extent_index, write, STRING))
2164  return true;
2165  if (read_wildcard(write_index, extent_index, write))
2166  return true;
2167  if (read_tail_wildcard(write_index, extent_index, write))
2168  return true;
2169 
2170  std::string st;
2171  if (str(st)) {
2172 
2173  if (write) {
2174 
2175  uint16 l = (uint16)st.length();
2176  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2177  current_object_->code_[extent_index++] = Atom::String(l);
2178  uint32 _st = 0;
2179  int8 shift = 0;
2180  for (uint16 i = 0; i < l; ++i) {
2181 
2182  _st |= st[i] << shift;
2183  shift += 8;
2184  if (shift == 32) {
2185 
2186  current_object_->code_[extent_index++] = _st;
2187  _st = 0;
2188  shift = 0;
2189  }
2190  }
2191  if (l % 4)
2192  current_object_->code_[extent_index++] = _st;
2193  }
2194  return true;
2195  }
2196  State s = save_state();
2197  if (expression(indented, STRING, write_index, extent_index, write))
2198  return true;
2199  restore_state(s);
2200  if (enforce) {
2201 
2202  set_error(" error: expected a string");
2203  return false;
2204  }
2205  return false;
2206 }
2207 
2208 bool Compiler::read_node(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL
2209 
2210  if (read_nil_nid(write_index, extent_index, write))
2211  return true;
2212  if (read_variable(write_index, extent_index, write, NODE_ID))
2213  return true;
2214  if (read_reference(write_index, extent_index, write, NODE_ID))
2215  return true;
2216  if (read_wildcard(write_index, extent_index, write))
2217  return true;
2218  if (read_tail_wildcard(write_index, extent_index, write))
2219  return true;
2220 
2221  std::streampos i = in_stream_->tellg();
2222  uint32 h;
2223  if (hex(h) && Atom(h).getDescriptor() == Atom::NODE) {
2224 
2225  if (write)
2226  current_object_->code_[write_index] = Atom(h);
2227  return true;
2228  }
2229  in_stream_->seekg(i);
2230  State s = save_state();
2231  if (expression(indented, NODE_ID, write_index, extent_index, write))
2232  return true;
2233  restore_state(s);
2234  if (enforce) {
2235 
2236  set_error(" error: expected a node id");
2237  return false;
2238  }
2239  return false;
2240 }
2241 
2242 bool Compiler::read_device(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL.
2243 
2244  if (read_nil_did(write_index, extent_index, write))
2245  return true;
2246  if (read_variable(write_index, extent_index, write, DEVICE_ID))
2247  return true;
2248  if (read_reference(write_index, extent_index, write, DEVICE_ID))
2249  return true;
2250  if (read_wildcard(write_index, extent_index, write))
2251  return true;
2252  if (read_tail_wildcard(write_index, extent_index, write))
2253  return true;
2254 
2255  std::streampos i = in_stream_->tellg();
2256  uint32 h;
2257  if (hex(h) && Atom(h).getDescriptor() == Atom::DEVICE) {
2258 
2259  if (write)
2260  current_object_->code_[write_index] = Atom(h);
2261  return true;
2262  }
2263  in_stream_->seekg(i);
2264  State s = save_state();
2265  if (expression(indented, DEVICE_ID, write_index, extent_index, write))
2266  return true;
2267  restore_state(s);
2268  if (enforce) {
2269 
2270  set_error(" error: expected a device id");
2271  return false;
2272  }
2273  return false;
2274 }
2275 
2276 bool Compiler::read_function(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL
2277 
2278  if (read_nil_fid(write_index, extent_index, write))
2279  return true;
2280  if (read_variable(write_index, extent_index, write, FUNCTION_ID))
2281  return true;
2282  if (read_reference(write_index, extent_index, write, FUNCTION_ID))
2283  return true;
2284  if (read_wildcard(write_index, extent_index, write))
2285  return true;
2286  if (read_tail_wildcard(write_index, extent_index, write))
2287  return true;
2288 
2289  Class _p;
2290  if (function(_p)) { // TODO: _p shall be used to parse the args in the embedding expression
2291 
2292  if (write)
2293  current_object_->code_[write_index] = _p.atom_;
2294  return true;
2295  }
2296  State s = save_state();
2297  if (expression(indented, FUNCTION_ID, write_index, extent_index, write))
2298  return true;
2299  restore_state(s);
2300  if (enforce) {
2301 
2302  set_error(" error: expected a device function");
2303  return false;
2304  }
2305  return false;
2306 }
2307 
2308 bool Compiler::read_expression(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) {
2309 
2310  if (read_nil(write_index, extent_index, write))
2311  return true;
2312  if (p && p->str_opcode != Class::Expression) {
2313 
2314  if (read_variable(write_index, extent_index, write, *p))
2315  return true;
2316  if (read_reference(write_index, extent_index, write, p->type))
2317  return true;
2318  } else {
2319 
2320  if (read_variable(write_index, extent_index, write, Class()))
2321  return true;
2322  if (read_reference(write_index, extent_index, write, ANY))
2323  return true;
2324  }
2325  if (read_wildcard(write_index, extent_index, write))
2326  return true;
2327  if (read_tail_wildcard(write_index, extent_index, write))
2328  return true;
2329 
2330  indented = false;
2331  if (p && p->str_opcode != Class::Expression) {
2332 
2333  if (expression(indented, *p, write_index, extent_index, write))
2334  return true;
2335  } else if (expression(indented, ANY, write_index, extent_index, write))
2336  return true;
2337  if (enforce) {
2338 
2339  std::string s = " error: expected an expression";
2340  if (p) {
2341 
2342  s += " of type: ";
2343  s += p->str_opcode;
2344  }
2345  set_error(s);
2346  return false;
2347  }
2348  return false;
2349 }
2350 
2351 bool Compiler::read_set(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) {
2352 
2353  if (read_nil_set(write_index, extent_index, write))
2354  return true;
2355  if (read_variable(write_index, extent_index, write, Class(SET)))
2356  return true;
2357  if (read_reference(write_index, extent_index, write, SET))
2358  return true;
2359  if (read_wildcard(write_index, extent_index, write))
2360  return true;
2361  if (read_tail_wildcard(write_index, extent_index, write))
2362  return true;
2363 
2364  indented = false;
2365  if (p) {
2366 
2367  if (set(indented, *p, write_index, extent_index, write))
2368  return true;
2369  } else if (set(indented, write_index, extent_index, write))
2370  return true;
2371  if (enforce) {
2372 
2373  set_error(" error: expected a set");
2374  return false;
2375  }
2376  return false;
2377 }
2378 
2379 bool Compiler::read_class(bool &indented, bool enforce, const Class *p, uint16 write_index, uint16 &extent_index, bool write) { // p always NULL.
2380 
2381  std::streampos i = in_stream_->tellg();
2382  std::string l;
2383  if (label(l)) {
2384 
2385  Class _p;
2386  if (!object(_p))
2387  if (!marker(_p))
2388  return false;
2389  local_references_[l] = Reference(write_index, _p, Class());
2390  if (write)
2391  current_object_->code_[write_index] = _p.atom_;
2392  return true;
2393  }
2394  in_stream_->clear();
2395  in_stream_->seekg(i);
2396  return false;
2397 }
2398 
2400 
2401 bool Compiler::read_nil(uint16 write_index, uint16 &extent_index, bool write) {
2402 
2403  if (nil()) {
2404 
2405  if (write)
2406  current_object_->code_[write_index] = Atom::Nil();
2407  return true;
2408  }
2409  return false;
2410 }
2411 
2412 bool Compiler::read_nil_set(uint16 write_index, uint16 &extent_index, bool write) {
2413 
2414  std::streampos i = in_stream_->tellg();
2415  if (match_symbol("|[]", false) ||
2416  // Treat [] as an empty set if it is not at the end of a line.
2417  (match_symbol("[]", false) && in_stream_->peek() >= 32)) {
2418 
2419  if (write) {
2420 
2421  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2422  current_object_->code_[extent_index++] = Atom::Set(0);
2423  }
2424  return true;
2425  }
2426  in_stream_->seekg(i);
2427  return false;
2428 }
2429 
2430 bool Compiler::read_nil_nb(uint16 write_index, uint16 &extent_index, bool write) {
2431 
2432  if (nil_nb()) {
2433 
2434  if (write)
2435  current_object_->code_[write_index] = Atom::UndefinedFloat();
2436  return true;
2437  }
2438  return false;
2439 }
2440 
2441 bool Compiler::read_nil_ts(uint16 write_index, uint16 &extent_index, bool write) {
2442 
2443  if (nil_ts()) {
2444 
2445  if (write) {
2446 
2447  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2448  current_object_->code_[extent_index++] = Atom::UndefinedTimestamp();
2449  current_object_->code_[extent_index++] = 0xFFFFFFFF;
2450  current_object_->code_[extent_index++] = 0xFFFFFFFF;
2451  }
2452  return true;
2453  }
2454  return false;
2455 }
2456 
2457 bool Compiler::read_forever_nb(uint16 write_index, uint16 &extent_index, bool write) {
2458 
2459  if (forever()) {
2460 
2461  if (write) {
2462 
2463  current_object_->code_[write_index] = Atom::PlusInfinity();
2464  }
2465  return true;
2466  }
2467  return false;
2468 }
2469 
2470 bool Compiler::read_nil_nid(uint16 write_index, uint16 &extent_index, bool write) {
2471 
2472  if (nil_nid()) {
2473 
2474  if (write)
2475  current_object_->code_[write_index] = Atom::UndefinedNode();
2476  return true;
2477  }
2478  return false;
2479 }
2480 
2481 bool Compiler::read_nil_did(uint16 write_index, uint16 &extent_index, bool write) {
2482 
2483  if (nil_did()) {
2484 
2485  if (write)
2486  current_object_->code_[write_index] = Atom::UndefinedDevice();
2487  return true;
2488  }
2489  return false;
2490 }
2491 
2492 bool Compiler::read_nil_fid(uint16 write_index, uint16 &extent_index, bool write) {
2493 
2494  if (nil_fid()) {
2495 
2496  if (write)
2497  current_object_->code_[write_index] = Atom::UndefinedDeviceFunction();
2498  return true;
2499  }
2500  return false;
2501 }
2502 
2503 bool Compiler::read_nil_bl(uint16 write_index, uint16 &extent_index, bool write) {
2504 
2505  if (nil_bl()) {
2506 
2507  if (write)
2508  current_object_->code_[write_index] = Atom::UndefinedBoolean();
2509  return true;
2510  }
2511  return false;
2512 }
2513 
2514 bool Compiler::read_nil_st(uint16 write_index, uint16 &extent_index, bool write) {
2515 
2516  if (nil_st()) {
2517 
2518  if (write)
2519  current_object_->code_[write_index] = Atom::UndefinedString();
2520  return true;
2521  }
2522  return false;
2523 }
2524 
2525 bool Compiler::read_variable(uint16 write_index, uint16 &extent_index, bool write, const Class p) {
2526 
2527  std::string v;
2528  if (variable(v)) {
2529 
2530  if (state_.pattern_lvl || allow_variables_and_wildcards_outside_pattern_skeleton_) {
2531 
2532  if (in_hlp_ ||
2533  (allow_variables_and_wildcards_outside_pattern_skeleton_ && current_class_.str_opcode != "pgm")) {
2534 
2535  uint8 variable_index = add_hlp_reference(v);
2536  if (write)
2537  current_object_->code_[write_index] = Atom::VLPointer(variable_index);
2538  } else {
2539 
2540  addLocalReference(v, write_index, p);
2541  if (write)
2542  current_object_->code_[write_index] = Atom::Wildcard(p.atom_.asOpcode()); // useless in skeleton expressions (already filled up in expression_head); usefull when the skeleton itself is a variable
2543  }
2544  return true;
2545  } else {
2546 
2547  set_error(" error: no variables allowed outside a pattern skeleton");
2548  return false;
2549  }
2550  }
2551  return false;
2552 }
2553 
2554 bool Compiler::read_reference(uint16 write_index, uint16 &extent_index, bool write, const ReturnType t) {
2555 
2556  uint16 index;
2557  if ((t == ANY || (t != ANY && current_class_.type == t)) && this_()) {
2558 
2559  if (write)
2560  current_object_->code_[write_index] = Atom::This();
2561  return true;
2562  }
2563  if (local_reference(index, t)) {
2564 
2565  if (write)
2566  current_object_->code_[write_index] = Atom::CodeVLPointer(index); // local references are always pointing to the value array
2567  return true;
2568  }
2569  if (global_reference(index, t)) { // index is the index held by a reference pointer
2570 
2571  if (write)
2572  current_object_->code_[write_index] = Atom::RPointer(index);
2573  return true;
2574  }
2575  vector<int16> v;
2576  if (this_indirection(v, t)) {
2577 
2578  if (write) {
2579 
2580  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2581  current_object_->code_[extent_index++] = Atom::CPointer(v.size() + 1);
2582  current_object_->code_[extent_index++] = Atom::This();
2583  for (uint16 i = 0; i < v.size(); ++i) {
2584 
2585  switch (v[i]) {
2586  case -1:
2587  current_object_->code_[extent_index++] = Atom::View();
2588  break;
2589  case -2:
2590  current_object_->code_[extent_index++] = Atom::Mks();
2591  break;
2592  case -3:
2593  current_object_->code_[extent_index++] = Atom::Vws();
2594  break;
2595  default:
2596  current_object_->code_[extent_index++] = Atom::IPointer(v[i]);
2597  break;
2598  }
2599  }
2600  }
2601  return true;
2602  }
2603  uint16 cast_opcode;
2604  if (local_indirection(v, t, cast_opcode)) {
2605 
2606  if (write) {
2607 
2608  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2609  current_object_->code_[extent_index++] = Atom::CPointer(v.size());
2610  current_object_->code_[extent_index++] = Atom::CodeVLPointer(v[0], cast_opcode);
2611  for (uint16 i = 1; i < v.size(); ++i) {
2612 
2613  switch (v[i]) {
2614  case -1:
2615  current_object_->code_[extent_index++] = Atom::View();
2616  break;
2617  case -2:
2618  current_object_->code_[extent_index++] = Atom::Mks();
2619  break;
2620  case -3:
2621  current_object_->code_[extent_index++] = Atom::Vws();
2622  break;
2623  default:
2624  current_object_->code_[extent_index++] = Atom::IPointer(v[i]);
2625  break;
2626  }
2627  }
2628  }
2629  return true;
2630  }
2631  if (global_indirection(v, t)) { // v[0] is the index held by a reference pointer
2632 
2633  if (write) {
2634 
2635  current_object_->code_[write_index] = Atom::IPointer(extent_index);
2636  current_object_->code_[extent_index++] = Atom::CPointer(v.size());
2637  current_object_->code_[extent_index++] = Atom::RPointer(v[0]);
2638  for (uint16 i = 1; i < v.size(); ++i) {
2639 
2640  switch (v[i]) {
2641  case -2:
2642  current_object_->code_[extent_index++] = Atom::Mks();
2643  break;
2644  case -3:
2645  current_object_->code_[extent_index++] = Atom::Vws();
2646  break;
2647  default:
2648  current_object_->code_[extent_index++] = Atom::IPointer(v[i]);
2649  break;
2650  }
2651  }
2652  }
2653  return true;
2654  }
2655  if (hlp_reference(index)) {
2656 
2657  if (write)
2658  current_object_->code_[write_index] = Atom::VLPointer(index);
2659  return true;
2660  }
2661  return false;
2662 }
2663 
2664 bool Compiler::read_wildcard(uint16 write_index, uint16 &extent_index, bool write) {
2665 
2666  if (wildcard()) {
2667 
2668  if (state_.pattern_lvl || allow_variables_and_wildcards_outside_pattern_skeleton_) {
2669 
2670  if (write)
2671  current_object_->code_[write_index] = Atom::Wildcard();
2672  return true;
2673  } else {
2674 
2675  set_error(" error: no wildcards allowed outside a pattern skeleton");
2676  return false;
2677  }
2678  }
2679  return false;
2680 }
2681 
2682 bool Compiler::read_tail_wildcard(uint16 write_index, uint16 &extent_index, bool write) {
2683 
2684  if (tail_wildcard()) {
2685 
2686  if (state_.pattern_lvl) {
2687 
2688  if (write)
2689  current_object_->code_[write_index] = Atom::TailWildcard();
2690  return true;
2691  } else {
2692 
2693  set_error(" error: no wildcards allowed outside a pattern skeleton");
2694  return false;
2695  }
2696  }
2697  return false;
2698 }
2699 
2700 std::string Compiler::getObjectName(const uint16 index) const {
2701 
2702  unordered_map<std::string, Reference>::const_iterator r;
2703  for (r = global_references_.begin(); r != global_references_.end(); ++r) {
2704 
2705  if (r->second.index_ == index)
2706  return r->first;
2707  }
2708  std::string s;
2709  return s;
2710 }
2711 }
r_code::Atom
Definition: atom.h:104
r_code::SysView
Definition: r_code/object.h:119
r_code::SysObject
Definition: r_code/object.h:136
r_code::ImageObject
Definition: r_code/object.h:106
r_comp::Image
Definition: segments.h:177
r_comp::Metadata
Definition: segments.h:109