as2js: /home/snapwebsites/snapcpp/contrib/as2js/lib/node.cpp Source File

as2js  0.1.14
AlexScript to JavaScript
node.cpp
Go to the documentation of this file.
1 /* lib/node.cpp
2 
3 Copyright (c) 2005-2019 Made to Order Software Corp. All Rights Reserved
4 
6 
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16 
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31 
32 */
33 
34 #include "as2js/node.h"
35 
36 #include "as2js/exceptions.h"
37 #include "as2js/message.h"
38 
39 #include <algorithm>
40 #include <sstream>
41 #include <iomanip>
42 
43 
55 namespace as2js
56 {
57 
58 
59 
60 /**********************************************************************/
61 /**********************************************************************/
62 /*** NODE ***********************************************************/
63 /**********************************************************************/
64 /**********************************************************************/
65 
66 
67 
105  : f_type(type)
106  //, f_flags() -- auto-init
107  //, f_attributes() -- auto-init
108  //, f_switch_operator(NODE_UNKNOWN) -- auto-init
109  //, f_lock(0) -- auto-init
110  //, f_position() -- auto-init
111  //, f_int() -- auto-init
112  //, f_float() -- auto-init
113  //, f_str() -- auto-init
114  //, f_parent() -- auto-init
115  //, f_offset(0) -- auto-init
116  //, f_children() -- auto-init
117  //, f_link() -- auto-init
118  //, f_variables() -- auto-init
119  //, f_labels() -- auto-init
120 {
121  switch(type)
122  {
123  case node_t::NODE_EOF:
125  case node_t::NODE_ADD:
134  case node_t::NODE_COLON:
135  case node_t::NODE_COMMA:
137  case node_t::NODE_DIVIDE:
139  case node_t::NODE_LESS:
141  case node_t::NODE_MODULO:
146  case node_t::NODE_MEMBER:
150  case node_t::NODE_ARRAY:
152  case node_t::NODE_AS:
173  case node_t::NODE_AUTO:
175  case node_t::NODE_BREAK:
176  case node_t::NODE_BYTE:
177  case node_t::NODE_CALL:
178  case node_t::NODE_CASE:
179  case node_t::NODE_CATCH:
180  case node_t::NODE_CHAR:
181  case node_t::NODE_CLASS:
183  case node_t::NODE_CONST:
188  case node_t::NODE_DELETE:
190  case node_t::NODE_DO:
191  case node_t::NODE_DOUBLE:
192  case node_t::NODE_ELSE:
193  case node_t::NODE_EMPTY:
194  case node_t::NODE_ENUM:
195  case node_t::NODE_ENSURE:
196  case node_t::NODE_EQUAL:
199  case node_t::NODE_EXPORT:
200  case node_t::NODE_FALSE:
201  case node_t::NODE_FINAL:
203  case node_t::NODE_FLOAT:
205  case node_t::NODE_FOR:
207  case node_t::NODE_GOTO:
210  case node_t::NODE_IF:
212  case node_t::NODE_IMPORT:
213  case node_t::NODE_IN:
216  case node_t::NODE_INLINE:
218  case node_t::NODE_INT64:
221  case node_t::NODE_IS:
222  case node_t::NODE_LABEL:
224  case node_t::NODE_LIST:
228  case node_t::NODE_LONG:
229  case node_t::NODE_MATCH:
232  case node_t::NODE_NAME:
234  case node_t::NODE_NATIVE:
235  case node_t::NODE_NEW:
238  case node_t::NODE_NULL:
241  case node_t::NODE_PARAM:
246  case node_t::NODE_POWER:
250  case node_t::NODE_PUBLIC:
251  case node_t::NODE_RANGE:
254  case node_t::NODE_REST:
255  case node_t::NODE_RETURN:
256  case node_t::NODE_ROOT:
259  case node_t::NODE_SCOPE:
260  case node_t::NODE_SET:
265  case node_t::NODE_SHORT:
266  case node_t::NODE_STATIC:
269  case node_t::NODE_STRING:
270  case node_t::NODE_SUPER:
271  case node_t::NODE_SWITCH:
273  case node_t::NODE_THEN:
274  case node_t::NODE_THIS:
275  case node_t::NODE_THROW:
276  case node_t::NODE_THROWS:
278  case node_t::NODE_TRUE:
279  case node_t::NODE_TRY:
280  case node_t::NODE_TYPE:
281  case node_t::NODE_TYPEOF:
283  case node_t::NODE_USE:
284  case node_t::NODE_VAR:
288  case node_t::NODE_VOID:
290  case node_t::NODE_WHILE:
291  case node_t::NODE_WITH:
292  case node_t::NODE_YIELD:
293  break;
294 
295  // WARNING: we use default here because some people may call the
296  // function with something other than a properly defined
297  // node_t type
298  default:
299  // ERROR: some values are not valid as a type
300  throw exception_incompatible_node_type("invalid type used to create a node");
301 
302  }
303 }
304 
305 
325 Node::~Node() noexcept(false)
326 {
327  if(f_lock > 0)
328  {
329  // This should never happen.
330  //
332  msg << "a node got deleted while still locked."; // LCOV_EXCL_LINE
333  std::terminate(); // LCOV_EXCL_LINE
334  }
335 }
336 
337 
338 
339 /**********************************************************************/
340 /**********************************************************************/
341 /*** NODE SWITCH ****************************************************/
342 /**********************************************************************/
343 /**********************************************************************/
344 
345 
370 {
372  {
373  throw exception_internal_error("INTERNAL ERROR: get_switch_operator() called on a node which is not a switch node.");
374  }
375 
376  return f_switch_operator;
377 }
378 
379 
422 {
424  {
425  throw exception_internal_error("INTERNAL ERROR: set_switch_operator() called on a node which is not a switch node.");
426  }
427 
428  switch(op)
429  {
432  case node_t::NODE_EQUAL:
435  case node_t::NODE_MATCH:
436  case node_t::NODE_IN:
437  case node_t::NODE_IS:
438  case node_t::NODE_AS:
440  case node_t::NODE_LESS:
445  break;
446 
447  default:
448  throw exception_internal_error("INTERNAL ERROR: set_switch_operator() called with an operator which is not valid for switch.");
449 
450  }
451 
452  f_switch_operator = op;
453 }
454 
455 
456 /**********************************************************************/
457 /**********************************************************************/
458 /*** NODE POSITION **************************************************/
459 /**********************************************************************/
460 /**********************************************************************/
461 
462 
477 {
478  Node::pointer_t n(new Node(f_type));
479 
480  // this is why we want to have a function instead of doing new Node().
481  n->f_type_node = f_type_node;
482  n->f_flags = f_flags;
483  n->f_attribute_node = f_attribute_node;
484  n->f_attributes = f_attributes;
485  n->f_switch_operator = f_switch_operator;
486  //n->f_lock = f_lock; -- that would not make any sense here
487  n->f_position = f_position;
488  //n->f_param_depth = f_param_depth; -- specific to functions
489  //n->f_param_index = f_param_index;
490  //n->f_parent = f_parent; -- tree parameters cannot be changed here
491  //n->f_offset = f_offset;
492  //n->f_children = f_children;
493  n->f_instance = f_instance;
494  n->f_goto_enter = f_goto_enter;
495  n->f_goto_exit = f_goto_exit;
496  n->f_variables = f_variables;
497  n->f_labels = f_labels;
498 
499  switch(f_type)
500  {
501  case node_t::NODE_FALSE:
502  case node_t::NODE_TRUE:
503  case node_t::NODE_NULL:
505  break;
506 
508  n->f_float = f_float;
509  break;
510 
511  case node_t::NODE_INT64:
512  n->f_int = f_int;
513  break;
514 
515  case node_t::NODE_STRING:
517  n->f_str = f_str;
518  break;
519 
520  //case node_t::NODE_OBJECT_LITERAL: -- this one has children... TBD
521 
522  default:
523  throw exception_internal_error("INTERNAL ERROR: node.cpp: clone_basic_node(): called with a node which is not considered to be a basic node.");
524 
525  }
526 
527  return n;
528 }
529 
530 
555 {
556  // TBD: should we limit the type of replacement nodes?
557  Node::pointer_t n(new Node(type));
558 
559  // this is why we want to have a function instead of doing new Node().
560  n->f_position = f_position;
561 
562  return n;
563 }
564 
565 
587 void Node::set_position(Position const& position)
588 {
589  f_position = position;
590 }
591 
592 
610 {
611  return f_position;
612 }
613 
614 
615 // /**********************************************************************/
616 // /**********************************************************************/
617 // /*** NODE LINK ******************************************************/
618 // /**********************************************************************/
619 // /**********************************************************************/
620 //
621 //
622 // /** \brief Save a link in this node.
623 // *
624 // * This function saves a link pointer in this node. It can later be
625 // * retrieved using the get_link() function.
626 // *
627 // * If a link was already defined at that offset, the function raises
628 // * an exception and the existing offset is not modified.
629 // *
630 // * It is possible to clear a link by passing an empty smart pointer
631 // * down (i.e. pass nullptr.) If you first clear a link in this way,
632 // * you can then replace it with another pointer.
633 // *
634 // * \code
635 // * // do not throw because we reset the link first:
636 // * node->set_link(Node::link_t::LINK_TYPE, nullptr);
637 // * node->set_link(Node::link_t::LINK_TYPE, link);
638 // * \endcode
639 // *
640 // * Links are used to save information about a node such as its
641 // * type and attributes.
642 // *
643 // * \note
644 // * Links are saved as full smart pointers, not weak pointers. This means
645 // * a node that references another in this way may generate loops that
646 // * will not easily break when trying to release the whole tree.
647 // *
648 // * \note
649 // * The Node must not be locked.
650 // *
651 // * \exception exception_index_out_of_range
652 // * The index is out of range. Links make use of a very few predefined
653 // * indexes such as Node::link_t::LINK_ATTRIBUTES. However,
654 // * Node::link_t::LINK_max cannot be used as an index.
655 // *
656 // * \exception exception_already_defined
657 // * The link at that index is already defined and the function was called
658 // * anyway. This is an internal error because you should check whether the
659 // * value was already defined and if so use that value.
660 // *
661 // * \param[in] index The index of the link to save.
662 // * \param[in] link A smart pointer to the link.
663 // *
664 // * \sa get_link()
665 // */
666 // void Node::set_link(link_t index, pointer_t link)
667 // {
668 // modifying();
669 //
670 // if(index >= link_t::LINK_max)
671 // {
672 // throw exception_index_out_of_range("set_link() called with an index out of bounds.");
673 // }
674 //
675 // // make sure the size is reserved on first set
676 // if(f_link.empty())
677 // {
678 // f_link.resize(static_cast<vector_of_pointers_t::size_type>(link_t::LINK_max));
679 // }
680 //
681 // if(link)
682 // {
683 // // link already set?
684 // if(f_link[static_cast<size_t>(index)].lock())
685 // {
686 // throw exception_already_defined("a link was set twice at the same offset");
687 // }
688 //
689 // f_link[static_cast<size_t>(index)] = link;
690 // }
691 // else
692 // {
693 // f_link[static_cast<size_t>(index)].reset();
694 // }
695 // }
696 //
697 //
698 // /** \brief Retrieve a link previously saved with set_link().
699 // *
700 // * This function returns a pointer to a link that was previously
701 // * saved in this node using the set_link() function.
702 // *
703 // * Links are used to save information about a node such as its
704 // * type and attributes.
705 // *
706 // * The function may return a null pointer. You are responsible
707 // * for checking the validity of the link.
708 // *
709 // * \exception exception_index_out_of_range
710 // * The index is out of range. Links make use of a very few predefined
711 // * indexes such as Node::link_t::LINK_ATTRIBUTES. However,
712 // * Node::link_t::LINK_max cannot be used as an index.
713 // *
714 // * \param[in] index The index of the link to retrieve.
715 // *
716 // * \return A smart pointer to this link node.
717 // */
718 // Node::pointer_t Node::get_link(link_t index)
719 // {
720 // if(index >= link_t::LINK_max)
721 // {
722 // throw exception_index_out_of_range("get_link() called with an index out of bounds.");
723 // }
724 //
725 // if(f_link.empty())
726 // {
727 // return Node::pointer_t();
728 // }
729 //
730 // return f_link[static_cast<size_t>(index)].lock();
731 // }
732 //
733 
734 /**********************************************************************/
735 /**********************************************************************/
736 /*** NODE GOTO ******************************************************/
737 /**********************************************************************/
738 /**********************************************************************/
739 
740 
749 {
750  return f_goto_enter.lock();
751 }
752 
753 
762 {
763  return f_goto_exit.lock();
764 }
765 
766 
775 {
776  f_goto_enter = node;
777 }
778 
779 
788 {
789  f_goto_exit = node;
790 }
791 
792 
793 
794 
795 /**********************************************************************/
796 /**********************************************************************/
797 /*** NODE VARIABLE **************************************************/
798 /**********************************************************************/
799 /**********************************************************************/
800 
801 
828 {
829  if(node_t::NODE_VARIABLE != variable->f_type)
830  {
831  throw exception_incompatible_node_type("the variable parameter of the add_variable() function must be a NODE_VARIABLE");
832  }
833  // TODO: test the destination (i.e. this) to make sure only valid nodes
834  // accept variables; make it a separate function as all the
835  // variable functions should call it!
836 
837  f_variables.push_back(variable);
838 }
839 
840 
856 {
857  return f_variables.size();
858 }
859 
860 
889 {
890  return f_variables.at(index).lock();
891 }
892 
893 
894 /**********************************************************************/
895 /**********************************************************************/
896 /*** NODE LABEL *****************************************************/
897 /**********************************************************************/
898 /**********************************************************************/
899 
900 
931 {
932  if(node_t::NODE_LABEL != label->f_type
934  {
935  throw exception_incompatible_node_type("invalid type of node to call add_label() with");
936  }
937  if(label->f_str.empty())
938  {
939  throw exception_incompatible_node_data("a label without a valid name cannot be added to a function");
940  }
941  if(f_labels.find(label->f_str) != f_labels.end())
942  {
943  throw exception_already_defined("a label with the same name is already defined in this function.");
944  }
945 
946  f_labels[label->f_str] = label;
947 }
948 
949 
965 {
966  map_of_weak_pointers_t::const_iterator it(f_labels.find(name));
967  return it == f_labels.end() ? pointer_t() : it->second.lock();
968 }
969 
970 
971 
972 
973 }
974 // namespace as2js
975 
976 // vim: ts=4 sw=4 et
void set_goto_enter(pointer_t node)
Define the "Goto Enter" pointer.
Definition: node.cpp:774
void add_label(pointer_t label)
Add a label to a function.
Definition: node.cpp:930
weak_pointer_t f_goto_enter
Definition: node.h:623
weak_pointer_t f_type_node
Definition: node.h:595
pointer_t get_goto_enter() const
Save a link in this node.
Definition: node.cpp:748
pointer_t get_variable(int index) const
Retrieve the variable at the specified index.
Definition: node.cpp:888
weak_pointer_t f_goto_exit
Definition: node.h:624
node_t f_type
Definition: node.h:594
weak_pointer_t f_instance
Definition: node.h:620
node_t get_switch_operator() const
Retrieve the switch operator.
Definition: node.cpp:369
pointer_t get_goto_exit() const
Retrieve the "Goto Exit" pointer.
Definition: node.cpp:761
String f_str
Definition: node.h:610
int32_t f_lock
Definition: node.h:602
flag_set_t f_flags
Definition: node.h:596
virtual ~Node() noexcept(false)
Verify that a node is clean when deleting it.
Definition: node.cpp:325
Position const & get_position() const
The position of the node.
Definition: node.cpp:609
std::shared_ptr< Node > pointer_t
Definition: node.h:67
attribute_set_t f_attributes
Definition: node.h:598
Node(node_t type)
Initialize a node.
Definition: node.cpp:104
Float64 f_float
Definition: node.h:609
vector_of_weak_pointers_t f_variables
Definition: node.h:627
map_of_weak_pointers_t f_labels
Definition: node.h:628
pointer_t clone_basic_node() const
Create a clone of a basic node.
Definition: node.cpp:476
Int64 f_int
Definition: node.h:608
Position f_position
Definition: node.h:605
void set_position(Position const &position)
Change the position of the node.
Definition: node.cpp:587
node_t f_switch_operator
Definition: node.h:599
The AlexScript to JavaScript namespace.
Definition: compiler.cpp:37
void set_switch_operator(node_t op)
Set the switch statement operator.
Definition: node.cpp:421
pointer_t f_attribute_node
Definition: node.h:597
size_t get_variable_size() const
Retrieve the number of variables defined in this node.
Definition: node.cpp:855
void add_variable(pointer_t variable)
Add a variable to this node.
Definition: node.cpp:827
pointer_t find_label(String const &name) const
Find a label previously added with the add_label() function.
Definition: node.cpp:964
pointer_t create_replacement(node_t type) const
Create a new node with the given type.
Definition: node.cpp:554
void set_goto_exit(pointer_t node)
Define the "Goto Exit" pointer.
Definition: node.cpp:787

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.

Syndicate content

Snap! Websites
An Open Source CMS System in C++

Contact Us Directly