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

as2js  0.1.14
AlexScript to JavaScript
optimizer_matches.cpp
Go to the documentation of this file.
1 /* lib/optimizer_matches.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 "optimizer_tables.h"
35 
36 #include "as2js/exceptions.h"
37 
38 
39 namespace as2js
40 {
41 namespace optimizer_details
42 {
43 
44 
50 namespace
51 {
52 
53 
85 {
86  // match node types
87  if(match->f_node_types_count > 0)
88  {
89  Node::node_t const node_type(node->get_type());
90  for(size_t idx(0);; ++idx)
91  {
92  if(idx >= match->f_node_types_count)
93  {
94  return false;
95  }
96  if(match->f_node_types[idx] == node_type)
97  {
98  break;
99  }
100  }
101  }
102 
103  if(match->f_with_value != nullptr)
104  {
106 
107  // note: we only need to check STRING, INT64, and FLOAT64 literals
108  switch(value->f_operator)
109  {
111  if(node->has_side_effects())
112  {
113  return false;
114  }
115  break;
116 
118  if(value->f_int64 != 0)
119  {
120  if(static_cast<size_t>(value->f_int64) >= node_array.size())
121  {
122  throw exception_internal_error("INTERNAL ERROR: identifier check using an index larger than the existing nodes"); // LCOV_EXCL_LINE
123  }
124  if(node_array[value->f_int64]->get_string() != node->get_string())
125  {
126  return false;
127  }
128  }
129  else
130  {
131  if(node->get_string() != value->f_string)
132  {
133  return false;
134  }
135  }
136  break;
137 
139  switch(node->get_type())
140  {
142  {
143  uint32_t mask(static_cast<uint32_t>(value->f_float64));
144  if((node->get_int64().get() & mask) != value->f_int64)
145  {
146  return false;
147  }
148  }
149  break;
150 
152  {
153  uint32_t mask(static_cast<uint32_t>(value->f_float64));
154  if((static_cast<uint32_t>(node->get_float64().get()) & mask) != value->f_int64)
155  {
156  return false;
157  }
158  }
159  break;
160 
161  default:
162  throw exception_internal_error("INTERNAL ERROR: optimizer optimization_literal_t table used against an unsupported node type."); // LCOV_EXCL_LINE
163 
164  }
165  break;
166 
169  switch(node->get_type())
170  {
171  // This is not yet accessible (as in, nothing makes use of it
172  // and I'm not totally sure it will come up, re-add later if
173  // useful.)
174  //case Node::node_t::NODE_STRING:
175  // if(node->get_string() != value->f_string)
176  // {
177  // return false;
178  // }
179  // break;
180 
182  if(node->get_int64().get() != value->f_int64)
183  {
184  return false;
185  }
186  break;
187 
189 #pragma GCC diagnostic push
190 #pragma GCC diagnostic ignored "-Wfloat-equal"
191  // if we expect a NaN make sure both are NaN
192  // remember that == and != always return false
193  // when checked with one or two NaN
194  if(std::isnan(value->f_float64))
195  {
196  if(!node->get_float64().is_NaN())
197  {
198  return false;
199  }
200  }
201  else if(node->get_float64().get() != value->f_float64)
202  {
203  return false;
204  }
205 #pragma GCC diagnostic pop
206  break;
207 
208  default:
209  throw exception_internal_error("INTERNAL ERROR: optimizer optimization_literal_t table used against an unsupported node type."); // LCOV_EXCL_LINE
210 
211  }
212  break;
213 
215  if(node->to_boolean_type_only() != Node::node_t::NODE_TRUE)
216  {
217  return false;
218  }
219  break;
220 
222  if(node->to_boolean_type_only() != Node::node_t::NODE_FALSE)
223  {
224  return false;
225  }
226  break;
227 
228  default:
229  throw exception_internal_error("INTERNAL ERROR: optimizer optimization_literal_t table using an unsupported comparison operator."); // LCOV_EXCL_LINE
230 
231  }
232  }
233 
234  // match node attributes
235  if(match->f_attributes_count > 0)
236  {
237  Node::attribute_set_t attrs;
238  // note: if the list of attributes is just one entry and that
239  // one entry is NODE_ATTR_max, we compare the same thing
240  // twice (i.e. that all attributes are false)
241  for(size_t idx(0); idx < match->f_attributes_count; ++idx)
242  {
244  {
245  if(!node->compare_all_attributes(attrs))
246  {
247  return false;
248  }
249  attrs.reset();
250  }
251  else
252  {
253  attrs[static_cast<size_t>(match->f_attributes[idx])] = true;
254  }
255  }
256  if(!node->compare_all_attributes(attrs))
257  {
258  return false;
259  }
260  }
261 
262  // match node flags
263  if(match->f_flags_count > 0)
264  {
265  Node::flag_set_t flags;
266  // note: if the list of flags is just one entry and that
267  // one entry is NODE_FALG_max, we compare the same thing
268  // twice (i.e. that all flags are false)
269  for(size_t idx(0); idx < match->f_flags_count; ++idx)
270  {
271  if(match->f_flags[idx] == Node::flag_t::NODE_FLAG_max)
272  {
273  if(!node->compare_all_flags(flags))
274  {
275  return false;
276  }
277  flags.reset();
278  }
279  else
280  {
281  flags[static_cast<size_t>(match->f_flags[idx])] = true;
282  }
283  }
284  if(!node->compare_all_flags(flags))
285  {
286  return false;
287  }
288  }
289 
290  // TODO: we may want to add tests for the instance, type node, goto exit, goto enter links
291 
292  // everything matched
293  return true;
294 }
295 
296 
297 }
298 // noname namespace
299 
300 
327 bool match_tree(node_pointer_vector_t& node_array, Node::pointer_t node, optimization_match_t const *match, size_t match_count, uint8_t depth)
328 {
329  // attempt a match only if proper depth
330  if(match->f_depth == depth
331  && match_node(node_array, node, match))
332  {
333  node_array.push_back(node);
334 //std::cerr << "Matched " << node->get_type_name()
335 // << ", depth=" << static_cast<int>(depth)
336 // << ", count=" << match_count
337 // << ", children? " << ((match->f_match_flags & OPTIMIZATION_MATCH_FLAG_CHILDREN) != 0 ? "YES" : "no")
338 // << ", size=" << node_array.size()
339 // << "\n";
340 
341  size_t const max_child(node->get_children_size());
342  size_t c(max_child);
343 
344  // it matched, do we have more to check in the tree?
345  --match_count;
346  if(match_count != 0 && (match->f_match_flags & OPTIMIZATION_MATCH_FLAG_CHILDREN) != 0)
347  {
348 
349 #if defined(_DEBUG) || defined(DEBUG)
350  if(depth >= 255)
351  {
352  throw exception_internal_error("INTERNAL ERROR: optimizer is using a depth of more than 255."); // LCOV_EXCL_LINE
353  }
354 #endif
355 
356  // check that the children are a match
357  uint8_t const next_level(depth + 1);
358 
359  c = 0;
360  for(; match_count > 0; --match_count)
361  {
362  ++match;
363  if(match->f_depth == next_level)
364  {
365  if(c >= max_child)
366  {
367  // another match is required, but no more children are
368  // available in this node...
369  return false;
370  }
371  if(!match_tree(node_array, node->get_child(c), match, match_count, next_level))
372  {
373  // not a match
374  return false;
375  }
376  ++c;
377  }
378  else if(match->f_depth < next_level)
379  {
380  // we arrived at the end of this list of children
381  break;
382  }
383  }
384  }
385 
386  // return true if all children were taken in account
387  return c >= max_child;
388  }
389 
390  // no matches
391  return false;
392 }
393 
394 
395 }
396 // namespace optimizer_details
397 }
398 // namespace as2js
399 
400 // vim: ts=4 sw=4 et
bool match_tree(node_pointer_vector_t &node_array, Node::pointer_t node, optimization_match_t const *match, size_t match_count, uint8_t depth)
Compare a node against an optimization tree.
Definition of internal tables of the optimizer.
optimization_literal_t const * f_with_value
uint32_t const OPTIMIZATION_MATCH_FLAG_CHILDREN
std::vector< Node::pointer_t > node_pointer_vector_t
Definition: node.h:634
bool match_node(node_pointer_vector_t &node_array, Node::pointer_t node, optimization_match_t const *match)
Compare a node against a specific match.
std::shared_ptr< Node > pointer_t
Definition: node.h:67
std::bitset< static_cast< int >attribute_t::NODE_ATTR_max)> attribute_set_t
Definition: node.h:421
std::bitset< static_cast< size_t >flag_t::NODE_FLAG_max)> flag_set_t
Definition: node.h:345
The AlexScript to JavaScript namespace.
Definition: compiler.cpp:37

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