ast.cc revision 1e0659c275bb392c045087af4f6b0d7565cb3d77
1// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ast.h"
31#include "jump-target-inl.h"
32#include "parser.h"
33#include "scopes.h"
34#include "string-stream.h"
35
36namespace v8 {
37namespace internal {
38
39unsigned AstNode::current_id_ = 0;
40unsigned AstNode::count_ = 0;
41VariableProxySentinel VariableProxySentinel::this_proxy_(true);
42VariableProxySentinel VariableProxySentinel::identifier_proxy_(false);
43ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_;
44Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0);
45Call Call::sentinel_(NULL, NULL, 0);
46
47
48// ----------------------------------------------------------------------------
49// All the Accept member functions for each syntax tree node type.
50
51void Slot::Accept(AstVisitor* v) { v->VisitSlot(this); }
52
53#define DECL_ACCEPT(type)                                       \
54  void type::Accept(AstVisitor* v) { v->Visit##type(this); }
55AST_NODE_LIST(DECL_ACCEPT)
56#undef DECL_ACCEPT
57
58
59// ----------------------------------------------------------------------------
60// Implementation of other node functionality.
61
62Assignment* ExpressionStatement::StatementAsSimpleAssignment() {
63  return (expression()->AsAssignment() != NULL &&
64          !expression()->AsAssignment()->is_compound())
65      ? expression()->AsAssignment()
66      : NULL;
67}
68
69
70CountOperation* ExpressionStatement::StatementAsCountOperation() {
71  return expression()->AsCountOperation();
72}
73
74
75VariableProxy::VariableProxy(Variable* var)
76    : name_(var->name()),
77      var_(NULL),  // Will be set by the call to BindTo.
78      is_this_(var->is_this()),
79      inside_with_(false),
80      is_trivial_(false) {
81  BindTo(var);
82}
83
84
85VariableProxy::VariableProxy(Handle<String> name,
86                             bool is_this,
87                             bool inside_with)
88  : name_(name),
89    var_(NULL),
90    is_this_(is_this),
91    inside_with_(inside_with),
92    is_trivial_(false) {
93  // names must be canonicalized for fast equality checks
94  ASSERT(name->IsSymbol());
95}
96
97
98VariableProxy::VariableProxy(bool is_this)
99  : var_(NULL),
100    is_this_(is_this),
101    inside_with_(false),
102    is_trivial_(false) {
103}
104
105
106void VariableProxy::BindTo(Variable* var) {
107  ASSERT(var_ == NULL);  // must be bound only once
108  ASSERT(var != NULL);  // must bind
109  ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
110  // Ideally CONST-ness should match. However, this is very hard to achieve
111  // because we don't know the exact semantics of conflicting (const and
112  // non-const) multiple variable declarations, const vars introduced via
113  // eval() etc.  Const-ness and variable declarations are a complete mess
114  // in JS. Sigh...
115  var_ = var;
116  var->set_is_used(true);
117}
118
119
120Assignment::Assignment(Token::Value op,
121                       Expression* target,
122                       Expression* value,
123                       int pos)
124    : op_(op),
125      target_(target),
126      value_(value),
127      pos_(pos),
128      binary_operation_(NULL),
129      compound_load_id_(kNoNumber),
130      assignment_id_(GetNextId()),
131      block_start_(false),
132      block_end_(false),
133      is_monomorphic_(false),
134      receiver_types_(NULL) {
135  ASSERT(Token::IsAssignmentOp(op));
136  if (is_compound()) {
137    binary_operation_ =
138        new BinaryOperation(binary_op(), target, value, pos + 1);
139    compound_load_id_ = GetNextId();
140  }
141}
142
143
144Token::Value Assignment::binary_op() const {
145  switch (op_) {
146    case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
147    case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
148    case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
149    case Token::ASSIGN_SHL: return Token::SHL;
150    case Token::ASSIGN_SAR: return Token::SAR;
151    case Token::ASSIGN_SHR: return Token::SHR;
152    case Token::ASSIGN_ADD: return Token::ADD;
153    case Token::ASSIGN_SUB: return Token::SUB;
154    case Token::ASSIGN_MUL: return Token::MUL;
155    case Token::ASSIGN_DIV: return Token::DIV;
156    case Token::ASSIGN_MOD: return Token::MOD;
157    default: UNREACHABLE();
158  }
159  return Token::ILLEGAL;
160}
161
162
163bool FunctionLiteral::AllowsLazyCompilation() {
164  return scope()->AllowsLazyCompilation();
165}
166
167
168ObjectLiteral::Property::Property(Literal* key, Expression* value) {
169  emit_store_ = true;
170  key_ = key;
171  value_ = value;
172  Object* k = *key->handle();
173  if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
174    kind_ = PROTOTYPE;
175  } else if (value_->AsMaterializedLiteral() != NULL) {
176    kind_ = MATERIALIZED_LITERAL;
177  } else if (value_->AsLiteral() != NULL) {
178    kind_ = CONSTANT;
179  } else {
180    kind_ = COMPUTED;
181  }
182}
183
184
185ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
186  emit_store_ = true;
187  key_ = new Literal(value->name());
188  value_ = value;
189  kind_ = is_getter ? GETTER : SETTER;
190}
191
192
193bool ObjectLiteral::Property::IsCompileTimeValue() {
194  return kind_ == CONSTANT ||
195      (kind_ == MATERIALIZED_LITERAL &&
196       CompileTimeValue::IsCompileTimeValue(value_));
197}
198
199
200void ObjectLiteral::Property::set_emit_store(bool emit_store) {
201  emit_store_ = emit_store;
202}
203
204
205bool ObjectLiteral::Property::emit_store() {
206  return emit_store_;
207}
208
209
210bool IsEqualString(void* first, void* second) {
211  ASSERT((*reinterpret_cast<String**>(first))->IsString());
212  ASSERT((*reinterpret_cast<String**>(second))->IsString());
213  Handle<String> h1(reinterpret_cast<String**>(first));
214  Handle<String> h2(reinterpret_cast<String**>(second));
215  return (*h1)->Equals(*h2);
216}
217
218
219bool IsEqualNumber(void* first, void* second) {
220  ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
221  ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
222
223  Handle<Object> h1(reinterpret_cast<Object**>(first));
224  Handle<Object> h2(reinterpret_cast<Object**>(second));
225  if (h1->IsSmi()) {
226    return h2->IsSmi() && *h1 == *h2;
227  }
228  if (h2->IsSmi()) return false;
229  Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
230  Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
231  ASSERT(isfinite(n1->value()));
232  ASSERT(isfinite(n2->value()));
233  return n1->value() == n2->value();
234}
235
236
237void ObjectLiteral::CalculateEmitStore() {
238  HashMap properties(&IsEqualString);
239  HashMap elements(&IsEqualNumber);
240  for (int i = this->properties()->length() - 1; i >= 0; i--) {
241    ObjectLiteral::Property* property = this->properties()->at(i);
242    Literal* literal = property->key();
243    Handle<Object> handle = literal->handle();
244
245    if (handle->IsNull()) {
246      continue;
247    }
248
249    uint32_t hash;
250    HashMap* table;
251    void* key;
252    if (handle->IsSymbol()) {
253      Handle<String> name(String::cast(*handle));
254      if (name->AsArrayIndex(&hash)) {
255        Handle<Object> key_handle = Factory::NewNumberFromUint(hash);
256        key = key_handle.location();
257        table = &elements;
258      } else {
259        key = name.location();
260        hash = name->Hash();
261        table = &properties;
262      }
263    } else if (handle->ToArrayIndex(&hash)) {
264      key = handle.location();
265      table = &elements;
266    } else {
267      ASSERT(handle->IsNumber());
268      double num = handle->Number();
269      char arr[100];
270      Vector<char> buffer(arr, ARRAY_SIZE(arr));
271      const char* str = DoubleToCString(num, buffer);
272      Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
273      key = name.location();
274      hash = name->Hash();
275      table = &properties;
276    }
277    // If the key of a computed property is in the table, do not emit
278    // a store for the property later.
279    if (property->kind() == ObjectLiteral::Property::COMPUTED) {
280      if (table->Lookup(key, hash, false) != NULL) {
281        property->set_emit_store(false);
282      }
283    }
284    // Add key to the table.
285    table->Lookup(key, hash, true);
286  }
287}
288
289
290void TargetCollector::AddTarget(BreakTarget* target) {
291  // Add the label to the collector, but discard duplicates.
292  int length = targets_->length();
293  for (int i = 0; i < length; i++) {
294    if (targets_->at(i) == target) return;
295  }
296  targets_->Add(target);
297}
298
299
300bool Expression::GuaranteedSmiResult() {
301  BinaryOperation* node = AsBinaryOperation();
302  if (node == NULL) return false;
303  Token::Value op = node->op();
304  switch (op) {
305    case Token::COMMA:
306    case Token::OR:
307    case Token::AND:
308    case Token::ADD:
309    case Token::SUB:
310    case Token::MUL:
311    case Token::DIV:
312    case Token::MOD:
313    case Token::BIT_XOR:
314    case Token::SHL:
315      return false;
316      break;
317    case Token::BIT_OR:
318    case Token::BIT_AND: {
319      Literal* left = node->left()->AsLiteral();
320      Literal* right = node->right()->AsLiteral();
321      if (left != NULL && left->handle()->IsSmi()) {
322        int value = Smi::cast(*left->handle())->value();
323        if (op == Token::BIT_OR && ((value & 0xc0000000) == 0xc0000000)) {
324          // Result of bitwise or is always a negative Smi.
325          return true;
326        }
327        if (op == Token::BIT_AND && ((value & 0xc0000000) == 0)) {
328          // Result of bitwise and is always a positive Smi.
329          return true;
330        }
331      }
332      if (right != NULL && right->handle()->IsSmi()) {
333        int value = Smi::cast(*right->handle())->value();
334        if (op == Token::BIT_OR && ((value & 0xc0000000) == 0xc0000000)) {
335          // Result of bitwise or is always a negative Smi.
336          return true;
337        }
338        if (op == Token::BIT_AND && ((value & 0xc0000000) == 0)) {
339          // Result of bitwise and is always a positive Smi.
340          return true;
341        }
342      }
343      return false;
344      break;
345    }
346    case Token::SAR:
347    case Token::SHR: {
348      Literal* right = node->right()->AsLiteral();
349       if (right != NULL && right->handle()->IsSmi()) {
350        int value = Smi::cast(*right->handle())->value();
351        if ((value & 0x1F) > 1 ||
352            (op == Token::SAR && (value & 0x1F) == 1)) {
353          return true;
354        }
355       }
356       return false;
357       break;
358    }
359    default:
360      UNREACHABLE();
361      break;
362  }
363  return false;
364}
365
366
367void Expression::CopyAnalysisResultsFrom(Expression* other) {
368  bitfields_ = other->bitfields_;
369  type_ = other->type_;
370}
371
372
373bool UnaryOperation::ResultOverwriteAllowed() {
374  switch (op_) {
375    case Token::BIT_NOT:
376    case Token::SUB:
377      return true;
378    default:
379      return false;
380  }
381}
382
383
384bool BinaryOperation::ResultOverwriteAllowed() {
385  switch (op_) {
386    case Token::COMMA:
387    case Token::OR:
388    case Token::AND:
389      return false;
390    case Token::BIT_OR:
391    case Token::BIT_XOR:
392    case Token::BIT_AND:
393    case Token::SHL:
394    case Token::SAR:
395    case Token::SHR:
396    case Token::ADD:
397    case Token::SUB:
398    case Token::MUL:
399    case Token::DIV:
400    case Token::MOD:
401      return true;
402    default:
403      UNREACHABLE();
404  }
405  return false;
406}
407
408
409BinaryOperation::BinaryOperation(Assignment* assignment) {
410  ASSERT(assignment->is_compound());
411  op_ = assignment->binary_op();
412  left_ = assignment->target();
413  right_ = assignment->value();
414  pos_ = assignment->position();
415  CopyAnalysisResultsFrom(assignment);
416}
417
418
419// ----------------------------------------------------------------------------
420// Inlining support
421
422bool Block::IsInlineable() const {
423  const int count = statements_.length();
424  for (int i = 0; i < count; ++i) {
425    if (!statements_[i]->IsInlineable()) return false;
426  }
427  return true;
428}
429
430
431bool ExpressionStatement::IsInlineable() const {
432  return expression()->IsInlineable();
433}
434
435
436bool IfStatement::IsInlineable() const {
437  return condition()->IsInlineable() && then_statement()->IsInlineable() &&
438      else_statement()->IsInlineable();
439}
440
441
442bool ReturnStatement::IsInlineable() const {
443  return expression()->IsInlineable();
444}
445
446
447bool Conditional::IsInlineable() const {
448  return condition()->IsInlineable() && then_expression()->IsInlineable() &&
449      else_expression()->IsInlineable();
450}
451
452
453bool VariableProxy::IsInlineable() const {
454  return var()->is_global() || var()->IsStackAllocated();
455}
456
457
458bool Assignment::IsInlineable() const {
459  return target()->IsInlineable() && value()->IsInlineable();
460}
461
462
463bool Property::IsInlineable() const {
464  return obj()->IsInlineable() && key()->IsInlineable();
465}
466
467
468bool Call::IsInlineable() const {
469  if (!expression()->IsInlineable()) return false;
470  const int count = arguments()->length();
471  for (int i = 0; i < count; ++i) {
472    if (!arguments()->at(i)->IsInlineable()) return false;
473  }
474  return true;
475}
476
477
478bool CallNew::IsInlineable() const {
479  if (!expression()->IsInlineable()) return false;
480  const int count = arguments()->length();
481  for (int i = 0; i < count; ++i) {
482    if (!arguments()->at(i)->IsInlineable()) return false;
483  }
484  return true;
485}
486
487
488bool CallRuntime::IsInlineable() const {
489  const int count = arguments()->length();
490  for (int i = 0; i < count; ++i) {
491    if (!arguments()->at(i)->IsInlineable()) return false;
492  }
493  return true;
494}
495
496
497bool UnaryOperation::IsInlineable() const {
498  return expression()->IsInlineable();
499}
500
501
502bool BinaryOperation::IsInlineable() const {
503  return left()->IsInlineable() && right()->IsInlineable();
504}
505
506
507bool CompareOperation::IsInlineable() const {
508  return left()->IsInlineable() && right()->IsInlineable();
509}
510
511
512bool CompareToNull::IsInlineable() const {
513  return expression()->IsInlineable();
514}
515
516
517bool CountOperation::IsInlineable() const {
518  return expression()->IsInlineable();
519}
520
521
522// ----------------------------------------------------------------------------
523// Recording of type feedback
524
525void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
526  // Record type feedback from the oracle in the AST.
527  is_monomorphic_ = oracle->LoadIsMonomorphic(this);
528  if (key()->IsPropertyName()) {
529    if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_ArrayLength)) {
530      is_array_length_ = true;
531    } else if (oracle->LoadIsBuiltin(this, Builtins::LoadIC_StringLength)) {
532      is_string_length_ = true;
533    } else if (oracle->LoadIsBuiltin(this,
534                                     Builtins::LoadIC_FunctionPrototype)) {
535      is_function_prototype_ = true;
536    } else {
537      Literal* lit_key = key()->AsLiteral();
538      ASSERT(lit_key != NULL && lit_key->handle()->IsString());
539      Handle<String> name = Handle<String>::cast(lit_key->handle());
540      ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
541      receiver_types_ = types;
542    }
543  } else if (is_monomorphic_) {
544    monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
545  }
546}
547
548
549void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
550  Property* prop = target()->AsProperty();
551  ASSERT(prop != NULL);
552  is_monomorphic_ = oracle->StoreIsMonomorphic(this);
553  if (prop->key()->IsPropertyName()) {
554    Literal* lit_key = prop->key()->AsLiteral();
555    ASSERT(lit_key != NULL && lit_key->handle()->IsString());
556    Handle<String> name = Handle<String>::cast(lit_key->handle());
557    ZoneMapList* types = oracle->StoreReceiverTypes(this, name);
558    receiver_types_ = types;
559  } else if (is_monomorphic_) {
560    // Record receiver type for monomorphic keyed loads.
561    monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
562  }
563}
564
565
566void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
567  TypeInfo info = oracle->SwitchType(this);
568  if (info.IsSmi()) {
569    compare_type_ = SMI_ONLY;
570  } else if (info.IsNonPrimitive()) {
571    compare_type_ = OBJECT_ONLY;
572  } else {
573    ASSERT(compare_type_ == NONE);
574  }
575}
576
577
578static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) {
579  SharedFunctionInfo* info = target->shared();
580  // If the number of formal parameters of the target function does
581  // not match the number of arguments we're passing, we don't want to
582  // deal with it. Otherwise, we can call it directly.
583  return !target->NeedsArgumentsAdaption() ||
584      info->formal_parameter_count() == arity;
585}
586
587
588bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
589  if (check_type_ == RECEIVER_MAP_CHECK) {
590    // For primitive checks the holder is set up to point to the
591    // corresponding prototype object, i.e. one step of the algorithm
592    // below has been already performed.
593    // For non-primitive checks we clear it to allow computing targets
594    // for polymorphic calls.
595    holder_ = Handle<JSObject>::null();
596  }
597  while (true) {
598    LookupResult lookup;
599    type->LookupInDescriptors(NULL, *name, &lookup);
600    // If the function wasn't found directly in the map, we start
601    // looking upwards through the prototype chain.
602    if (!lookup.IsFound() && type->prototype()->IsJSObject()) {
603      holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
604      type = Handle<Map>(holder()->map());
605    } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
606      target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
607      return CanCallWithoutIC(target_, arguments()->length());
608    } else {
609      return false;
610    }
611  }
612}
613
614
615bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
616                               Handle<String> name) {
617  target_ = Handle<JSFunction>::null();
618  cell_ = Handle<JSGlobalPropertyCell>::null();
619  LookupResult lookup;
620  global->Lookup(*name, &lookup);
621  if (lookup.IsProperty() &&
622      lookup.type() == NORMAL &&
623      lookup.holder() == *global) {
624    cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(&lookup));
625    if (cell_->value()->IsJSFunction()) {
626      Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
627      // If the function is in new space we assume it's more likely to
628      // change and thus prefer the general IC code.
629      if (!Heap::InNewSpace(*candidate) &&
630          CanCallWithoutIC(candidate, arguments()->length())) {
631        target_ = candidate;
632        return true;
633      }
634    }
635  }
636  return false;
637}
638
639
640void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
641  Property* property = expression()->AsProperty();
642  ASSERT(property != NULL);
643  // Specialize for the receiver types seen at runtime.
644  Literal* key = property->key()->AsLiteral();
645  ASSERT(key != NULL && key->handle()->IsString());
646  Handle<String> name = Handle<String>::cast(key->handle());
647  receiver_types_ = oracle->CallReceiverTypes(this, name);
648#ifdef DEBUG
649  if (FLAG_enable_slow_asserts) {
650    if (receiver_types_ != NULL) {
651      int length = receiver_types_->length();
652      for (int i = 0; i < length; i++) {
653        Handle<Map> map = receiver_types_->at(i);
654        ASSERT(!map.is_null() && *map != NULL);
655      }
656    }
657  }
658#endif
659  is_monomorphic_ = oracle->CallIsMonomorphic(this);
660  check_type_ = oracle->GetCallCheckType(this);
661  if (is_monomorphic_) {
662    Handle<Map> map;
663    if (receiver_types_ != NULL && receiver_types_->length() > 0) {
664      ASSERT(check_type_ == RECEIVER_MAP_CHECK);
665      map = receiver_types_->at(0);
666    } else {
667      ASSERT(check_type_ != RECEIVER_MAP_CHECK);
668      holder_ = Handle<JSObject>(
669          oracle->GetPrototypeForPrimitiveCheck(check_type_));
670      map = Handle<Map>(holder_->map());
671    }
672    is_monomorphic_ = ComputeTarget(map, name);
673  }
674}
675
676
677void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
678  TypeInfo info = oracle->CompareType(this);
679  if (info.IsSmi()) {
680    compare_type_ = SMI_ONLY;
681  } else if (info.IsNonPrimitive()) {
682    compare_type_ = OBJECT_ONLY;
683  } else {
684    ASSERT(compare_type_ == NONE);
685  }
686}
687
688
689// ----------------------------------------------------------------------------
690// Implementation of AstVisitor
691
692bool AstVisitor::CheckStackOverflow() {
693  if (stack_overflow_) return true;
694  StackLimitCheck check;
695  if (!check.HasOverflowed()) return false;
696  return (stack_overflow_ = true);
697}
698
699
700void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
701  for (int i = 0; i < declarations->length(); i++) {
702    Visit(declarations->at(i));
703  }
704}
705
706
707void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
708  for (int i = 0; i < statements->length(); i++) {
709    Visit(statements->at(i));
710  }
711}
712
713
714void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
715  for (int i = 0; i < expressions->length(); i++) {
716    // The variable statement visiting code may pass NULL expressions
717    // to this code. Maybe this should be handled by introducing an
718    // undefined expression or literal?  Revisit this code if this
719    // changes
720    Expression* expression = expressions->at(i);
721    if (expression != NULL) Visit(expression);
722  }
723}
724
725
726// ----------------------------------------------------------------------------
727// Regular expressions
728
729#define MAKE_ACCEPT(Name)                                            \
730  void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) {   \
731    return visitor->Visit##Name(this, data);                         \
732  }
733FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
734#undef MAKE_ACCEPT
735
736#define MAKE_TYPE_CASE(Name)                                         \
737  RegExp##Name* RegExpTree::As##Name() {                             \
738    return NULL;                                                     \
739  }                                                                  \
740  bool RegExpTree::Is##Name() { return false; }
741FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
742#undef MAKE_TYPE_CASE
743
744#define MAKE_TYPE_CASE(Name)                                        \
745  RegExp##Name* RegExp##Name::As##Name() {                          \
746    return this;                                                    \
747  }                                                                 \
748  bool RegExp##Name::Is##Name() { return true; }
749FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
750#undef MAKE_TYPE_CASE
751
752RegExpEmpty RegExpEmpty::kInstance;
753
754
755static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
756  Interval result = Interval::Empty();
757  for (int i = 0; i < children->length(); i++)
758    result = result.Union(children->at(i)->CaptureRegisters());
759  return result;
760}
761
762
763Interval RegExpAlternative::CaptureRegisters() {
764  return ListCaptureRegisters(nodes());
765}
766
767
768Interval RegExpDisjunction::CaptureRegisters() {
769  return ListCaptureRegisters(alternatives());
770}
771
772
773Interval RegExpLookahead::CaptureRegisters() {
774  return body()->CaptureRegisters();
775}
776
777
778Interval RegExpCapture::CaptureRegisters() {
779  Interval self(StartRegister(index()), EndRegister(index()));
780  return self.Union(body()->CaptureRegisters());
781}
782
783
784Interval RegExpQuantifier::CaptureRegisters() {
785  return body()->CaptureRegisters();
786}
787
788
789bool RegExpAssertion::IsAnchoredAtStart() {
790  return type() == RegExpAssertion::START_OF_INPUT;
791}
792
793
794bool RegExpAssertion::IsAnchoredAtEnd() {
795  return type() == RegExpAssertion::END_OF_INPUT;
796}
797
798
799bool RegExpAlternative::IsAnchoredAtStart() {
800  ZoneList<RegExpTree*>* nodes = this->nodes();
801  for (int i = 0; i < nodes->length(); i++) {
802    RegExpTree* node = nodes->at(i);
803    if (node->IsAnchoredAtStart()) { return true; }
804    if (node->max_match() > 0) { return false; }
805  }
806  return false;
807}
808
809
810bool RegExpAlternative::IsAnchoredAtEnd() {
811  ZoneList<RegExpTree*>* nodes = this->nodes();
812  for (int i = nodes->length() - 1; i >= 0; i--) {
813    RegExpTree* node = nodes->at(i);
814    if (node->IsAnchoredAtEnd()) { return true; }
815    if (node->max_match() > 0) { return false; }
816  }
817  return false;
818}
819
820
821bool RegExpDisjunction::IsAnchoredAtStart() {
822  ZoneList<RegExpTree*>* alternatives = this->alternatives();
823  for (int i = 0; i < alternatives->length(); i++) {
824    if (!alternatives->at(i)->IsAnchoredAtStart())
825      return false;
826  }
827  return true;
828}
829
830
831bool RegExpDisjunction::IsAnchoredAtEnd() {
832  ZoneList<RegExpTree*>* alternatives = this->alternatives();
833  for (int i = 0; i < alternatives->length(); i++) {
834    if (!alternatives->at(i)->IsAnchoredAtEnd())
835      return false;
836  }
837  return true;
838}
839
840
841bool RegExpLookahead::IsAnchoredAtStart() {
842  return is_positive() && body()->IsAnchoredAtStart();
843}
844
845
846bool RegExpCapture::IsAnchoredAtStart() {
847  return body()->IsAnchoredAtStart();
848}
849
850
851bool RegExpCapture::IsAnchoredAtEnd() {
852  return body()->IsAnchoredAtEnd();
853}
854
855
856// Convert regular expression trees to a simple sexp representation.
857// This representation should be different from the input grammar
858// in as many cases as possible, to make it more difficult for incorrect
859// parses to look as correct ones which is likely if the input and
860// output formats are alike.
861class RegExpUnparser: public RegExpVisitor {
862 public:
863  RegExpUnparser();
864  void VisitCharacterRange(CharacterRange that);
865  SmartPointer<const char> ToString() { return stream_.ToCString(); }
866#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
867  FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
868#undef MAKE_CASE
869 private:
870  StringStream* stream() { return &stream_; }
871  HeapStringAllocator alloc_;
872  StringStream stream_;
873};
874
875
876RegExpUnparser::RegExpUnparser() : stream_(&alloc_) {
877}
878
879
880void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
881  stream()->Add("(|");
882  for (int i = 0; i <  that->alternatives()->length(); i++) {
883    stream()->Add(" ");
884    that->alternatives()->at(i)->Accept(this, data);
885  }
886  stream()->Add(")");
887  return NULL;
888}
889
890
891void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
892  stream()->Add("(:");
893  for (int i = 0; i <  that->nodes()->length(); i++) {
894    stream()->Add(" ");
895    that->nodes()->at(i)->Accept(this, data);
896  }
897  stream()->Add(")");
898  return NULL;
899}
900
901
902void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
903  stream()->Add("%k", that.from());
904  if (!that.IsSingleton()) {
905    stream()->Add("-%k", that.to());
906  }
907}
908
909
910
911void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
912                                          void* data) {
913  if (that->is_negated())
914    stream()->Add("^");
915  stream()->Add("[");
916  for (int i = 0; i < that->ranges()->length(); i++) {
917    if (i > 0) stream()->Add(" ");
918    VisitCharacterRange(that->ranges()->at(i));
919  }
920  stream()->Add("]");
921  return NULL;
922}
923
924
925void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
926  switch (that->type()) {
927    case RegExpAssertion::START_OF_INPUT:
928      stream()->Add("@^i");
929      break;
930    case RegExpAssertion::END_OF_INPUT:
931      stream()->Add("@$i");
932      break;
933    case RegExpAssertion::START_OF_LINE:
934      stream()->Add("@^l");
935      break;
936    case RegExpAssertion::END_OF_LINE:
937      stream()->Add("@$l");
938       break;
939    case RegExpAssertion::BOUNDARY:
940      stream()->Add("@b");
941      break;
942    case RegExpAssertion::NON_BOUNDARY:
943      stream()->Add("@B");
944      break;
945  }
946  return NULL;
947}
948
949
950void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
951  stream()->Add("'");
952  Vector<const uc16> chardata = that->data();
953  for (int i = 0; i < chardata.length(); i++) {
954    stream()->Add("%k", chardata[i]);
955  }
956  stream()->Add("'");
957  return NULL;
958}
959
960
961void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
962  if (that->elements()->length() == 1) {
963    that->elements()->at(0).data.u_atom->Accept(this, data);
964  } else {
965    stream()->Add("(!");
966    for (int i = 0; i < that->elements()->length(); i++) {
967      stream()->Add(" ");
968      that->elements()->at(i).data.u_atom->Accept(this, data);
969    }
970    stream()->Add(")");
971  }
972  return NULL;
973}
974
975
976void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
977  stream()->Add("(# %i ", that->min());
978  if (that->max() == RegExpTree::kInfinity) {
979    stream()->Add("- ");
980  } else {
981    stream()->Add("%i ", that->max());
982  }
983  stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
984  that->body()->Accept(this, data);
985  stream()->Add(")");
986  return NULL;
987}
988
989
990void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
991  stream()->Add("(^ ");
992  that->body()->Accept(this, data);
993  stream()->Add(")");
994  return NULL;
995}
996
997
998void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
999  stream()->Add("(-> ");
1000  stream()->Add(that->is_positive() ? "+ " : "- ");
1001  that->body()->Accept(this, data);
1002  stream()->Add(")");
1003  return NULL;
1004}
1005
1006
1007void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
1008                                         void* data) {
1009  stream()->Add("(<- %i)", that->index());
1010  return NULL;
1011}
1012
1013
1014void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
1015  stream()->Put('%');
1016  return NULL;
1017}
1018
1019
1020SmartPointer<const char> RegExpTree::ToString() {
1021  RegExpUnparser unparser;
1022  Accept(&unparser, NULL);
1023  return unparser.ToString();
1024}
1025
1026
1027RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
1028    : alternatives_(alternatives) {
1029  ASSERT(alternatives->length() > 1);
1030  RegExpTree* first_alternative = alternatives->at(0);
1031  min_match_ = first_alternative->min_match();
1032  max_match_ = first_alternative->max_match();
1033  for (int i = 1; i < alternatives->length(); i++) {
1034    RegExpTree* alternative = alternatives->at(i);
1035    min_match_ = Min(min_match_, alternative->min_match());
1036    max_match_ = Max(max_match_, alternative->max_match());
1037  }
1038}
1039
1040
1041RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
1042    : nodes_(nodes) {
1043  ASSERT(nodes->length() > 1);
1044  min_match_ = 0;
1045  max_match_ = 0;
1046  for (int i = 0; i < nodes->length(); i++) {
1047    RegExpTree* node = nodes->at(i);
1048    min_match_ += node->min_match();
1049    int node_max_match = node->max_match();
1050    if (kInfinity - max_match_ < node_max_match) {
1051      max_match_ = kInfinity;
1052    } else {
1053      max_match_ += node->max_match();
1054    }
1055  }
1056}
1057
1058
1059CaseClause::CaseClause(Expression* label,
1060                       ZoneList<Statement*>* statements,
1061                       int pos)
1062    : label_(label),
1063      statements_(statements),
1064      position_(pos),
1065      compare_type_(NONE) {}
1066
1067} }  // namespace v8::internal
1068