1fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org
7196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/api.h"
8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/ast.h"
9b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org#include "src/bailout-reason.h"
105de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/platform.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/bootstrapper.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/char-predicates-inl.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/compiler.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/messages.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/parser.h"
17196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/preparser.h"
18196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/runtime.h"
19196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/scanner-character-streams.h"
20196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/scopeinfo.h"
21196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/string-stream.h"
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
2471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.orgRegExpBuilder::RegExpBuilder(Zone* zone)
27400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org    : zone_(zone),
28c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      pending_empty_(false),
29c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      characters_(NULL),
30c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      terms_(),
31c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      alternatives_()
32a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#ifdef DEBUG
33c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    , last_added_(ADD_NONE)
34a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif
35a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  {}
36a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
37a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
38a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::FlushCharacters() {
39a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  pending_empty_ = false;
40a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (characters_ != NULL) {
41c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
42a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    characters_ = NULL;
437028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    text_.Add(atom, zone());
44a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    LAST(ADD_ATOM);
45a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
46a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
47a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
48a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
49a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::FlushText() {
50a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushCharacters();
51a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int num_text = text_.length();
52a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_text == 0) {
53a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
54a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (num_text == 1) {
557028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    terms_.Add(text_.last(), zone());
56a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
577028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    RegExpText* text = new(zone()) RegExpText(zone());
58a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    for (int i = 0; i < num_text; i++)
597028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      text_.Get(i)->AppendToText(text, zone());
607028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    terms_.Add(text, zone());
61a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
62a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  text_.Clear();
63a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
64a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
65a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
66a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddCharacter(uc16 c) {
67a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  pending_empty_ = false;
68a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (characters_ == NULL) {
697028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    characters_ = new(zone()) ZoneList<uc16>(4, zone());
70a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
717028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  characters_->Add(c, zone());
72a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_CHAR);
73a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
74a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
75a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
76a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddEmpty() {
77a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  pending_empty_ = true;
78a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
79a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
80a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
81a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddAtom(RegExpTree* term) {
82a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (term->IsEmpty()) {
83a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    AddEmpty();
84a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
85a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
86a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (term->IsTextElement()) {
87a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushCharacters();
887028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    text_.Add(term, zone());
89a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
90a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushText();
917028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    terms_.Add(term, zone());
92a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
93a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_ATOM);
94a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
95a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
96a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
97a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::AddAssertion(RegExpTree* assert) {
98a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushText();
997028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  terms_.Add(assert, zone());
100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_ASSERT);
101a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
102a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
103a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::NewAlternative() {
105a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushTerms();
106a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
107a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
108a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
109a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpBuilder::FlushTerms() {
110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushText();
111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int num_terms = terms_.length();
112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  RegExpTree* alternative;
113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_terms == 0) {
114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    alternative = RegExpEmpty::GetInstance();
115a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (num_terms == 1) {
116a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    alternative = terms_.last();
117a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
1187028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    alternative = new(zone()) RegExpAlternative(terms_.GetList(zone()));
119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
1207028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  alternatives_.Add(alternative, zone());
121a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  terms_.Clear();
122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_NONE);
123a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
124a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
125a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
126a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpBuilder::ToRegExp() {
127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  FlushTerms();
128a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int num_alternatives = alternatives_.length();
129a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_alternatives == 0) {
130a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return RegExpEmpty::GetInstance();
131a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
132a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_alternatives == 1) {
133a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return alternatives_.last();
134a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
1357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  return new(zone()) RegExpDisjunction(alternatives_.GetList(zone()));
136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
139dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgvoid RegExpBuilder::AddQuantifierToAtom(
140dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    int min, int max, RegExpQuantifier::QuantifierType quantifier_type) {
141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (pending_empty_) {
142a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    pending_empty_ = false;
143a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
144a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  RegExpTree* atom;
146a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (characters_ != NULL) {
147e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(last_added_ == ADD_CHAR);
148a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Last atom was character.
149a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Vector<const uc16> char_vector = characters_->ToConstVector();
150a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int num_chars = char_vector.length();
151a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (num_chars > 1) {
152a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
1537028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      text_.Add(new(zone()) RegExpAtom(prefix), zone());
154a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      char_vector = char_vector.SubVector(num_chars - 1, num_chars);
155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    characters_ = NULL;
157c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    atom = new(zone()) RegExpAtom(char_vector);
158a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushText();
159a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (text_.length() > 0) {
160e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(last_added_ == ADD_ATOM);
161a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    atom = text_.RemoveLast();
162a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    FlushText();
163a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (terms_.length() > 0) {
164e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(last_added_ == ADD_ATOM);
165a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    atom = terms_.RemoveLast();
16637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (atom->max_match() == 0) {
16737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      // Guaranteed to only match an empty string.
168a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      LAST(ADD_TERM);
169a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (min == 0) {
170a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return;
171a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
1727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      terms_.Add(atom, zone());
173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return;
174a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
175a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
176a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Only call immediately after adding an atom or character!
177a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    UNREACHABLE();
178a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
179a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
180dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  terms_.Add(
181dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      new(zone()) RegExpQuantifier(min, max, quantifier_type, atom), zone());
182a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  LAST(ADD_TERM);
183a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
184a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
185a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
18670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgFunctionEntry ParseData::GetFunctionEntry(int start) {
187d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // The current pre-data entry must be a FunctionEntry with the given
188d236f4d96b5dd21acc5ec57f4e50fa97cdd97bb6ricow@chromium.org  // start position.
18970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if ((function_index_ + FunctionEntry::kSize <= Length()) &&
19070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      (static_cast<int>(Data()[function_index_]) == start)) {
1915b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    int index = function_index_;
1925b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org    function_index_ += FunctionEntry::kSize;
19370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
19470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    return FunctionEntry(subvector);
19543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
19643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return FunctionEntry();
19743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
19843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
20070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgint ParseData::FunctionCount() {
20170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int functions_size = FunctionsSize();
20270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (functions_size < 0) return 0;
20370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (functions_size % FunctionEntry::kSize != 0) return 0;
20470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  return functions_size / FunctionEntry::kSize;
2055b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org}
2065b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org
2075b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org
20870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgbool ParseData::IsSane() {
2095b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // Check that the header data is valid and doesn't specify
2105b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // point to positions outside the store.
21170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int data_length = Length();
21270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (data_length < PreparseDataConstants::kHeaderSize) return false;
21370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (Magic() != PreparseDataConstants::kMagicNumber) return false;
21470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (Version() != PreparseDataConstants::kCurrentVersion) return false;
21570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (HasError()) return false;
2165b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  // Check that the space allocated for function entries is sane.
21770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int functions_size = FunctionsSize();
2185b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (functions_size < 0) return false;
2195b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  if (functions_size % FunctionEntry::kSize != 0) return false;
220d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Check that the total size has room for header and function entries.
2215b2fbee8f0b54371d42843c8fd90249a24093678ager@chromium.org  int minimum_size =
222beb2571dca14508fbbbb47a2f606327d5968ee92ager@chromium.org      PreparseDataConstants::kHeaderSize + functions_size;
22370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (data_length < minimum_size) return false;
22443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return true;
22543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
22643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
22870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgvoid ParseData::Initialize() {
22970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // Prepares state for use.
23070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  int data_length = Length();
23170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  if (data_length >= PreparseDataConstants::kHeaderSize) {
23270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    function_index_ = PreparseDataConstants::kHeaderSize;
23365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org  }
23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
23543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgbool ParseData::HasError() {
23870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  return Data()[PreparseDataConstants::kHasErrorOffset];
239ed1a63112185152bc10fbd02418393804a5fcf04machenbach@chromium.org}
240ed1a63112185152bc10fbd02418393804a5fcf04machenbach@chromium.org
241ed1a63112185152bc10fbd02418393804a5fcf04machenbach@chromium.org
24270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgunsigned ParseData::Magic() {
24370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  return Data()[PreparseDataConstants::kMagicOffset];
24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgunsigned ParseData::Version() {
24870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  return Data()[PreparseDataConstants::kVersionOffset];
24943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
25043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgint ParseData::FunctionsSize() {
25370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
25443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
25543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.orgvoid Parser::SetCachedData() {
2584c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  if (compile_options() == ScriptCompiler::kNoCompileOptions) {
25970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    cached_parse_data_ = NULL;
26070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  } else {
261e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(info_->cached_data() != NULL);
2624c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    if (compile_options() == ScriptCompiler::kConsumeParserCache) {
26370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      cached_parse_data_ = new ParseData(*info_->cached_data());
26470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    }
26570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  }
26643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
26743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
269dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgScope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
2706313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  DCHECK(ast_value_factory());
27108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  Scope* result =
2726313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      new (zone()) Scope(parent, scope_type, ast_value_factory(), zone());
273394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  result->Initialize();
27443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
27543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
27643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2774f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
27943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Target is a support class to facilitate manipulation of the
28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Parser's target_stack_ (the stack of potential 'break' and
28143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// 'continue' statement targets). Upon construction, a new target is
28243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// added; it is removed upon destruction.
28343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass Target BASE_EMBEDDED {
28543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
286e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target(Target** variable, AstNode* node)
287e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org      : variable_(variable), node_(node), previous_(*variable) {
288e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable = this;
28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
29043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ~Target() {
292e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable_ = previous_;
29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
295b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Target* previous() { return previous_; }
2960b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  AstNode* node() { return node_; }
297b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
29843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
299e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target** variable_;
3000b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org  AstNode* node_;
301b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Target* previous_;
30243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
30343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
30443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
30543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass TargetScope BASE_EMBEDDED {
30643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
307e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  explicit TargetScope(Target** variable)
308e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org      : variable_(variable), previous_(*variable) {
309e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable = NULL;
31043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
31143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
31243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ~TargetScope() {
313e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org    *variable_ = previous_;
31443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
31543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
31643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
317e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target** variable_;
318b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  Target* previous_;
31943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
32043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
32143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
32243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
32343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The CHECK_OK macro is a convenient macro to enforce error
32443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// handling for functions that may fail (by returning !*ok).
32543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
32643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// CAUTION: This macro appends extra statements after a call,
32743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// thus it must never be used where only a single statement
32843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// is correct (e.g. an if statement branch w/o braces)!
32943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define CHECK_OK  ok);   \
33143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (!*ok) return NULL; \
33243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ((void)0
33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define DUMMY )  // to make indentation work
33443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#undef DUMMY
33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
336a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define CHECK_FAILED  /**/);   \
337a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (failed_) return NULL; \
338a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ((void)0
339a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#define DUMMY )  // to make indentation work
340a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef DUMMY
34143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
34243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
34343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Implementation of Parser
34443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
345f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.orgclass ParserTraits::Checkpoint
346f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org    : public ParserBase<ParserTraits>::CheckpointBase {
347f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org public:
348f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org  explicit Checkpoint(ParserBase<ParserTraits>* parser)
349a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org      : CheckpointBase(parser), parser_(parser) {
350a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    saved_ast_node_id_gen_ = *parser_->ast_node_id_gen_;
351f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org  }
352f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org
353f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org  void Restore() {
354f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org    CheckpointBase::Restore();
355a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org    *parser_->ast_node_id_gen_ = saved_ast_node_id_gen_;
356f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org  }
357f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org
358f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org private:
359a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  ParserBase<ParserTraits>* parser_;
360a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  AstNode::IdGen saved_ast_node_id_gen_;
361f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org};
362f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org
363f1a5a1dc668380a183184ee7629703846eefcfaemachenbach@chromium.org
36408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgbool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
3656313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  return identifier == parser_->ast_value_factory()->eval_string() ||
3666313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org         identifier == parser_->ast_value_factory()->arguments_string();
367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
370a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgbool ParserTraits::IsPrototype(const AstRawString* identifier) const {
371a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  return identifier == parser_->ast_value_factory()->prototype_string();
372a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
373a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
374a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
375a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgbool ParserTraits::IsConstructor(const AstRawString* identifier) const {
376a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  return identifier == parser_->ast_value_factory()->constructor_string();
377a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
378a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
379a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
3806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgbool ParserTraits::IsThisProperty(Expression* expression) {
381e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expression != NULL);
3826b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  Property* property = expression->AsProperty();
3836b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  return property != NULL &&
3846b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org      property->obj()->AsVariableProxy() != NULL &&
3856b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org      property->obj()->AsVariableProxy()->is_this();
3866b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org}
3876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
3886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
38969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.orgbool ParserTraits::IsIdentifier(Expression* expression) {
39069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  VariableProxy* operand = expression->AsVariableProxy();
39169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  return operand != NULL && !operand->is_this();
39269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org}
39369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
39469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
395fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.orgvoid ParserTraits::PushPropertyName(FuncNameInferrer* fni,
396fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                    Expression* expression) {
397fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  if (expression->IsPropertyName()) {
39808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
399fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  } else {
400fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    fni->PushLiteralName(
4016313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        parser_->ast_value_factory()->anonymous_function_string());
402fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
403fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org}
404fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
405fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
4066b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgvoid ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
4076b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org                                                           Expression* right) {
408e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left != NULL);
4096b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  if (left->AsProperty() != NULL &&
4106b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org      right->AsFunctionLiteral() != NULL) {
4116b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org    right->AsFunctionLiteral()->set_pretenure();
4126b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  }
4136b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org}
4146b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
4156b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
416fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.orgvoid ParserTraits::CheckPossibleEvalCall(Expression* expression,
417fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org                                         Scope* scope) {
418fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  VariableProxy* callee = expression->AsVariableProxy();
419fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  if (callee != NULL &&
4206313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      callee->raw_name() == parser_->ast_value_factory()->eval_string()) {
421fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org    scope->DeclarationScope()->RecordEvalCall();
422fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  }
423fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org}
424fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
425fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org
426248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.orgExpression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) {
427248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  VariableProxy* proxy =
428248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      expression != NULL ? expression->AsVariableProxy() : NULL;
429248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  if (proxy != NULL) proxy->set_is_assigned();
4306b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  return expression;
4316b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org}
4326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
4336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
4342904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.orgbool ParserTraits::ShortcutNumericLiteralBinaryExpression(
4352904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org    Expression** x, Expression* y, Token::Value op, int pos,
4362904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org    AstNodeFactory<AstConstructionVisitor>* factory) {
43708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
43808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
43908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
44008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    double y_val = y->AsLiteral()->raw_value()->AsNumber();
4412904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org    switch (op) {
4422904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::ADD:
4432904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(x_val + y_val, pos);
4442904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4452904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::SUB:
4462904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(x_val - y_val, pos);
4472904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4482904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::MUL:
4492904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(x_val * y_val, pos);
4502904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4512904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::DIV:
4522904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(x_val / y_val, pos);
4532904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4542904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::BIT_OR: {
4552904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
4562904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(value, pos);
4572904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4582904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      }
4592904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::BIT_AND: {
4602904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
4612904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(value, pos);
4622904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4632904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      }
4642904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::BIT_XOR: {
4652904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
4662904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(value, pos);
4672904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4682904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      }
4692904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::SHL: {
4702904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
4712904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(value, pos);
4722904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4732904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      }
4742904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::SHR: {
4752904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
4762904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        uint32_t value = DoubleToUint32(x_val) >> shift;
4772904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(value, pos);
4782904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4792904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      }
4802904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      case Token::SAR: {
4812904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
4822904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
4832904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        *x = factory->NewNumberLiteral(value, pos);
4842904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        return true;
4852904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      }
4862904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      default:
4872904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org        break;
4882904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org    }
4892904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  }
4902904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org  return false;
4912904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org}
4922904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
4932904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org
49469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.orgExpression* ParserTraits::BuildUnaryExpression(
49569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    Expression* expression, Token::Value op, int pos,
49669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    AstNodeFactory<AstConstructionVisitor>* factory) {
497e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(expression != NULL);
498196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org  if (expression->IsLiteral()) {
49908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstValue* literal = expression->AsLiteral()->raw_value();
50069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    if (op == Token::NOT) {
50169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // Convert the literal to a boolean condition and negate it.
50269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      bool condition = literal->BooleanValue();
50308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      return factory->NewBooleanLiteral(!condition, pos);
50469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    } else if (literal->IsNumber()) {
50569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      // Compute some expressions involving only number literals.
50608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      double value = literal->AsNumber();
50769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      switch (op) {
50869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        case Token::ADD:
50969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org          return expression;
51069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        case Token::SUB:
51169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org          return factory->NewNumberLiteral(-value, pos);
51269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        case Token::BIT_NOT:
51369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org          return factory->NewNumberLiteral(~DoubleToInt32(value), pos);
51469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        default:
51569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org          break;
51669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org      }
51769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    }
51869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
51969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  // Desugar '+foo' => 'foo*1'
52069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  if (op == Token::ADD) {
52169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    return factory->NewBinaryOperation(
52269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        Token::MUL, expression, factory->NewNumberLiteral(1, pos), pos);
52369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
52469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  // The same idea for '-foo' => 'foo*(-1)'.
52569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  if (op == Token::SUB) {
52669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    return factory->NewBinaryOperation(
52769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
52869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
52969f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  // ...and one more time for '~foo' => 'foo^(~0)'.
53069f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  if (op == Token::BIT_NOT) {
53169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    return factory->NewBinaryOperation(
53269f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org        Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
53369f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
53469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  return factory->NewUnaryOperation(op, expression, pos);
53569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org}
53669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
53769f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
5384edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.orgExpression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
5394edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  return NewThrowError(
5406313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      parser_->ast_value_factory()->make_reference_error_string(), message,
5416313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      NULL, pos);
5424edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org}
5434edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5444edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5454edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.orgExpression* ParserTraits::NewThrowSyntaxError(
54608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const char* message, const AstRawString* arg, int pos) {
5476313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  return NewThrowError(parser_->ast_value_factory()->make_syntax_error_string(),
54808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                       message, arg, pos);
5494edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org}
5504edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5514edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5524edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.orgExpression* ParserTraits::NewThrowTypeError(
55308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const char* message, const AstRawString* arg, int pos) {
5546313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  return NewThrowError(parser_->ast_value_factory()->make_type_error_string(),
55508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                       message, arg, pos);
5564edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org}
5574edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5584edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5594edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.orgExpression* ParserTraits::NewThrowError(
56008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* constructor, const char* message,
56108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* arg, int pos) {
5624edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  Zone* zone = parser_->zone();
56308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  int argc = arg != NULL ? 1 : 0;
56408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* type =
5656313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      parser_->ast_value_factory()->GetOneByteString(message);
56608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  ZoneList<const AstRawString*>* array =
56708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      new (zone) ZoneList<const AstRawString*>(argc, zone);
56808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  if (arg != NULL) {
56908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    array->Add(arg, zone);
57008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  }
57108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
57208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  args->Add(parser_->factory()->NewStringLiteral(type, pos), zone);
57308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  args->Add(parser_->factory()->NewStringListLiteral(array, pos), zone);
5744edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  CallRuntime* call_constructor =
5754edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org      parser_->factory()->NewCallRuntime(constructor, NULL, args, pos);
5764edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  return parser_->factory()->NewThrow(call_constructor, pos);
5774edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org}
5784edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
5794edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid ParserTraits::ReportMessageAt(Scanner::Location source_location,
581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                   const char* message,
582285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org                                   const char* arg,
5832904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org                                   bool is_reference_error) {
58497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  if (parser_->stack_overflow()) {
58597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    // Suppress the error message (syntax error or such) in the presence of a
58697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    // stack overflow. The isolate allows only one pending exception at at time
58797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    // and we want to report the stack overflow later.
58897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return;
58997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
5906a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->has_pending_error_ = true;
5916a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_location_ = source_location;
5926a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_message_ = message;
5936a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_char_arg_ = arg;
59408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  parser_->pending_error_arg_ = NULL;
5956a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_is_reference_error_ = is_reference_error;
596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid ParserTraits::ReportMessage(const char* message,
60008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                 const char* arg,
60108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                 bool is_reference_error) {
60208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  Scanner::Location source_location = parser_->scanner()->location();
60308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  ReportMessageAt(source_location, message, arg, is_reference_error);
60408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org}
60508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org
60608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org
60708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgvoid ParserTraits::ReportMessage(const char* message,
60808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                 const AstRawString* arg,
6092904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org                                 bool is_reference_error) {
610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scanner::Location source_location = parser_->scanner()->location();
611285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org  ReportMessageAt(source_location, message, arg, is_reference_error);
612f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
614f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid ParserTraits::ReportMessageAt(Scanner::Location source_location,
616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                   const char* message,
61708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                   const AstRawString* arg,
6182904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org                                   bool is_reference_error) {
61997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  if (parser_->stack_overflow()) {
62097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    // Suppress the error message (syntax error or such) in the presence of a
62197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    // stack overflow. The isolate allows only one pending exception at at time
62297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    // and we want to report the stack overflow later.
62397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return;
62497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  }
6256a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->has_pending_error_ = true;
6266a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_location_ = source_location;
6276a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_message_ = message;
6286a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_char_arg_ = NULL;
6296a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_arg_ = arg;
6306a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  parser_->pending_error_is_reference_error_ = is_reference_error;
631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
63408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgconst AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
63508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* result =
6366313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      parser_->scanner()->CurrentSymbol(parser_->ast_value_factory());
637e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result != NULL);
638b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  return result;
639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
642a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.orgconst AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
643a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  double double_value = parser_->scanner()->DoubleValue();
644a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  char array[100];
645a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  const char* string =
646fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org      DoubleToCString(double_value, Vector<char>(array, arraysize(array)));
647a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org  return ast_value_factory()->GetOneByteString(string);
648a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org}
649a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
650a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
65108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgconst AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
6526313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgExpression* ParserTraits::ThisExpression(
6579d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) {
6589d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org  return factory->NewVariableProxy(scope->receiver(), pos);
659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
6615e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.orgExpression* ParserTraits::SuperReference(
6625e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) {
6635e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  return factory->NewSuperReference(
6645e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      ThisExpression(scope, factory, pos)->AsVariableProxy(),
6655e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org      pos);
6665e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org}
667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
668a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgExpression* ParserTraits::ClassLiteral(
669a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    const AstRawString* name, Expression* extends, Expression* constructor,
670a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    ZoneList<ObjectLiteral::Property*>* properties, int pos,
671a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    AstNodeFactory<AstConstructionVisitor>* factory) {
672a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  return factory->NewClassLiteral(name, extends, constructor, properties, pos);
673a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
674a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
675486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.orgLiteral* ParserTraits::ExpressionFromLiteral(
676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Token::Value token, int pos,
677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Scanner* scanner,
678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    AstNodeFactory<AstConstructionVisitor>* factory) {
679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  switch (token) {
680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    case Token::NULL_LITERAL:
68108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      return factory->NewNullLiteral(pos);
682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    case Token::TRUE_LITERAL:
68308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      return factory->NewBooleanLiteral(true, pos);
684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    case Token::FALSE_LITERAL:
68508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      return factory->NewBooleanLiteral(false, pos);
686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    case Token::NUMBER: {
68797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      double value = scanner->DoubleValue();
688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      return factory->NewNumberLiteral(value, pos);
689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    default:
691e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(false);
692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  return NULL;
694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgExpression* ParserTraits::ExpressionFromIdentifier(
69808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* name, int pos, Scope* scope,
699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    AstNodeFactory<AstConstructionVisitor>* factory) {
700f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The name may refer to a module instance object, so its type is unknown.
702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG
703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (FLAG_print_interface_details)
70408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    PrintF("# Variable %.*s ", name->length(), name->raw_data());
705f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif
706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Interface* interface = Interface::NewUnknown(parser_->zone());
707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  return scope->NewUnresolved(factory, name, interface, pos);
708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgExpression* ParserTraits::ExpressionFromString(
712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int pos, Scanner* scanner,
713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    AstNodeFactory<AstConstructionVisitor>* factory) {
71408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* symbol = GetSymbol(scanner);
715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
71608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  return factory->NewStringLiteral(symbol, pos);
717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
7203e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.orgExpression* ParserTraits::GetIterator(
7213e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    Expression* iterable, AstNodeFactory<AstConstructionVisitor>* factory) {
7223e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  Expression* iterator_symbol_literal =
7233e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      factory->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
7243e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  int pos = iterable->position();
7253e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  Expression* prop =
7263e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org      factory->NewProperty(iterable, iterator_symbol_literal, pos);
7273e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  Zone* zone = parser_->zone();
7283e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
7293e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org  return factory->NewCall(prop, args, pos);
7303e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org}
7313e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
7323e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org
733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgLiteral* ParserTraits::GetLiteralTheHole(
734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int position, AstNodeFactory<AstConstructionVisitor>* factory) {
73508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgExpression* ParserTraits::ParseV8Intrinsic(bool* ok) {
740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  return parser_->ParseV8Intrinsic(ok);
741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
744486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.orgFunctionLiteral* ParserTraits::ParseFunctionLiteral(
7452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const AstRawString* name, Scanner::Location function_name_location,
7462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    bool name_is_strict_reserved, FunctionKind kind,
7472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    int function_token_position, FunctionLiteral::FunctionType type,
7482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
7492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  return parser_->ParseFunctionLiteral(
7502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      name, function_name_location, name_is_strict_reserved, kind,
7512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      function_token_position, type, arity_restriction, ok);
752486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org}
753486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
754486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
75521d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.orgParser::Parser(CompilationInfo* info, ParseInfo* parse_info)
75621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    : ParserBase<ParserTraits>(&scanner_, parse_info->stack_limit,
75721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org                               info->extension(), NULL, info->zone(),
75821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org                               info->ast_node_id_gen(), this),
75921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      scanner_(parse_info->unicode_cache),
7601b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org      reusable_preparser_(NULL),
7611e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      original_scope_(NULL),
76243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      target_stack_(NULL),
76370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      cached_parse_data_(NULL),
7646a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org      info_(info),
7656a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org      has_pending_error_(false),
7666a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org      pending_error_message_(NULL),
76708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      pending_error_arg_(NULL),
76821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      pending_error_char_arg_(NULL),
76921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      total_preparse_skipped_(0),
77021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      pre_parse_timer_(NULL) {
771b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(!script().is_null() || info->source_stream() != NULL);
772e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
773e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_modules(!info->is_native() && FLAG_harmony_modules);
774e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
775e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  set_allow_lazy(false);  // Must be explicitly enabled.
7769bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  set_allow_arrow_functions(FLAG_harmony_arrow_functions);
777ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org  set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
7785e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  set_allow_classes(FLAG_harmony_classes);
7792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  set_allow_harmony_object_literals(FLAG_harmony_object_literals);
7805de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
7815de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org       ++feature) {
7825de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org    use_counts_[feature] = 0;
7835de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  }
7846313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (info->ast_value_factory() == NULL) {
7856313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    // info takes ownership of AstValueFactory.
7866313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    info->SetAstValueFactory(
7876313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        new AstValueFactory(zone(), parse_info->hash_seed));
78821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  }
78943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
79043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
79143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
7925a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgFunctionLiteral* Parser::ParseProgram() {
7934000f228dd279f96628ed845f1e81d01ba7e14d8jkummerow@chromium.org  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
7944000f228dd279f96628ed845f1e81d01ba7e14d8jkummerow@chromium.org  // see comment for HistogramTimerScope class.
79521d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org
79621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // It's OK to use the counters here, since this function is only called in
79721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // the main thread.
7984000f228dd279f96628ed845f1e81d01ba7e14d8jkummerow@chromium.org  HistogramTimerScope timer_scope(isolate()->counters()->parse(), true);
7996313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  Handle<String> source(String::cast(script()->source()));
8007979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  isolate()->counters()->total_parse_size()->Increment(source->length());
8015de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::ElapsedTimer timer;
802dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (FLAG_trace_parse) {
803dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    timer.Start();
804dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
8056313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
80643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
80743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Initialize parser state.
80869f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  CompleteParserRecorder recorder;
8094c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org
8104c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  if (compile_options() == ScriptCompiler::kProduceParserCache) {
81169f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    log_ = &recorder;
8124c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  } else if (compile_options() == ScriptCompiler::kConsumeParserCache) {
81370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    cached_parse_data_->Initialize();
81469f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
81569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org
8169e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  source = String::Flatten(source);
817304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  FunctionLiteral* result;
818b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
819b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Scope* top_scope = NULL;
820b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Scope* eval_scope = NULL;
8215f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (source->IsExternalTwoByteString()) {
8225f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    // Notice that the stream is destroyed at the end of the branch block.
8235f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    // The last line of the blocks can't be moved outside, even though they're
8245f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org    // identical calls.
825154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    ExternalTwoByteStringUtf16CharacterStream stream(
8265f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org        Handle<ExternalTwoByteString>::cast(source), 0, source->length());
8279e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    scanner_.Initialize(&stream);
828b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    result = DoParseProgram(info(), &top_scope, &eval_scope);
8295f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  } else {
830154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    GenericStringUtf16CharacterStream stream(source, 0, source->length());
8319e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org    scanner_.Initialize(&stream);
832b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    result = DoParseProgram(info(), &top_scope, &eval_scope);
833b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  }
834b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  top_scope->set_end_position(source->length());
835b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  if (eval_scope != NULL) {
836b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    eval_scope->set_end_position(source->length());
8375f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
83821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  HandleSourceURLComments();
839304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
840304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  if (FLAG_trace_parse && result != NULL) {
841dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    double ms = timer.Elapsed().InMillisecondsF();
842304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    if (info()->is_eval()) {
843304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      PrintF("[parsing eval");
844304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    } else if (info()->script()->name()->IsString()) {
845304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      String* name = String::cast(info()->script()->name());
846304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      SmartArrayPointer<char> name_chars = name->ToCString();
847afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org      PrintF("[parsing script: %s", name_chars.get());
848304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    } else {
849304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org      PrintF("[parsing script");
850304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    }
851304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org    PrintF(" - took %0.3f ms]\n", ms);
852304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
8534c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  if (compile_options() == ScriptCompiler::kProduceParserCache) {
85470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
85569f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org    log_ = NULL;
85669f64b1a8bfa6f5418b7c1f71d4e0833f76e93edmachenbach@chromium.org  }
857304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  return result;
8585f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
8595f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
8605f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
861b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgFunctionLiteral* Parser::DoParseProgram(CompilationInfo* info, Scope** scope,
862b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                        Scope** eval_scope) {
863e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(scope_ == NULL);
864e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(target_stack_ == NULL);
86543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
86643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  FunctionLiteral* result = NULL;
867b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  {
868b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    *scope = NewScope(scope_, GLOBAL_SCOPE);
869b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    info->SetGlobalScope(*scope);
87012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (!info->context().is_null() && !info->context()->IsNativeContext()) {
871b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      *scope = Scope::DeserializeScopeChain(*info->context(), *scope, zone());
87208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
87308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      // means the Parser cannot operate independent of the V8 heap. Tell the
87408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      // string table to internalize strings and values right after they're
87508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      // created.
8766313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      ast_value_factory()->Internalize(isolate());
877355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    }
878b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    original_scope_ = *scope;
8792c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org    if (info->is_eval()) {
880b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      if (!(*scope)->is_global_scope() || info->strict_mode() == STRICT) {
881b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org        *scope = NewScope(*scope, EVAL_SCOPE);
8822c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org      }
883355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    } else if (info->is_global()) {
884b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      *scope = NewScope(*scope, GLOBAL_SCOPE);
88527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    }
886b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    (*scope)->set_start_position(0);
887b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    // End position will be set by the caller.
888355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
889cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org    // Compute the parsing mode.
890e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    Mode mode = (FLAG_lazy && allow_lazy()) ? PARSE_LAZILY : PARSE_EAGERLY;
891b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    if (allow_natives_syntax() || extension_ != NULL ||
892b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org        (*scope)->is_eval_scope()) {
893cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org      mode = PARSE_EAGERLY;
894cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org    }
895cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org    ParsingModeScope parsing_mode(this, mode);
896cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org
897f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org    // Enters 'scope'.
898b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    FunctionState function_state(&function_state_, &scope_, *scope, zone(),
8996313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                                 ast_value_factory(), info->ast_node_id_gen());
900f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org
901486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    scope_->SetStrictMode(info->strict_mode());
9027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
90343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    bool ok = true;
904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int beg_pos = scanner()->location().beg_pos;
905b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    ParseSourceElements(body, Token::EOS, info->is_eval(), true, eval_scope,
906b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                        &ok);
907d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
908486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    if (ok && strict_mode() == STRICT) {
909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
9100ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    }
9111805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
912a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    if (ok && allow_harmony_scoping() && strict_mode() == STRICT) {
913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CheckConflictingVarDeclarations(scope_, &ok);
9141805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    }
9151805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
9169faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
9179faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      if (body->length() != 1 ||
9189faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org          !body->at(0)->IsExpressionStatement() ||
9199faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org          !body->at(0)->AsExpressionStatement()->
9209faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org              expression()->IsFunctionLiteral()) {
921285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org        ReportMessage("single_function_literal");
9229faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org        ok = false;
9239faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org      }
9249faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org    }
9259faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org
92643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (ok) {
927b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      result = factory()->NewFunctionLiteral(
9286313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->empty_string(), ast_value_factory(), scope_,
9296313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          body, function_state.materialized_literal_count(),
930c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org          function_state.expected_property_count(),
9319d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org          function_state.handler_count(), 0,
93256454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org          FunctionLiteral::kNoDuplicateParameters,
9339d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org          FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
9342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org          FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
935b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      result->set_ast_properties(factory()->visitor()->ast_properties());
9362c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org      result->set_dont_optimize_reason(
9372c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org          factory()->visitor()->dont_optimize_reason());
93843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
93943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
94043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
94143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure the target stack is empty.
942e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(target_stack_ == NULL);
94343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
94443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
94543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
94643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
947f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
9485a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.orgFunctionLiteral* Parser::ParseLazy() {
94921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // It's OK to use the counters here, since this function is only called in
95021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // the main thread.
951dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
9526313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  Handle<String> source(String::cast(script()->source()));
9537979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  isolate()->counters()->total_parse_size()->Increment(source->length());
9545de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  base::ElapsedTimer timer;
955dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  if (FLAG_trace_parse) {
956dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    timer.Start();
957dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org  }
9585a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
959304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
9605f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  // Initialize parser state.
9619e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  source = String::Flatten(source);
962304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  FunctionLiteral* result;
9635f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  if (source->IsExternalTwoByteString()) {
964154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    ExternalTwoByteStringUtf16CharacterStream stream(
9655f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org        Handle<ExternalTwoByteString>::cast(source),
9664d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org        shared_info->start_position(),
9674d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org        shared_info->end_position());
9681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    result = ParseLazy(&stream);
9695f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  } else {
970154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org    GenericStringUtf16CharacterStream stream(source,
971154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org                                             shared_info->start_position(),
972154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org                                             shared_info->end_position());
9731510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org    result = ParseLazy(&stream);
9745f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org  }
975304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org
976304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  if (FLAG_trace_parse && result != NULL) {
977dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org    double ms = timer.Elapsed().InMillisecondsF();
978de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
979afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org    PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
980304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  }
981304cc33f8259ef467e8e3c79f448d0bae0e8cd85yangguo@chromium.org  return result;
9825f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org}
9835f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
9845f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
9851510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.orgFunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
9865a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  Handle<SharedFunctionInfo> shared_info = info()->shared_info();
9879e3e0b618a14a05efd7d66f20bac4423dd3a1a2ffschneider@chromium.org  scanner_.Initialize(source);
988e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(scope_ == NULL);
989e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(target_stack_ == NULL);
9905f0c45f2cacb31d36a8f80c31f17bda7751a3644ager@chromium.org
9914d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org  Handle<String> name(String::cast(shared_info->name()));
9926313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  DCHECK(ast_value_factory());
9936313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
9946313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  const AstRawString* raw_name = ast_value_factory()->GetString(name);
99508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  fni_->PushEnclosingName(raw_name);
99665fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
997471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
99843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
99943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Place holder for the result.
100043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  FunctionLiteral* result = NULL;
100143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
100243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  {
100343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parse the function literal.
1004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
10055a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    info()->SetGlobalScope(scope);
10065a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    if (!info()->closure().is_null()) {
10075a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
10087028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                           zone());
10094d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    }
10101e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org    original_scope_ = scope;
101108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    FunctionState function_state(&function_state_, &scope_, scope, zone(),
10126313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                                 ast_value_factory(),
10136313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                                 info()->ast_node_id_gen());
1014e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
1015e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(info()->strict_mode() == shared_info->strict_mode());
1016486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    scope->SetStrictMode(shared_info->strict_mode());
1017dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    FunctionLiteral::FunctionType function_type = shared_info->is_expression()
10187c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org        ? (shared_info->is_anonymous()
10197c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org              ? FunctionLiteral::ANONYMOUS_EXPRESSION
10207c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org              : FunctionLiteral::NAMED_EXPRESSION)
10217c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org        : FunctionLiteral::DECLARATION;
102243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    bool ok = true;
10239d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org
10249d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    if (shared_info->is_arrow()) {
10259d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org      Expression* expression = ParseExpression(false, &ok);
1026e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(expression->IsFunctionLiteral());
10279d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org      result = expression->AsFunctionLiteral();
10289d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    } else {
10299d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org      result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
10309d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org                                    false,  // Strict mode name already checked.
10312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                    shared_info->kind(), RelocInfo::kNoPosition,
10329d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org                                    function_type,
10339d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org                                    FunctionLiteral::NORMAL_ARITY, &ok);
10349d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    }
103543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Make sure the results agree.
1036e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ok == (result != NULL));
103743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
103843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
103943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure the target stack is empty.
1040e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(target_stack_ == NULL);
104143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
104221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  if (result != NULL) {
10434d3fe4e246b0312eba361689f288ddf8dd516960danno@chromium.org    Handle<String> inferred_name(shared_info->inferred_name());
1044a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    result->set_inferred_name(inferred_name);
104543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
104643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
104743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
104843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1049f05f2913e034b9332e55c02c9395e701725c02c1kmillikin@chromium.org
1050fa943b736b1d996084393011529d568165bb5d83lrn@chromium.orgvoid* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
1051b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                  int end_token, bool is_eval, bool is_global,
1052b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                  Scope** eval_scope, bool* ok) {
105343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // SourceElements ::
1054f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //   (ModuleElement)* <end_token>
105543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
105643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Allocate a target stack to use for this set of source
105743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // elements. This way, all scripts and functions get their own
105843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // target stack thus avoiding illegal breaks and continues across
105943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // functions.
1060e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  TargetScope scope(&this->target_stack_);
106143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1062e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(processor != NULL);
10630a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  bool directive_prologue = true;     // Parsing directive prologue.
10640a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
106543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != end_token) {
10660a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (directive_prologue && peek() != Token::STRING) {
10670a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      directive_prologue = false;
10680a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
10690a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
1070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Scanner::Location token_loc = scanner()->peek_location();
107133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    Statement* stat;
107233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    if (is_global && !is_eval) {
107333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      stat = ParseModuleElement(NULL, CHECK_OK);
107433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    } else {
107533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org      stat = ParseBlockElement(NULL, CHECK_OK);
107633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org    }
10770a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (stat == NULL || stat->IsEmpty()) {
10780a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      directive_prologue = false;   // End of directive prologue.
10790a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      continue;
10800a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
10810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
10820a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    if (directive_prologue) {
10830a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      // A shot at a directive.
1084f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      ExpressionStatement* e_stat;
1085f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com      Literal* literal;
10860a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      // Still processing directive prologue?
10870a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      if ((e_stat = stat->AsExpressionStatement()) != NULL &&
10880a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          (literal = e_stat->expression()->AsLiteral()) != NULL &&
108908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org          literal->raw_value()->IsString()) {
10905de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org        // Check "use strict" directive (ES5 14.1) and "use asm" directive. Only
10915de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org        // one can be present.
1092486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        if (strict_mode() == SLOPPY &&
109308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org            literal->raw_value()->AsString() ==
10946313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                ast_value_factory()->use_strict_string() &&
10955de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org            token_loc.end_pos - token_loc.beg_pos ==
10966313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                ast_value_factory()->use_strict_string()->length() + 2) {
10972c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // TODO(mstarzinger): Global strict eval calls, need their own scope
10982c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // as specified in ES5 10.4.2(3). The correct fix would be to always
10992c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // add this scope in DoParseProgram(), but that requires adaptations
11002c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          // all over the code base, so we go with a quick-fix for now.
1101cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org          // In the same manner, we have to patch the parsing mode.
1102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          if (is_eval && !scope_->is_eval_scope()) {
1103e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org            DCHECK(scope_->is_global_scope());
1104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            Scope* scope = NewScope(scope_, EVAL_SCOPE);
1105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            scope->set_start_position(scope_->start_position());
1106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            scope->set_end_position(scope_->end_position());
1107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            scope_ = scope;
1108b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org            if (eval_scope != NULL) {
1109b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org              // Caller will correct the positions of the ad hoc eval scope.
1110b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org              *eval_scope = scope;
1111b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org            }
1112cddc71f18a46e6117cc765b1c53ca122e7aaa318rossberg@chromium.org            mode_ = PARSE_EAGERLY;
11132c067b150f65db3e076b6b5a813e7f6f2492f770rossberg@chromium.org          }
1114486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          scope_->SetStrictMode(STRICT);
11150a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          // "use strict" is the only directive for now.
11160a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org          directive_prologue = false;
11175de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org        } else if (literal->raw_value()->AsString() ==
11186313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                       ast_value_factory()->use_asm_string() &&
11195de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org                   token_loc.end_pos - token_loc.beg_pos ==
11206313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                       ast_value_factory()->use_asm_string()->length() + 2) {
11215de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org          // Store the usage count; The actual use counter on the isolate is
11225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org          // incremented after parsing is done.
11235de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org          ++use_counts_[v8::Isolate::kUseAsm];
1124a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org          scope_->SetAsmModule();
11250a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        }
11260a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      } else {
11270a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        // End of the directive prologue.
11280a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org        directive_prologue = false;
11290a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org      }
11300a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
11310a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
11327028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    processor->Add(stat, zone());
113343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
1134911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
113543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return 0;
113643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
113743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
113843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
113908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels,
1140f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org                                      bool* ok) {
1141f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // (Ecma 262 5th Edition, clause 14):
1142f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // SourceElement:
1143f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Statement
1144f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    FunctionDeclaration
1145f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //
1146f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // In harmony mode we allow additionally the following productions
1147f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModuleElement:
1148f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    LetDeclaration
1149f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ConstDeclaration
1150f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ModuleDeclaration
1151f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ImportDeclaration
1152f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ExportDeclaration
1153f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //    GeneratorDeclaration
1154f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1155f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  switch (peek()) {
1156f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::FUNCTION:
1157812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseFunctionDeclaration(NULL, ok);
1158a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    case Token::CLASS:
1159a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      return ParseClassDeclaration(NULL, ok);
1160f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::IMPORT:
1161f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseImportDeclaration(ok);
1162f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::EXPORT:
1163f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseExportDeclaration(ok);
116470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    case Token::CONST:
116570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      return ParseVariableStatement(kModuleElement, NULL, ok);
116670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    case Token::LET:
1167e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(allow_harmony_scoping());
116870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      if (strict_mode() == STRICT) {
116970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        return ParseVariableStatement(kModuleElement, NULL, ok);
117070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      }
117170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      // Fall through.
1172a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    default: {
1173a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      Statement* stmt = ParseStatement(labels, CHECK_OK);
1174a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      // Handle 'module' as a context-sensitive keyword.
1175a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      if (FLAG_harmony_modules &&
1176a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org          peek() == Token::IDENTIFIER &&
1177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          !scanner()->HasAnyLineTerminatorBeforeNext() &&
1178a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org          stmt != NULL) {
1179a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org        ExpressionStatement* estmt = stmt->AsExpressionStatement();
118008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
118108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org            estmt->expression()->AsVariableProxy()->raw_name() ==
11826313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                ast_value_factory()->module_string() &&
1183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            !scanner()->literal_contains_escapes()) {
1184812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          return ParseModuleDeclaration(NULL, ok);
1185a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org        }
1186a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      }
1187a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      return stmt;
1188a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    }
1189f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1190f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1191f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1192f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
119308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
119408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                          bool* ok) {
1195f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModuleDeclaration:
1196f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    'module' Identifier Module
1197f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1198a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
119908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name =
120008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1201bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1202bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1203bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details)
120408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    PrintF("# Module %.*s ", name->length(), name->raw_data());
1205bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1206bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1207812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Module* module = ParseModule(CHECK_OK);
12088e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
1209812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declaration* declaration =
1210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      factory()->NewModuleDeclaration(proxy, module, scope_, pos);
1211812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declare(declaration, true, CHECK_OK);
1212812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1213bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1214bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details)
121508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    PrintF("# Module %.*s ", name->length(), name->raw_data());
1216bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interfaces) {
121708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    PrintF("module %.*s: ", name->length(), name->raw_data());
1218bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    module->interface()->Print();
1219bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  }
1220bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1221bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
12227028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  if (names) names->Add(name, zone());
122381cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  if (module->body() == NULL)
1224a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewEmptyStatement(pos);
122581cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  else
1226a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewModuleStatement(proxy, module->body(), pos);
1227f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1228f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1229f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1230f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModule(bool* ok) {
1231f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Module:
1232f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    '{' ModuleElement '}'
1233812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    '=' ModulePath ';'
1234812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'at' String ';'
1235f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1236f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  switch (peek()) {
1237f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::LBRACE:
1238f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseModuleLiteral(ok);
1239f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1240812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::ASSIGN: {
1241f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      Expect(Token::ASSIGN, CHECK_OK);
1242812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      Module* result = ParseModulePath(CHECK_OK);
1243812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ExpectSemicolon(CHECK_OK);
1244812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return result;
1245812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
1246f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1247812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    default: {
12481fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ExpectContextualKeyword(CStrVector("at"), CHECK_OK);
1249812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      Module* result = ParseModuleUrl(CHECK_OK);
1250812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ExpectSemicolon(CHECK_OK);
1251812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return result;
1252812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
1253f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1254f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1255f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1256f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1257f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModuleLiteral(bool* ok) {
1258f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Module:
1259f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    '{' ModuleElement '}'
1260f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1261a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1262f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Construct block expecting 16 statements.
1263a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* body = factory()->NewBlock(NULL, 16, false, RelocInfo::kNoPosition);
1264bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1265bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details) PrintF("# Literal ");
1266bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* scope = NewScope(scope_, MODULE_SCOPE);
1268f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1269f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Expect(Token::LBRACE, CHECK_OK);
1270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  scope->set_start_position(scanner()->location().beg_pos);
1271486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  scope->SetStrictMode(STRICT);
1272f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1273f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  {
1274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    BlockState block_state(&scope_, scope);
12757028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    TargetCollector collector(zone());
1276f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    Target target(&this->target_stack_, &collector);
1277f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    Target target_body(&this->target_stack_, body);
1278f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1279f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    while (peek() != Token::RBRACE) {
1280f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      Statement* stat = ParseModuleElement(NULL, CHECK_OK);
1281f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      if (stat && !stat->IsEmpty()) {
1282400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body->AddStatement(stat, zone());
1283f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      }
1284f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    }
1285f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1286f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1287f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Expect(Token::RBRACE, CHECK_OK);
1288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  scope->set_end_position(scanner()->location().end_pos);
1289ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  body->set_scope(scope);
1290bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
129181cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  // Check that all exports are bound.
1292ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Interface* interface = scope->interface();
129381cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  for (Interface::Iterator it = interface->iterator();
129481cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org       !it.done(); it.Advance()) {
1295fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org    if (scope->LookupLocal(it.name()) == NULL) {
1296285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ParserTraits::ReportMessage("module_export_undefined", it.name());
129781cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org      *ok = false;
129881cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org      return NULL;
129981cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org    }
130081cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  }
130181cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org
1302ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  interface->MakeModule(ok);
1303e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(*ok);
1304ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  interface->Freeze(ok);
1305e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(*ok);
1306a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewModuleLiteral(body, interface, pos);
1307f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1308f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1309f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1310f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModulePath(bool* ok) {
1311f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModulePath:
1312f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Identifier
1313f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ModulePath '.' Identifier
1314f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1315a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1316f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Module* result = ParseModuleVariable(CHECK_OK);
1317f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  while (Check(Token::PERIOD)) {
131808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* name = ParseIdentifierName(CHECK_OK);
1319bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1320bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_print_interface_details)
132108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      PrintF("# Path .%.*s ", name->length(), name->raw_data());
1322bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1323a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    Module* member = factory()->NewModulePath(result, name, pos);
13247028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    result->interface()->Add(name, member->interface(), zone(), ok);
1325bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (!*ok) {
1326bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1327bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (FLAG_print_interfaces) {
132808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data());
1329bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("result: ");
1330bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        result->interface()->Print();
1331bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("member: ");
1332bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        member->interface()->Print();
1333bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      }
1334bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1335285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ParserTraits::ReportMessage("invalid_module_path", name);
1336bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      return NULL;
1337bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    }
1338bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    result = member;
1339f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1340f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1341f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  return result;
1342f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1343f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1344f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1345f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModuleVariable(bool* ok) {
1346f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // ModulePath:
1347f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Identifier
1348f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1349a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
135008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name =
135108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1352bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1353bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details)
135408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    PrintF("# Module variable %.*s ", name->length(), name->raw_data());
1355bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  VariableProxy* proxy = scope_->NewUnresolved(
135728583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org      factory(), name, Interface::NewModule(zone()),
1358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      scanner()->location().beg_pos);
1359bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1360a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewModuleVariable(proxy, pos);
1361f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1362f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1363f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1364f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgModule* Parser::ParseModuleUrl(bool* ok) {
1365f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // Module:
1366812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    String
1367f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1368a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1369f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Expect(Token::STRING, CHECK_OK);
137008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* symbol = GetSymbol(scanner());
1371f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1372bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  // TODO(ES6): Request JS resource from environment...
1373bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1374bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1375bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (FLAG_print_interface_details) PrintF("# Url ");
1376bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1377ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
13788e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  // Create an empty literal as long as the feature isn't finished.
13798e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  USE(symbol);
1380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* scope = NewScope(scope_, MODULE_SCOPE);
1381a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
13828e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  body->set_scope(scope);
13838e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  Interface* interface = scope->interface();
1384a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Module* result = factory()->NewModuleLiteral(body, interface, pos);
1385ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  interface->Freeze(ok);
1386e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(*ok);
138781cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  interface->Unify(scope->interface(), zone(), ok);
1388e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(*ok);
1389ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  return result;
1390f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1391f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1392f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1393812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgModule* Parser::ParseModuleSpecifier(bool* ok) {
1394812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // ModuleSpecifier:
1395812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    String
1396812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    ModulePath
1397812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1398812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  if (peek() == Token::STRING) {
1399812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    return ParseModuleUrl(ok);
1400812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  } else {
1401812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    return ParseModulePath(ok);
1402812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1403812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org}
1404812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1405812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1406f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.orgBlock* Parser::ParseImportDeclaration(bool* ok) {
1407812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // ImportDeclaration:
1408812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
1409812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //
1410812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // TODO(ES6): implement destructuring ImportSpecifiers
1411812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1412a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
1413812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Expect(Token::IMPORT, CHECK_OK);
141408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  ZoneList<const AstRawString*> names(1, zone());
1415812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
141608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = ParseIdentifierName(CHECK_OK);
14177028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  names.Add(name, zone());
1418812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  while (peek() == Token::COMMA) {
1419812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Consume(Token::COMMA);
1420812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    name = ParseIdentifierName(CHECK_OK);
14217028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    names.Add(name, zone());
1422812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1423812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
14241fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
1425812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Module* module = ParseModuleSpecifier(CHECK_OK);
1426812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  ExpectSemicolon(CHECK_OK);
1427812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1428812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // Generate a separate declaration for each identifier.
1429812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // TODO(ES6): once we implement destructuring, make that one declaration.
1430a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
1431812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  for (int i = 0; i < names.length(); ++i) {
1432bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1433bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_print_interface_details)
143408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      PrintF("# Import %.*s ", name->length(), name->raw_data());
1435bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
14367028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Interface* interface = Interface::NewUnknown(zone());
14377028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    module->interface()->Add(names[i], interface, zone(), ok);
1438bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (!*ok) {
1439bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1440bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (FLAG_print_interfaces) {
144108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(),
144208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org               name->raw_data());
1443bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        PrintF("module: ");
1444bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        module->interface()->Print();
1445bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      }
1446bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1447285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ParserTraits::ReportMessage("invalid_module_path", name);
1448bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      return NULL;
1449bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    }
1450bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
1451812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declaration* declaration =
1452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        factory()->NewImportDeclaration(proxy, module, scope_, pos);
1453812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declare(declaration, true, CHECK_OK);
1454812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1455812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1456812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  return block;
1457f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1458f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1459f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1460812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgStatement* Parser::ParseExportDeclaration(bool* ok) {
1461812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // ExportDeclaration:
1462812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' Identifier (',' Identifier)* ';'
1463812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' VariableDeclaration
1464812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' FunctionDeclaration
1465f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //    'export' GeneratorDeclaration
1466812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //    'export' ModuleDeclaration
1467812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  //
1468812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  // TODO(ES6): implement structuring ExportSpecifiers
1469812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1470812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Expect(Token::EXPORT, CHECK_OK);
1471812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1472812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Statement* result = NULL;
147308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  ZoneList<const AstRawString*> names(1, zone());
1474812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  switch (peek()) {
1475812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::IDENTIFIER: {
1476a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      int pos = position();
147708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      const AstRawString* name =
14788297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org          ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1479812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      // Handle 'module' as a context-sensitive keyword.
14806313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      if (name != ast_value_factory()->module_string()) {
14817028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        names.Add(name, zone());
1482812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        while (peek() == Token::COMMA) {
1483812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org          Consume(Token::COMMA);
14848297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org          name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
14857028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          names.Add(name, zone());
1486812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        }
1487812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        ExpectSemicolon(CHECK_OK);
1488a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        result = factory()->NewEmptyStatement(pos);
1489812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      } else {
1490812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org        result = ParseModuleDeclaration(&names, CHECK_OK);
1491812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      }
1492812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      break;
1493812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    }
1494812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1495812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::FUNCTION:
1496812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      result = ParseFunctionDeclaration(&names, CHECK_OK);
1497812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      break;
1498812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1499a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    case Token::CLASS:
1500a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      result = ParseClassDeclaration(&names, CHECK_OK);
1501a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      break;
1502a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1503812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::VAR:
1504812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::LET:
1505812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    case Token::CONST:
1506812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
1507812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      break;
1508812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1509812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    default:
1510812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      *ok = false;
1511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      ReportUnexpectedToken(scanner()->current_token());
1512812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return NULL;
1513812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1514812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
15157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Every export of a module may be assigned.
15167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  for (int i = 0; i < names.length(); ++i) {
15177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    Variable* var = scope_->Lookup(names[i]);
15187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (var == NULL) {
15197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // TODO(sigurds) This is an export that has no definition yet,
15207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      // not clear what to do in this case.
15217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      continue;
15227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
15237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (!IsImmutableVariableMode(var->mode())) {
15247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      var->set_maybe_assigned();
15257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
15267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
15277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1528bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  // Extract declared names into export declarations and interface.
1529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Interface* interface = scope_->interface();
1530812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  for (int i = 0; i < names.length(); ++i) {
1531bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1532bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_print_interface_details)
153308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data());
1534bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
15357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Interface* inner = Interface::NewUnknown(zone());
15367028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    interface->Add(names[i], inner, zone(), CHECK_OK);
15377028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (!*ok)
15387028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      return NULL;
1539bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    VariableProxy* proxy = NewUnresolved(names[i], LET, inner);
1540bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    USE(proxy);
1541bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // TODO(rossberg): Rethink whether we actually need to store export
1542bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // declarations (for compilation?).
1543bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    // ExportDeclaration* declaration =
1544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //     factory()->NewExportDeclaration(proxy, scope_, position);
1545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // scope_->AddDeclaration(declaration);
1546812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  }
1547812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1548e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result != NULL);
1549812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  return result;
1550f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1551f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1552f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
155308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels,
1554f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org                                     bool* ok) {
1555f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // (Ecma 262 5th Edition, clause 14):
1556f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // SourceElement:
1557f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    Statement
1558f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    FunctionDeclaration
1559f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //
1560f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // In harmony mode we allow additionally the following productions
1561f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // BlockElement (aka SourceElement):
1562f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    LetDeclaration
1563f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //    ConstDeclaration
1564f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //    GeneratorDeclaration
1565a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //    ClassDeclaration
1566f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1567f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  switch (peek()) {
1568f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::FUNCTION:
1569812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseFunctionDeclaration(NULL, ok);
1570a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    case Token::CLASS:
1571a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      return ParseClassDeclaration(NULL, ok);
1572f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    case Token::CONST:
1573812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseVariableStatement(kModuleElement, NULL, ok);
157470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    case Token::LET:
1575e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(allow_harmony_scoping());
157670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      if (strict_mode() == STRICT) {
157770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        return ParseVariableStatement(kModuleElement, NULL, ok);
157870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      }
157970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      // Fall through.
1580f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    default:
1581f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      return ParseStatement(labels, ok);
1582f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  }
1583f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org}
1584f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
1585f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org
158608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
158708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                  bool* ok) {
158843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Statement ::
158943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Block
159043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   VariableStatement
159143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   EmptyStatement
159243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ExpressionStatement
159343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   IfStatement
159443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   IterationStatement
159543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ContinueStatement
159643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   BreakStatement
159743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ReturnStatement
159843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   WithStatement
159943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   LabelledStatement
160043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   SwitchStatement
160143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   ThrowStatement
160243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   TryStatement
160343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   DebuggerStatement
160443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
160543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note: Since labels can only be used by 'break' and 'continue'
160643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // statements, which themselves are only valid within blocks,
160743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // iterations or 'switch' statements (i.e., BreakableStatements),
160843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // labels can be simply ignored in all other cases; except for
16093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // trivial labeled break statements 'label: break label' which is
161043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // parsed into an empty statement.
161143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  switch (peek()) {
161243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::LBRACE:
161343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return ParseBlock(labels, ok);
161443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
161543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::SEMICOLON:
161643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Next();
1617a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
161843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
161943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::IF:
1620a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseIfStatement(labels, ok);
162143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::DO:
1623a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseDoWhileStatement(labels, ok);
162443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::WHILE:
1626a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseWhileStatement(labels, ok);
162743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
162843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::FOR:
1629a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseForStatement(labels, ok);
163043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
163143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::CONTINUE:
1632a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseContinueStatement(ok);
163343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
163443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::BREAK:
1635a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseBreakStatement(labels, ok);
163643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
163743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::RETURN:
1638a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseReturnStatement(ok);
163943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::WITH:
1641a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseWithStatement(labels, ok);
164243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::SWITCH:
1644a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseSwitchStatement(labels, ok);
164543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::THROW:
1647a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseThrowStatement(ok);
164843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
164943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::TRY: {
165043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // NOTE: It is somewhat complicated to have labels on
165143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // try-statements. When breaking out of a try-finally statement,
165243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // one must take great care not to treat it as a
165343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // fall-through. It is much easier just to wrap the entire
165443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // try-statement in a statement block and put the labels there
1655a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      Block* result =
1656a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
1657e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org      Target target(&this->target_stack_, result);
165843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      TryStatement* statement = ParseTryStatement(CHECK_OK);
1659400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      if (result) result->AddStatement(statement, zone());
166043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return result;
166143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
166243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
16639ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    case Token::FUNCTION: {
1664c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // FunctionDeclaration is only allowed in the context of SourceElements
1665c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // (Ecma 262 5th Edition, clause 14):
1666c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // SourceElement:
1667c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      //    Statement
1668c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      //    FunctionDeclaration
1669c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Common language extension is to allow function declaration in place
1670c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // of any statement. This language extension is disabled in strict mode.
1671f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      //
1672f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // In Harmony mode, this case also handles the extension:
1673f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      // Statement:
1674f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org      //    GeneratorDeclaration
1675486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      if (strict_mode() == STRICT) {
1676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        ReportMessageAt(scanner()->peek_location(), "strict_function");
16779ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        *ok = false;
16789ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        return NULL;
16799ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org      }
1680812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      return ParseFunctionDeclaration(NULL, ok);
16819ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    }
168243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1683a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    case Token::CLASS:
1684a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      return ParseClassDeclaration(NULL, ok);
1685a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
168643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    case Token::DEBUGGER:
1687a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseDebuggerStatement(ok);
168843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
168970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    case Token::VAR:
169070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    case Token::CONST:
169170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      return ParseVariableStatement(kStatement, NULL, ok);
169270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
169370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    case Token::LET:
1694e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(allow_harmony_scoping());
169570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      if (strict_mode() == STRICT) {
169670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        return ParseVariableStatement(kStatement, NULL, ok);
169770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      }
169870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      // Fall through.
169943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    default:
1700a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      return ParseExpressionOrLabelledStatement(labels, ok);
170143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
170243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
170343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
170443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
170508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgVariableProxy* Parser::NewUnresolved(const AstRawString* name,
170608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                     VariableMode mode, Interface* interface) {
1707b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // If we are inside a function, a declaration of a var/const variable is a
1708b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // truly local variable, and the scope of the variable is always the function
1709b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // scope.
1710394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Let/const variables in harmony mode are always added to the immediately
1711394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // enclosing scope.
1712812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  return DeclarationScope(mode)->NewUnresolved(
1713a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory(), name, interface, position());
1714812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org}
1715812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1716812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
1717812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.orgvoid Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
1718bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  VariableProxy* proxy = declaration->proxy();
1719e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(proxy->raw_name() != NULL);
172008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = proxy->raw_name();
1721812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  VariableMode mode = declaration->mode();
1722812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Scope* declaration_scope = DeclarationScope(mode);
1723812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Variable* var = NULL;
172443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
172581cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org  // If a suitable scope exists, then we can statically declare this
172643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // variable and also set its mode. In any case, a Declaration node
172743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // will be added to the scope so that the declaration can be added
172843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to the corresponding activation frame at runtime if necessary.
172943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // For instance declarations inside an eval scope need to be added
173043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to the calling function context.
17318e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  // Similarly, strict mode eval scope does not leak variable declarations to
17328e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  // the caller's scope so we declare all locals, too.
17334f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (declaration_scope->is_function_scope() ||
1734486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      declaration_scope->is_strict_eval_scope() ||
1735f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      declaration_scope->is_block_scope() ||
1736bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      declaration_scope->is_module_scope() ||
1737355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      declaration_scope->is_global_scope()) {
173881cac2ba397bd57f2967c8b4b677bef08a869991danno@chromium.org    // Declare the variable in the declaration scope.
1739355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // For the global scope, we have to check for collisions with earlier
1740355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // (i.e., enclosing) global scopes, to maintain the illusion of a single
1741355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    // global scope.
1742355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    var = declaration_scope->is_global_scope()
1743355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        ? declaration_scope->Lookup(name)
1744fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org        : declaration_scope->LookupLocal(name);
174543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (var == NULL) {
174643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // Declare the name.
17477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      var = declaration_scope->DeclareLocal(name, mode,
17487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            declaration->initialization(),
17497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                            kNotAssigned, proxy->interface());
175012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(var->mode())
175112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org               || ((mode == CONST_LEGACY || var->mode() == CONST_LEGACY) &&
175212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org                   !declaration_scope->is_global_scope())) {
17531805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // The name was declared in this scope before; check for conflicting
17541805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // re-declarations. We have a conflict if either of the declarations is
1755355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // not a var (in the global scope, we also have to ignore legacy const for
1756355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // compatibility). There is similar code in runtime.cc in the Declare
175712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // functions. The function CheckConflictingVarDeclarations checks for
17581805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // var and let bindings from different scopes whereas this is a check for
17591805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // conflicting declarations within the same scope. This check also covers
1760355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      // the special case
17611805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      //
17621805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // function () { let x; { var x; } }
17631805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      //
17641805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // because the var declaration is hoisted to the function scope where 'x'
17651805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org      // is already bound.
1766e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(IsDeclaredVariableMode(var->mode()));
1767a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      if (allow_harmony_scoping() && strict_mode() == STRICT) {
1768486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        // In harmony we treat re-declarations as early errors. See
1769355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        // ES5 16 for a definition of early errors.
1770285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org        ParserTraits::ReportMessage("var_redeclaration", name);
1771355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        *ok = false;
1772355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        return;
177343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
17744edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org      Expression* expression = NewThrowTypeError(
17754edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org          "var_redeclaration", name, declaration->position());
1776355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      declaration_scope->SetIllegalRedeclaration(expression);
1777248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org    } else if (mode == VAR) {
1778248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org      var->set_maybe_assigned();
177943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
178043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
178143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
178243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // We add a declaration node for every declaration. The compiler
178343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // will only generate code if necessary. In particular, declarations
178443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // for inner local variables that do not represent functions won't
178543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // result in any generated code.
178643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
178743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note that we always add an unresolved proxy even if it's not
178843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // used, simply because we don't know in this method (w/o extra
178943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // parameters) if the proxy is needed or not. The proxy will be
179043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // bound during variable resolution time unless it was pre-bound
179143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // below.
179243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
179343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // WARNING: This will lead to multiple declaration nodes for the
179443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // same variable if it is declared several times. This is not a
179543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // semantic issue as long as we keep the source order, but it may be
179643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // a performance issue since it may lead to repeated
17979bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // RuntimeHidden_DeclareLookupSlot calls.
1798812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  declaration_scope->AddDeclaration(declaration);
179943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1800486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  if (mode == CONST_LEGACY && declaration_scope->is_global_scope()) {
180127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // For global const variables we bind the proxy to a variable.
1802e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(resolve);  // should be set by all callers
18033e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org    Variable::Kind kind = Variable::NORMAL;
18047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    var = new (zone())
18057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        Variable(declaration_scope, name, mode, true, kind,
18067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 kNeedsInitialization, kNotAssigned, proxy->interface());
180727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  } else if (declaration_scope->is_eval_scope() &&
1808486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org             declaration_scope->strict_mode() == SLOPPY) {
1809486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    // For variable declarations in a sloppy eval scope the proxy is bound
181027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // to a lookup variable to force a dynamic declaration using the
18119bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    // DeclareLookupSlot runtime function.
181227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    Variable::Kind kind = Variable::NORMAL;
18137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // TODO(sigurds) figure out if kNotAssigned is OK here
18147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    var = new (zone()) Variable(declaration_scope, name, mode, true, kind,
18157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                declaration->initialization(), kNotAssigned,
18167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                proxy->interface());
181727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    var->AllocateTo(Variable::LOOKUP, -1);
181827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    resolve = true;
181943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
182043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
182143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // If requested and we have a local variable, bind the proxy to the variable
182243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // at parse-time. This is used for functions (and consts) declared inside
182343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // statements: the corresponding function (or const) variable must be in the
182443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // function scope and not a statement-local scope, e.g. as provided with a
182543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // 'with' statement:
182643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
182743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   with (obj) {
182843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     function f() {}
182943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   }
183043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
183143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // which is translated into:
183243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
183343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   with (obj) {
183443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     // in this case this is not: 'var f; f = function () {};'
183543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //     var f = function () {};
183643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   }
183743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
183843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note that if 'f' is accessed from inside the 'with' statement, it
183943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // will be allocated in the context (because we must be able to look
184043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // it up dynamically) but it will also be accessed statically, i.e.,
184143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // with a context slot index and a context chain length for this
184243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // initialization code. Thus, inside the 'with' statement, we need
184343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // both access to the static and the dynamic context chain; the
184443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // runtime needs to provide both.
1845bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  if (resolve && var != NULL) {
1846bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    proxy->BindTo(var);
1847bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com
1848bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    if (FLAG_harmony_modules) {
1849bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      bool ok;
1850bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
185108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      if (FLAG_print_interface_details) {
185208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        PrintF("# Declare %.*s ", var->raw_name()->length(),
185308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org               var->raw_name()->raw_data());
185408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      }
1855bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
18567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      proxy->interface()->Unify(var->interface(), zone(), &ok);
1857bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      if (!ok) {
1858bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#ifdef DEBUG
1859bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        if (FLAG_print_interfaces) {
1860bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          PrintF("DECLARE TYPE ERROR\n");
1861bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          PrintF("proxy: ");
1862bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          proxy->interface()->Print();
1863bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          PrintF("var: ");
1864bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com          var->interface()->Print();
1865bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com        }
1866bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com#endif
1867285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org        ParserTraits::ReportMessage("module_type_error", name);
1868bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      }
1869bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    }
1870bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  }
187143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
187243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
187343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
187443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Language extension which is only enabled for source files loaded
187543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// through the API's extension mechanism.  A native function
187643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// declaration is resolved by looking up the function through a
187743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// callback provided by the extension.
187843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseNativeDeclaration(bool* ok) {
1879a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
188043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::FUNCTION, CHECK_OK);
18818297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org  // Allow "eval" or "arguments" for backward compatibility.
188208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
188343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
188443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool done = (peek() == Token::RPAREN);
188543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (!done) {
18868297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
188743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    done = (peek() == Token::RPAREN);
1888fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    if (!done) {
1889fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      Expect(Token::COMMA, CHECK_OK);
1890fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    }
189143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
189243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
189343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, CHECK_OK);
189443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
189543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Make sure that the function containing the native declaration
189643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // isn't lazily compiled. The extension structures are only
189743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // accessible while parsing the first time not when reparsing
189843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // because of lazy compilation.
1899812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  DeclarationScope(VAR)->ForceEagerCompilation();
190043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
190143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // TODO(1240846): It's weird that native function declarations are
190243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // introduced dynamically when we meet their declarations, whereas
1903f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  // other functions are set up when entering the surrounding scope.
190428583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org  VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
1905812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declaration* declaration =
1906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
1907812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declare(declaration, true, CHECK_OK);
1908a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
1909a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      name, extension_, RelocInfo::kNoPosition);
1910b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  return factory()->NewExpressionStatement(
1911b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      factory()->NewAssignment(
1912a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition),
1913a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      pos);
191443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
191543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
191643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
191708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseFunctionDeclaration(
191808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ZoneList<const AstRawString*>* names, bool* ok) {
1919c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // FunctionDeclaration ::
1920c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1921f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  // GeneratorDeclaration ::
1922f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //   'function' '*' Identifier '(' FormalParameterListopt ')'
1923f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org  //      '{' FunctionBody '}'
192443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::FUNCTION, CHECK_OK);
1925a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
1926d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  bool is_generator = Check(Token::MUL);
192704921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org  bool is_strict_reserved = false;
192808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = ParseIdentifierOrStrictReservedWord(
192904921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      &is_strict_reserved, CHECK_OK);
19302c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  FunctionLiteral* fun =
19312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
19322c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                           is_generator ? FunctionKind::kGeneratorFunction
19332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                        : FunctionKind::kNormalFunction,
19342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                           pos, FunctionLiteral::DECLARATION,
19352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                           FunctionLiteral::NORMAL_ARITY, CHECK_OK);
1936c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // Even if we're not at the top-level of the global or a function
1937355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  // scope, we treat it as such and introduce the function with its
1938c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org  // initial value upon entering the corresponding scope.
193912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // In ES6, a function behaves as a lexical binding, except in the
194012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  // global scope, or the initial scope of eval or another function.
1941355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  VariableMode mode =
194212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      allow_harmony_scoping() && strict_mode() == STRICT &&
194312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      !(scope_->is_global_scope() || scope_->is_eval_scope() ||
194412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          scope_->is_function_scope()) ? LET : VAR;
194528583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org  VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
1946812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declaration* declaration =
1947f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
1948812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Declare(declaration, true, CHECK_OK);
19497028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  if (names) names->Add(name, zone());
1950a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
195143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
195243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
195343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1954a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgStatement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
1955a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                                         bool* ok) {
1956a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // ClassDeclaration ::
1957a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //   'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
1958a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //
1959a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // A ClassDeclaration
1960a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //
1961a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //   class C { ... }
1962a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //
1963a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // has the same semantics as:
1964a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //
1965a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //   let C = class C { ... };
1966a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  //
1967a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  // so rewrite it as such.
1968a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1969a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Expect(Token::CLASS, CHECK_OK);
1970a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  int pos = position();
1971a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  bool is_strict_reserved = false;
1972a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  const AstRawString* name =
1973a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
1974a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Expression* value = ParseClassLiteral(name, scanner()->location(),
1975a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                                        is_strict_reserved, pos, CHECK_OK);
1976a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1977a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Block* block = factory()->NewBlock(NULL, 1, true, pos);
1978a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  VariableMode mode = LET;
1979a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
1980a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Declaration* declaration =
1981a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
1982a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Declare(declaration, true, CHECK_OK);
1983a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1984a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Token::Value init_op = Token::INIT_LET;
1985a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos);
1986a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  block->AddStatement(
1987a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
1988a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      zone());
1989a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1990a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  if (names) names->Add(name, zone());
1991a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  return block;
1992a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org}
1993a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
1994a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
199508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgBlock* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
1996a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  if (allow_harmony_scoping() && strict_mode() == STRICT) {
1997486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    return ParseScopedBlock(labels, ok);
1998486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  }
19994acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
200043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Block ::
200143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '{' Statement* '}'
200243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
200343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Note that a Block does not introduce a new execution scope!
200443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // (ECMA-262, 3rd, 12.2)
200543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
200643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Construct block expecting 16 statements.
2007a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* result =
2008a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2009e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, result);
201043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LBRACE, CHECK_OK);
201143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::RBRACE) {
201243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Statement* stat = ParseStatement(NULL, CHECK_OK);
20136db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    if (stat && !stat->IsEmpty()) {
2014400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      result->AddStatement(stat, zone());
20156db8871df97e7137d11f956af3c772f4f8370761sgjesse@chromium.org    }
201643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
201743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RBRACE, CHECK_OK);
201843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
201943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
202043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
202143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
202208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgBlock* Parser::ParseScopedBlock(ZoneList<const AstRawString*>* labels,
202308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                bool* ok) {
2024f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  // The harmony mode uses block elements instead of statements.
2025c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  //
2026c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Block ::
2027f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  //   '{' BlockElement* '}'
2028c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
20294acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Construct block expecting 16 statements.
2030a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* body =
2031a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
2032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
20334acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
20344acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // Parse the statements and collect escaping labels.
20354acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  Expect(Token::LBRACE, CHECK_OK);
2036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  block_scope->set_start_position(scanner()->location().beg_pos);
2037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  { BlockState block_state(&scope_, block_scope);
20387028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    TargetCollector collector(zone());
2039394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Target target(&this->target_stack_, &collector);
20404acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    Target target_body(&this->target_stack_, body);
20414acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
20424acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    while (peek() != Token::RBRACE) {
2043f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org      Statement* stat = ParseBlockElement(NULL, CHECK_OK);
20444acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      if (stat && !stat->IsEmpty()) {
2045400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body->AddStatement(stat, zone());
20464acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org      }
20474acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org    }
20484acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  }
20494acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  Expect(Token::RBRACE, CHECK_OK);
2050f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  block_scope->set_end_position(scanner()->location().end_pos);
20511805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  block_scope = block_scope->FinalizeBlockScope();
2052ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  body->set_scope(block_scope);
2053486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org  return body;
20544acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org}
20554acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
20564acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org
2057b645116853c677aca8a316381b87441ba6004f67danno@chromium.orgBlock* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
205808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                      ZoneList<const AstRawString*>* names,
2059b645116853c677aca8a316381b87441ba6004f67danno@chromium.org                                      bool* ok) {
206043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // VariableStatement ::
206143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   VariableDeclarations ';'
206243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
206308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* ignore;
2064f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org  Block* result =
2065812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org      ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
206643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
206743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
206843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
206943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2070ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
207143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// If the variable declaration declares exactly one non-const
207278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org// variable, then *out is set to that variable. In all other cases,
207378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org// *out is untouched; in particular, it is the caller's responsibility
207443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// to initialize it properly. This mechanism is used for the parsing
207543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// of 'for-in' loops.
2076394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.comBlock* Parser::ParseVariableDeclarations(
2077394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    VariableDeclarationContext var_context,
2078394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    VariableDeclarationProperties* decl_props,
207908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ZoneList<const AstRawString*>* names,
208008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString** out,
2081394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    bool* ok) {
208243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // VariableDeclarations ::
2083394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
2084394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //
2085394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // The ES6 Draft Rev3 specifies the following grammar for const declarations
2086394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //
2087394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ConstDeclaration ::
2088394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   const ConstBinding (',' ConstBinding)* ';'
2089394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ConstBinding ::
2090394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   Identifier '=' AssignmentExpression
2091394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //
2092394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // TODO(ES6):
2093394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // ConstBinding ::
2094394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  //   BindingPattern '=' AssignmentExpression
2095a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org
2096a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
2097b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  VariableMode mode = VAR;
209880c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // True if the binding needs initialization. 'let' and 'const' declared
209980c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // bindings are created uninitialized by their declaration nodes and
210080c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // need initialization. 'var' declared bindings are always initialized
210180c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  // immediately by their declaration nodes.
210280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  bool needs_init = false;
210343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool is_const = false;
210480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org  Token::Value init_op = Token::INIT_VAR;
210543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::VAR) {
210643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::VAR);
210743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else if (peek() == Token::CONST) {
21081b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
21091b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
21101b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
21111b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
21121b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // * It is a Syntax Error if the code that matches this production is not
21131b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   contained in extended code.
21141b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //
2115486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    // However disallowing const in sloppy mode will break compatibility with
21161b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // existing pages. Therefore we keep allowing const with the old
2117486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    // non-harmony semantics in sloppy mode.
211843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::CONST);
2119486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    switch (strict_mode()) {
2120486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      case SLOPPY:
2121486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        mode = CONST_LEGACY;
2122486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        init_op = Token::INIT_CONST_LEGACY;
21231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        break;
2124486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      case STRICT:
2125a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        if (allow_harmony_scoping()) {
2126486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          if (var_context == kStatement) {
2127486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org            // In strict mode 'const' declarations are only allowed in source
2128486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org            // element positions.
2129285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org            ReportMessage("unprotected_const");
2130486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org            *ok = false;
2131486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org            return NULL;
2132486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          }
2133486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          mode = CONST;
2134486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org          init_op = Token::INIT_CONST;
2135486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        } else {
2136285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org          ReportMessage("strict_const");
21371b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          *ok = false;
21381b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org          return NULL;
21391b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org        }
21409ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org    }
214143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    is_const = true;
214280c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    needs_init = true;
214370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  } else if (peek() == Token::LET && strict_mode() == STRICT) {
2144e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(allow_harmony_scoping());
2145b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    Consume(Token::LET);
2146f7a588466d1e61e14fec951e5f10c7cec501b3b4jkummerow@chromium.org    if (var_context == kStatement) {
2147394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      // Let declarations are only allowed in source element positions.
2148285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ReportMessage("unprotected_let");
2149b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      *ok = false;
2150b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      return NULL;
2151b645116853c677aca8a316381b87441ba6004f67danno@chromium.org    }
2152b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org    mode = LET;
215380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    needs_init = true;
215480c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    init_op = Token::INIT_LET;
215543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
215643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    UNREACHABLE();  // by current callers
215743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
215843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2159812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  Scope* declaration_scope = DeclarationScope(mode);
2160812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org
2161b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // The scope of a var/const declared variable anywhere inside a function
216243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
2163b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // transform a source-level var/const declaration into a (Function)
216443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Scope declaration, and rewrite the source-level initialization into an
216543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // assignment statement. We use a block to collect multiple assignments.
216643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
216743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // We mark the block as initializer block because we don't want the
216843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // rewriter to add a '.result' assignment to such a block (to get compliant
216943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // behavior for code such as print(eval('var x = 7')), and for cosmetic
217043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // reasons when pretty-printing. Also, unless an assignment (initialization)
217143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // is inside an initializer block, it is ignored.
217243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
217343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Create new block with one expected declaration.
2174a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  Block* block = factory()->NewBlock(NULL, 1, true, pos);
217543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int nvars = 0;  // the number of variables declared
217608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = NULL;
217743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  do {
217865fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->Enter();
217965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
218043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parse variable name.
218143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (nvars > 0) Consume(Token::COMMA);
21828297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
218365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->PushVariableName(name);
218443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
218543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Declare variable.
218643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Note that we *always* must treat the initial value via a separate init
218743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // assignment for variables and constants because the value must be assigned
218843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // when the variable is encountered in the source. But the variable/constant
218943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is declared (and set to 'undefined') upon entering the function within
219043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // which the variable or constant is declared. Only function variables have
219143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // an initial value in the declaration (because they are initialized upon
219243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // entering the function).
219343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
219443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If we have a const declaration, in an inner scope, the proxy is always
219543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // bound to the declared variable (independent of possibly surrounding with
219643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // statements).
2197394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // For let/const declarations in harmony mode, we can also immediately
2198394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // pre-resolve the proxy because it resides in the same scope as the
2199394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // declaration.
220028583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    Interface* interface =
220128583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org        is_const ? Interface::NewConst() : Interface::NewValue();
220228583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org    VariableProxy* proxy = NewUnresolved(name, mode, interface);
2203812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declaration* declaration =
2204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
2205812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org    Declare(declaration, mode != VAR, CHECK_OK);
220643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    nvars++;
22074f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
2208196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org      ReportMessage("too_many_variables");
22097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      *ok = false;
22107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org      return NULL;
22117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    }
22127028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (names) names->Add(name, zone());
221343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
221443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Parse initialization expression if present and/or needed. A
221543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration of the form:
221643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
221743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //    var v = x;
221843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
221943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is syntactic sugar for:
222043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
222143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //    var v; v = x;
222243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
2223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // In particular, we need to re-lookup 'v' (in scope_, not
22244f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // declaration_scope) as it may be a different 'v' than the 'v' in the
22254f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // declaration (e.g., if we are inside a 'with' statement or 'catch'
22264f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // block).
222743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
222843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // However, note that const declarations are different! A const
222943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration of the form:
223043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
223143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //   const c = x;
223243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
223343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is *not* syntactic sugar for:
223443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
223543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //   const c; c = x;
223643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
223743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // The "variable" c initialized to x is the same as the declared
223843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // one - there is no re-lookup (see the last parameter of the
223943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Declare() call above).
224043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Scope* initialization_scope = is_const ? declaration_scope : scope_;
224243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* value = NULL;
2243a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    int pos = -1;
2244394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Harmony consts have non-optional initializers.
2245486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    if (peek() == Token::ASSIGN || mode == CONST) {
224643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expect(Token::ASSIGN, CHECK_OK);
2247a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      pos = position();
2248b645116853c677aca8a316381b87441ba6004f67danno@chromium.org      value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
224965fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org      // Don't infer if it is "a = function(){...}();"-like expression.
225004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      if (fni_ != NULL &&
225104921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          value->AsCall() == NULL &&
225204921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org          value->AsCallNew() == NULL) {
225304921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org        fni_->Infer();
2254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      } else {
2255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        fni_->RemoveLastFunction();
225604921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      }
2257394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      if (decl_props != NULL) *decl_props = kHasInitializers;
225843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
225943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2260c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    // Record the end position of the initializer.
2261c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    if (proxy->var() != NULL) {
2262a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      proxy->var()->set_initializer_position(position());
2263c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org    }
2264c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org
226580c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
226680c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    if (value == NULL && needs_init) {
2267a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      value = GetLiteralUndefined(position());
226843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
226943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
227043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Global variable declarations must be compiled in a specific
227143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // way. When the script containing the global variable declaration
227243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // is entered, the global variable must be declared, so that if it
2273ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com    // doesn't exist (on the global object itself, see ES5 errata) it
227443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // gets created with an initial undefined value. This is handled
227543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // by the declarations part of the function representing the
227643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // top-level global code; see Runtime::DeclareGlobalVariable. If
227743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // it already exists (in the object or in a prototype), it is
227843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // *not* touched until the variable declaration statement is
227943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // executed.
228043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //
228143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // Executing the variable declaration statement will always
228212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // guarantee to give the global object an own property.
228312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    // This way, global variable declarations can shadow
228443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // properties in the prototype chain, but only after the variable
228543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration statement has been executed. This is important in
228643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // browsers where the global object (window) has lots of
228743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // properties defined in prototype objects.
2288355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org    if (initialization_scope->is_global_scope() &&
2289355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org        !IsLexicalVariableMode(mode)) {
229043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      // Compute the arguments for the runtime call.
22917028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ZoneList<Expression*>* arguments =
22927028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          new(zone()) ZoneList<Expression*>(3, zone());
2293c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      // We have at least 1 parameter.
229408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      arguments->Add(factory()->NewStringLiteral(name, pos), zone());
229543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      CallRuntime* initialize;
22969ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
229743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (is_const) {
22987028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        arguments->Add(value, zone());
22999ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        value = NULL;  // zap the value to avoid the unnecessary assignment
23009ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
23019ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Construct the call to Runtime_InitializeConstGlobal
23029ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // and add it to the initialization statement block.
23039ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Note that the function does different things depending on
23049ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // the number of arguments (1 or 2).
2305b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        initialize = factory()->NewCallRuntime(
23066313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org            ast_value_factory()->initialize_const_global_string(),
23076313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org            Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments,
23086313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org            pos);
230943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
23109ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Add strict mode.
23119ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // We may want to pass singleton to avoid Literal allocations.
2312486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        StrictMode strict_mode = initialization_scope->strict_mode();
2313486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
23149ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
23159ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // Be careful not to assign a value to the global variable if
23169ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // we're in a with. The initialization value should not
23179ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // necessarily be stored in the global object in that case,
23189ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        // which is why we need to generate a separate assignment node.
23199ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        if (value != NULL && !inside_with()) {
23207028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          arguments->Add(value, zone());
23219ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org          value = NULL;  // zap the value to avoid the unnecessary assignment
23229bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org          // Construct the call to Runtime_InitializeVarGlobal
23239bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org          // and add it to the initialization statement block.
23249bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org          initialize = factory()->NewCallRuntime(
23256313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org              ast_value_factory()->initialize_var_global_string(),
23269bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org              Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments,
23279bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org              pos);
23289bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org        } else {
23299bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org          initialize = NULL;
23309ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org        }
233143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
23329ee27ae43ab88e9bb6417ff9e27af64e0cf13729ager@chromium.org
23339bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org      if (initialize != NULL) {
23349bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org        block->AddStatement(factory()->NewExpressionStatement(
23359bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                                initialize, RelocInfo::kNoPosition),
23369bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                            zone());
23379bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org      }
233827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    } else if (needs_init) {
233927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // Constant initializations always assign to the declared constant which
234027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // is always at the function scope level. This is only relevant for
234127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // dynamically looked-up variables and constants (the start context for
234227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // constant lookups is always the function context, while it is the top
234327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // context for var declared variables). Sigh...
234427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // For 'let' and 'const' declared variables in harmony mode the
234527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // initialization also always assigns to the declared variable.
2346e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(proxy != NULL);
2347e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(proxy->var() != NULL);
2348e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(value != NULL);
234927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      Assignment* assignment =
2350a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewAssignment(init_op, proxy, value, pos);
2351a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      block->AddStatement(
2352a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2353a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          zone());
235427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      value = NULL;
235543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
235643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2357486075aa3f2e6d0031ff182961b9eab00e1081d8jkummerow@chromium.org    // Add an assignment node to the initialization statement block if we still
235827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // have a pending initialization value.
235943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (value != NULL) {
2360e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(mode == VAR);
236127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // 'var' initializations are simply assignments (with all the consequences
236227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // if they are inside a 'with' statement - they may change a 'with' object
236327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      // property).
2364b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org      VariableProxy* proxy =
236528583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org          initialization_scope->NewUnresolved(factory(), name, interface);
2366c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      Assignment* assignment =
2367a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewAssignment(init_op, proxy, value, pos);
2368a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      block->AddStatement(
2369a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
2370a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org          zone());
237143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
237265fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org
237365fae84840520e9ce49a78bf542abf073b49ac3fricow@chromium.org    if (fni_ != NULL) fni_->Leave();
237443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } while (peek() == Token::COMMA);
237543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23764f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // If there was a single non-const declaration, return it in the output
23774f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // parameter for possible use by for/in.
23784f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  if (nvars == 1 && !is_const) {
23794f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    *out = name;
238043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
238143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
238243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return block;
238343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
238443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
238543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
238608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgstatic bool ContainsLabel(ZoneList<const AstRawString*>* labels,
238708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                          const AstRawString* label) {
2388e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(label != NULL);
23891e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  if (labels != NULL) {
23901e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    for (int i = labels->length(); i-- > 0; ) {
239108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      if (labels->at(i) == label) {
239243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return true;
23931e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org      }
23941e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org    }
23951e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org  }
239643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return false;
239743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
239843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
239943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
240008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseExpressionOrLabelledStatement(
240108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ZoneList<const AstRawString*>* labels, bool* ok) {
240243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ExpressionStatement | LabelledStatement ::
240343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Expression ';'
240443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   Identifier ':' Statement
2405a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
240683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  bool starts_with_idenfifier = peek_any_identifier();
240743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* expr = ParseExpression(true, CHECK_OK);
24087b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
240943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      expr->AsVariableProxy() != NULL &&
241043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      !expr->AsVariableProxy()->is_this()) {
24114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    // Expression is a single identifier, and not, e.g., a parenthesized
24124a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com    // identifier.
241343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    VariableProxy* var = expr->AsVariableProxy();
241408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* label = var->raw_name();
241543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // TODO(1240780): We don't check for redeclaration of labels
241643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // during preparsing since keeping track of the set of active
241743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // labels requires nontrivial changes to the way scopes are
241843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // structured.  However, these are probably changes we want to
241943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // make later anyway so we should go back and fix this then.
2420fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2421285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ParserTraits::ReportMessage("label_redeclaration", label);
2422fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      *ok = false;
2423fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      return NULL;
242443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
24257028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (labels == NULL) {
242608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
24277028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    }
24287028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    labels->Add(label, zone());
2429fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // Remove the "ghost" variable that turned out to be a label
2430fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // from the top scope. This way, we don't try to resolve it
2431fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org    // during the scope processing.
2432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    scope_->RemoveUnresolved(var);
243343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::COLON, CHECK_OK);
243443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return ParseStatement(labels, ok);
243543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
243643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24377b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // If we have an extension, we allow a native function declaration.
24387b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // A native function declaration starts with "native function" with
24397b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  // no line-terminator between the two words.
24406313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (extension_ != NULL && peek() == Token::FUNCTION &&
24416313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
24427b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org      expr->AsVariableProxy() != NULL &&
244308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      expr->AsVariableProxy()->raw_name() ==
24446313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->native_string() &&
2445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      !scanner()->literal_contains_escapes()) {
24467b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org    return ParseNativeDeclaration(ok);
24477b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org  }
24487b26015ac58e54e88f4214e248f772ad4f055477whesse@chromium.org
2449a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  // Parsed expression statement, or the context-sensitive 'module' keyword.
2450a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  // Only expect semicolon in the former case.
24516313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  if (!FLAG_harmony_modules || peek() != Token::IDENTIFIER ||
2452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      scanner()->HasAnyLineTerminatorBeforeNext() ||
2453a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org      expr->AsVariableProxy() == NULL ||
245408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      expr->AsVariableProxy()->raw_name() !=
24556313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->module_string() ||
2456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      scanner()->literal_contains_escapes()) {
2457a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org    ExpectSemicolon(CHECK_OK);
2458a7d3df915ae6a29cd392dba32a26049d7b9b008fyangguo@chromium.org  }
2459a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewExpressionStatement(expr, pos);
246043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
246143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
246243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
246308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgIfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
246408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                      bool* ok) {
246543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // IfStatement ::
246643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'if' '(' Expression ')' Statement ('else' Statement)?
246743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2468a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
246943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::IF, CHECK_OK);
247043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
247143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* condition = ParseExpression(true, CHECK_OK);
247243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
247343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* then_statement = ParseStatement(labels, CHECK_OK);
247443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* else_statement = NULL;
247543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::ELSE) {
247643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Next();
247743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    else_statement = ParseStatement(labels, CHECK_OK);
2478fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  } else {
2479a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
248043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
2481a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewIfStatement(
2482a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      condition, then_statement, else_statement, pos);
248343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
248443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
248543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
248643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseContinueStatement(bool* ok) {
248743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ContinueStatement ::
248843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'continue' Identifier? ';'
248943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2490a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
249143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::CONTINUE, CHECK_OK);
249208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* label = NULL;
249343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
2494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
24959258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
24968297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    // ECMA allows "eval" or "arguments" as labels even in strict mode.
24978297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
249843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
249908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
2500fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (target == NULL) {
2501c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    // Illegal continue statement.
2502c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    const char* message = "illegal_continue";
250308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    if (label != NULL) {
2504c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      message = "unknown_label";
2505c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    }
2506196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org    ParserTraits::ReportMessage(message, label);
2507c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    *ok = false;
2508c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return NULL;
250943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
251043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
2511a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewContinueStatement(target, pos);
251243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
251343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
251443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
251508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
251608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                       bool* ok) {
251743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // BreakStatement ::
251843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'break' Identifier? ';'
251943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2520a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
252143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::BREAK, CHECK_OK);
252208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* label = NULL;
252343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
2524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
25259258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
25268297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    // ECMA allows "eval" or "arguments" as labels even in strict mode.
25278297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
252843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
25293291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Parse labeled break statements that target themselves into
253043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // empty statements, e.g. 'l1: l2: l3: break l2;'
253108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  if (label != NULL && ContainsLabel(labels, label)) {
2532b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    ExpectSemicolon(CHECK_OK);
2533a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return factory()->NewEmptyStatement(pos);
253443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
253543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  BreakableStatement* target = NULL;
2536fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  target = LookupBreakTarget(label, CHECK_OK);
2537fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (target == NULL) {
2538c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    // Illegal break statement.
2539c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    const char* message = "illegal_break";
254008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    if (label != NULL) {
2541c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org      message = "unknown_label";
2542c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    }
2543196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org    ParserTraits::ReportMessage(message, label);
2544c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    *ok = false;
2545c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    return NULL;
254643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
254743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
2548a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewBreakStatement(target, pos);
254943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
255043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
255143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
255243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseReturnStatement(bool* ok) {
255343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ReturnStatement ::
255443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'return' Expression? ';'
255543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2556a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  // Consume the return token. It is necessary to do that before
255743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // reporting any errors on it, because of the way errors are
255843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // reported (underlining).
255943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RETURN, CHECK_OK);
25604edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  Scanner::Location loc = scanner()->location();
256143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
256264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Token::Value tok = peek();
256364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  Statement* result;
256477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  Expression* return_value;
2565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
256664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      tok == Token::SEMICOLON ||
256764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      tok == Token::RBRACE ||
256864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      tok == Token::EOS) {
2569a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    return_value = GetLiteralUndefined(position());
257064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  } else {
257177ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    return_value = ParseExpression(true, CHECK_OK);
257277ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  }
257377ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  ExpectSemicolon(CHECK_OK);
257477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  if (is_generator()) {
257577ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    Expression* generator = factory()->NewVariableProxy(
2576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        function_state_->generator_object_variable());
257777ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org    Expression* yield = factory()->NewYield(
2578ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org        generator, return_value, Yield::kFinal, loc.beg_pos);
25794edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    result = factory()->NewExpressionStatement(yield, loc.beg_pos);
258077ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org  } else {
25814edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    result = factory()->NewReturnStatement(return_value, loc.beg_pos);
258264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
258364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
25844edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  Scope* decl_scope = scope_->DeclarationScope();
25854edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org  if (decl_scope->is_global_scope() || decl_scope->is_eval_scope()) {
25864edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    ReportMessageAt(loc, "illegal_return");
25874edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    *ok = false;
25884edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org    return NULL;
258943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
259064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  return result;
259143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
259243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
259343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
259408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
259508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                      bool* ok) {
259643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // WithStatement ::
259743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'with' '(' Expression ')' Statement
259843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
259943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::WITH, CHECK_OK);
2600a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
26010a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
2602486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  if (strict_mode() == STRICT) {
2603285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    ReportMessage("strict_mode_with");
26040a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    *ok = false;
26050a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    return NULL;
26060a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  }
26070a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
260843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
260943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* expr = ParseExpression(true, CHECK_OK);
261043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
261143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2612f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  scope_->DeclarationScope()->RecordWithStatement();
2613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* with_scope = NewScope(scope_, WITH_SCOPE);
2614394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  Statement* stmt;
2615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  { BlockState block_state(&scope_, with_scope);
2616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    with_scope->set_start_position(scanner()->peek_location().beg_pos);
2617394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    stmt = ParseStatement(labels, CHECK_OK);
2618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    with_scope->set_end_position(scanner()->location().end_pos);
2619394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
2620a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewWithStatement(with_scope, expr, stmt, pos);
262143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
262243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
262343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
262443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenCaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
262543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // CaseClause ::
262643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'case' Expression ':' Statement*
262743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'default' ':' Statement*
262843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
262943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* label = NULL;  // NULL expression indicates default case
263043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::CASE) {
263143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::CASE, CHECK_OK);
263243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    label = ParseExpression(true, CHECK_OK);
263343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
263443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::DEFAULT, CHECK_OK);
263543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (*default_seen_ptr) {
2636285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ReportMessage("multiple_defaults_in_switch");
263743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      *ok = false;
263843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return NULL;
263943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
264043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *default_seen_ptr = true;
264143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
264243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::COLON, CHECK_OK);
2643a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
26447028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<Statement*>* statements =
26457028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      new(zone()) ZoneList<Statement*>(5, zone());
264643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::CASE &&
264743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen         peek() != Token::DEFAULT &&
264843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen         peek() != Token::RBRACE) {
264943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Statement* stat = ParseStatement(NULL, CHECK_OK);
26507028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    statements->Add(stat, zone());
265143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
265243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2653a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewCaseClause(label, statements, pos);
265443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
265543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
265643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
265708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgSwitchStatement* Parser::ParseSwitchStatement(
265808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ZoneList<const AstRawString*>* labels, bool* ok) {
265943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // SwitchStatement ::
266043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'switch' '(' Expression ')' '{' CaseClause* '}'
266143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2662a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  SwitchStatement* statement =
2663a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewSwitchStatement(labels, peek_position());
2664e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, statement);
266543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
266643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SWITCH, CHECK_OK);
266743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
266843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* tag = ParseExpression(true, CHECK_OK);
266943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
267043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
267143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool default_seen = false;
26727028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4, zone());
267343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LBRACE, CHECK_OK);
267443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (peek() != Token::RBRACE) {
267543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
26767028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    cases->Add(clause, zone());
267743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
267843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RBRACE, CHECK_OK);
267943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2680fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (statement) statement->Initialize(tag, cases);
268143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return statement;
268243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
268343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
268443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
268543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenStatement* Parser::ParseThrowStatement(bool* ok) {
268643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ThrowStatement ::
268743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'throw' Expression ';'
268843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
268943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::THROW, CHECK_OK);
2690a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
2691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
2692285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    ReportMessage("newline_after_throw");
269343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *ok = false;
269443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return NULL;
269543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
269643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* exception = ParseExpression(true, CHECK_OK);
269743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
269843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2699a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewExpressionStatement(
2700a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewThrow(exception, pos), pos);
270143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
270243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
270343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
270443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenTryStatement* Parser::ParseTryStatement(bool* ok) {
270543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // TryStatement ::
270643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'try' Block Catch
270743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'try' Block Finally
270843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'try' Block Catch Finally
270943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
271043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Catch ::
271143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'catch' '(' Identifier ')' Block
271243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //
271343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Finally ::
271443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'finally' Block
271543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
271643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::TRY, CHECK_OK);
2717a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = position();
271843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27197028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  TargetCollector try_collector(zone());
272043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Block* try_block;
272143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27226d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  { Target target(&this->target_stack_, &try_collector);
272343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    try_block = ParseBlock(NULL, CHECK_OK);
272443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
272543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
272643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Token::Value tok = peek();
272743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tok != Token::CATCH && tok != Token::FINALLY) {
2728285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    ReportMessage("no_catch_or_finally");
272943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    *ok = false;
273043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return NULL;
273143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
273243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
273343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // If we can break out from the catch block and there is a finally block,
27346d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // then we will need to collect escaping targets from the catch
27356d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // block. Since we don't know yet if there will be a finally block, we
27366d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // always collect the targets.
27377028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  TargetCollector catch_collector(zone());
27384f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Scope* catch_scope = NULL;
27394f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  Variable* catch_variable = NULL;
27406d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  Block* catch_block = NULL;
274108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = NULL;
274243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (tok == Token::CATCH) {
274343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::CATCH);
274443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
274543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::LPAREN, CHECK_OK);
2746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    catch_scope = NewScope(scope_, CATCH_SCOPE);
2747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    catch_scope->set_start_position(scanner()->location().beg_pos);
27488297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org    name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
27490a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
275043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::RPAREN, CHECK_OK);
275143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2752bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    Target target(&this->target_stack_, &catch_collector);
2753486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    VariableMode mode =
2754a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        allow_harmony_scoping() && strict_mode() == STRICT ? LET : VAR;
27557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    catch_variable = catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
2756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    BlockState block_state(&scope_, catch_scope);
2757bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    catch_block = ParseBlock(NULL, CHECK_OK);
2758bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org
2759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    catch_scope->set_end_position(scanner()->location().end_pos);
276043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    tok = peek();
276143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
276243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27636d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  Block* finally_block = NULL;
2764e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(tok == Token::FINALLY || catch_block != NULL);
2765bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org  if (tok == Token::FINALLY) {
276643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Consume(Token::FINALLY);
276743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    finally_block = ParseBlock(NULL, CHECK_OK);
276843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
276943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
277043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Simplify the AST nodes by converting:
27716d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  //   'try B0 catch B1 finally B2'
277243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // to:
27736d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  //   'try { try B0 catch B1 } finally B2'
277443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2775fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (catch_block != NULL && finally_block != NULL) {
27764f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    // If we have both, create an inner try/catch.
2777e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(catch_scope != NULL && catch_variable != NULL);
2778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int index = function_state_->NextHandlerIndex();
2779b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    TryCatchStatement* statement = factory()->NewTryCatchStatement(
2780a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        index, try_block, catch_scope, catch_variable, catch_block,
2781a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        RelocInfo::kNoPosition);
27826d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    statement->set_escaping_targets(try_collector.targets());
2783a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
2784400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org    try_block->AddStatement(statement, zone());
27854f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    catch_block = NULL;  // Clear to indicate it's been handled.
278643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
278743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
278843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  TryStatement* result = NULL;
2789fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  if (catch_block != NULL) {
2790e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(finally_block == NULL);
2791e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(catch_scope != NULL && catch_variable != NULL);
2792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int index = function_state_->NextHandlerIndex();
2793b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    result = factory()->NewTryCatchStatement(
2794a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        index, try_block, catch_scope, catch_variable, catch_block, pos);
2795fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org  } else {
2796e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(finally_block != NULL);
2797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int index = function_state_->NextHandlerIndex();
2798a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    result = factory()->NewTryFinallyStatement(
2799a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        index, try_block, finally_block, pos);
28006d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    // Combine the jump targets of the try block and the possible catch block.
28017028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    try_collector.targets()->AddAll(*catch_collector.targets(), zone());
280243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
280343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28046d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  result->set_escaping_targets(try_collector.targets());
280543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return result;
280643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
280743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
280843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
280908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgDoWhileStatement* Parser::ParseDoWhileStatement(
281008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ZoneList<const AstRawString*>* labels, bool* ok) {
281143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // DoStatement ::
281243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'do' Statement 'while' '(' Expression ')' ';'
281343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2814a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  DoWhileStatement* loop =
2815a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      factory()->NewDoWhileStatement(labels, peek_position());
2816e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, loop);
281743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
281843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::DO, CHECK_OK);
281943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* body = ParseStatement(NULL, CHECK_OK);
282043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::WHILE, CHECK_OK);
282143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
2822c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org
282343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* cond = ParseExpression(true, CHECK_OK);
282443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
282543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
282643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Allow do-statements to be terminated with and without
282743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // semi-colons. This allows code such as 'do;while(0)return' to
282843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // parse, which would not be the case if we had used the
282943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ExpectSemicolon() functionality here.
283043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
283143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28329d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (loop != NULL) loop->Initialize(cond, body);
283343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return loop;
283443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
283543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
283643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
283708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgWhileStatement* Parser::ParseWhileStatement(
283808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ZoneList<const AstRawString*>* labels, bool* ok) {
283943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // WhileStatement ::
284043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'while' '(' Expression ')' Statement
284143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2842a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
2843e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, loop);
284443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
284543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::WHILE, CHECK_OK);
284643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
284743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* cond = ParseExpression(true, CHECK_OK);
284843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
284943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* body = ParseStatement(NULL, CHECK_OK);
285043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28519d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com  if (loop != NULL) loop->Initialize(cond, body);
285243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return loop;
285343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
285443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
285543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
285641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.orgbool Parser::CheckInOrOf(bool accept_OF,
285741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org                         ForEachStatement::VisitMode* visit_mode) {
28581fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  if (Check(Token::IN)) {
28591fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    *visit_mode = ForEachStatement::ENUMERATE;
28601fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    return true;
28618640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org  } else if (accept_OF && CheckContextualKeyword(CStrVector("of"))) {
28621fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    *visit_mode = ForEachStatement::ITERATE;
28631fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    return true;
28641fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  }
28651fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  return false;
28661fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org}
28671fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
28681fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
28691fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.orgvoid Parser::InitializeForEachStatement(ForEachStatement* stmt,
28701fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                                        Expression* each,
28711fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                                        Expression* subject,
28721fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org                                        Statement* body) {
28731fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  ForOfStatement* for_of = stmt->AsForOfStatement();
28741fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
28751fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  if (for_of != NULL) {
2876f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Variable* iterator = scope_->DeclarationScope()->NewTemporary(
28776313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        ast_value_factory()->dot_iterator_string());
2878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Variable* result = scope_->DeclarationScope()->NewTemporary(
28796313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        ast_value_factory()->dot_result_string());
28801fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
28811fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* assign_iterator;
28821fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* next_result;
28831fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* result_done;
28841fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    Expression* assign_each;
28851fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
2886f2af15a6b44ea6276bdd609ee122babe52842a42machenbach@chromium.org    // var iterator = subject[Symbol.iterator]();
28873e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org    assign_iterator = factory()->NewAssignment(
28883e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org        Token::ASSIGN, factory()->NewVariableProxy(iterator),
28893e3d253bd8018d7627422bf55a5c7bb7e7d6ad7emachenbach@chromium.org        GetIterator(subject, factory()), RelocInfo::kNoPosition);
28901fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
28911fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // var result = iterator.next();
28921fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
28931fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
289408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      Expression* next_literal = factory()->NewStringLiteral(
28956313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->next_string(), RelocInfo::kNoPosition);
28961fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* next_property = factory()->NewProperty(
28971fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          iterator_proxy, next_literal, RelocInfo::kNoPosition);
28981fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ZoneList<Expression*>* next_arguments =
28991fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          new(zone()) ZoneList<Expression*>(0, zone());
29001fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* next_call = factory()->NewCall(
29011fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          next_property, next_arguments, RelocInfo::kNoPosition);
29021fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_proxy = factory()->NewVariableProxy(result);
29031fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      next_result = factory()->NewAssignment(
29041fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          Token::ASSIGN, result_proxy, next_call, RelocInfo::kNoPosition);
29051fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
29061fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
29071fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // result.done
29081fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
290908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      Expression* done_literal = factory()->NewStringLiteral(
29106313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->done_string(), RelocInfo::kNoPosition);
29111fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_proxy = factory()->NewVariableProxy(result);
29121fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      result_done = factory()->NewProperty(
29131fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          result_proxy, done_literal, RelocInfo::kNoPosition);
29141fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
29151fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
29161fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    // each = result.value
29171fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    {
291808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      Expression* value_literal = factory()->NewStringLiteral(
29196313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->value_string(), RelocInfo::kNoPosition);
29201fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_proxy = factory()->NewVariableProxy(result);
29211fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      Expression* result_value = factory()->NewProperty(
29221fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          result_proxy, value_literal, RelocInfo::kNoPosition);
29231fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      assign_each = factory()->NewAssignment(
29241fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org          Token::ASSIGN, each, result_value, RelocInfo::kNoPosition);
29251fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    }
29261fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
29271fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    for_of->Initialize(each, subject, body,
29281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                       assign_iterator,
29291845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                       next_result,
29301845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                       result_done,
29311845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org                       assign_each);
29321fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  } else {
29331fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org    stmt->Initialize(each, subject, body);
29341fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org  }
29351fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org}
29361fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
29371fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
29387e6132b924829c353864933f29124419916db550machenbach@chromium.orgStatement* Parser::DesugarLetBindingsInForStatement(
293908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    Scope* inner_scope, ZoneList<const AstRawString*>* names,
294008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    ForStatement* loop, Statement* init, Expression* cond, Statement* next,
294108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    Statement* body, bool* ok) {
29427e6132b924829c353864933f29124419916db550machenbach@chromium.org  // ES6 13.6.3.4 specifies that on each loop iteration the let variables are
29437e6132b924829c353864933f29124419916db550machenbach@chromium.org  // copied into a new environment. After copying, the "next" statement of the
29447e6132b924829c353864933f29124419916db550machenbach@chromium.org  // loop is executed to update the loop variables. The loop condition is
29457e6132b924829c353864933f29124419916db550machenbach@chromium.org  // checked and the loop body is executed.
29467e6132b924829c353864933f29124419916db550machenbach@chromium.org  //
29477e6132b924829c353864933f29124419916db550machenbach@chromium.org  // We rewrite a for statement of the form
29487e6132b924829c353864933f29124419916db550machenbach@chromium.org  //
29497e6132b924829c353864933f29124419916db550machenbach@chromium.org  //  for (let x = i; cond; next) body
29507e6132b924829c353864933f29124419916db550machenbach@chromium.org  //
29517e6132b924829c353864933f29124419916db550machenbach@chromium.org  // into
29527e6132b924829c353864933f29124419916db550machenbach@chromium.org  //
29537e6132b924829c353864933f29124419916db550machenbach@chromium.org  //  {
29547e6132b924829c353864933f29124419916db550machenbach@chromium.org  //     let x = i;
29557e6132b924829c353864933f29124419916db550machenbach@chromium.org  //     temp_x = x;
29567e6132b924829c353864933f29124419916db550machenbach@chromium.org  //     flag = 1;
29577e6132b924829c353864933f29124419916db550machenbach@chromium.org  //     for (;;) {
29587e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        let x = temp_x;
29597e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        if (flag == 1) {
29607e6132b924829c353864933f29124419916db550machenbach@chromium.org  //          flag = 0;
29617e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        } else {
29627e6132b924829c353864933f29124419916db550machenbach@chromium.org  //          next;
29637e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        }
29647e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        if (cond) {
29657e6132b924829c353864933f29124419916db550machenbach@chromium.org  //          <empty>
29667e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        } else {
29677e6132b924829c353864933f29124419916db550machenbach@chromium.org  //          break;
29687e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        }
29697e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        b
29707e6132b924829c353864933f29124419916db550machenbach@chromium.org  //        temp_x = x;
29717e6132b924829c353864933f29124419916db550machenbach@chromium.org  //     }
29727e6132b924829c353864933f29124419916db550machenbach@chromium.org  //  }
29737e6132b924829c353864933f29124419916db550machenbach@chromium.org
2974e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(names->length() > 0);
29757e6132b924829c353864933f29124419916db550machenbach@chromium.org  Scope* for_scope = scope_;
29767e6132b924829c353864933f29124419916db550machenbach@chromium.org  ZoneList<Variable*> temps(names->length(), zone());
29777e6132b924829c353864933f29124419916db550machenbach@chromium.org
29787e6132b924829c353864933f29124419916db550machenbach@chromium.org  Block* outer_block = factory()->NewBlock(NULL, names->length() + 3, false,
29797e6132b924829c353864933f29124419916db550machenbach@chromium.org                                           RelocInfo::kNoPosition);
29807e6132b924829c353864933f29124419916db550machenbach@chromium.org  outer_block->AddStatement(init, zone());
29817e6132b924829c353864933f29124419916db550machenbach@chromium.org
29826313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  const AstRawString* temp_name = ast_value_factory()->dot_for_string();
29837e6132b924829c353864933f29124419916db550machenbach@chromium.org
29847e6132b924829c353864933f29124419916db550machenbach@chromium.org  // For each let variable x:
29857e6132b924829c353864933f29124419916db550machenbach@chromium.org  //   make statement: temp_x = x.
29867e6132b924829c353864933f29124419916db550machenbach@chromium.org  for (int i = 0; i < names->length(); i++) {
29877e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* proxy =
29887e6132b924829c353864933f29124419916db550machenbach@chromium.org        NewUnresolved(names->at(i), LET, Interface::NewValue());
29897e6132b924829c353864933f29124419916db550machenbach@chromium.org    Variable* temp = scope_->DeclarationScope()->NewTemporary(temp_name);
29907e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
29917e6132b924829c353864933f29124419916db550machenbach@chromium.org    Assignment* assignment = factory()->NewAssignment(
29927e6132b924829c353864933f29124419916db550machenbach@chromium.org        Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
29937e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* assignment_statement = factory()->NewExpressionStatement(
29947e6132b924829c353864933f29124419916db550machenbach@chromium.org        assignment, RelocInfo::kNoPosition);
29957e6132b924829c353864933f29124419916db550machenbach@chromium.org    outer_block->AddStatement(assignment_statement, zone());
29967e6132b924829c353864933f29124419916db550machenbach@chromium.org    temps.Add(temp, zone());
29977e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
29987e6132b924829c353864933f29124419916db550machenbach@chromium.org
29997e6132b924829c353864933f29124419916db550machenbach@chromium.org  Variable* flag = scope_->DeclarationScope()->NewTemporary(temp_name);
30007e6132b924829c353864933f29124419916db550machenbach@chromium.org  // Make statement: flag = 1.
30017e6132b924829c353864933f29124419916db550machenbach@chromium.org  {
30027e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
300308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
30047e6132b924829c353864933f29124419916db550machenbach@chromium.org    Assignment* assignment = factory()->NewAssignment(
30057e6132b924829c353864933f29124419916db550machenbach@chromium.org        Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
30067e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* assignment_statement = factory()->NewExpressionStatement(
30077e6132b924829c353864933f29124419916db550machenbach@chromium.org        assignment, RelocInfo::kNoPosition);
30087e6132b924829c353864933f29124419916db550machenbach@chromium.org    outer_block->AddStatement(assignment_statement, zone());
30097e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
30107e6132b924829c353864933f29124419916db550machenbach@chromium.org
30117e6132b924829c353864933f29124419916db550machenbach@chromium.org  outer_block->AddStatement(loop, zone());
30127e6132b924829c353864933f29124419916db550machenbach@chromium.org  outer_block->set_scope(for_scope);
30137e6132b924829c353864933f29124419916db550machenbach@chromium.org  scope_ = inner_scope;
30147e6132b924829c353864933f29124419916db550machenbach@chromium.org
30157e6132b924829c353864933f29124419916db550machenbach@chromium.org  Block* inner_block = factory()->NewBlock(NULL, 2 * names->length() + 3,
30167e6132b924829c353864933f29124419916db550machenbach@chromium.org                                           false, RelocInfo::kNoPosition);
30177e6132b924829c353864933f29124419916db550machenbach@chromium.org  int pos = scanner()->location().beg_pos;
30187e6132b924829c353864933f29124419916db550machenbach@chromium.org  ZoneList<Variable*> inner_vars(names->length(), zone());
30197e6132b924829c353864933f29124419916db550machenbach@chromium.org
30207e6132b924829c353864933f29124419916db550machenbach@chromium.org  // For each let variable x:
30217e6132b924829c353864933f29124419916db550machenbach@chromium.org  //    make statement: let x = temp_x.
30227e6132b924829c353864933f29124419916db550machenbach@chromium.org  for (int i = 0; i < names->length(); i++) {
30237e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* proxy =
30247e6132b924829c353864933f29124419916db550machenbach@chromium.org        NewUnresolved(names->at(i), LET, Interface::NewValue());
30257e6132b924829c353864933f29124419916db550machenbach@chromium.org    Declaration* declaration =
30267e6132b924829c353864933f29124419916db550machenbach@chromium.org        factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
30277e6132b924829c353864933f29124419916db550machenbach@chromium.org    Declare(declaration, true, CHECK_OK);
30287e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_vars.Add(declaration->proxy()->var(), zone());
30297e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
30307e6132b924829c353864933f29124419916db550machenbach@chromium.org    Assignment* assignment = factory()->NewAssignment(
30317e6132b924829c353864933f29124419916db550machenbach@chromium.org        Token::INIT_LET, proxy, temp_proxy, pos);
30327e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* assignment_statement = factory()->NewExpressionStatement(
30337e6132b924829c353864933f29124419916db550machenbach@chromium.org        assignment, pos);
30347e6132b924829c353864933f29124419916db550machenbach@chromium.org    proxy->var()->set_initializer_position(pos);
30357e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_block->AddStatement(assignment_statement, zone());
30367e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
30377e6132b924829c353864933f29124419916db550machenbach@chromium.org
30387e6132b924829c353864933f29124419916db550machenbach@chromium.org  // Make statement: if (flag == 1) { flag = 0; } else { next; }.
303912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (next) {
30407e6132b924829c353864933f29124419916db550machenbach@chromium.org    Expression* compare = NULL;
30417e6132b924829c353864933f29124419916db550machenbach@chromium.org    // Make compare expresion: flag == 1.
30427e6132b924829c353864933f29124419916db550machenbach@chromium.org    {
304308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
30447e6132b924829c353864933f29124419916db550machenbach@chromium.org      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
30457e6132b924829c353864933f29124419916db550machenbach@chromium.org      compare = factory()->NewCompareOperation(
30461e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org          Token::EQ, flag_proxy, const1, pos);
30477e6132b924829c353864933f29124419916db550machenbach@chromium.org    }
30487e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* clear_flag = NULL;
30497e6132b924829c353864933f29124419916db550machenbach@chromium.org    // Make statement: flag = 0.
30507e6132b924829c353864933f29124419916db550machenbach@chromium.org    {
30517e6132b924829c353864933f29124419916db550machenbach@chromium.org      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
305208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
30537e6132b924829c353864933f29124419916db550machenbach@chromium.org      Assignment* assignment = factory()->NewAssignment(
30547e6132b924829c353864933f29124419916db550machenbach@chromium.org          Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
30557e6132b924829c353864933f29124419916db550machenbach@chromium.org      clear_flag = factory()->NewExpressionStatement(assignment, pos);
30567e6132b924829c353864933f29124419916db550machenbach@chromium.org    }
30577e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* clear_flag_or_next = factory()->NewIfStatement(
30587e6132b924829c353864933f29124419916db550machenbach@chromium.org        compare, clear_flag, next, RelocInfo::kNoPosition);
30597e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_block->AddStatement(clear_flag_or_next, zone());
30607e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
30617e6132b924829c353864933f29124419916db550machenbach@chromium.org
30627e6132b924829c353864933f29124419916db550machenbach@chromium.org
30637e6132b924829c353864933f29124419916db550machenbach@chromium.org  // Make statement: if (cond) { } else { break; }.
306412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org  if (cond) {
30657e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
306608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    BreakableStatement* t = LookupBreakTarget(NULL, CHECK_OK);
30677e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition);
30687e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* if_not_cond_break = factory()->NewIfStatement(
30691e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org        cond, empty, stop, cond->position());
30707e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_block->AddStatement(if_not_cond_break, zone());
30717e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
30727e6132b924829c353864933f29124419916db550machenbach@chromium.org
30737e6132b924829c353864933f29124419916db550machenbach@chromium.org  inner_block->AddStatement(body, zone());
30747e6132b924829c353864933f29124419916db550machenbach@chromium.org
30757e6132b924829c353864933f29124419916db550machenbach@chromium.org  // For each let variable x:
30767e6132b924829c353864933f29124419916db550machenbach@chromium.org  //   make statement: temp_x = x;
30777e6132b924829c353864933f29124419916db550machenbach@chromium.org  for (int i = 0; i < names->length(); i++) {
30787e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
30797e6132b924829c353864933f29124419916db550machenbach@chromium.org    int pos = scanner()->location().end_pos;
30807e6132b924829c353864933f29124419916db550machenbach@chromium.org    VariableProxy* proxy = factory()->NewVariableProxy(inner_vars.at(i), pos);
30817e6132b924829c353864933f29124419916db550machenbach@chromium.org    Assignment* assignment = factory()->NewAssignment(
30827e6132b924829c353864933f29124419916db550machenbach@chromium.org        Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
30837e6132b924829c353864933f29124419916db550machenbach@chromium.org    Statement* assignment_statement = factory()->NewExpressionStatement(
30847e6132b924829c353864933f29124419916db550machenbach@chromium.org        assignment, RelocInfo::kNoPosition);
30857e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_block->AddStatement(assignment_statement, zone());
30867e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
30877e6132b924829c353864933f29124419916db550machenbach@chromium.org
30887e6132b924829c353864933f29124419916db550machenbach@chromium.org  inner_scope->set_end_position(scanner()->location().end_pos);
30897e6132b924829c353864933f29124419916db550machenbach@chromium.org  inner_block->set_scope(inner_scope);
30907e6132b924829c353864933f29124419916db550machenbach@chromium.org  scope_ = for_scope;
30917e6132b924829c353864933f29124419916db550machenbach@chromium.org
30927e6132b924829c353864933f29124419916db550machenbach@chromium.org  loop->Initialize(NULL, NULL, NULL, inner_block);
30937e6132b924829c353864933f29124419916db550machenbach@chromium.org  return outer_block;
30947e6132b924829c353864933f29124419916db550machenbach@chromium.org}
30957e6132b924829c353864933f29124419916db550machenbach@chromium.org
30967e6132b924829c353864933f29124419916db550machenbach@chromium.org
309708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgStatement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
309808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                     bool* ok) {
309943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // ForStatement ::
310043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
310143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3102a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
310343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* init = NULL;
310408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  ZoneList<const AstRawString*> let_bindings(1, zone());
310543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3106394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  // Create an in-between scope for let-bound iteration variables.
3107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* saved_scope = scope_;
3108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  scope_ = for_scope;
3110394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
311143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::FOR, CHECK_OK);
311243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::LPAREN, CHECK_OK);
3113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for_scope->set_start_position(scanner()->location().beg_pos);
311443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::SEMICOLON) {
311543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (peek() == Token::VAR || peek() == Token::CONST) {
311628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org      bool is_const = peek() == Token::CONST;
311708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      const AstRawString* name = NULL;
311841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      VariableDeclarationProperties decl_props = kHasNoInitializers;
311943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Block* variable_statement =
312041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org          ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
312141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org                                    CHECK_OK);
312241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      bool accept_OF = decl_props == kHasNoInitializers;
31231fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ForEachStatement::VisitMode mode;
31244f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
312508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
312628583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org        Interface* interface =
312728583c92ca8f528df625800519088ac88996d504jkummerow@chromium.org            is_const ? Interface::NewConst() : Interface::NewValue();
3128a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        ForEachStatement* loop =
3129a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewForEachStatement(mode, labels, pos);
3130e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        Target target(&this->target_stack_, loop);
313143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
313243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expression* enumerable = ParseExpression(true, CHECK_OK);
313343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expect(Token::RPAREN, CHECK_OK);
313443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
313533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        VariableProxy* each =
3136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            scope_->NewUnresolved(factory(), name, interface);
313743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Statement* body = ParseStatement(NULL, CHECK_OK);
31381fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org        InitializeForEachStatement(loop, each, enumerable, body);
3139a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        Block* result =
3140a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
3141400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        result->AddStatement(variable_statement, zone());
3142400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        result->AddStatement(loop, zone());
3143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        scope_ = saved_scope;
3144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        for_scope->set_end_position(scanner()->location().end_pos);
3145394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope = for_scope->FinalizeBlockScope();
3146e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(for_scope == NULL);
3147fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org        // Parsed for-in loop w/ variable/const declaration.
3148fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org        return result;
314943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
315043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        init = variable_statement;
315143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
315270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    } else if (peek() == Token::LET && strict_mode() == STRICT) {
3153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(allow_harmony_scoping());
315408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      const AstRawString* name = NULL;
3155394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      VariableDeclarationProperties decl_props = kHasNoInitializers;
3156394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      Block* variable_statement =
315708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org          ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
315808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                    &name, CHECK_OK);
315908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      bool accept_IN = name != NULL && decl_props != kHasInitializers;
316041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      bool accept_OF = decl_props == kHasNoInitializers;
31611fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ForEachStatement::VisitMode mode;
31621fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
316341728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
3164394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // Rewrite a for-in statement of the form
3165394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //
3166394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   for (let x in e) b
3167394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //
3168394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // into
3169394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //
3170394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   <let x' be a temporary variable>
3171394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   for (x' in e) {
3172394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //     let x;
3173394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //     x = x';
3174394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //     b;
3175394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        //   }
3176394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
3177394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // TODO(keuchel): Move the temporary variable to the block scope, after
3178394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // implementing stack allocated block scoped variables.
317908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        Variable* temp = scope_->DeclarationScope()->NewTemporary(
31806313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org            ast_value_factory()->dot_for_string());
3181b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
3182a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        ForEachStatement* loop =
3183a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewForEachStatement(mode, labels, pos);
3184394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Target target(&this->target_stack_, loop);
3185394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
318633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        // The expression does not see the loop variable.
3187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        scope_ = saved_scope;
3188394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Expression* enumerable = ParseExpression(true, CHECK_OK);
3189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        scope_ = for_scope;
3190394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Expect(Token::RPAREN, CHECK_OK);
319143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
319233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org        VariableProxy* each =
3193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            scope_->NewUnresolved(factory(), name, Interface::NewValue());
3194394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        Statement* body = ParseStatement(NULL, CHECK_OK);
3195a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        Block* body_block =
3196a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
3197b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org        Assignment* assignment = factory()->NewAssignment(
3198b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org            Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
3199a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        Statement* assignment_statement = factory()->NewExpressionStatement(
3200a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            assignment, RelocInfo::kNoPosition);
3201400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body_block->AddStatement(variable_statement, zone());
3202400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body_block->AddStatement(assignment_statement, zone());
3203400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        body_block->AddStatement(body, zone());
32041fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org        InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
3205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        scope_ = saved_scope;
3206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        for_scope->set_end_position(scanner()->location().end_pos);
3207394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope = for_scope->FinalizeBlockScope();
3208ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com        body_block->set_scope(for_scope);
3209394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        // Parsed for-in loop w/ let declaration.
3210394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        return loop;
3211394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com
3212394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      } else {
3213394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        init = variable_statement;
3214394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      }
321543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    } else {
32162904d1a42292be3056c2dd3f98822f8e1470fa72machenbach@chromium.org      Scanner::Location lhs_location = scanner()->peek_location();
321743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      Expression* expression = ParseExpression(false, CHECK_OK);
32181fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      ForEachStatement::VisitMode mode;
321941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      bool accept_OF = expression->AsVariableProxy();
32201fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org
322141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org      if (CheckInOrOf(accept_OF, &mode)) {
32224edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org        expression = this->CheckAndRewriteReferenceExpression(
32234edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org            expression, lhs_location, "invalid_lhs_in_for", CHECK_OK);
32244edebd5691ee147fa134ad8aaf6cc3c939831b93machenbach@chromium.org
3225a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        ForEachStatement* loop =
3226a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            factory()->NewForEachStatement(mode, labels, pos);
3227e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org        Target target(&this->target_stack_, loop);
322843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
322943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expression* enumerable = ParseExpression(true, CHECK_OK);
323043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Expect(Token::RPAREN, CHECK_OK);
323143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
323243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        Statement* body = ParseStatement(NULL, CHECK_OK);
32331fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org        InitializeForEachStatement(loop, expression, enumerable, body);
3234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        scope_ = saved_scope;
3235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        for_scope->set_end_position(scanner()->location().end_pos);
3236394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com        for_scope = for_scope->FinalizeBlockScope();
3237e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(for_scope == NULL);
323843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        // Parsed for-in loop.
323943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        return loop;
324043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
324143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      } else {
3242a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org        init = factory()->NewExpressionStatement(
3243a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org            expression, RelocInfo::kNoPosition);
324443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      }
324543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
324643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
324743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
324843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Standard 'for' loop
3249a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  ForStatement* loop = factory()->NewForStatement(labels, pos);
3250e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org  Target target(&this->target_stack_, loop);
325143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
325243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Parsed initializer at this point.
325343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, CHECK_OK);
325443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
32557e6132b924829c353864933f29124419916db550machenbach@chromium.org  // If there are let bindings, then condition and the next statement of the
32567e6132b924829c353864933f29124419916db550machenbach@chromium.org  // for loop must be parsed in a new scope.
32577e6132b924829c353864933f29124419916db550machenbach@chromium.org  Scope* inner_scope = NULL;
32587e6132b924829c353864933f29124419916db550machenbach@chromium.org  if (let_bindings.length() > 0) {
32597e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_scope = NewScope(for_scope, BLOCK_SCOPE);
32607e6132b924829c353864933f29124419916db550machenbach@chromium.org    inner_scope->set_start_position(scanner()->location().beg_pos);
32617e6132b924829c353864933f29124419916db550machenbach@chromium.org    scope_ = inner_scope;
32627e6132b924829c353864933f29124419916db550machenbach@chromium.org  }
32637e6132b924829c353864933f29124419916db550machenbach@chromium.org
326443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expression* cond = NULL;
326543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::SEMICOLON) {
326643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    cond = ParseExpression(true, CHECK_OK);
326743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
326843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::SEMICOLON, CHECK_OK);
326943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
327043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* next = NULL;
327143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (peek() != Token::RPAREN) {
327243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expression* exp = ParseExpression(true, CHECK_OK);
3273a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org    next = factory()->NewExpressionStatement(exp, RelocInfo::kNoPosition);
327443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
327543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::RPAREN, CHECK_OK);
327643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
327743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Statement* body = ParseStatement(NULL, CHECK_OK);
32787e6132b924829c353864933f29124419916db550machenbach@chromium.org
32797e6132b924829c353864933f29124419916db550machenbach@chromium.org  Statement* result = NULL;
32807e6132b924829c353864933f29124419916db550machenbach@chromium.org  if (let_bindings.length() > 0) {
32817e6132b924829c353864933f29124419916db550machenbach@chromium.org    scope_ = for_scope;
32827e6132b924829c353864933f29124419916db550machenbach@chromium.org    result = DesugarLetBindingsInForStatement(inner_scope, &let_bindings, loop,
32837e6132b924829c353864933f29124419916db550machenbach@chromium.org                                              init, cond, next, body, CHECK_OK);
32847e6132b924829c353864933f29124419916db550machenbach@chromium.org    scope_ = saved_scope;
32857e6132b924829c353864933f29124419916db550machenbach@chromium.org    for_scope->set_end_position(scanner()->location().end_pos);
3286394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  } else {
32877e6132b924829c353864933f29124419916db550machenbach@chromium.org    scope_ = saved_scope;
32887e6132b924829c353864933f29124419916db550machenbach@chromium.org    for_scope->set_end_position(scanner()->location().end_pos);
328912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    for_scope = for_scope->FinalizeBlockScope();
329012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (for_scope) {
329112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // Rewrite a for statement of the form
329212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //   for (const x = i; c; n) b
329312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //
329412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      // into
329512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //
329612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //   {
329712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //     const x = i;
329812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //     for (; c; n) b
329912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      //   }
3300e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(init != NULL);
330112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      Block* block =
330212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org          factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
330312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      block->AddStatement(init, zone());
330412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      block->AddStatement(loop, zone());
330512e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      block->set_scope(for_scope);
330612e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      loop->Initialize(NULL, cond, next, body);
330712e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      result = block;
330812e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    } else {
330912e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      loop->Initialize(init, cond, next, body);
331012e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      result = loop;
331112e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
3312394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
33137e6132b924829c353864933f29124419916db550machenbach@chromium.org  return result;
331443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
331543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
331643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
331743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenDebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
331843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
331943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // contexts this is used as a statement which invokes the debugger as i a
332043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // break point is present.
332143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // DebuggerStatement ::
332243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   'debugger' ';'
332343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3324a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
332543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::DEBUGGER, CHECK_OK);
332643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ExpectSemicolon(CHECK_OK);
3327a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewDebuggerStatement(pos);
332843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
332943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
333043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3331bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgbool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3332196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org  if (expression->IsLiteral()) return true;
3333bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3334bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return lit != NULL && lit->is_simple();
3335bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3336bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
33370b9f850f0e9dc624b9e0c5254393112ecc7f8bc9ricow@chromium.org
33383d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.orgHandle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
33393d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org                                              Expression* expression) {
33403d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org  Factory* factory = isolate->factory();
3341e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(IsCompileTimeValue(expression));
3342d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
3343bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  ObjectLiteral* object_literal = expression->AsObjectLiteral();
3344bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  if (object_literal != NULL) {
3345e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(object_literal->is_simple());
3346f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    if (object_literal->fast_elements()) {
3347dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
3348f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    } else {
3349dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
3350f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org    }
3351bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    result->set(kElementsSlot, *object_literal->constant_properties());
3352bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  } else {
3353bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    ArrayLiteral* array_literal = expression->AsArrayLiteral();
3354e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(array_literal != NULL && array_literal->is_simple());
3355dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
33560c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    result->set(kElementsSlot, *array_literal->constant_elements());
3357bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  }
3358bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return result;
3359bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3360bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3361bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3362dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgCompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
3363dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    Handle<FixedArray> value) {
3364dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
3365dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  return static_cast<LiteralType>(literal_type->value());
3366bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3367bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3368bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3369bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgHandle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3370bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3371bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
3372bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
3373bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
33749bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.orgbool CheckAndDeclareArrowParameter(ParserTraits* traits, Expression* expression,
33759bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                                   Scope* scope, int* num_params,
33769bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                                   Scanner::Location* dupe_loc) {
33779bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Case for empty parameter lists:
33789bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  //   () => ...
33799bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  if (expression == NULL) return true;
33809bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
33819bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Too many parentheses around expression:
33829bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  //   (( ... )) => ...
33839bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  if (expression->parenthesization_level() > 1) return false;
33849bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
33859bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Case for a single parameter:
33869bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  //   (foo) => ...
33879bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  //   foo => ...
33889bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  if (expression->IsVariableProxy()) {
33899bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    if (expression->AsVariableProxy()->is_this()) return false;
33909bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
33919bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    const AstRawString* raw_name = expression->AsVariableProxy()->raw_name();
33929bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    if (traits->IsEvalOrArguments(raw_name) ||
33939bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org        traits->IsFutureStrictReserved(raw_name))
33949bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org      return false;
33959bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
33969bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    if (scope->IsDeclared(raw_name)) {
33979bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org      *dupe_loc = Scanner::Location(
33989bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org          expression->position(), expression->position() + raw_name->length());
33999bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org      return false;
34009bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    }
34019bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34029bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    scope->DeclareParameter(raw_name, VAR);
34039bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    ++(*num_params);
34049bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    return true;
34059bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  }
34069bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34079bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Case for more than one parameter:
34089bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  //   (foo, bar [, ...]) => ...
34099bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  if (expression->IsBinaryOperation()) {
34109bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    BinaryOperation* binop = expression->AsBinaryOperation();
34119bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    if (binop->op() != Token::COMMA || binop->left()->is_parenthesized() ||
34129bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org        binop->right()->is_parenthesized())
34139bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org      return false;
34149bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34159bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    return CheckAndDeclareArrowParameter(traits, binop->left(), scope,
34169bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                                         num_params, dupe_loc) &&
34179bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org           CheckAndDeclareArrowParameter(traits, binop->right(), scope,
34189bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                                         num_params, dupe_loc);
34199bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  }
34209bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34219bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  // Any other kind of expression is not a valid parameter list.
34229bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  return false;
34239bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org}
34249bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34259bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34269bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.orgint ParserTraits::DeclareArrowParametersFromExpression(
34279bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    Expression* expression, Scope* scope, Scanner::Location* dupe_loc,
34289bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    bool* ok) {
34299bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  int num_params = 0;
34309bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  *ok = CheckAndDeclareArrowParameter(this, expression, scope, &num_params,
34319bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org                                      dupe_loc);
34329bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org  return num_params;
34339bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org}
34349bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
34359bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org
3436dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.orgFunctionLiteral* Parser::ParseFunctionLiteral(
34372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    const AstRawString* function_name, Scanner::Location function_name_location,
34382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
3439dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    FunctionLiteral::FunctionType function_type,
34402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
344143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Function ::
344243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
3443dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org  //
3444dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org  // Getter ::
3445dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org  //   '(' ')' '{' FunctionBody '}'
3446dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org  //
3447dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org  // Setter ::
3448dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org  //   '(' PropertySetParameterList ')' '{' FunctionBody '}'
344943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3450a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = function_token_pos == RelocInfo::kNoPosition
3451a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      ? peek_position() : function_token_pos;
3452a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org
34532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  bool is_generator = IsGeneratorFunction(kind);
34542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org
34557c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // Anonymous functions were passed either the empty symbol or a null
34567c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // handle as the function name.  Remember if we were passed a non-empty
34577c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // handle to decide whether to invoke function name inference.
345808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  bool should_infer_name = function_name == NULL;
34597c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org
34607c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  // We want a non-null handle as the function name.
34617c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  if (should_infer_name) {
34626313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    function_name = ast_value_factory()->empty_string();
346343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
346443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
346543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  int num_parameters = 0;
3466b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // Function declarations are function scoped in normal mode, so they are
3467b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // hoisted. In harmony block scoping mode they are block scoped, so they
3468b645116853c677aca8a316381b87441ba6004f67danno@chromium.org  // are not hoisted.
34691e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //
34701e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // One tricky case are function declarations in a local sloppy-mode eval:
34711e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // their declaration is hoisted, but they still see the local scope. E.g.,
34721e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //
34731e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // function() {
34741e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   var x = 0
34751e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   try { throw 1 } catch (x) { eval("function g() { return x }") }
34761e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   return g()
34771e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // }
34781e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //
34791e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // needs to return 1. To distinguish such cases, we need to detect
34801e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // (1) whether a function stems from a sloppy eval, and
34811e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // (2) whether it actually hoists across the eval.
34821e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
34831e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // either information available directly, especially not when lazily compiling
34841e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // a function like 'g'. We hence rely on the following invariants:
34851e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // - (1) is the case iff the innermost scope of the deserialized scope chain
34861e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   under which we compile is _not_ a declaration scope. This holds because
34871e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   in all normal cases, function declarations are fully hoisted to a
34881e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   declaration scope and compiled relative to that.
34891e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  // - (2) is the case iff the current declaration scope is still the original
34901e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   one relative to the deserialized scope chain. Otherwise we must be
34911e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   compiling a function in an inner declaration scope in the eval, e.g. a
34921e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  //   nested function, and hoisting works normally relative to that.
3493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Scope* declaration_scope = scope_->DeclarationScope();
34941e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org  Scope* original_declaration_scope = original_scope_->DeclarationScope();
3495dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org  Scope* scope =
3496486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      function_type == FunctionLiteral::DECLARATION &&
3497a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      (!allow_harmony_scoping() || strict_mode() == SLOPPY) &&
34981e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org      (original_scope_ == original_declaration_scope ||
34991e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org       declaration_scope != original_declaration_scope)
35001e8da746019f818a22dfdc6f691dbc0447048cadjkummerow@chromium.org          ? NewScope(declaration_scope, FUNCTION_SCOPE)
3501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          : NewScope(scope_, FUNCTION_SCOPE);
350204e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  ZoneList<Statement*>* body = NULL;
35031b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int materialized_literal_count = -1;
35041b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  int expected_property_count = -1;
350504e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org  int handler_count = 0;
350656454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org  FunctionLiteral::ParameterFlag duplicate_parameters =
350756454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org      FunctionLiteral::kNoDuplicateParameters;
3508471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
3509471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      ? FunctionLiteral::kIsParenthesized
3510471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org      : FunctionLiteral::kNotParenthesized;
3511b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  AstProperties ast_properties;
35122c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  BailoutReason dont_optimize_reason = kNoReason;
351343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Parse function body.
351408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  {
351508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    FunctionState function_state(&function_state_, &scope_, scope, zone(),
35166313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                                 ast_value_factory(),
35176313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org                                 info()->ast_node_id_gen());
3518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    scope_->SetScopeName(function_name);
351943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3520e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (is_generator) {
3521e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // For generators, allocating variables in contexts is currently a win
3522e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // because it minimizes the work needed to suspend and resume an
3523e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // activation.
3524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      scope_->ForceContextAllocation();
3525e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
3526e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // Calling a generator returns a generator object.  That object is stored
3527e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      // in a temporary variable, a definition that is used by "yield"
3528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // expressions. This also marks the FunctionState as a generator.
3529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Variable* temp = scope_->DeclarationScope()->NewTemporary(
35306313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org          ast_value_factory()->dot_generator_object_string());
3531e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      function_state.set_generator_object_variable(temp);
3532e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    }
3533e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
353443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //  FormalParameterList ::
353543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    //    '(' (Identifier)*[','] ')'
353643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::LPAREN, CHECK_OK);
3537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    scope->set_start_position(scanner()->location().beg_pos);
3538bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org
3539bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    // We don't yet know if the function will be strict, so we cannot yet
3540bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    // produce errors for parameter names or duplicates. However, we remember
3541bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    // the locations of these errors if they occur and produce the errors later.
3542bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    Scanner::Location eval_args_error_log = Scanner::Location::invalid();
3543bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org    Scanner::Location dupe_error_loc = Scanner::Location::invalid();
35441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Scanner::Location reserved_loc = Scanner::Location::invalid();
35450a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
3546dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org    bool done = arity_restriction == FunctionLiteral::GETTER_ARITY ||
3547dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org        (peek() == Token::RPAREN &&
3548dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org         arity_restriction != FunctionLiteral::SETTER_ARITY);
354943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    while (!done) {
355004921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      bool is_strict_reserved = false;
355108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      const AstRawString* param_name =
35520cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org          ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
3553378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
3554378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      // Store locations for possible future error reports.
3555bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org      if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) {
3556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        eval_args_error_log = scanner()->location();
3557378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org      }
355804921a8093ce8bbec34084bd742b7aa3d299be15ager@chromium.org      if (!reserved_loc.IsValid() && is_strict_reserved) {
3559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        reserved_loc = scanner()->location();
356083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org      }
3561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
3562bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org        duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
3563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        dupe_error_loc = scanner()->location();
3564bb8234d89692f5088ce3fe3ff5a8e8da2f038cfemachenbach@chromium.org      }
3565378b34e3f8852e94739bb77a528278fe0e2bb532ager@chromium.org
35667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      Variable* var = scope_->DeclareParameter(param_name, VAR);
35678640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org      if (scope->strict_mode() == SLOPPY) {
35688640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org        // TODO(sigurds) Mark every parameter as maybe assigned. This is a
35698640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org        // conservative approximation necessary to account for parameters
35708640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org        // that are assigned via the arguments array.
35718640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org        var->set_maybe_assigned();
35728640107360766c74218cf16d51b714b1f2138839machenbach@chromium.org      }
35737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3574fa943b736b1d996084393011529d568165bb5d83lrn@chromium.org      num_parameters++;
3575876cca833d7212e476250d102cad185cdcfa9dfesvenpanne@chromium.org      if (num_parameters > Code::kMaxArguments) {
3576196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org        ReportMessage("too_many_parameters");
3577d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com        *ok = false;
3578d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com        return NULL;
3579d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com      }
3580dc9f731404454341ef693636fc6e2fc4bc50888eulan@chromium.org      if (arity_restriction == FunctionLiteral::SETTER_ARITY) break;
358143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      done = (peek() == Token::RPAREN);
358243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      if (!done) Expect(Token::COMMA, CHECK_OK);
358343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
358443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::RPAREN, CHECK_OK);
358543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
358643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    Expect(Token::LBRACE, CHECK_OK);
358743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
358843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // If we have a named function expression, we add a local variable
358943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // declaration to the body of the function with the name of the
359043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // function and let it refer to the function itself (closure).
359143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // NOTE: We create a proxy and resolve it here so that in the
359243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // future we can change the AST to only refer to VariableProxies
359343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // instead of Variables and Proxis as is the case now.
359404e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org    Variable* fvar = NULL;
3595486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
3596dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
3597a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      if (allow_harmony_scoping() && strict_mode() == STRICT) {
3598486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        fvar_init_op = Token::INIT_CONST;
3599486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      }
3600a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org      VariableMode fvar_mode =
360170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org          allow_harmony_scoping() && strict_mode() == STRICT
360270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org              ? CONST : CONST_LEGACY;
3603e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(function_name != NULL);
36047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      fvar = new (zone())
36057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org          Variable(scope_, function_name, fvar_mode, true /* is valid LHS */,
36067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   Variable::NORMAL, kCreatedInitialized, kNotAssigned,
36077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   Interface::NewConst());
3608ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com      VariableProxy* proxy = factory()->NewVariableProxy(fvar);
3609a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org      VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
3610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org          proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
3611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      scope_->DeclareFunctionVar(fvar_declaration);
361243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
361343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3614f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Determine if the function can be parsed lazily. Lazy parsing is different
3615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // from lazy compilation; we need to parse more eagerly than we compile.
3616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // We can only parse lazily if we also compile lazily. The heuristics for
3618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // lazy compilation are:
36191b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // - It must not have been prohibited by the caller to Parse (some callers
36201b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   need a full AST).
36219c741c80bfc8026103e86b46e15e2544095ce67eyangguo@chromium.org    // - The outer scope must allow lazy compilation of inner functions.
36221b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // - The function mustn't be a function expression with an open parenthesis
36231b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   before; we consider that a hint that the function will be called
36241b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   immediately, and it would be a waste of time to make it lazily
36251b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    //   compiled.
36261b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // These are all things we can know at this point, without looking at the
36271b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    // function itself.
3628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // In addition, we need to distinguish between these cases:
3630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // (function foo() {
3631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //   bar = function() { return 1; }
3632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //  })();
3633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // and
3634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // (function foo() {
3635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //   var a = 1;
3636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //   bar = function() { return a; }
3637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //  })();
3638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
3640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // parenthesis before the function means that it will be called
3641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // immediately). The inner function *must* be parsed eagerly to resolve the
3642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // possible reference to the variable in foo's scope. However, it's possible
3643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // that it will be compiled lazily.
3644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
3645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // To make this additional case work, both Parser and PreParser implement a
3646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // logic where only top-level functions will be parsed lazily.
3647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
3648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             scope_->AllowsLazyCompilation() &&
3649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             !parenthesized_function_);
3650c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org    parenthesized_function_ = false;  // The bit was set for this function only.
365143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (is_lazily_parsed) {
3653e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      SkipLazyFunctionBody(function_name, &materialized_literal_count,
3654e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                           &expected_property_count, CHECK_OK);
3655e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    } else {
3656e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
3657e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                    is_generator, CHECK_OK);
3658c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      materialized_literal_count = function_state.materialized_literal_count();
3659c612e0211bdb8821cbd7886e15b0273ed82d2e9edanno@chromium.org      expected_property_count = function_state.expected_property_count();
366004e4f1e9e1291ac270e1cb7d8384b2af2fd2d685jkummerow@chromium.org      handler_count = function_state.handler_count();
366143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
366243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
36634b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org    // Validate strict mode.
36642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    // Concise methods use StrictFormalParameters.
36652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (strict_mode() == STRICT || IsConciseMethod(kind)) {
36664b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org      CheckStrictFunctionNameAndParameters(function_name,
36674b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org                                           name_is_strict_reserved,
36684b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org                                           function_name_location,
36694b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org                                           eval_args_error_log,
36704b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org                                           dupe_error_loc,
36714b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org                                           reserved_loc,
36724b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org                                           CHECK_OK);
36732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    }
36742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    if (strict_mode() == STRICT) {
3675394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      CheckOctalLiteral(scope->start_position(),
3676394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                        scope->end_position(),
3677394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                        CHECK_OK);
36780a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    }
3679b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org    ast_properties = *factory()->visitor()->ast_properties();
36802c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org    dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
36810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org
368212e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    if (allow_harmony_scoping() && strict_mode() == STRICT) {
368312e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org      CheckConflictingVarDeclarations(scope, CHECK_OK);
368412e05e8fde625d746b998a15049e8487c43a3b17machenbach@chromium.org    }
36851805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  }
36861805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
36879d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
36886313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org      function_name, ast_value_factory(), scope, body,
36899d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org      materialized_literal_count, expected_property_count, handler_count,
36909d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org      num_parameters, duplicate_parameters, function_type,
36919d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org      FunctionLiteral::kIsFunction, parenthesized, kind, pos);
3692a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  function_literal->set_function_token_position(function_token_pos);
3693b1df11df5b7bdcc201852bfcdce0a8eace33b011svenpanne@chromium.org  function_literal->set_ast_properties(&ast_properties);
36942c9426bdda5e95459527292063d885c98180cb0fjkummerow@chromium.org  function_literal->set_dont_optimize_reason(dont_optimize_reason);
36955d8f0e6e7b477f422e3064bdf0dd5f2a23f75544kmillikin@chromium.org
36967c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
369744bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.org  return function_literal;
369843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
369943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
370043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
370108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgvoid Parser::SkipLazyFunctionBody(const AstRawString* function_name,
3702e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                  int* materialized_literal_count,
3703e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                  int* expected_property_count,
3704e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                  bool* ok) {
3705e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  int function_block_pos = position();
37064c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org  if (compile_options() == ScriptCompiler::kConsumeParserCache) {
3707e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    // If we have cached data, we use it to skip parsing the function body. The
3708e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    // data contains the information we need to construct the lazy function.
3709e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    FunctionEntry entry =
371070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org        cached_parse_data_->GetFunctionEntry(function_block_pos);
371170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    // Check that cached data is valid.
371270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    CHECK(entry.is_valid());
371370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    // End position greater than end of stream is safe, and hard to check.
371470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    CHECK(entry.end_pos() > function_block_pos);
371570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    scanner()->SeekForward(entry.end_pos() - 1);
371670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org
371770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    scope_->set_end_position(entry.end_pos());
371870d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    Expect(Token::RBRACE, ok);
371970d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    if (!*ok) {
3720e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      return;
3721e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    }
372221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    total_preparse_skipped_ += scope_->end_position() - function_block_pos;
372370d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    *materialized_literal_count = entry.literal_count();
372470d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    *expected_property_count = entry.property_count();
372570d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    scope_->SetStrictMode(entry.strict_mode());
3726e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  } else {
3727e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    // With no cached data, we partially parse the function, without building an
3728e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    // AST. This gathers the data needed to build a lazy function.
3729e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    SingletonLogger logger;
3730e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    PreParser::PreParseResult result =
3731e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        ParseLazyFunctionBodyWithPreParser(&logger);
3732e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    if (result == PreParser::kPreParseStackOverflow) {
3733e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      // Propagate stack overflow.
3734e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      set_stack_overflow();
3735e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      *ok = false;
3736e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      return;
3737e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    }
3738e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    if (logger.has_error()) {
3739e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      ParserTraits::ReportMessageAt(
3740e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org          Scanner::Location(logger.start(), logger.end()),
3741285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org          logger.message(), logger.argument_opt(), logger.is_reference_error());
3742e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      *ok = false;
3743e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      return;
3744e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    }
3745e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    scope_->set_end_position(logger.end());
3746e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    Expect(Token::RBRACE, ok);
3747e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    if (!*ok) {
3748e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      return;
3749e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    }
375021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    total_preparse_skipped_ += scope_->end_position() - function_block_pos;
3751e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    *materialized_literal_count = logger.literals();
3752e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    *expected_property_count = logger.properties();
3753e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    scope_->SetStrictMode(logger.strict_mode());
37544c3ce7c3fd2802da8f91c6516a9c9aea3cd93f1emachenbach@chromium.org    if (compile_options() == ScriptCompiler::kProduceParserCache) {
3755e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(log_);
3756e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      // Position right after terminal '}'.
3757e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      int body_end = scanner()->location().end_pos;
3758e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org      log_->LogFunction(function_block_pos, body_end,
3759e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                        *materialized_literal_count,
3760e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                        *expected_property_count,
3761e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                        scope_->strict_mode());
3762e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    }
3763e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  }
3764e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org}
3765e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3766e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3767e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.orgZoneList<Statement*>* Parser::ParseEagerFunctionBody(
376808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* function_name, int pos, Variable* fvar,
3769e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    Token::Value fvar_init_op, bool is_generator, bool* ok) {
3770e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  // Everything inside an eagerly parsed function will be parsed eagerly
3771e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  // (see comment above).
3772e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
3773e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8, zone());
3774e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  if (fvar != NULL) {
3775e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    VariableProxy* fproxy = scope_->NewUnresolved(
3776e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        factory(), function_name, Interface::NewConst());
3777e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    fproxy->BindTo(fvar);
3778e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    body->Add(factory()->NewExpressionStatement(
3779e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        factory()->NewAssignment(fvar_init_op,
3780e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                 fproxy,
3781e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                 factory()->NewThisFunction(pos),
3782e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org                                 RelocInfo::kNoPosition),
3783e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        RelocInfo::kNoPosition), zone());
3784e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  }
3785e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3786e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  // For generators, allocate and yield an iterator on function entry.
3787e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  if (is_generator) {
3788e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    ZoneList<Expression*>* arguments =
3789e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        new(zone()) ZoneList<Expression*>(0, zone());
3790e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    CallRuntime* allocation = factory()->NewCallRuntime(
37916313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        ast_value_factory()->empty_string(),
37926313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject), arguments,
37936313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org        pos);
3794e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    VariableProxy* init_proxy = factory()->NewVariableProxy(
3795e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        function_state_->generator_object_variable());
3796e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    Assignment* assignment = factory()->NewAssignment(
3797e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
3798e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    VariableProxy* get_proxy = factory()->NewVariableProxy(
3799e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        function_state_->generator_object_variable());
3800e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    Yield* yield = factory()->NewYield(
3801ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org        get_proxy, assignment, Yield::kInitial, RelocInfo::kNoPosition);
3802e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    body->Add(factory()->NewExpressionStatement(
3803e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        yield, RelocInfo::kNoPosition), zone());
3804e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  }
3805e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3806b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  ParseSourceElements(body, Token::RBRACE, false, false, NULL, CHECK_OK);
3807e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3808e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  if (is_generator) {
3809e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    VariableProxy* get_proxy = factory()->NewVariableProxy(
3810e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        function_state_->generator_object_variable());
381108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    Expression* undefined =
381208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
3813ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::kFinal,
381408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                       RelocInfo::kNoPosition);
3815e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org    body->Add(factory()->NewExpressionStatement(
3816e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org        yield, RelocInfo::kNoPosition), zone());
3817e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  }
3818e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3819e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  Expect(Token::RBRACE, CHECK_OK);
3820e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  scope_->set_end_position(scanner()->location().end_pos);
3821e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3822e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org  return body;
3823e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org}
3824e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3825e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.org
3826e9fd6580f52407c94d77bfcb4be04207f2ebb2f1machenbach@chromium.orgPreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
38271b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org    SingletonLogger* logger) {
382821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // This function may be called on a background thread too; record only the
382921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // main thread preparse times.
383021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  if (pre_parse_timer_ != NULL) {
383121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    pre_parse_timer_->Start();
383221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  }
3833e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(Token::LBRACE, scanner()->current_token());
38341b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
38351b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  if (reusable_preparser_ == NULL) {
383621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit_);
3837e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
3838e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_modules(allow_modules());
3839e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
3840e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    reusable_preparser_->set_allow_lazy(true);
38419bf7aff6cc5ed8807b7b2abc11b6cf77b928ded1machenbach@chromium.org    reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions());
3842ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org    reusable_preparser_->set_allow_harmony_numeric_literals(
3843ba72ec861b69b67139c93fc6dd56f4a73c9b3135jkummerow@chromium.org        allow_harmony_numeric_literals());
38447dae5b9f8500ada1f217a27db8a1f5c62becd404machenbach@chromium.org    reusable_preparser_->set_allow_classes(allow_classes());
38452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    reusable_preparser_->set_allow_harmony_object_literals(
38462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        allow_harmony_object_literals());
38471b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  }
3848a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  PreParser::PreParseResult result =
3849486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      reusable_preparser_->PreParseLazyFunction(strict_mode(),
3850f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org                                                is_generator(),
38511b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org                                                logger);
385221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  if (pre_parse_timer_ != NULL) {
385321d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    pre_parse_timer_->Stop();
385421d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  }
38551b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org  return result;
38561b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org}
38571b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
38581b3afd1cab9087ca3c4e585d3da77d374d65c082mstarzinger@chromium.org
385943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenExpression* Parser::ParseV8Intrinsic(bool* ok) {
386043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // CallRuntime ::
386143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  //   '%' Identifier Arguments
386243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3863a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  int pos = peek_position();
386443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  Expect(Token::MOD, CHECK_OK);
38658297530cd2b71ba1a2fe6f27ba1c030a20468306machenbach@chromium.org  // Allow "eval" or "arguments" for backward compatibility.
386608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
386743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3868d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com
3869d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (extension_ != NULL) {
387043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // The extension structures are only accessible while parsing the
387143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // very first time not when reparsing because of lazy compilation.
3872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    scope_->DeclarationScope()->ForceEagerCompilation();
387343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
387443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
387508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  const Runtime::Function* function = Runtime::FunctionForName(name->string());
387643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3877d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Check for built-in IS_VAR macro.
3878d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (function != NULL &&
3879d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->intrinsic_type == Runtime::RUNTIME &&
3880d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->function_id == Runtime::kIS_VAR) {
3881d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // %IS_VAR(x) evaluates to x if x is a variable,
3882d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // leads to a parse error otherwise.  Could be implemented as an
3883d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    // inline function %_IS_VAR(x) to eliminate this special case.
3884d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
3885d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      return args->at(0);
3886d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    } else {
3887285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org      ReportMessage("not_isvar");
3888d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      *ok = false;
388943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return NULL;
389043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
389143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
389243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3893d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // Check that the expected number of arguments are being passed.
3894d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  if (function != NULL &&
3895d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->nargs != -1 &&
3896d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com      function->nargs != args->length()) {
3897285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    ReportMessage("illegal_access");
3898d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    *ok = false;
3899d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com    return NULL;
3900de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  }
3901de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org
3902de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org  // Check that the function is defined if it's an inline runtime call.
390308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  if (function == NULL && name->FirstCharacter() == '_') {
3904285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    ParserTraits::ReportMessage("not_defined", name);
3905de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    *ok = false;
3906de64f721c489207a7b9018406d39c7fb04bb9424verwaest@chromium.org    return NULL;
3907f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org  }
3908f837290e142d49c9e1332841ec2c49ee2f09584avegorov@chromium.org
3909d88afa260e45de10e729b05a20146184a488aff7erik.corry@gmail.com  // We have a valid intrinsics call or a call to a builtin.
3910a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.org  return factory()->NewCallRuntime(name, function, args, pos);
391143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
391243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
391343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3914a2e1a40f85577979749d4c0d6de30e992d996659mstarzinger@chromium.orgLiteral* Parser::GetLiteralUndefined(int position) {
391508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  return factory()->NewUndefinedLiteral(position);
391643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
391743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
391843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
39191805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgvoid Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
39201805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  Declaration* decl = scope->CheckConflictingVarDeclarations();
39211805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  if (decl != NULL) {
39221805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    // In harmony mode we treat conflicting variable bindinds as early
39231805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    // errors. See ES5 16 for a definition of early errors.
392408e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    const AstRawString* name = decl->proxy()->raw_name();
39251805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    int position = decl->proxy()->position();
39261805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    Scanner::Location location = position == RelocInfo::kNoPosition
39271805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org        ? Scanner::Location::invalid()
39281805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org        : Scanner::Location(position, position + 1);
3929285f85a5a149f36516a20200a76899651dd95fb6machenbach@chromium.org    ParserTraits::ReportMessageAt(location, "var_redeclaration", name);
39301805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org    *ok = false;
39311805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  }
39321805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org}
39331805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
39341805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
393543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
393643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Parser support
393743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
393843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
393908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgbool Parser::TargetStackContainsLabel(const AstRawString* label) {
3940b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3941b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    BreakableStatement* stat = t->node()->AsBreakableStatement();
394243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (stat != NULL && ContainsLabel(stat->labels(), label))
394343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return true;
394443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
394543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return false;
394643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
394743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
394843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
394908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgBreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
395008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org                                              bool* ok) {
395108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  bool anonymous = label == NULL;
3952b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3953b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    BreakableStatement* stat = t->node()->AsBreakableStatement();
395443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (stat == NULL) continue;
395543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if ((anonymous && stat->is_target_for_anonymous()) ||
395643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen        (!anonymous && ContainsLabel(stat->labels(), label))) {
3957b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      RegisterTargetUse(stat->break_target(), t->previous());
395843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return stat;
395943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
396043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
396143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return NULL;
396243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
396343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
396443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
396508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.orgIterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
396643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                 bool* ok) {
396708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  bool anonymous = label == NULL;
3968b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
3969b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    IterationStatement* stat = t->node()->AsIterationStatement();
397043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (stat == NULL) continue;
397143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3972e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(stat->is_target_for_anonymous());
397343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    if (anonymous || ContainsLabel(stat->labels(), label)) {
3974b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org      RegisterTargetUse(stat->continue_target(), t->previous());
397543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      return stat;
397643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
397743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
397843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return NULL;
397943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
398043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
398143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
398244bc7080a85cc25bff3b9b77cd53f7beffab711bkarlklose@chromium.orgvoid Parser::RegisterTargetUse(Label* target, Target* stop) {
3983b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  // Register that a break target found at the given stop in the
39847be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // target stack has been used from the top of the target stack. Add
39857be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org  // the break target to any TargetCollectors passed on the stack.
3986b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org  for (Target* t = target_stack_; t != stop; t = t->previous()) {
3987b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    TargetCollector* collector = t->node()->AsTargetCollector();
39887028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    if (collector != NULL) collector->AddTarget(target, zone());
398943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
399043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
399143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
399243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3993d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.orgvoid Parser::HandleSourceURLComments() {
3994d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  if (scanner_.source_url()->length() > 0) {
3995d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    Handle<String> source_url = scanner_.source_url()->Internalize(isolate());
3996d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    info_->script()->set_source_url(*source_url);
3997d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  }
3998d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  if (scanner_.source_mapping_url()->length() > 0) {
3999d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    Handle<String> source_mapping_url =
4000d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org        scanner_.source_mapping_url()->Internalize(isolate());
4001d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org    info_->script()->set_source_mapping_url(*source_mapping_url);
4002d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  }
4003d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org}
4004d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
4005d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
40066a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.orgvoid Parser::ThrowPendingError() {
40076313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  DCHECK(ast_value_factory()->IsInternalized());
40086a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  if (has_pending_error_) {
40096313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    MessageLocation location(script(), pending_error_location_.beg_pos,
40106a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                             pending_error_location_.end_pos);
40116a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    Factory* factory = isolate()->factory();
40126a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    bool has_arg =
401308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org        pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
40146a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
401508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    if (pending_error_arg_ != NULL) {
401608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      Handle<String> arg_string = pending_error_arg_->string();
401708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org      elements->set(0, *arg_string);
40186a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    } else if (pending_error_char_arg_ != NULL) {
40196a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org      Handle<String> arg_string =
40206a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org          factory->NewStringFromUtf8(CStrVector(pending_error_char_arg_))
40216a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org          .ToHandleChecked();
40226a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org      elements->set(0, *arg_string);
40236a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    }
40246313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    isolate()->debug()->OnCompileError(script());
4025248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org
40266a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org    Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
4027ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    Handle<Object> error;
4028ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    MaybeHandle<Object> maybe_error =
4029ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org        pending_error_is_reference_error_
4030ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org            ? factory->NewReferenceError(pending_error_message_, array)
4031ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org            : factory->NewSyntaxError(pending_error_message_, array);
4032ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    if (maybe_error.ToHandle(&error)) isolate()->Throw(*error, &location);
40336a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org  }
40346a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org}
40356a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org
40366a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org
403721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.orgvoid Parser::Internalize() {
403821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // Internalize strings.
40396313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  ast_value_factory()->Internalize(isolate());
404021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org
404121d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // Error processing.
404221d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  if (info()->function() == NULL) {
404321d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    if (stack_overflow()) {
404421d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      isolate()->StackOverflow();
404521d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    } else {
404621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      ThrowPendingError();
404721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    }
404821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  }
404921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org
405021d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  // Move statistics to Isolate.
40515de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
40525de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org       ++feature) {
40535de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org    for (int i = 0; i < use_counts_[feature]; ++i) {
40545de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org      isolate()->CountUsage(v8::Isolate::UseCounterFeature(feature));
40555de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org    }
40565de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  }
405721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  isolate()->counters()->total_preparse_skipped()->Increment(
405821d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org      total_preparse_skipped_);
40595de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org}
40605de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org
40615de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org
4062b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org// ----------------------------------------------------------------------------
4063a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Regular expressions
4064a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4065a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4066a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpParser::RegExpParser(FlatStringReader* in,
4067a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                           Handle<String>* error,
40685a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                           bool multiline,
40695a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                           Zone* zone)
40703d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org    : isolate_(zone->isolate()),
40715a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org      zone_(zone),
4072ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      error_(error),
4073ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      captures_(NULL),
4074ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      in_(in),
4075ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      current_(kEndMarker),
4076ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      next_pos_(0),
4077ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      capture_count_(0),
4078ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      has_more_(true),
4079ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      multiline_(multiline),
4080ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      simple_(false),
4081ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      contains_anchor_(false),
4082ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      is_scanned_for_captures_(false),
4083ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      failed_(false) {
4084023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Advance();
4085a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4086a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4087a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4088a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orguc32 RegExpParser::Next() {
4089a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (has_next()) {
4090a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return in()->Get(next_pos_);
4091a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4092a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return kEndMarker;
4093a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4094a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4095a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4096a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4097a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::Advance() {
4098a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (next_pos_ < in()->length()) {
4099ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    StackLimitCheck check(isolate());
4100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (check.HasOverflowed()) {
4101ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      ReportError(CStrVector(Isolate::kStackOverflowMessage));
41025a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org    } else if (zone()->excess_allocation()) {
4103a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      ReportError(CStrVector("Regular expression too large"));
4104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
4105a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      current_ = in()->Get(next_pos_);
4106a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      next_pos_++;
4107a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4108a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4109a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    current_ = kEndMarker;
4110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    has_more_ = false;
4111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4115a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::Reset(int pos) {
4116a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  next_pos_ = pos;
411753ad17558c81e6099cef4442237d7da643a5becfsvenpanne@chromium.org  has_more_ = (pos < in()->length());
4118a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4120a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4121a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::Advance(int dist) {
4123023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  next_pos_ += dist - 1;
4124023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  Advance();
4125a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4126a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
412837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.combool RegExpParser::simple() {
412937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  return simple_;
4130a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4131a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4132e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
4133a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ReportError(Vector<const char> message) {
4134a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  failed_ = true;
4135b67f96038c787a6bd6a835e6c436c82e1b245486machenbach@chromium.org  *error_ = isolate()->factory()->NewStringFromAscii(message).ToHandleChecked();
4136a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Zip to the end to make sure the no more input is read.
4137a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  current_ = kEndMarker;
4138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  next_pos_ = in()->length();
4139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return NULL;
4140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4142a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4143a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Pattern ::
4144a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Disjunction
4145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ParsePattern() {
4146a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
4147e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!has_more());
41487ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  // If the result of parsing is a literal string atom, and it has the
41497ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  // same length as the input, then the atom is identical to the input.
41507ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
41517ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org    simple_ = true;
41527ccf02469d7fca9d9e02385346d316b5a679d4dbkasperl@chromium.org  }
4153a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return result;
4154a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4157a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Disjunction ::
4158a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Alternative
4159a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Alternative | Disjunction
4160a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Alternative ::
4161a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   [empty]
4162a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Term Alternative
4163a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Term ::
4164a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Assertion
4165a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Atom
4166a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   Atom Quantifier
4167a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ParseDisjunction() {
416886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Used to store current state while parsing subexpressions.
4169400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org  RegExpParserState initial_state(NULL, INITIAL, 0, zone());
417086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  RegExpParserState* stored_state = &initial_state;
417186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  // Cache the builder in a local variable for quick access.
417286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org  RegExpBuilder* builder = initial_state.builder();
4173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (true) {
4174a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (current()) {
4175a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case kEndMarker:
417686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      if (stored_state->IsSubexpression()) {
417786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        // Inside a parenthesized group when hitting end of input.
417886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        ReportError(CStrVector("Unterminated group") CHECK_FAILED);
417986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      }
4180e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_EQ(INITIAL, stored_state->group_type());
418186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Parsing completed successfully.
418286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      return builder->ToRegExp();
418386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    case ')': {
418486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      if (!stored_state->IsSubexpression()) {
418586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
418686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      }
4187e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_NE(INITIAL, stored_state->group_type());
418886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
4189a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
419086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // End disjunction parsing and convert builder content to new single
419186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // regexp atom.
419286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      RegExpTree* body = builder->ToRegExp();
419386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
419486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      int end_capture_index = captures_started();
419586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
419686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      int capture_index = stored_state->capture_index();
4197dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      SubexpressionType group_type = stored_state->group_type();
419886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
419986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Restore previous state.
420086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      stored_state = stored_state->previous_state();
420186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder = stored_state->builder();
420286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org
420386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Build result of subexpression.
4204dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      if (group_type == CAPTURE) {
4205c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org        RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
420686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        captures_->at(capture_index - 1) = capture;
420786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        body = capture;
4208dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      } else if (group_type != GROUPING) {
4209e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(group_type == POSITIVE_LOOKAHEAD ||
4210dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org               group_type == NEGATIVE_LOOKAHEAD);
4211dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org        bool is_positive = (group_type == POSITIVE_LOOKAHEAD);
4212c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org        body = new(zone()) RegExpLookahead(body,
421386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                   is_positive,
421486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                   end_capture_index - capture_index,
421586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org                                   capture_index);
4216a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
421786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddAtom(body);
421849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // For compatability with JSC and ES3, we allow quantifiers after
421949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // lookaheads, and break in all cases.
422086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      break;
422186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    }
422286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org    case '|': {
422386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      Advance();
422486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->NewAlternative();
4225a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4226a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4227a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '*':
4228a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '+':
4229a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '?':
4230e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org      return ReportError(CStrVector("Nothing to repeat"));
4231a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '^': {
4232a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4233245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      if (multiline_) {
423486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4235c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
4236245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      } else {
423786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4238c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
4239245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        set_contains_anchor();
4240245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      }
4241a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4242a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4243a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '$': {
4244a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4245dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      RegExpAssertion::AssertionType assertion_type =
4246a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          multiline_ ? RegExpAssertion::END_OF_LINE :
4247a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                       RegExpAssertion::END_OF_INPUT;
4248dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      builder->AddAssertion(new(zone()) RegExpAssertion(assertion_type));
4249a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4250a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4251a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '.': {
4252a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4253a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // everything except \x0a, \x0d, \u2028 and \u2029
425440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org      ZoneList<CharacterRange>* ranges =
42557028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          new(zone()) ZoneList<CharacterRange>(2, zone());
42567028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      CharacterRange::AddClassEscape('.', ranges, zone());
4257c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org      RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
425886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddAtom(atom);
4259a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4260a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4261a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '(': {
4262dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      SubexpressionType subexpr_type = CAPTURE;
426386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      Advance();
426486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      if (current() == '?') {
426586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        switch (Next()) {
426686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          case ':':
4267dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org            subexpr_type = GROUPING;
426886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
426986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          case '=':
4270dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org            subexpr_type = POSITIVE_LOOKAHEAD;
427186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
427286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          case '!':
4273dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org            subexpr_type = NEGATIVE_LOOKAHEAD;
427486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
427586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          default:
427686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            ReportError(CStrVector("Invalid group") CHECK_FAILED);
427786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
427886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        }
427986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        Advance(2);
428086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      } else {
428186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        if (captures_ == NULL) {
42827028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org          captures_ = new(zone()) ZoneList<RegExpCapture*>(2, zone());
428386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        }
428486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        if (captures_started() >= kMaxCaptures) {
428586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          ReportError(CStrVector("Too many captures") CHECK_FAILED);
428686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        }
42877028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        captures_->Add(NULL, zone());
428886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      }
428986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      // Store current state and begin new disjunction parsing.
4290dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      stored_state = new(zone()) RegExpParserState(stored_state, subexpr_type,
4291400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org                                                   captures_started(), zone());
429286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder = stored_state->builder();
429349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      continue;
4294a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4295a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '[': {
4296a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
429786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddAtom(atom);
4298a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4299a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4300a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // Atom ::
4301a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   \ AtomEscape
4302a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '\\':
4303a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      switch (Next()) {
4304a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case kEndMarker:
4305e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        return ReportError(CStrVector("\\ at end of pattern"));
4306a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'b':
4307a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
430886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4309c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
4310a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
4311a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'B':
4312a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
431386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAssertion(
4314c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org            new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
4315a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
431649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // AtomEscape ::
431749edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      //   CharacterClassEscape
431849edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      //
431949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      // CharacterClassEscape :: one of
432049edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      //   d D s S w W
4321a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
4322a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 c = Next();
4323a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
432440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org        ZoneList<CharacterRange>* ranges =
43257028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org            new(zone()) ZoneList<CharacterRange>(2, zone());
43267028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        CharacterRange::AddClassEscape(c, ranges, zone());
4327c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org        RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
432886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddAtom(atom);
432986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        break;
4330a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4331a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '1': case '2': case '3': case '4': case '5': case '6':
4332a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '7': case '8': case '9': {
4333a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        int index = 0;
4334a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (ParseBackReferenceIndex(&index)) {
433586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          RegExpCapture* capture = NULL;
433686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          if (captures_ != NULL && index <= captures_->length()) {
433786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            capture = captures_->at(index - 1);
433886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          }
433986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          if (capture == NULL) {
434086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            builder->AddEmpty();
434186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org            break;
4342a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          }
4343c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org          RegExpTree* atom = new(zone()) RegExpBackReference(capture);
434486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddAtom(atom);
434586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          break;
4346a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
4347a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 first_digit = Next();
4348a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (first_digit == '8' || first_digit == '9') {
4349a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          // Treat as identity escape
435086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter(first_digit);
4351a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          Advance(2);
4352a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          break;
4353a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
4354a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4355a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // FALLTHROUGH
4356a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '0': {
4357a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance();
4358a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 octal = ParseOctalLiteral();
435986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter(octal);
4360a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4361a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4362a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // ControlEscape :: one of
4363a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      //   f n r t v
4364a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'f':
4365a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
436686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\f');
4367a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4368a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'n':
4369a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
437086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\n');
4371a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4372a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'r':
4373a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
437486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\r');
4375a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4376a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 't':
4377a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
437886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\t');
4379a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4380a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'v':
4381a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
438286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter('\v');
4383a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4384a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'c': {
4385d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        Advance();
4386d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        uc32 controlLetter = Next();
4387d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // Special case if it is an ASCII letter.
4388d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // Convert lower case letters to uppercase.
4389d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        uc32 letter = controlLetter & ~('a' ^ 'A');
4390d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        if (letter < 'A' || 'Z' < letter) {
4391d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
4392d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // This is outside the specification. We match JSC in
4393d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // reading the backslash as a literal character instead
4394d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          // of as starting an escape.
4395d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          builder->AddCharacter('\\');
4396d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        } else {
4397d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          Advance(2);
4398d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          builder->AddCharacter(controlLetter & 0x1f);
4399d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        }
4400a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4401a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4402a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'x': {
4403a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
4404a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 value;
4405a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (ParseHexEscape(2, &value)) {
440686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter(value);
4407a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        } else {
440886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter('x');
4409a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
4410a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4411a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4412a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'u': {
4413a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
4414a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 value;
4415a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (ParseHexEscape(4, &value)) {
441686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter(value);
4417a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        } else {
441886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org          builder->AddCharacter('u');
4419a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
4420a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4421a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4422a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      default:
4423a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // Identity escape.
442486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org        builder->AddCharacter(Next());
4425a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
4426a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4427a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4428a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4429a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '{': {
4430a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      int dummy;
4431a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseIntervalQuantifier(&dummy, &dummy)) {
4432a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
4433a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4434a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // fallthrough
4435a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4436a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default:
443786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org      builder->AddCharacter(current());
4438a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4439a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4440a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }  // end switch(current())
4441a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4442a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int min;
4443a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int max;
4444a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (current()) {
4445a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // QuantifierPrefix ::
4446a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   *
4447a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   +
4448a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   ?
4449a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   {
4450a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '*':
4451a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      min = 0;
445237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      max = RegExpTree::kInfinity;
4453a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4454a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4455a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '+':
4456a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      min = 1;
445737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      max = RegExpTree::kInfinity;
4458a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4459a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4460a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '?':
4461a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      min = 0;
4462a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      max = 1;
4463a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4464a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4465a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '{':
4466a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseIntervalQuantifier(&min, &max)) {
4467245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        if (max < min) {
4468245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          ReportError(CStrVector("numbers out of order in {} quantifier.")
4469245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                      CHECK_FAILED);
4470245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        }
4471a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4472a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      } else {
4473a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        continue;
4474a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4475a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default:
4476a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      continue;
4477a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4478dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    RegExpQuantifier::QuantifierType quantifier_type = RegExpQuantifier::GREEDY;
4479a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (current() == '?') {
4480dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      quantifier_type = RegExpQuantifier::NON_GREEDY;
44810c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      Advance();
44820c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
44830c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      // FLAG_regexp_possessive_quantifier is a debug-only flag.
4484dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org      quantifier_type = RegExpQuantifier::POSSESSIVE;
4485a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4486a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4487dfe53073738bbf16023d96fce5118358a1037fd3ulan@chromium.org    builder->AddQuantifierToAtom(min, max, quantifier_type);
4488a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4489a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4490a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4491a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4492a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#ifdef DEBUG
4493e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org// Currently only used in an DCHECK.
4494a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic bool IsSpecialClassEscape(uc32 c) {
4495a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  switch (c) {
4496a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'd': case 'D':
4497a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 's': case 'S':
4498a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'w': case 'W':
4499a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return true;
4500a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default:
4501a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
4502a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4503a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4504a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif
4505a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4506a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4507a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// In order to know whether an escape is a backreference or not we have to scan
4508a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// the entire regexp and find the number of capturing parentheses.  However we
4509a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// don't want to scan the regexp twice unless it is necessary.  This mini-parser
4510a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// is called when needed.  It can see the difference between capturing and
4511a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// noncapturing parentheses and can skip character classes and backslash-escaped
4512a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// characters.
4513a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpParser::ScanForCaptures() {
4514a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Start with captures started previous to current position
4515a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int capture_count = captures_started();
4516a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Add count of captures after this position.
4517a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int n;
4518a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while ((n = current()) != kEndMarker) {
4519a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4520a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (n) {
4521a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '\\':
4522a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance();
4523a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4524a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '[': {
4525a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        int c;
4526a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        while ((c = current()) != kEndMarker) {
4527a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          Advance();
4528a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          if (c == '\\') {
4529a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            Advance();
4530a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          } else {
4531a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            if (c == ']') break;
4532a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org          }
4533a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
4534a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4535a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4536a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case '(':
4537a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (current() != '?') capture_count++;
4538a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4539a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4540a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4541a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  capture_count_ = capture_count;
4542a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  is_scanned_for_captures_ = true;
4543a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4544a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4545a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4546a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool RegExpParser::ParseBackReferenceIndex(int* index_out) {
4547e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ('\\', current());
4548e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK('1' <= Next() && Next() <= '9');
4549245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  // Try to parse a decimal literal that is no greater than the total number
4550245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  // of left capturing parentheses in the input.
4551a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int start = position();
4552a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int value = Next() - '0';
4553a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance(2);
4554a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (true) {
4555a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    uc32 c = current();
4556a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (IsDecimalDigit(c)) {
4557a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      value = 10 * value + (c - '0');
4558245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      if (value > kMaxCaptures) {
4559245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        Reset(start);
4560245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        return false;
4561245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      }
4562a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4563a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
4564a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      break;
4565a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4566a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4567a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (value > captures_started()) {
4568a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!is_scanned_for_captures_) {
4569a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      int saved_position = position();
4570a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      ScanForCaptures();
4571a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Reset(saved_position);
4572a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4573a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (value > capture_count_) {
4574a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Reset(start);
4575a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
4576a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4577a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4578a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *index_out = value;
4579a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
4580a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4581a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4582a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4583a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// QuantifierPrefix ::
4584a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   { DecimalDigits }
4585a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   { DecimalDigits , }
4586a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//   { DecimalDigits , DecimalDigits }
4587245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org//
4588245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org// Returns true if parsing succeeds, and set the min_out and max_out
4589245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org// values. Values are truncated to RegExpTree::kInfinity if they overflow.
4590a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
4591e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(current(), '{');
4592a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int start = position();
4593a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4594a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int min = 0;
4595a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!IsDecimalDigit(current())) {
4596a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Reset(start);
4597a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
4598a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4599a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (IsDecimalDigit(current())) {
4600245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    int next = current() - '0';
4601245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    if (min > (RegExpTree::kInfinity - next) / 10) {
4602245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      // Overflow. Skip past remaining decimal digits and return -1.
4603245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      do {
4604245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        Advance();
4605245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      } while (IsDecimalDigit(current()));
4606245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      min = RegExpTree::kInfinity;
4607245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org      break;
4608245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    }
4609245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    min = 10 * min + next;
4610a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4611a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4612a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int max = 0;
4613a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (current() == '}') {
4614a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    max = min;
4615a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4616a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else if (current() == ',') {
4617a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4618a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (current() == '}') {
461937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      max = RegExpTree::kInfinity;
4620a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4621a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
4622a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      while (IsDecimalDigit(current())) {
4623245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        int next = current() - '0';
4624245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        if (max > (RegExpTree::kInfinity - next) / 10) {
4625245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          do {
4626245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org            Advance();
4627245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          } while (IsDecimalDigit(current()));
4628245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          max = RegExpTree::kInfinity;
4629245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org          break;
4630245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        }
4631245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        max = 10 * max + next;
4632a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance();
4633a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4634a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (current() != '}') {
4635a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Reset(start);
4636a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return false;
4637a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4638a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4639a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4640a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4641a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Reset(start);
4642a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
4643a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4644a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *min_out = min;
4645a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *max_out = max;
4646a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
4647a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4648a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4649a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4650a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orguc32 RegExpParser::ParseOctalLiteral() {
4651e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(('0' <= current() && current() <= '7') || current() == kEndMarker);
4652a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // For compatibility with some other browsers (not all), we parse
4653a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // up to three octal digits with a value below 256.
4654a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  uc32 value = current() - '0';
4655a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4656a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if ('0' <= current() && current() <= '7') {
4657a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    value = value * 8 + current() - '0';
4658a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4659a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (value < 32 && '0' <= current() && current() <= '7') {
4660a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      value = value * 8 + current() - '0';
4661a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4662a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4663a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4664a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return value;
4665a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4666a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4667a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4668a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool RegExpParser::ParseHexEscape(int length, uc32 *value) {
4669a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  int start = position();
4670a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  uc32 val = 0;
4671a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  bool done = false;
4672a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  for (int i = 0; !done; i++) {
4673a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    uc32 c = current();
4674a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    int d = HexValue(c);
4675a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (d < 0) {
4676a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Reset(start);
4677a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return false;
4678a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4679a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    val = val * 16 + d;
4680a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4681a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (i == length - 1) {
4682a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      done = true;
4683a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4684a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4685a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  *value = val;
4686a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return true;
4687a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4688a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4689a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4690a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orguc32 RegExpParser::ParseClassCharacterEscape() {
4691e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(current() == '\\');
4692e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(has_next() && !IsSpecialClassEscape(Next()));
4693a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4694a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  switch (current()) {
4695a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'b':
4696a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4697a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\b';
4698a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // ControlEscape :: one of
4699a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    //   f n r t v
4700a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'f':
4701a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4702a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\f';
4703a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'n':
4704a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4705a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\n';
4706a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'r':
4707a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4708a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\r';
4709a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 't':
4710a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4711a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\t';
4712a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'v':
4713a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4714a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return '\v';
4715d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    case 'c': {
4716d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      uc32 controlLetter = Next();
4717d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      uc32 letter = controlLetter & ~('A' ^ 'a');
4718d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // For compatibility with JSC, inside a character class
4719d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // we also accept digits and underscore as control characters.
4720d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      if ((controlLetter >= '0' && controlLetter <= '9') ||
4721d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          controlLetter == '_' ||
4722d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org          (letter >= 'A' && letter <= 'Z')) {
4723d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        Advance(2);
4724d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // Control letters mapped to ASCII control characters in the range
4725d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        // 0x00-0x1f.
4726d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org        return controlLetter & 0x1f;
4727d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      }
4728d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // We match JSC in reading the backslash as a literal
4729d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      // character instead of as starting an escape.
4730d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org      return '\\';
4731d2c22f0121ebc55ee26a9e742f0fd7c0b8397730kmillikin@chromium.org    }
4732a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '0': case '1': case '2': case '3': case '4': case '5':
4733a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case '6': case '7':
4734a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // For compatibility, we interpret a decimal escape that isn't
4735a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // a back reference (and therefore either \0 or not valid according
4736a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // to the specification) as a 1..3 digit octal character code.
4737a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return ParseOctalLiteral();
4738a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'x': {
4739a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4740a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      uc32 value;
4741a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseHexEscape(2, &value)) {
4742a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return value;
4743a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4744a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // If \x is not followed by a two-digit hexadecimal, treat it
4745a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // as an identity escape.
4746a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return 'x';
4747a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4748a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    case 'u': {
4749a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4750a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      uc32 value;
4751a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (ParseHexEscape(4, &value)) {
4752a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return value;
4753a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4754a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // If \u is not followed by a four-digit hexadecimal, treat it
4755a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // as an identity escape.
4756a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return 'u';
4757a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4758a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    default: {
4759a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // Extended identity escape. We accept any character that hasn't
4760a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // been matched by a more specific case, not just the subset required
4761a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      // by the ECMAScript specification.
4762a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      uc32 result = current();
4763a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4764a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return result;
4765a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4766a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4767a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return 0;
4768a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4769a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4770a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4771a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgCharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4772e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, *char_class);
4773a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  uc32 first = current();
4774a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (first == '\\') {
4775a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    switch (Next()) {
4776a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4777a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        *char_class = Next();
4778a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Advance(2);
4779a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return CharacterRange::Singleton(0);  // Return dummy value.
4780a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
478137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      case kEndMarker:
4782e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org        return ReportError(CStrVector("\\ at end of pattern"));
4783a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      default:
4784a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4785a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return CharacterRange::Singleton(c);
4786a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4787a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4788a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4789a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return CharacterRange::Singleton(first);
4790a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4791a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4792a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4793a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
479414a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.orgstatic const uc16 kNoCharClass = 0;
479514a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org
479614a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org// Adds range or pre-defined character class to character ranges.
479714a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org// If char_class is not kInvalidClass, it's interpreted as a class
479814a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org// escape (i.e., 's' means whitespace, from '\s').
479914a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.orgstatic inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
480014a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org                                    uc16 char_class,
48017028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                    CharacterRange range,
48027028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org                                    Zone* zone) {
480314a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org  if (char_class != kNoCharClass) {
48047028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    CharacterRange::AddClassEscape(char_class, ranges, zone);
480514a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org  } else {
48067028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    ranges->Add(range, zone);
480714a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org  }
480814a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org}
480914a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org
481014a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org
4811a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpTree* RegExpParser::ParseCharacterClass() {
4812a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  static const char* kUnterminated = "Unterminated character class";
4813a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  static const char* kRangeOutOfOrder = "Range out of order in character class";
4814a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4815e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(current(), '[');
4816a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4817a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  bool is_negated = false;
4818a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (current() == '^') {
4819a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    is_negated = true;
4820a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Advance();
4821a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
48227028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  ZoneList<CharacterRange>* ranges =
48237028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      new(zone()) ZoneList<CharacterRange>(2, zone());
4824a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  while (has_more() && current() != ']') {
482514a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org    uc16 char_class = kNoCharClass;
4826a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
4827a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (current() == '-') {
4828a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Advance();
4829a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (current() == kEndMarker) {
4830a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // If we reach the end we break out of the loop and let the
4831a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // following code report an error.
4832a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4833a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      } else if (current() == ']') {
48347028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        AddRangeOrEscape(ranges, char_class, first, zone());
48357028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        ranges->Add(CharacterRange::Singleton('-'), zone());
4836a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        break;
4837a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
483814a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org      uc16 char_class_2 = kNoCharClass;
483914a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org      CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
484014a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org      if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
484114a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org        // Either end is an escaped character class. Treat the '-' verbatim.
48427028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        AddRangeOrEscape(ranges, char_class, first, zone());
48437028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        ranges->Add(CharacterRange::Singleton('-'), zone());
48447028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org        AddRangeOrEscape(ranges, char_class_2, next, zone());
484514a7035652e3bc60a2172d11dc9b8850e4efce3alrn@chromium.org        continue;
4846a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
4847a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      if (first.from() > next.to()) {
4848a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4849a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
48507028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      ranges->Add(CharacterRange::Range(first.from(), next.to()), zone());
4851a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    } else {
48527028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org      AddRangeOrEscape(ranges, char_class, first, zone());
4853a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
4854a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4855a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (!has_more()) {
4856a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4857a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4858a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Advance();
4859a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (ranges->length() == 0) {
48607028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    ranges->Add(CharacterRange::Everything(), zone());
4861a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    is_negated = !is_negated;
4862a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4863c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  return new(zone()) RegExpCharacterClass(ranges, is_negated);
4864a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4865a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4866a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4867a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// ----------------------------------------------------------------------------
486843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The Parser interface.
486943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4870e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.orgbool RegExpParser::ParseRegExp(FlatStringReader* input,
4871e03fb64ef23331755b7986d2560bc4c00ba3e67bfschneider@chromium.org                               bool multiline,
48725a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                               RegExpCompileData* result,
48735a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org                               Zone* zone) {
4874e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result != NULL);
48755a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  RegExpParser parser(input, &result->error, multiline, zone);
487637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  RegExpTree* tree = parser.ParsePattern();
4877a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (parser.failed()) {
4878e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(tree == NULL);
4879e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!result->error.is_null());
4880a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  } else {
4881e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(tree != NULL);
4882e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result->error.is_null());
488337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result->tree = tree;
488437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    int capture_count = parser.captures_started();
488537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
4886245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    result->contains_anchor = parser.contains_anchor();
488737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result->capture_count = capture_count;
4888a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
4889a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return !parser.failed();
4890a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
4891a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4892a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4893e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool Parser::Parse() {
4894e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(info()->function() == NULL);
4895b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org  FunctionLiteral* result = NULL;
489621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  pre_parse_timer_ = isolate()->counters()->pre_parse();
489742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  if (FLAG_trace_parse || allow_natives_syntax() || extension_ != NULL) {
489808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    // If intrinsics are allowed, the Parser cannot operate independent of the
489921d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org    // V8 heap because of Runtime. Tell the string table to internalize strings
490008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    // and values right after they're created.
49016313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org    ast_value_factory()->Internalize(isolate());
490208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  }
490308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org
4904e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (info()->is_lazy()) {
4905e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!info()->is_eval());
4906e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (info()->shared_info()->is_function()) {
4907e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      result = ParseLazy();
490856454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    } else {
4909e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      result = ParseProgram();
491056454717593e7552d6846198b8e0f661fa36a3cayangguo@chromium.org    }
4911b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  } else {
491270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org    SetCachedData();
4913f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org    result = ParseProgram();
4914b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org  }
4915e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  info()->SetFunction(result);
491621d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org
491721d700eedcdd6570eff22ece724b63a5eefe78cbmachenbach@chromium.org  Internalize();
49186313e220249748eb26e1ddcee2bbe857fef03b42machenbach@chromium.org  DCHECK(ast_value_factory()->IsInternalized());
4919b61a0d13e9690ef4c2de424bbe82a38884d981a6ager@chromium.org  return (result != NULL);
492043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
492143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4922b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4923b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid Parser::ParseOnBackground() {
4924b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(info()->function() == NULL);
4925b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  FunctionLiteral* result = NULL;
4926b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
4927b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4928b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  CompleteParserRecorder recorder;
4929b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  if (compile_options() == ScriptCompiler::kProduceParserCache) {
4930b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    log_ = &recorder;
4931b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  }
4932b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4933b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(info()->source_stream() != NULL);
4934b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  ExternalStreamingStream stream(info()->source_stream(),
4935b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                 info()->source_stream_encoding());
4936b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  scanner_.Initialize(&stream);
4937b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(info()->context().is_null() || info()->context()->IsNativeContext());
4938b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4939b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // When streaming, we don't know the length of the source until we have parsed
4940b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // it. The raw data can be UTF-8, so we wouldn't know the source length until
4941b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // we have decoded it anyway even if we knew the raw data length (which we
4942b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // don't). We work around this by storing all the scopes which need their end
4943b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // position set at the end of the script (the top scope and possible eval
4944b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // scopes) and set their end position after we know the script length.
4945b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Scope* top_scope = NULL;
4946b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Scope* eval_scope = NULL;
4947b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  result = DoParseProgram(info(), &top_scope, &eval_scope);
4948b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4949b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  top_scope->set_end_position(scanner()->location().end_pos);
4950b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  if (eval_scope != NULL) {
4951b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    eval_scope->set_end_position(scanner()->location().end_pos);
4952b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  }
4953b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4954b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  info()->SetFunction(result);
4955b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4956b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // We cannot internalize on a background thread; a foreground task will take
4957b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // care of calling Parser::Internalize just before compilation.
4958b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
4959b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  if (compile_options() == ScriptCompiler::kProduceParserCache) {
4960b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    if (result != NULL) *info_->cached_data() = recorder.GetScriptData();
4961b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    log_ = NULL;
4962b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  }
4963b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org}
496443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} }  // namespace v8::internal
4965