13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "api.h"
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "ast.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "bootstrapper.h"
33589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "char-predicates-inl.h"
346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "codegen.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "compiler.h"
3680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "func-name-inferrer.h"
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "messages.h"
3825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#include "parser.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h"
403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu#include "preparser.h"
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "runtime.h"
42589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "scanner-character-streams.h"
433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#include "scopeinfo.h"
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h"
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// PositionStack is used for on-stack allocation of token positions for
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// new expressions. Please look at ParseNewExpression.
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass PositionStack  {
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~PositionStack() { ASSERT(!*ok_ || is_empty()); }
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class Element  {
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Element(PositionStack* stack, int value) {
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      previous_ = stack->top();
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value_ = value;
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stack->set_top(this);
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   private:
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Element* previous() { return previous_; }
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int value() { return value_; }
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    friend class PositionStack;
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Element* previous_;
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int value_;
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_empty() { return top_ == NULL; }
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pop() {
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!is_empty());
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int result = top_->value();
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    top_ = top_->previous();
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return result;
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Element* top() { return top_; }
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_top(Element* value) { top_ = value; }
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Element* top_;
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool* ok_;
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpBuilder::RegExpBuilder()
908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : zone_(Isolate::Current()->zone()),
918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      pending_empty_(false),
928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      characters_(NULL),
938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      terms_(),
948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      alternatives_()
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    , last_added_(ADD_NONE)
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {}
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::FlushCharacters() {
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pending_empty_ = false;
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (characters_ != NULL) {
1048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    RegExpTree* atom = new(zone()) RegExpAtom(characters_->ToConstVector());
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    characters_ = NULL;
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    text_.Add(atom);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    LAST(ADD_ATOM);
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::FlushText() {
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FlushCharacters();
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_text = text_.length();
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_text == 0) {
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (num_text == 1) {
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    terms_.Add(text_.last());
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    RegExpText* text = new(zone()) RegExpText();
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < num_text; i++)
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      text_.Get(i)->AppendToText(text);
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    terms_.Add(text);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  text_.Clear();
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::AddCharacter(uc16 c) {
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pending_empty_ = false;
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (characters_ == NULL) {
132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    characters_ = new(zone()) ZoneList<uc16>(4);
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  characters_->Add(c);
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LAST(ADD_CHAR);
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::AddEmpty() {
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pending_empty_ = true;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::AddAtom(RegExpTree* term) {
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (term->IsEmpty()) {
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AddEmpty();
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (term->IsTextElement()) {
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    FlushCharacters();
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    text_.Add(term);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    FlushText();
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    terms_.Add(term);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LAST(ADD_ATOM);
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::AddAssertion(RegExpTree* assert) {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FlushText();
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  terms_.Add(assert);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LAST(ADD_ASSERT);
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::NewAlternative() {
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FlushTerms();
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpBuilder::FlushTerms() {
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FlushText();
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_terms = terms_.length();
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpTree* alternative;
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_terms == 0) {
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    alternative = RegExpEmpty::GetInstance();
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (num_terms == 1) {
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    alternative = terms_.last();
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    alternative = new(zone()) RegExpAlternative(terms_.GetList());
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  alternatives_.Add(alternative);
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  terms_.Clear();
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LAST(ADD_NONE);
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpTree* RegExpBuilder::ToRegExp() {
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FlushTerms();
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_alternatives = alternatives_.length();
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_alternatives == 0) {
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return RegExpEmpty::GetInstance();
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_alternatives == 1) {
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return alternatives_.last();
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) RegExpDisjunction(alternatives_.GetList());
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
202e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid RegExpBuilder::AddQuantifierToAtom(int min,
203e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        int max,
204e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                                        RegExpQuantifier::Type type) {
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (pending_empty_) {
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pending_empty_ = false;
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpTree* atom;
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (characters_ != NULL) {
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(last_added_ == ADD_CHAR);
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Last atom was character.
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Vector<const uc16> char_vector = characters_->ToConstVector();
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int num_chars = char_vector.length();
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (num_chars > 1) {
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Vector<const uc16> prefix = char_vector.SubVector(0, num_chars - 1);
2178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      text_.Add(new(zone()) RegExpAtom(prefix));
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      char_vector = char_vector.SubVector(num_chars - 1, num_chars);
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    characters_ = NULL;
2218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    atom = new(zone()) RegExpAtom(char_vector);
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    FlushText();
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (text_.length() > 0) {
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(last_added_ == ADD_ATOM);
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    atom = text_.RemoveLast();
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    FlushText();
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (terms_.length() > 0) {
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(last_added_ == ADD_ATOM);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    atom = terms_.RemoveLast();
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (atom->max_match() == 0) {
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Guaranteed to only match an empty string.
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      LAST(ADD_TERM);
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (min == 0) {
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return;
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      terms_.Add(atom);
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Only call immediately after adding an atom or character!
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNREACHABLE();
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  terms_.Add(new(zone()) RegExpQuantifier(min, max, type, atom));
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  LAST(ADD_TERM);
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2499fac840a46e8b7e26894f4792ba26dde14c56b04Steve BlockHandle<String> Parser::LookupSymbol(int symbol_id) {
2503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Length of symbol cache is the number of identified symbols.
2513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // If we are larger than that, or negative, it's not a cached symbol.
2523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // This might also happen if there is no preparser symbol data, even
2533e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // if there is some preparser data.
2543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (static_cast<unsigned>(symbol_id)
2553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      >= static_cast<unsigned>(symbol_cache_.length())) {
2569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (scanner().is_literal_ascii()) {
25744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return isolate()->factory()->LookupAsciiSymbol(
25844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          scanner().literal_ascii_string());
2599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    } else {
26044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return isolate()->factory()->LookupTwoByteSymbol(
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scanner().literal_utf16_string());
2629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
2633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  }
2649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return LookupCachedSymbol(symbol_id);
2653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu}
2663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
2673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
2689fac840a46e8b7e26894f4792ba26dde14c56b04Steve BlockHandle<String> Parser::LookupCachedSymbol(int symbol_id) {
2693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // Make sure the cache is large enough to hold the symbol identifier.
2703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (symbol_cache_.length() <= symbol_id) {
2713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    // Increase length to index + 1.
2723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    symbol_cache_.AddBlock(Handle<String>::null(),
2733e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                           symbol_id + 1 - symbol_cache_.length());
2743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  }
2753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Handle<String> result = symbol_cache_.at(symbol_id);
2763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (result.is_null()) {
2779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (scanner().is_literal_ascii()) {
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      result = isolate()->factory()->LookupAsciiSymbol(
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          scanner().literal_ascii_string());
2809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    } else {
28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      result = isolate()->factory()->LookupTwoByteSymbol(
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scanner().literal_utf16_string());
2839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
2843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    symbol_cache_.at(symbol_id) = result;
2859ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    return result;
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate()->counters()->total_preparse_symbols_skipped()->Increment();
2883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  return result;
2893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu}
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenFunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
29380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The current pre-data entry must be a FunctionEntry with the given
29480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // start position.
2959ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if ((function_index_ + FunctionEntry::kSize <= store_.length())
2969ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      && (static_cast<int>(store_[function_index_]) == start)) {
2979ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    int index = function_index_;
2989ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    function_index_ += FunctionEntry::kSize;
29980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return FunctionEntry(store_.SubVector(index,
30080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                                          index + FunctionEntry::kSize));
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return FunctionEntry();
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3060d5e116f6aee03185f237311a943491bb079a768Kristian Monsenint ScriptDataImpl::GetSymbolIdentifier() {
3070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return ReadNumber(&symbol_data_);
3089ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick}
3099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
3109ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick
3119ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrickbool ScriptDataImpl::SanityCheck() {
3129ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Check that the header data is valid and doesn't specify
3139ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // point to positions outside the store.
3148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
3158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (magic() != PreparseDataConstants::kMagicNumber) return false;
3168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (version() != PreparseDataConstants::kCurrentVersion) return false;
3179ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (has_error()) {
3189ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    // Extra sane sanity check for error message encoding.
3198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    if (store_.length() <= PreparseDataConstants::kHeaderSize
3208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                         + PreparseDataConstants::kMessageTextPos) {
3218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      return false;
3228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
3238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    if (Read(PreparseDataConstants::kMessageStartPos) >
3248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        Read(PreparseDataConstants::kMessageEndPos)) {
3258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      return false;
3268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
3278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
3288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int pos = PreparseDataConstants::kMessageTextPos;
3299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    for (unsigned int i = 0; i <= arg_count; i++) {
3308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
3318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        return false;
3328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
3339ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      int length = static_cast<int>(Read(pos));
3349ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      if (length < 0) return false;
3359ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      pos += 1 + length;
3369ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    }
3378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
3388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      return false;
3398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
3409ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick    return true;
3419ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  }
3429ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Check that the space allocated for function entries is sane.
3439ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  int functions_size =
3448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
3459ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (functions_size < 0) return false;
3469ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (functions_size % FunctionEntry::kSize != 0) return false;
3479ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  // Check that the count of symbols is non-negative.
3489ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  int symbol_count =
3498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
3509ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (symbol_count < 0) return false;
3510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check that the total size has room for header and function entries.
3529ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  int minimum_size =
3538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      PreparseDataConstants::kHeaderSize + functions_size;
3549ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (store_.length() < minimum_size) return false;
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
35959151504615d929945dc59db37bf1166937748c6Steve Block
36080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenconst char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int length = start[0];
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* result = NewArray<char>(length + 1);
36380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  for (int i = 0; i < length; i++) {
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result[i] = start[i + 1];
36580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result[length] = '\0';
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (chars != NULL) *chars = length;
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScanner::Location ScriptDataImpl::MessageLocation() {
3728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
3738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  int end_pos = Read(PreparseDataConstants::kMessageEndPos);
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Scanner::Location(beg_pos, end_pos);
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* ScriptDataImpl::BuildMessage() {
3798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
38080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return ReadString(start, NULL);
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVector<const char*> ScriptDataImpl::BuildArgs() {
3858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char** array = NewArray<const char*>(arg_count);
3870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Position after text found by skipping past length field and
3880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // length field content words.
3898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  int pos = PreparseDataConstants::kMessageTextPos + 1
3908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      + Read(PreparseDataConstants::kMessageTextPos);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < arg_count; i++) {
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int count = 0;
39380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    array[i] = ReadString(ReadAddress(pos), &count);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    pos += count + 1;
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Vector<const char*>(array, arg_count);
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunsigned ScriptDataImpl::Read(int position) {
4018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return store_[PreparseDataConstants::kHeaderSize + position];
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockunsigned* ScriptDataImpl::ReadAddress(int position) {
4068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return &store_[PreparseDataConstants::kHeaderSize + position];
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochScope* Parser::NewScope(Scope* parent, ScopeType type) {
4118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Scope* result = new(zone()) Scope(parent, type);
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  result->Initialize();
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Target is a support class to facilitate manipulation of the
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Parser's target_stack_ (the stack of potential 'break' and
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 'continue' statement targets). Upon construction, a new target is
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// added; it is removed upon destruction.
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Target BASE_EMBEDDED {
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
4253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target(Target** variable, AstNode* node)
4263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      : variable_(variable), node_(node), previous_(*variable) {
4273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    *variable = this;
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~Target() {
4313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    *variable_ = previous_;
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Target* previous() { return previous_; }
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AstNode* node() { return node_; }
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
4383e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target** variable_;
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AstNode* node_;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Target* previous_;
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass TargetScope BASE_EMBEDDED {
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
4463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  explicit TargetScope(Target** variable)
4473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      : variable_(variable), previous_(*variable) {
4483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    *variable = NULL;
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~TargetScope() {
4523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    *variable_ = previous_;
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
4563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target** variable_;
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Target* previous_;
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// FunctionState and BlockState together implement the parser's scope stack.
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The parser's current scope is in top_scope_.  The BlockState and
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// FunctionState constructors push on the scope stack and the destructors
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// pop.  They are also used to hold the parser's per-function and per-block
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// state.
467592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass Parser::BlockState BASE_EMBEDDED {
469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch public:
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  BlockState(Parser* parser, Scope* scope)
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : parser_(parser),
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        outer_scope_(parser->top_scope_) {
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    parser->top_scope_ = scope;
474592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
475592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ~BlockState() { parser_->top_scope_ = outer_scope_; }
477592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch private:
479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Parser* parser_;
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* outer_scope_;
481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch};
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochParser::FunctionState::FunctionState(Parser* parser,
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Scope* scope,
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     Isolate* isolate)
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      next_handler_index_(0),
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      expected_property_count_(0),
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      only_simple_this_property_assignments_(false),
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      this_property_assignments_(isolate->factory()->empty_fixed_array()),
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      parser_(parser),
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      outer_function_state_(parser->current_function_state_),
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      outer_scope_(parser->top_scope_),
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      saved_ast_node_id_(isolate->ast_node_id()),
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory_(isolate) {
49744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  parser->top_scope_ = scope;
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  parser->current_function_state_ = this;
499589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
50044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
50144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochParser::FunctionState::~FunctionState() {
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  parser_->top_scope_ = outer_scope_;
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  parser_->current_function_state_ = outer_function_state_;
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (outer_function_state_ != NULL) {
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The CHECK_OK macro is a convenient macro to enforce error
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// handling for functions that may fail (by returning !*ok).
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// CAUTION: This macro appends extra statements after a call,
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// thus it must never be used where only a single statement
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is correct (e.g. an if statement branch w/o braces)!
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CHECK_OK  ok);   \
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!*ok) return NULL; \
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ((void)0
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DUMMY )  // to make indentation work
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DUMMY
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CHECK_FAILED  /**/);   \
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (failed_) return NULL; \
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ((void)0
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DUMMY )  // to make indentation work
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DUMMY
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Parser
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockParser::Parser(Handle<Script> script,
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               int parser_flags,
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               v8::Extension* extension,
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               ScriptDataImpl* pre_data)
53944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(script->GetIsolate()),
54044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      symbol_cache_(pre_data ? pre_data->symbol_count() : 0),
5413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      script_(script),
5428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      scanner_(isolate_->unicode_cache()),
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reusable_preparser_(NULL),
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      top_scope_(NULL),
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_function_state_(NULL),
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      target_stack_(NULL),
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      extension_(extension),
5486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      pre_data_(pre_data),
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      fni_(NULL),
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      allow_natives_syntax_((parser_flags & kAllowNativesSyntax) != 0),
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      allow_lazy_((parser_flags & kAllowLazy) != 0),
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      allow_modules_((parser_flags & kAllowModules) != 0),
553b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      stack_overflow_(false),
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      parenthesized_function_(false) {
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate_->set_ast_node_id(0);
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((parser_flags & kLanguageModeMask) == EXTENDED_MODE) {
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scanner().SetHarmonyScoping(true);
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((parser_flags & kAllowModules) != 0) {
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scanner().SetHarmonyModules(true);
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochFunctionLiteral* Parser::ParseProgram(CompilationInfo* info) {
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HistogramTimerScope timer(isolate()->counters()->parse());
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> source(String::cast(script_->source()));
57044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate()->counters()->total_parse_size()->Increment(source->length());
5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  fni_ = new(zone()) FuncNameInferrer(isolate());
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize parser state.
5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  source->TryFlatten();
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (source->IsExternalTwoByteString()) {
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Notice that the stream is destroyed at the end of the branch block.
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The last line of the blocks can't be moved outside, even though they're
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // identical calls.
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalTwoByteStringUtf16CharacterStream stream(
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<ExternalTwoByteString>::cast(source), 0, source->length());
5819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    scanner_.Initialize(&stream);
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return DoParseProgram(info, source, &zone_scope);
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenericStringUtf16CharacterStream stream(source, 0, source->length());
5859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    scanner_.Initialize(&stream);
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return DoParseProgram(info, source, &zone_scope);
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochFunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Handle<String> source,
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        ZoneScope* zone_scope) {
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(top_scope_ == NULL);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(target_stack_ == NULL);
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (pre_data_ != NULL) pre_data_->Initialize();
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the parsing mode.
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  mode_ = (FLAG_lazy && allow_lazy_) ? PARSE_LAZILY : PARSE_EAGERLY;
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (allow_natives_syntax_ || extension_ != NULL) mode_ = PARSE_EAGERLY;
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> no_name = isolate()->factory()->empty_symbol();
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FunctionLiteral* result = NULL;
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    info->SetGlobalScope(scope);
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (info->is_eval()) {
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<SharedFunctionInfo> shared = info->shared_info();
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!info->is_global() && (shared.is_null() || shared->is_function())) {
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scope = Scope::DeserializeScopeChain(*info->calling_context(), scope);
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scope = NewScope(scope, EVAL_SCOPE);
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope->set_start_position(0);
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope->set_end_position(source->length());
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FunctionState function_state(this, scope, isolate());
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    top_scope_->SetLanguageMode(info->language_mode());
620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool ok = true;
6221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int beg_loc = scanner().location().beg_pos;
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ParseSourceElements(body, Token::EOS, info->is_eval(), &ok);
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (ok && !top_scope_->is_classic_mode()) {
6251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
627589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (ok && is_extended_mode()) {
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckConflictingVarDeclarations(top_scope_, &ok);
630589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    }
631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (ok) {
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewFunctionLiteral(
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          no_name,
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          top_scope_,
6363e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu          body,
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          function_state.materialized_literal_count(),
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          function_state.expected_property_count(),
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          function_state.handler_count(),
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          function_state.only_simple_this_property_assignments(),
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          function_state.this_property_assignments(),
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          0,
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FunctionLiteral::kNoDuplicateParameters,
6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          FunctionLiteral::ANONYMOUS_EXPRESSION,
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FunctionLiteral::kGlobalOrEval);
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result->set_ast_properties(factory()->visitor()->ast_properties());
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else if (stack_overflow_) {
64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->StackOverflow();
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the target stack is empty.
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(target_stack_ == NULL);
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If there was a syntax error we have to get rid of the AST
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and it is not safe to do so before the scope has been deleted.
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (result == NULL) zone_scope->DeleteOnExit();
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
66244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockFunctionLiteral* Parser::ParseLazy(CompilationInfo* info) {
6633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT);
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HistogramTimerScope timer(isolate()->counters()->parse_lazy());
665f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Handle<String> source(String::cast(script_->source()));
66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate()->counters()->total_parse_size()->Increment(source->length());
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<SharedFunctionInfo> shared_info = info->shared_info();
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Initialize parser state.
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  source->TryFlatten();
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (source->IsExternalTwoByteString()) {
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalTwoByteStringUtf16CharacterStream stream(
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Handle<ExternalTwoByteString>::cast(source),
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        shared_info->start_position(),
67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        shared_info->end_position());
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return result;
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenericStringUtf16CharacterStream stream(source,
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             shared_info->start_position(),
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                             shared_info->end_position());
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    FunctionLiteral* result = ParseLazy(info, &stream, &zone_scope);
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return result;
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
68844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockFunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Utf16CharacterStream* source,
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   ZoneScope* zone_scope) {
69144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<SharedFunctionInfo> shared_info = info->shared_info();
6929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  scanner_.Initialize(source);
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(top_scope_ == NULL);
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(target_stack_ == NULL);
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<String> name(String::cast(shared_info->name()));
6973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  fni_ = new(zone()) FuncNameInferrer(isolate());
69880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  fni_->PushEnclosingName(name);
69980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  mode_ = PARSE_EAGERLY;
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Place holder for the result.
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FunctionLiteral* result = NULL;
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  {
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parse the function literal.
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    info->SetGlobalScope(scope);
70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!info->closure().is_null()) {
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scope = Scope::DeserializeScopeChain(info->closure()->context(), scope);
7111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FunctionState function_state(this, scope, isolate());
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(scope->language_mode() != STRICT_MODE || !info->is_classic_mode());
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(scope->language_mode() != EXTENDED_MODE ||
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           info->is_extended_mode());
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(info->language_mode() == shared_info->language_mode());
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope->SetLanguageMode(shared_info->language_mode());
7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    FunctionLiteral::Type type = shared_info->is_expression()
7193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ? (shared_info->is_anonymous()
7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              ? FunctionLiteral::ANONYMOUS_EXPRESSION
7213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              : FunctionLiteral::NAMED_EXPRESSION)
7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        : FunctionLiteral::DECLARATION;
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool ok = true;
7241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    result = ParseFunctionLiteral(name,
7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  false,  // Strict mode name already checked.
7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  RelocInfo::kNoPosition,
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  type,
7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  &ok);
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make sure the results agree.
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(ok == (result != NULL));
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure the target stack is empty.
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(target_stack_ == NULL);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If there was a stack overflow we have to get rid of AST and it is
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // not safe to do before scope has been deleted.
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result == NULL) {
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    zone_scope->DeleteOnExit();
74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (stack_overflow_) isolate()->StackOverflow();
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<String> inferred_name(shared_info->inferred_name());
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    result->set_inferred_name(inferred_name);
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
748f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
7493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui ZhuHandle<String> Parser::GetSymbol(bool* ok) {
7503e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  int symbol_id = -1;
7513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (pre_data() != NULL) {
7523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    symbol_id = pre_data()->GetSymbolIdentifier();
7534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
7549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  return LookupSymbol(symbol_id);
7554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Parser::ReportMessage(const char* type, Vector<const char*> args) {
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Scanner::Location source_location = scanner().location();
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ReportMessageAt(source_location, type, args);
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Parser::ReportMessage(const char* type, Vector<Handle<String> > args) {
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scanner::Location source_location = scanner().location();
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ReportMessageAt(source_location, type, args);
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid Parser::ReportMessageAt(Scanner::Location source_location,
7713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                             const char* type,
7723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                             Vector<const char*> args) {
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MessageLocation location(script_,
774b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           source_location.beg_pos,
775b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           source_location.end_pos);
77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Factory* factory = isolate()->factory();
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args.length(); i++) {
77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    elements->set(i, *arg_string);
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> result = factory->NewSyntaxError(type, array);
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate()->Throw(*result, &location);
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
788b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid Parser::ReportMessageAt(Scanner::Location source_location,
789b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             const char* type,
790b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                             Vector<Handle<String> > args) {
791b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  MessageLocation location(script_,
792b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           source_location.beg_pos,
793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           source_location.end_pos);
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Factory* factory = isolate()->factory();
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<FixedArray> elements = factory->NewFixedArray(args.length());
796b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  for (int i = 0; i < args.length(); i++) {
797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    elements->set(i, *args[i]);
798b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> result = factory->NewSyntaxError(type, array);
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate()->Throw(*result, &location);
802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
803b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
804b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Base class containing common code for the different finder classes used by
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the parser.
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ParserFinder {
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ParserFinder() {}
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Assignment* AsAssignment(Statement* stat) {
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (stat == NULL) return NULL;
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ExpressionStatement* exp_stat = stat->AsExpressionStatement();
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (exp_stat == NULL) return NULL;
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return exp_stat->expression()->AsAssignment();
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An InitializationBlockFinder finds and marks sequences of statements of the
820d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// form expr.a = ...; expr.b = ...; etc.
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InitializationBlockFinder : public ParserFinder {
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We find and mark the initialization blocks in top level
8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // non-looping code only. This is because the optimization prevents
8253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // reuse of the map transitions, so it should be used only for code
8263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // that will only be run once.
8273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  InitializationBlockFinder(Scope* top_scope, Target* target)
8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : enabled_(top_scope->DeclarationScope()->is_global_scope() &&
8293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                 !IsLoopTarget(target)),
8303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        first_in_block_(NULL),
8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        last_in_block_(NULL),
8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        block_size_(0) {}
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~InitializationBlockFinder() {
8353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!enabled_) return;
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (InBlock()) EndBlock();
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Update(Statement* stat) {
8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!enabled_) return;
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Assignment* assignment = AsAssignment(stat);
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (InBlock()) {
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (BlockContinues(assignment)) {
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        UpdateBlock(assignment);
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        EndBlock();
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!InBlock() && (assignment != NULL) &&
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        (assignment->op() == Token::ASSIGN)) {
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      StartBlock(assignment);
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
8563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // The minimum number of contiguous assignment that will
8573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // be treated as an initialization block. Benchmarks show that
8583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  // the overhead exceeds the savings below this limit.
8593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  static const int kMinInitializationBlock = 3;
8603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
8613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static bool IsLoopTarget(Target* target) {
8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while (target != NULL) {
8633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (target->node()->AsIterationStatement() != NULL) return true;
8643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      target = target->previous();
8653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return false;
8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns true if the expressions appear to denote the same object.
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In the context of initialization blocks, we only consider expressions
871d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // of the form 'expr.x' or expr["x"].
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool SameObject(Expression* e1, Expression* e2) {
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    VariableProxy* v1 = e1->AsVariableProxy();
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    VariableProxy* v2 = e2->AsVariableProxy();
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (v1 != NULL && v2 != NULL) {
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return v1->name()->Equals(*v2->name());
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Property* p1 = e1->AsProperty();
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Property* p2 = e2->AsProperty();
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((p1 == NULL) || (p2 == NULL)) return false;
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Literal* key1 = p1->key()->AsLiteral();
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Literal* key2 = p2->key()->AsLiteral();
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((key1 == NULL) || (key2 == NULL)) return false;
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!key1->handle()->IsString() || !key2->handle()->IsString()) {
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    String* name1 = String::cast(*key1->handle());
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    String* name2 = String::cast(*key2->handle());
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!name1->Equals(name2)) return false;
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return SameObject(p1->obj(), p2->obj());
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns true if the expressions appear to denote different properties
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the same object.
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool PropertyOfSameObject(Expression* e1, Expression* e2) {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Property* p1 = e1->AsProperty();
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Property* p2 = e2->AsProperty();
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((p1 == NULL) || (p2 == NULL)) return false;
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return SameObject(p1->obj(), p2->obj());
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool BlockContinues(Assignment* assignment) {
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((assignment == NULL) || (first_in_block_ == NULL)) return false;
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (assignment->op() != Token::ASSIGN) return false;
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return PropertyOfSameObject(first_in_block_->target(),
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                assignment->target());
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void StartBlock(Assignment* assignment) {
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    first_in_block_ = assignment;
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_in_block_ = assignment;
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    block_size_ = 1;
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateBlock(Assignment* assignment) {
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_in_block_ = assignment;
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ++block_size_;
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EndBlock() {
9213e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (block_size_ >= kMinInitializationBlock) {
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      first_in_block_->mark_block_start();
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      last_in_block_->mark_block_end();
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_in_block_ = first_in_block_ = NULL;
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    block_size_ = 0;
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool InBlock() { return first_in_block_ != NULL; }
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const bool enabled_;
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assignment* first_in_block_;
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Assignment* last_in_block_;
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int block_size_;
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder);
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A ThisNamedPropertyAssignmentFinder finds and marks statements of the form
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this.x = ...;, where x is a named property. It also determines whether a
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function contains only assignments of this type.
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass ThisNamedPropertyAssignmentFinder : public ParserFinder {
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ThisNamedPropertyAssignmentFinder(Isolate* isolate)
94644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : isolate_(isolate),
94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        only_simple_this_property_assignments_(true),
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        names_(0),
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assigned_arguments_(0),
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assigned_constants_(0) {
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Update(Scope* scope, Statement* stat) {
954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // Bail out if function already has property assignment that are
955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // not simple this property assignments.
956d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!only_simple_this_property_assignments_) {
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check whether this statement is of the form this.x = ...;
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Assignment* assignment = AsAssignment(stat);
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsThisPropertyAssignment(assignment)) {
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HandleThisPropertyAssignment(scope, assignment);
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      only_simple_this_property_assignments_ = false;
966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns whether only statements of the form this.x = y; where y is either a
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constant or a function argument was encountered.
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool only_simple_this_property_assignments() {
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return only_simple_this_property_assignments_;
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns a fixed array containing three elements for each assignment of the
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // form this.x = y;
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<FixedArray> GetThisPropertyAssignments() {
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (names_.is_empty()) {
97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return isolate_->factory()->empty_fixed_array();
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(names_.length(), assigned_arguments_.length());
9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT_EQ(names_.length(), assigned_constants_.length());
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<FixedArray> assignments =
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        isolate_->factory()->NewFixedArray(names_.length() * 3);
9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < names_.length(); ++i) {
9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      assignments->set(i * 3, *names_[i]);
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_[i]));
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      assignments->set(i * 3 + 2, *assigned_constants_[i]);
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return assignments;
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsThisPropertyAssignment(Assignment* assignment) {
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (assignment != NULL) {
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Property* property = assignment->target()->AsProperty();
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return assignment->op() == Token::ASSIGN
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             && property != NULL
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             && property->obj()->AsVariableProxy() != NULL
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block             && property->obj()->AsVariableProxy()->is_this();
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Check that the property assigned to is a named property, which is not
10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // __proto__.
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Property* property = assignment->target()->AsProperty();
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(property != NULL);
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Literal* literal = property->key()->AsLiteral();
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t dummy;
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (literal != NULL &&
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        literal->handle()->IsString() &&
101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        !String::cast(*(literal->handle()))->Equals(
101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block            isolate_->heap()->Proto_symbol()) &&
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<String> key = Handle<String>::cast(literal->handle());
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Check whether the value assigned is either a constant or matches the
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // name of one of the arguments to the function.
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (assignment->value()->AsLiteral() != NULL) {
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Constant assigned.
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Literal* literal = assignment->value()->AsLiteral();
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        AssignmentFromConstant(key, literal->handle());
1025d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block        return;
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (assignment->value()->AsVariableProxy() != NULL) {
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Variable assigned.
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<String> name =
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            assignment->value()->AsVariableProxy()->name();
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Check whether the variable assigned matches an argument name.
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        for (int i = 0; i < scope->num_parameters(); i++) {
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (*scope->parameter(i)->name() == *name) {
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // Assigned from function argument.
1034d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            AssignmentFromParameter(key, i);
1035d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block            return;
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1040d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // It is not a simple "this.x = value;" assignment with a constant
1041d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    // or parameter value.
1042d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    AssignmentFromSomethingElse();
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We will potentially reorder the property assignments, so they must be
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // simple enough that the ordering does not matter.
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AssignmentFromParameter(Handle<String> name, int index) {
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EnsureInitialized();
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < names_.length(); ++i) {
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (name->Equals(*names_[i])) {
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assigned_arguments_[i] = index;
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assigned_constants_[i] = isolate_->factory()->undefined_value();
10563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return;
10573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    names_.Add(name);
10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    assigned_arguments_.Add(index);
10613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    assigned_constants_.Add(isolate_->factory()->undefined_value());
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EnsureInitialized();
10663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < names_.length(); ++i) {
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (name->Equals(*names_[i])) {
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assigned_arguments_[i] = -1;
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        assigned_constants_[i] = value;
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return;
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    names_.Add(name);
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    assigned_arguments_.Add(-1);
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    assigned_constants_.Add(value);
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1078d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AssignmentFromSomethingElse() {
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The this assignment is not a simple one.
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    only_simple_this_property_assignments_ = false;
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EnsureInitialized() {
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (names_.capacity() == 0) {
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(assigned_arguments_.capacity() == 0);
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(assigned_constants_.capacity() == 0);
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      names_.Initialize(4);
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      assigned_arguments_.Initialize(4);
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      assigned_constants_.Initialize(4);
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate_;
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool only_simple_this_property_assignments_;
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneStringList names_;
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<int> assigned_arguments_;
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneObjectList assigned_constants_;
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhuvoid* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  int end_token,
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  bool is_eval,
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  bool* ok) {
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // SourceElements ::
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   (ModuleElement)* <end_token>
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a target stack to use for this set of source
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // elements. This way, all scripts and functions get their own
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // target stack thus avoiding illegal breaks and continues across
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // functions.
11123e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  TargetScope scope(&this->target_stack_);
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(processor != NULL);
11153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  InitializationBlockFinder block_finder(top_scope_, target_stack_);
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate());
11171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool directive_prologue = true;     // Parsing directive prologue.
11181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() != end_token) {
11201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (directive_prologue && peek() != Token::STRING) {
11211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      directive_prologue = false;
11221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
11231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Scanner::Location token_loc = scanner().peek_location();
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Statement* stat = ParseModuleElement(NULL, CHECK_OK);
11261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (stat == NULL || stat->IsEmpty()) {
11271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      directive_prologue = false;   // End of directive prologue.
11281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      continue;
11291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
11301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (directive_prologue) {
11321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // A shot at a directive.
11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExpressionStatement* e_stat;
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Literal* literal;
11351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Still processing directive prologue?
11361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if ((e_stat = stat->AsExpressionStatement()) != NULL &&
11371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          (literal = e_stat->expression()->AsLiteral()) != NULL &&
11381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          literal->handle()->IsString()) {
11391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Handle<String> directive = Handle<String>::cast(literal->handle());
11401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // Check "use strict" directive (ES5 14.1).
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (top_scope_->is_classic_mode() &&
114344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            directive->Equals(isolate()->heap()->use_strict()) &&
11441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            token_loc.end_pos - token_loc.beg_pos ==
114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block              isolate()->heap()->use_strict()->length() + 2) {
11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // TODO(mstarzinger): Global strict eval calls, need their own scope
11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // as specified in ES5 10.4.2(3). The correct fix would be to always
11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // add this scope in DoParseProgram(), but that requires adaptations
11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // all over the code base, so we go with a quick-fix for now.
11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (is_eval && !top_scope_->is_eval_scope()) {
11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ASSERT(top_scope_->is_global_scope());
11523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Scope* scope = NewScope(top_scope_, EVAL_SCOPE);
11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            scope->set_start_position(top_scope_->start_position());
11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            scope->set_end_position(top_scope_->end_position());
11553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            top_scope_ = scope;
11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // TODO(ES6): Fix entering extended mode, once it is specified.
11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          top_scope_->SetLanguageMode(FLAG_harmony_scoping
11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      ? EXTENDED_MODE : STRICT_MODE);
11601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          // "use strict" is the only directive for now.
11611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block          directive_prologue = false;
11621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        }
11631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      } else {
11641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        // End of the directive prologue.
11651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        directive_prologue = false;
11661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
11671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
11681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
11693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    block_finder.Update(stat);
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Find and mark all assignments to named properties in this (this.x =)
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (top_scope_->is_function_scope()) {
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      this_property_assignment_finder.Update(top_scope_, stat);
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    processor->Add(stat);
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Propagate the collected information on this property assignments.
11783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (top_scope_->is_function_scope()) {
1179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    bool only_simple_this_property_assignments =
1180402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        this_property_assignment_finder.only_simple_this_property_assignments()
1181402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu        && top_scope_->declarations()->length() == 0;
1182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (only_simple_this_property_assignments) {
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      current_function_state_->SetThisPropertyAssignmentInfo(
1184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block          only_simple_this_property_assignments,
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          this_property_assignment_finder.GetThisPropertyAssignments());
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 0;
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochStatement* Parser::ParseModuleElement(ZoneStringList* labels,
11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      bool* ok) {
11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (Ecma 262 5th Edition, clause 14):
11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // SourceElement:
11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    Statement
11983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    FunctionDeclaration
11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In harmony mode we allow additionally the following productions
12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ModuleElement:
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    LetDeclaration
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ConstDeclaration
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ModuleDeclaration
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ImportDeclaration
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ExportDeclaration
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (peek()) {
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::FUNCTION:
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseFunctionDeclaration(NULL, ok);
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LET:
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::CONST:
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseVariableStatement(kModuleElement, NULL, ok);
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::IMPORT:
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseImportDeclaration(ok);
12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::EXPORT:
12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseExportDeclaration(ok);
12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default: {
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Statement* stmt = ParseStatement(labels, CHECK_OK);
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Handle 'module' as a context-sensitive keyword.
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_harmony_modules &&
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          peek() == Token::IDENTIFIER &&
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          !scanner().HasAnyLineTerminatorBeforeNext() &&
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          stmt != NULL) {
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExpressionStatement* estmt = stmt->AsExpressionStatement();
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (estmt != NULL &&
12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            estmt->expression()->AsVariableProxy() != NULL &&
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            estmt->expression()->AsVariableProxy()->name()->Equals(
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                isolate()->heap()->module_symbol()) &&
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            !scanner().literal_contains_escapes()) {
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return ParseModuleDeclaration(NULL, ok);
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return stmt;
12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochBlock* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ModuleDeclaration:
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'module' Identifier Module
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Create new block with one expected declaration.
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* block = factory()->NewBlock(NULL, 1, true);
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = ParseIdentifier(CHECK_OK);
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_print_interface_details)
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("# Module %s...\n", name->ToAsciiArray());
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Module* module = ParseModule(CHECK_OK);
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableProxy* proxy = NewUnresolved(name, LET, module->interface());
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Declaration* declaration =
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewModuleDeclaration(proxy, module, top_scope_);
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Declare(declaration, true, CHECK_OK);
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_print_interface_details)
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("# Module %s.\n", name->ToAsciiArray());
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_print_interfaces) {
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("module %s : ", name->ToAsciiArray());
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    module->interface()->Print();
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(rossberg): Add initialization statement to block.
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (names) names->Add(name);
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return block;
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochModule* Parser::ParseModule(bool* ok) {
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Module:
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    '{' ModuleElement '}'
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    '=' ModulePath ';'
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'at' String ';'
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (peek()) {
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LBRACE:
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseModuleLiteral(ok);
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::ASSIGN: {
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Expect(Token::ASSIGN, CHECK_OK);
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Module* result = ParseModulePath(CHECK_OK);
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExpectSemicolon(CHECK_OK);
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return result;
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default: {
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExpectContextualKeyword("at", CHECK_OK);
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Module* result = ParseModuleUrl(CHECK_OK);
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ExpectSemicolon(CHECK_OK);
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return result;
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochModule* Parser::ParseModuleLiteral(bool* ok) {
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Module:
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    '{' ModuleElement '}'
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Construct block expecting 16 statements.
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* body = factory()->NewBlock(NULL, 16, false);
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_print_interface_details) PrintF("# Literal ");
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expect(Token::LBRACE, CHECK_OK);
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope->set_start_position(scanner().location().beg_pos);
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope->SetLanguageMode(EXTENDED_MODE);
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BlockState block_state(this, scope);
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TargetCollector collector;
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Target target(&this->target_stack_, &collector);
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Target target_body(&this->target_stack_, body);
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InitializationBlockFinder block_finder(top_scope_, target_stack_);
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    while (peek() != Token::RBRACE) {
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Statement* stat = ParseModuleElement(NULL, CHECK_OK);
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (stat && !stat->IsEmpty()) {
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        body->AddStatement(stat);
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        block_finder.Update(stat);
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expect(Token::RBRACE, CHECK_OK);
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope->set_end_position(scanner().location().end_pos);
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  body->set_block_scope(scope);
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope->interface()->Freeze(ok);
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(ok);
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewModuleLiteral(body, scope->interface());
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochModule* Parser::ParseModulePath(bool* ok) {
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ModulePath:
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    Identifier
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ModulePath '.' Identifier
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Module* result = ParseModuleVariable(CHECK_OK);
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (Check(Token::PERIOD)) {
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name = ParseIdentifierName(CHECK_OK);
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_print_interface_details)
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("# Path .%s ", name->ToAsciiArray());
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Module* member = factory()->NewModulePath(result, name);
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result->interface()->Add(name, member->interface(), ok);
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!*ok) {
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_print_interfaces) {
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray());
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("result: ");
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result->interface()->Print();
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("member: ");
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        member->interface()->Print();
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return NULL;
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result = member;
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return result;
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochModule* Parser::ParseModuleVariable(bool* ok) {
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ModulePath:
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    Identifier
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = ParseIdentifier(CHECK_OK);
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_print_interface_details)
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("# Module variable %s ", name->ToAsciiArray());
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableProxy* proxy = top_scope_->NewUnresolved(
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory(), name, scanner().location().beg_pos, Interface::NewModule());
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewModuleVariable(proxy);
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochModule* Parser::ParseModuleUrl(bool* ok) {
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Module:
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    String
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expect(Token::STRING, CHECK_OK);
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> symbol = GetSymbol(CHECK_OK);
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(ES6): Request JS resource from environment...
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_print_interface_details) PrintF("# Url ");
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewModuleUrl(symbol);
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochModule* Parser::ParseModuleSpecifier(bool* ok) {
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ModuleSpecifier:
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    String
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ModulePath
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (peek() == Token::STRING) {
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ParseModuleUrl(ok);
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ParseModulePath(ok);
14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochBlock* Parser::ParseImportDeclaration(bool* ok) {
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ImportDeclaration:
14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'import' IdentifierName (',' IdentifierName)* 'from' ModuleSpecifier ';'
14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(ES6): implement destructuring ImportSpecifiers
14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expect(Token::IMPORT, CHECK_OK);
14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneStringList names(1);
14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = ParseIdentifierName(CHECK_OK);
14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  names.Add(name);
14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (peek() == Token::COMMA) {
14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Consume(Token::COMMA);
14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    name = ParseIdentifierName(CHECK_OK);
14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    names.Add(name);
14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectContextualKeyword("from", CHECK_OK);
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Module* module = ParseModuleSpecifier(CHECK_OK);
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExpectSemicolon(CHECK_OK);
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generate a separate declaration for each identifier.
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(ES6): once we implement destructuring, make that one declaration.
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* block = factory()->NewBlock(NULL, 1, true);
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < names.length(); ++i) {
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_print_interface_details)
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("# Import %s ", names[i]->ToAsciiArray());
14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Interface* interface = Interface::NewUnknown();
14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    module->interface()->Add(names[i], interface, ok);
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!*ok) {
14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_print_interfaces) {
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray());
14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("module: ");
14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        module->interface()->Print();
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return NULL;
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Declaration* declaration =
14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        factory()->NewImportDeclaration(proxy, module, top_scope_);
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Declare(declaration, true, CHECK_OK);
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(rossberg): Add initialization statement to block.
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return block;
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochStatement* Parser::ParseExportDeclaration(bool* ok) {
14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ExportDeclaration:
14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'export' Identifier (',' Identifier)* ';'
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'export' VariableDeclaration
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'export' FunctionDeclaration
14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    'export' ModuleDeclaration
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(ES6): implement structuring ExportSpecifiers
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expect(Token::EXPORT, CHECK_OK);
14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Statement* result = NULL;
14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneStringList names(1);
14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (peek()) {
14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::IDENTIFIER: {
14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<String> name = ParseIdentifier(CHECK_OK);
14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Handle 'module' as a context-sensitive keyword.
14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!name->IsEqualTo(CStrVector("module"))) {
14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        names.Add(name);
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        while (peek() == Token::COMMA) {
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Consume(Token::COMMA);
14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          name = ParseIdentifier(CHECK_OK);
14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          names.Add(name);
14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExpectSemicolon(CHECK_OK);
15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = factory()->NewEmptyStatement();
15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = ParseModuleDeclaration(&names, CHECK_OK);
15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::FUNCTION:
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = ParseFunctionDeclaration(&names, CHECK_OK);
15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::VAR:
15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LET:
15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::CONST:
15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = ParseVariableStatement(kModuleElement, &names, CHECK_OK);
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *ok = false;
15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ReportUnexpectedToken(scanner().current_token());
15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return NULL;
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Extract declared names into export declarations and interface.
15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Interface* interface = top_scope_->interface();
15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < names.length(); ++i) {
15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_print_interface_details)
15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("# Export %s ", names[i]->ToAsciiArray());
15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Interface* inner = Interface::NewUnknown();
15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    interface->Add(names[i], inner, CHECK_OK);
15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VariableProxy* proxy = NewUnresolved(names[i], LET, inner);
15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    USE(proxy);
15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(rossberg): Rethink whether we actually need to store export
15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // declarations (for compilation?).
15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ExportDeclaration* declaration =
15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //     factory()->NewExportDeclaration(proxy, top_scope_);
15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // top_scope_->AddDeclaration(declaration);
15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(result != NULL);
15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return result;
15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochStatement* Parser::ParseBlockElement(ZoneStringList* labels,
15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     bool* ok) {
15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (Ecma 262 5th Edition, clause 14):
15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // SourceElement:
15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    Statement
15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    FunctionDeclaration
15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // In harmony mode we allow additionally the following productions
15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // BlockElement (aka SourceElement):
15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    LetDeclaration
15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    ConstDeclaration
15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  switch (peek()) {
15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::FUNCTION:
15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseFunctionDeclaration(NULL, ok);
15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LET:
15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::CONST:
15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseVariableStatement(kModuleElement, NULL, ok);
15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    default:
15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseStatement(labels, ok);
15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Statement ::
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   Block
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   VariableStatement
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   EmptyStatement
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ExpressionStatement
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   IfStatement
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   IterationStatement
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ContinueStatement
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   BreakStatement
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ReturnStatement
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   WithStatement
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   LabelledStatement
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   SwitchStatement
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ThrowStatement
1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   TryStatement
1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   DebuggerStatement
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note: Since labels can only be used by 'break' and 'continue'
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // statements, which themselves are only valid within blocks,
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // iterations or 'switch' statements (i.e., BreakableStatements),
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // labels can be simply ignored in all other cases; except for
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // trivial labeled break statements 'label: break label' which is
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parsed into an empty statement.
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Keep the source position of the statement
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int statement_pos = scanner().peek_location().beg_pos;
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* stmt = NULL;
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (peek()) {
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::LBRACE:
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return ParseBlock(labels, ok);
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::CONST:  // fall through
16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case Token::LET:
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::VAR:
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      stmt = ParseVariableStatement(kStatement, NULL, ok);
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::SEMICOLON:
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Next();
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return factory()->NewEmptyStatement();
1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::IF:
1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseIfStatement(labels, ok);
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::DO:
16183ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      stmt = ParseDoWhileStatement(labels, ok);
1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::WHILE:
1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseWhileStatement(labels, ok);
1623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::FOR:
1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseForStatement(labels, ok);
1627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::CONTINUE:
1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseContinueStatement(ok);
1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::BREAK:
1634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseBreakStatement(labels, ok);
1635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::RETURN:
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseReturnStatement(ok);
1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::WITH:
1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseWithStatement(labels, ok);
1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::SWITCH:
1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseSwitchStatement(labels, ok);
1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::THROW:
1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseThrowStatement(ok);
1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::TRY: {
1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // NOTE: It is somewhat complicated to have labels on
1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // try-statements. When breaking out of a try-finally statement,
1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // one must take great care not to treat it as a
1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // fall-through. It is much easier just to wrap the entire
1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // try-statement in a statement block and put the labels there
16593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Block* result = factory()->NewBlock(labels, 1, false);
16603e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      Target target(&this->target_stack_, result);
1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      TryStatement* statement = ParseTryStatement(CHECK_OK);
1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (statement) {
1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        statement->set_statement_pos(statement_pos);
1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (result) result->AddStatement(statement);
1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return result;
1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    case Token::FUNCTION: {
16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // FunctionDeclaration is only allowed in the context of SourceElements
16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // (Ecma 262 5th Edition, clause 14):
16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // SourceElement:
16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      //    Statement
16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      //    FunctionDeclaration
16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Common language extension is to allow function declaration in place
16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // of any statement. This language extension is disabled in strict mode.
16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!top_scope_->is_classic_mode()) {
1678e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ReportMessageAt(scanner().peek_location(), "strict_function",
1679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                        Vector<const char*>::empty());
1680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *ok = false;
1681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        return NULL;
1682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ParseFunctionDeclaration(NULL, ok);
1684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
1685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::DEBUGGER:
1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseDebuggerStatement(ok);
1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stmt = ParseExpressionOrLabelledStatement(labels, ok);
1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the source position of the statement
1695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (stmt != NULL) stmt->set_statement_pos(statement_pos);
1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return stmt;
1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVariableProxy* Parser::NewUnresolved(
17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String> name, VariableMode mode, Interface* interface) {
170269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // If we are inside a function, a declaration of a var/const variable is a
170369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // truly local variable, and the scope of the variable is always the function
170469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // scope.
17053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Let/const variables in harmony mode are always added to the immediately
17063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // enclosing scope.
17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return DeclarationScope(mode)->NewUnresolved(
17083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory(), name, scanner().location().beg_pos, interface);
17093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
17103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
17133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableProxy* proxy = declaration->proxy();
17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> name = proxy->name();
17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableMode mode = declaration->mode();
17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* declaration_scope = DeclarationScope(mode);
17173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Variable* var = NULL;
1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If a function scope exists, then we can statically declare this
1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // variable and also set its mode. In any case, a Declaration node
1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will be added to the scope so that the declaration can be added
1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the corresponding activation frame at runtime if necessary.
1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For instance declarations inside an eval scope need to be added
1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the calling function context.
1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Similarly, strict mode eval scope does not leak variable declarations to
1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // the caller's scope so we declare all locals, too.
17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Also for block scoped let/const bindings the variable can be
17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // statically declared.
17293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (declaration_scope->is_function_scope() ||
17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      declaration_scope->is_strict_or_extended_eval_scope() ||
17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      declaration_scope->is_block_scope() ||
17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      declaration_scope->is_module_scope() ||
17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      declaration->AsModuleDeclaration() != NULL) {
1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Declare the variable in the function scope.
17353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    var = declaration_scope->LocalLookup(name);
1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (var == NULL) {
1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Declare the name.
17383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      var = declaration_scope->DeclareLocal(
17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          name, mode, declaration->initialization(), proxy->interface());
1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1741589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // The name was declared in this scope before; check for conflicting
1742589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // re-declarations. We have a conflict if either of the declarations is
1743589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // not a var. There is similar code in runtime.cc in the Declare
1744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // functions. The function CheckNonConflictingScope checks for conflicting
1745589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // var and let bindings from different scopes whereas this is a check for
1746589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // conflicting declarations within the same scope. This check also covers
1747589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      //
1748589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // function () { let x; { var x; } }
1749589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      //
1750589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // because the var declaration is hoisted to the function scope where 'x'
1751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      // is already bound.
17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if ((mode != VAR) || (var->mode() != VAR)) {
175369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // We only have vars, consts and lets in declarations.
17543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(var->mode() == VAR ||
17553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               var->mode() == CONST ||
17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               var->mode() == CONST_HARMONY ||
17573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch               var->mode() == LET);
17583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (is_extended_mode()) {
1759589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // In harmony mode we treat re-declarations as early errors. See
1760589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          // ES5 16 for a definition of early errors.
1761589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1762589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          const char* elms[2] = { "Variable", *c_string };
1763589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          Vector<const char*> args(elms, 2);
1764589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          ReportMessage("redeclaration", args);
1765589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          *ok = false;
17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return;
1767589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        }
17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const char* type = (var->mode() == VAR)
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? "var" : var->is_const_mode() ? "const" : "let";
1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<String> type_string =
177144f0eee88ff00398ff7f715fab053374d808c90dSteve Block            isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expression* expression =
177344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              type_string, name);
17753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        declaration_scope->SetIllegalRedeclaration(expression);
1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We add a declaration node for every declaration. The compiler
1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will only generate code if necessary. In particular, declarations
1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for inner local variables that do not represent functions won't
1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result in any generated code.
1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that we always add an unresolved proxy even if it's not
1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // used, simply because we don't know in this method (w/o extra
1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parameters) if the proxy is needed or not. The proxy will be
1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bound during variable resolution time unless it was pre-bound
1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // below.
1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // WARNING: This will lead to multiple declaration nodes for the
1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // same variable if it is declared several times. This is not a
1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // semantic issue as long as we keep the source order, but it may be
1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // a performance issue since it may lead to repeated
1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime::DeclareContextSlot() calls.
17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  declaration_scope->AddDeclaration(declaration);
1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
17983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if ((mode == CONST || mode == CONST_HARMONY) &&
17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      declaration_scope->is_global_scope()) {
18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For global const variables we bind the proxy to a variable.
1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(resolve);  // should be set by all callers
1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Variable::Kind kind = Variable::NORMAL;
18033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    var = new(zone()) Variable(declaration_scope,
18043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                               name,
18053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               mode,
1806592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                               true,
18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               kind,
18083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               kNeedsInitialization);
18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (declaration_scope->is_eval_scope() &&
18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             declaration_scope->is_classic_mode()) {
18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For variable declarations in a non-strict eval scope the proxy is bound
18123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // to a lookup variable to force a dynamic declaration using the
18133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // DeclareContextSlot runtime function.
18143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Variable::Kind kind = Variable::NORMAL;
18153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    var = new(zone()) Variable(declaration_scope,
18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               name,
18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               mode,
18183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               true,
18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               kind,
18203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               declaration->initialization());
18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    var->AllocateTo(Variable::LOOKUP, -1);
18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    resolve = true;
1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If requested and we have a local variable, bind the proxy to the variable
1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // at parse-time. This is used for functions (and consts) declared inside
1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // statements: the corresponding function (or const) variable must be in the
1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function scope and not a statement-local scope, e.g. as provided with a
1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 'with' statement:
1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   with (obj) {
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //     function f() {}
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   }
1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // which is translated into:
1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   with (obj) {
1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //     // in this case this is not: 'var f; f = function () {};'
1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //     var f = function () {};
1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   }
1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that if 'f' is accessed from inside the 'with' statement, it
1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // will be allocated in the context (because we must be able to look
1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it up dynamically) but it will also be accessed statically, i.e.,
1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // with a context slot index and a context chain length for this
1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // initialization code. Thus, inside the 'with' statement, we need
1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // both access to the static and the dynamic context chain; the
1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // runtime needs to provide both.
18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (resolve && var != NULL) {
18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    proxy->BindTo(var);
1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_harmony_modules) {
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bool ok;
18543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_print_interface_details)
18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("# Declare %s\n", var->name()->ToAsciiArray());
18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      proxy->interface()->Unify(var->interface(), &ok);
18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!ok) {
18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (FLAG_print_interfaces) {
18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("DECLARE TYPE ERROR\n");
18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("proxy: ");
18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          proxy->interface()->Print();
18653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF("var: ");
18663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          var->interface()->Print();
18673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
18693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1));
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
18713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
18723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Language extension which is only enabled for source files loaded
1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// through the API's extension mechanism.  A native function
1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// declaration is resolved by looking up the function through a
1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// callback provided by the extension.
1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseNativeDeclaration(bool* ok) {
1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::FUNCTION, CHECK_OK);
1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> name = ParseIdentifier(CHECK_OK);
1883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done = (peek() == Token::RPAREN);
1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!done) {
1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ParseIdentifier(CHECK_OK);
1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    done = (peek() == Token::RPAREN);
18883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (!done) {
18893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      Expect(Token::COMMA, CHECK_OK);
18903e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    }
1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::SEMICOLON, CHECK_OK);
1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Make sure that the function containing the native declaration
1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // isn't lazily compiled. The extension structures are only
1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // accessible while parsing the first time not when reparsing
1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // because of lazy compilation.
18993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeclarationScope(VAR)->ForceEagerCompilation();
1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the function template for the native function.
1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Handle<v8::FunctionTemplate> fun_template =
1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      extension_->GetNativeFunction(v8::Utils::ToLocal(name));
1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!fun_template.IsEmpty());
1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Instantiate the function and create a shared function info from it.
1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int literals = fun->NumberOfLiterals();
1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>(fun->shared()->code());
1910e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
19116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Handle<SharedFunctionInfo> shared =
191244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
19133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Handle<ScopeInfo>(fun->shared()->scope_info()));
19146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared->set_construct_stub(*construct_stub);
19156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
19166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Copy the function data to the shared function info.
19176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared->set_function_data(fun->shared()->function_data());
1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int parameters = fun->shared()->formal_parameter_count();
19196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  shared->set_formal_parameter_count(parameters);
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1240846): It's weird that native function declarations are
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // introduced dynamically when we meet their declarations, whereas
19233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // other functions are set up when entering the surrounding scope.
19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableProxy* proxy = NewUnresolved(name, VAR);
19253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Declaration* declaration =
19263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewVariableDeclaration(proxy, VAR, top_scope_);
19273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Declare(declaration, true, CHECK_OK);
19288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SharedFunctionInfoLiteral* lit =
19293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewSharedFunctionInfoLiteral(shared);
19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewExpressionStatement(
19313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewAssignment(
19323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition));
1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochStatement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // FunctionDeclaration ::
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::FUNCTION, CHECK_OK);
1940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int function_token_position = scanner().location().beg_pos;
19413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_strict_reserved = false;
19423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> name = ParseIdentifierOrStrictReservedWord(
19433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      &is_strict_reserved, CHECK_OK);
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  FunctionLiteral* fun = ParseFunctionLiteral(name,
19453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              is_strict_reserved,
1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              function_token_position,
19473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              FunctionLiteral::DECLARATION,
1948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              CHECK_OK);
1949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Even if we're not at the top-level of the global or a function
1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scope, we treat is as such and introduce the function with it's
1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // initial value upon entering the corresponding scope.
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableMode mode = is_extended_mode() ? LET : VAR;
19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableProxy* proxy = NewUnresolved(name, mode);
19543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Declaration* declaration =
19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Declare(declaration, true, CHECK_OK);
19573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (names) names->Add(name);
19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewEmptyStatement();
1959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBlock* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
196469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Block ::
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '{' Statement* '}'
1967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that a Block does not introduce a new execution scope!
1969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (ECMA-262, 3rd, 12.2)
1970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
1971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Construct block expecting 16 statements.
19723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* result = factory()->NewBlock(labels, 16, false);
19733e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target target(&this->target_stack_, result);
1974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LBRACE, CHECK_OK);
19753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  InitializationBlockFinder block_finder(top_scope_, target_stack_);
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() != Token::RBRACE) {
1977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Statement* stat = ParseStatement(NULL, CHECK_OK);
19783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (stat && !stat->IsEmpty()) {
19793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      result->AddStatement(stat);
19803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      block_finder.Update(stat);
19813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RBRACE, CHECK_OK);
1984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
1985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochBlock* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
19893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The harmony mode uses block elements instead of statements.
19903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
19913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Block ::
19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   '{' BlockElement* '}'
19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
199469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Construct block expecting 16 statements.
19953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* body = factory()->NewBlock(labels, 16, false);
19963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
199769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
199869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Parse the statements and collect escaping labels.
199969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Expect(Token::LBRACE, CHECK_OK);
20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  block_scope->set_start_position(scanner().location().beg_pos);
20013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { BlockState block_state(this, block_scope);
20023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TargetCollector collector;
20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Target target(&this->target_stack_, &collector);
200469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Target target_body(&this->target_stack_, body);
200569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    InitializationBlockFinder block_finder(top_scope_, target_stack_);
200669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
200769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    while (peek() != Token::RBRACE) {
20083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Statement* stat = ParseBlockElement(NULL, CHECK_OK);
200969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (stat && !stat->IsEmpty()) {
201069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        body->AddStatement(stat);
201169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        block_finder.Update(stat);
201269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
201369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
201469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
201569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Expect(Token::RBRACE, CHECK_OK);
20163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  block_scope->set_end_position(scanner().location().end_pos);
2017589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  block_scope = block_scope->FinalizeBlockScope();
2018589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  body->set_block_scope(block_scope);
2019589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return body;
202069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
202169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
202269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
202369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochBlock* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      ZoneStringList* names,
202569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                      bool* ok) {
2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // VariableStatement ::
2027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   VariableDeclarations ';'
2028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> ignore;
20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* result =
20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectSemicolon(CHECK_OK);
2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
2034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
203744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool Parser::IsEvalOrArguments(Handle<String> string) {
203844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return string.is_identical_to(isolate()->factory()->eval_symbol()) ||
203944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      string.is_identical_to(isolate()->factory()->arguments_symbol());
20401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If the variable declaration declares exactly one non-const
20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// variable, then *out is set to that variable. In all other cases,
20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// *out is untouched; in particular, it is the caller's responsibility
2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to initialize it properly. This mechanism is used for the parsing
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of 'for-in' loops.
20483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochBlock* Parser::ParseVariableDeclarations(
20493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VariableDeclarationContext var_context,
20503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VariableDeclarationProperties* decl_props,
20513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ZoneStringList* names,
20523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Handle<String>* out,
20533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool* ok) {
2054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // VariableDeclarations ::
20553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
20563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The ES6 Draft Rev3 specifies the following grammar for const declarations
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
20593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ConstDeclaration ::
20603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   const ConstBinding (',' ConstBinding)* ';'
20613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ConstBinding ::
20623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   Identifier '=' AssignmentExpression
20633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //
20643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(ES6):
20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ConstBinding ::
20663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   BindingPattern '=' AssignmentExpression
20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableMode mode = VAR;
206869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // True if the binding needs initialization. 'let' and 'const' declared
206969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // bindings are created uninitialized by their declaration nodes and
207069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // need initialization. 'var' declared bindings are always initialized
207169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // immediately by their declaration nodes.
207269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  bool needs_init = false;
2073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_const = false;
207469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Token::Value init_op = Token::INIT_VAR;
2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::VAR) {
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Consume(Token::VAR);
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (peek() == Token::CONST) {
20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads:
20793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
20803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';'
20813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
20823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // * It is a Syntax Error if the code that matches this production is not
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   contained in extended code.
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // However disallowing const in classic mode will break compatibility with
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // existing pages. Therefore we keep allowing const with the old
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // non-harmony semantics in classic mode.
2088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Consume(Token::CONST);
20893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (top_scope_->language_mode()) {
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case CLASSIC_MODE:
20913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mode = CONST;
20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        init_op = Token::INIT_CONST;
20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        break;
20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case STRICT_MODE:
20953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ReportMessage("strict_const", Vector<const char*>::empty());
20963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *ok = false;
20973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return NULL;
20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case EXTENDED_MODE:
20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (var_context == kStatement) {
21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // In extended mode 'const' declarations are only allowed in source
21013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // element positions.
21023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ReportMessage("unprotected_const", Vector<const char*>::empty());
21033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          *ok = false;
21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return NULL;
21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        mode = CONST_HARMONY;
21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        init_op = Token::INIT_CONST_HARMONY;
2108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    is_const = true;
211069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    needs_init = true;
211169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  } else if (peek() == Token::LET) {
21123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // ES6 Draft Rev4 section 12.2.1:
21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // LetDeclaration : let LetBindingList ;
21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
21163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // * It is a Syntax Error if the code that matches this production is not
21173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   contained in extended code.
21183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!is_extended_mode()) {
21193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ReportMessage("illegal_let", Vector<const char*>::empty());
21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *ok = false;
21213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return NULL;
21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
212369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Consume(Token::LET);
21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (var_context == kStatement) {
21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Let declarations are only allowed in source element positions.
212669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ReportMessage("unprotected_let", Vector<const char*>::empty());
212769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      *ok = false;
212869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return NULL;
212969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mode = LET;
213169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    needs_init = true;
213269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    init_op = Token::INIT_LET;
2133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNREACHABLE();  // by current callers
2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* declaration_scope = DeclarationScope(mode);
21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
213969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The scope of a var/const declared variable anywhere inside a function
2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
214169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // transform a source-level var/const declaration into a (Function)
2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scope declaration, and rewrite the source-level initialization into an
2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // assignment statement. We use a block to collect multiple assignments.
2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
2145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We mark the block as initializer block because we don't want the
2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // rewriter to add a '.result' assignment to such a block (to get compliant
2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // behavior for code such as print(eval('var x = 7')), and for cosmetic
2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reasons when pretty-printing. Also, unless an assignment (initialization)
2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is inside an initializer block, it is ignored.
2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create new block with one expected declaration.
21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Block* block = factory()->NewBlock(NULL, 1, true);
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int nvars = 0;  // the number of variables declared
21543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> name;
2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  do {
215680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (fni_ != NULL) fni_->Enter();
215780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parse variable name.
2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (nvars > 0) Consume(Token::COMMA);
21603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    name = ParseIdentifier(CHECK_OK);
216180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (fni_ != NULL) fni_->PushVariableName(name);
2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Strict mode variables may not be named eval or arguments
21643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) {
21651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ReportMessage("strict_var_name", Vector<const char*>::empty());
21661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      *ok = false;
21671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return NULL;
21681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
21691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Declare variable.
2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note that we *always* must treat the initial value via a separate init
2172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // assignment for variables and constants because the value must be assigned
2173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // when the variable is encountered in the source. But the variable/constant
2174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // is declared (and set to 'undefined') upon entering the function within
2175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // which the variable or constant is declared. Only function variables have
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // an initial value in the declaration (because they are initialized upon
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // entering the function).
2178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we have a const declaration, in an inner scope, the proxy is always
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // bound to the declared variable (independent of possibly surrounding with
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // statements).
21823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // For let/const declarations in harmony mode, we can also immediately
21833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // pre-resolve the proxy because it resides in the same scope as the
21843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // declaration.
21853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VariableProxy* proxy = NewUnresolved(name, mode);
21863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Declaration* declaration =
21873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        factory()->NewVariableDeclaration(proxy, mode, top_scope_);
21883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Declare(declaration, mode != VAR, CHECK_OK);
2189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    nvars++;
21903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
2191053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      ReportMessageAt(scanner().location(), "too_many_variables",
2192053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block                      Vector<const char*>::empty());
2193053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      *ok = false;
2194053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      return NULL;
2195053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    }
21963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (names) names->Add(name);
2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parse initialization expression if present and/or needed. A
2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // declaration of the form:
2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //    var v = x;
2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // is syntactic sugar for:
2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //    var v; v = x;
2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
22073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // In particular, we need to re-lookup 'v' (in top_scope_, not
22083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // declaration_scope) as it may be a different 'v' than the 'v' in the
22093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // declaration (e.g., if we are inside a 'with' statement or 'catch'
22103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // block).
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // However, note that const declarations are different! A const
2213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // declaration of the form:
2214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   const c = x;
2216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // is *not* syntactic sugar for:
2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   const c; c = x;
2220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The "variable" c initialized to x is the same as the declared
2222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // one - there is no re-lookup (see the last parameter of the
2223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Declare() call above).
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* value = NULL;
2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int position = -1;
22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Harmony consts have non-optional initializers.
22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
2230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Expect(Token::ASSIGN, CHECK_OK);
2231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      position = scanner().location().beg_pos;
223269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
223380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // Don't infer if it is "a = function(){...}();"-like expression.
22343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (fni_ != NULL &&
22353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          value->AsCall() == NULL &&
22363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          value->AsCallNew() == NULL) {
22373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        fni_->Infer();
223869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
223969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        fni_->RemoveLastFunction();
22403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (decl_props != NULL) *decl_props = kHasInitializers;
22423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Record the end position of the initializer.
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (proxy->var() != NULL) {
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      proxy->var()->set_initializer_position(scanner().location().end_pos);
2247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Make sure that 'const x' and 'let x' initialize 'x' to undefined.
225069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (value == NULL && needs_init) {
2251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = GetLiteralUndefined();
2252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Global variable declarations must be compiled in a specific
2255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // way. When the script containing the global variable declaration
2256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // is entered, the global variable must be declared, so that if it
2257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // doesn't exist (not even in a prototype of the global object) it
2258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // gets created with an initial undefined value. This is handled
2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // by the declarations part of the function representing the
2260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // top-level global code; see Runtime::DeclareGlobalVariable. If
2261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // it already exists (in the object or in a prototype), it is
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // *not* touched until the variable declaration statement is
2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // executed.
2264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Executing the variable declaration statement will always
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // guarantee to give the global object a "local" variable; a
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // variable defined in the global object and not in any
2268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // prototype. This way, global variable declarations can shadow
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // properties in the prototype chain, but only after the variable
2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // declaration statement has been executed. This is important in
2271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // browsers where the global object (window) has lots of
2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // properties defined in prototype objects.
22733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (initialization_scope->is_global_scope()) {
2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Compute the arguments for the runtime call.
2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
22768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // We have at least 1 parameter.
22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      arguments->Add(factory()->NewLiteral(name));
2278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CallRuntime* initialize;
2279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (is_const) {
2281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        arguments->Add(value);
2282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        value = NULL;  // zap the value to avoid the unnecessary assignment
2283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Construct the call to Runtime_InitializeConstGlobal
2285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // and add it to the initialization statement block.
2286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Note that the function does different things depending on
2287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // the number of arguments (1 or 2).
22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        initialize = factory()->NewCallRuntime(
22893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            isolate()->factory()->InitializeConstGlobal_symbol(),
22903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            arguments);
2292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
2293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Add strict mode.
2294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // We may want to pass singleton to avoid Literal allocations.
22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        LanguageMode language_mode = initialization_scope->language_mode();
22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        arguments->Add(factory()->NewNumberLiteral(language_mode));
2297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Be careful not to assign a value to the global variable if
2299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // we're in a with. The initialization value should not
2300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // necessarily be stored in the global object in that case,
2301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // which is why we need to generate a separate assignment node.
2302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (value != NULL && !inside_with()) {
2303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          arguments->Add(value);
2304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          value = NULL;  // zap the value to avoid the unnecessary assignment
2305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
2306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
2307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Construct the call to Runtime_InitializeVarGlobal
2308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // and add it to the initialization statement block.
2309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // Note that the function does different things depending on
2310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        // the number of arguments (2 or 3).
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        initialize = factory()->NewCallRuntime(
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            isolate()->factory()->InitializeVarGlobal_symbol(),
23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            arguments);
2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
23173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      block->AddStatement(factory()->NewExpressionStatement(initialize));
23183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (needs_init) {
23193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Constant initializations always assign to the declared constant which
23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // is always at the function scope level. This is only relevant for
23213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // dynamically looked-up variables and constants (the start context for
23223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // constant lookups is always the function context, while it is the top
23233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // context for var declared variables). Sigh...
23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // For 'let' and 'const' declared variables in harmony mode the
23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // initialization also always assigns to the declared variable.
23263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(proxy != NULL);
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(proxy->var() != NULL);
23283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(value != NULL);
23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Assignment* assignment =
23303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          factory()->NewAssignment(init_op, proxy, value, position);
23313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      block->AddStatement(factory()->NewExpressionStatement(assignment));
23323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      value = NULL;
2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Add an assignment node to the initialization statement block if we still
23363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // have a pending initialization value.
2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value != NULL) {
23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(mode == VAR);
23393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // 'var' initializations are simply assignments (with all the consequences
23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // if they are inside a 'with' statement - they may change a 'with' object
23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // property).
23425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      VariableProxy* proxy =
23433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          initialization_scope->NewUnresolved(factory(), name);
23448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Assignment* assignment =
23453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          factory()->NewAssignment(init_op, proxy, value, position);
23463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      block->AddStatement(factory()->NewExpressionStatement(assignment));
2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
234880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
234980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (fni_ != NULL) fni_->Leave();
2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (peek() == Token::COMMA);
2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If there was a single non-const declaration, return it in the output
23533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // parameter for possible use by for/in.
23543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (nvars == 1 && !is_const) {
23553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    *out = name;
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return block;
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!label.is_null());
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (labels != NULL)
2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = labels->length(); i-- > 0; )
2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (labels->at(i).is_identical_to(label))
2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return true;
2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                      bool* ok) {
2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ExpressionStatement | LabelledStatement ::
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   Expression ';'
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   Identifier ':' Statement
23781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool starts_with_idenfifier = peek_any_identifier();
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* expr = ParseExpression(true, CHECK_OK);
23803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      expr->AsVariableProxy() != NULL &&
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      !expr->AsVariableProxy()->is_this()) {
23838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // Expression is a single identifier, and not, e.g., a parenthesized
23848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    // identifier.
2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    VariableProxy* var = expr->AsVariableProxy();
2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> label = var->name();
2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // TODO(1240780): We don't check for redeclaration of labels
2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // during preparsing since keeping track of the set of active
2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // labels requires nontrivial changes to the way scopes are
2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // structured.  However, these are probably changes we want to
2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // make later anyway so we should go back and fix this then.
23923e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
2393589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
23943e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      const char* elms[2] = { "Label", *c_string };
23953e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      Vector<const char*> args(elms, 2);
23963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      ReportMessage("redeclaration", args);
23973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      *ok = false;
23983e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      return NULL;
2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    if (labels == NULL) labels = new(zone()) ZoneStringList(4);
24013e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    labels->Add(label);
24023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    // Remove the "ghost" variable that turned out to be a label
24033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    // from the top scope. This way, we don't try to resolve it
24043e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    // during the scope processing.
24053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    top_scope_->RemoveUnresolved(var);
2406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::COLON, CHECK_OK);
2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ParseStatement(labels, ok);
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
24103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If we have an extension, we allow a native function declaration.
24113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // A native function declaration starts with "native function" with
24123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // no line-terminator between the two words.
24133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (extension_ != NULL &&
24143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      peek() == Token::FUNCTION &&
24153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      !scanner().HasAnyLineTerminatorBeforeNext() &&
24163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      expr != NULL &&
24173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      expr->AsVariableProxy() != NULL &&
24183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      expr->AsVariableProxy()->name()->Equals(
24193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          isolate()->heap()->native_symbol()) &&
24203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      !scanner().literal_contains_escapes()) {
24213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return ParseNativeDeclaration(ok);
24223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
24233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
24243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Parsed expression statement, or the context-sensitive 'module' keyword.
24253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only expect semicolon in the former case.
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_harmony_modules ||
24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      peek() != Token::IDENTIFIER ||
24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scanner().HasAnyLineTerminatorBeforeNext() ||
24293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      expr->AsVariableProxy() == NULL ||
24303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      !expr->AsVariableProxy()->name()->Equals(
24313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          isolate()->heap()->module_symbol()) ||
24323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scanner().literal_contains_escapes()) {
24333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExpectSemicolon(CHECK_OK);
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewExpressionStatement(expr);
2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockIfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // IfStatement ::
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'if' '(' Expression ')' Statement ('else' Statement)?
2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::IF, CHECK_OK);
2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* condition = ParseExpression(true, CHECK_OK);
2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
2447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* then_statement = ParseStatement(labels, CHECK_OK);
2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* else_statement = NULL;
2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::ELSE) {
2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Next();
2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else_statement = ParseStatement(labels, CHECK_OK);
24523e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else {
24533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    else_statement = factory()->NewEmptyStatement();
2454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewIfStatement(condition, then_statement, else_statement);
2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseContinueStatement(bool* ok) {
2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ContinueStatement ::
2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'continue' Identifier? ';'
2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::CONTINUE, CHECK_OK);
2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> label = Handle<String>::null();
2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value tok = peek();
24663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!scanner().HasAnyLineTerminatorBeforeNext() &&
2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    label = ParseIdentifier(CHECK_OK);
2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IterationStatement* target = NULL;
24713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  target = LookupContinueTarget(label, CHECK_OK);
24723e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (target == NULL) {
2473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Illegal continue statement.
2474b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    const char* message = "illegal_continue";
2475b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Vector<Handle<String> > args;
2476b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (!label.is_null()) {
2477b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      message = "unknown_label";
2478b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      args = Vector<Handle<String> >(&label, 1);
2479b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
2480b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ReportMessageAt(scanner().location(), message, args);
2481b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    *ok = false;
2482b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return NULL;
2483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectSemicolon(CHECK_OK);
24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewContinueStatement(target);
2486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
2490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // BreakStatement ::
2491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'break' Identifier? ';'
2492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::BREAK, CHECK_OK);
2494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> label;
2495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value tok = peek();
24963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!scanner().HasAnyLineTerminatorBeforeNext() &&
2497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
2498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    label = ParseIdentifier(CHECK_OK);
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parse labeled break statements that target themselves into
2501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // empty statements, e.g. 'l1: l2: l3: break l2;'
2502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!label.is_null() && ContainsLabel(labels, label)) {
25033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExpectSemicolon(CHECK_OK);
25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return factory()->NewEmptyStatement();
2505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  BreakableStatement* target = NULL;
25073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  target = LookupBreakTarget(label, CHECK_OK);
25083e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (target == NULL) {
2509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Illegal break statement.
2510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    const char* message = "illegal_break";
2511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Vector<Handle<String> > args;
2512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (!label.is_null()) {
2513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      message = "unknown_label";
2514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      args = Vector<Handle<String> >(&label, 1);
2515b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
2516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ReportMessageAt(scanner().location(), message, args);
2517b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    *ok = false;
2518b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return NULL;
2519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectSemicolon(CHECK_OK);
25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewBreakStatement(target);
2522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseReturnStatement(bool* ok) {
2526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ReturnStatement ::
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'return' Expression? ';'
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Consume the return token. It is necessary to do the before
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reporting any errors on it, because of the way errors are
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reported (underlining).
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RETURN, CHECK_OK);
2533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2534692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  Token::Value tok = peek();
2535692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  Statement* result;
2536692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  if (scanner().HasAnyLineTerminatorBeforeNext() ||
2537692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch      tok == Token::SEMICOLON ||
2538692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch      tok == Token::RBRACE ||
2539692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch      tok == Token::EOS) {
2540692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    ExpectSemicolon(CHECK_OK);
25413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result = factory()->NewReturnStatement(GetLiteralUndefined());
2542692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  } else {
2543692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    Expression* expr = ParseExpression(true, CHECK_OK);
2544692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch    ExpectSemicolon(CHECK_OK);
25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result = factory()->NewReturnStatement(expr);
2546692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  }
2547692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
2548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // An ECMAScript program is considered syntactically incorrect if it
2549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // contains a return statement that is not within the body of a
2550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function. See ECMA-262, section 12.9, page 67.
2551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // To be consistent with KJS we report the syntax error at runtime.
25533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* declaration_scope = top_scope_->DeclarationScope();
25543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (declaration_scope->is_global_scope() ||
25553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      declaration_scope->is_eval_scope()) {
255644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<String> type = isolate()->factory()->illegal_return_symbol();
2557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return factory()->NewExpressionStatement(throw_error);
2559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2560692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  return result;
2561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
2565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // WithStatement ::
2566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'with' '(' Expression ')' Statement
2567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::WITH, CHECK_OK);
25691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!top_scope_->is_classic_mode()) {
25711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ReportMessage("strict_mode_with", Vector<const char*>::empty());
25721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    *ok = false;
25731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return NULL;
25741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
25751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
2577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* expr = ParseExpression(true, CHECK_OK);
2578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
2579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  top_scope_->DeclarationScope()->RecordWithStatement();
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Statement* stmt;
25833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { BlockState block_state(this, with_scope);
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    with_scope->set_start_position(scanner().peek_location().beg_pos);
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    stmt = ParseStatement(labels, CHECK_OK);
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    with_scope->set_end_position(scanner().location().end_pos);
25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewWithStatement(expr, stmt);
2589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
2593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // CaseClause ::
2594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'case' Expression ':' Statement*
2595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'default' ':' Statement*
2596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* label = NULL;  // NULL expression indicates default case
2598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::CASE) {
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::CASE, CHECK_OK);
2600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    label = ParseExpression(true, CHECK_OK);
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::DEFAULT, CHECK_OK);
2603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (*default_seen_ptr) {
2604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ReportMessage("multiple_defaults_in_switch",
2605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    Vector<const char*>::empty());
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *ok = false;
2607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return NULL;
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *default_seen_ptr = true;
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::COLON, CHECK_OK);
2612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int pos = scanner().location().beg_pos;
2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<Statement*>* statements = new(zone()) ZoneList<Statement*>(5);
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() != Token::CASE &&
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         peek() != Token::DEFAULT &&
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         peek() != Token::RBRACE) {
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Statement* stat = ParseStatement(NULL, CHECK_OK);
26183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    statements->Add(stat);
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return new(zone()) CaseClause(isolate(), label, statements, pos);
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              bool* ok) {
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // SwitchStatement ::
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'switch' '(' Expression ')' '{' CaseClause* '}'
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SwitchStatement* statement = factory()->NewSwitchStatement(labels);
26313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target target(&this->target_stack_, statement);
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::SWITCH, CHECK_OK);
2634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
2635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* tag = ParseExpression(true, CHECK_OK);
2636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
2637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool default_seen = false;
2639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<CaseClause*>* cases = new(zone()) ZoneList<CaseClause*>(4);
2640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LBRACE, CHECK_OK);
2641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() != Token::RBRACE) {
2642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
26433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    cases->Add(clause);
2644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RBRACE, CHECK_OK);
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (statement) statement->Initialize(tag, cases);
2648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return statement;
2649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseThrowStatement(bool* ok) {
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ThrowStatement ::
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'throw' Expression ';'
2655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::THROW, CHECK_OK);
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pos = scanner().location().beg_pos;
26583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (scanner().HasAnyLineTerminatorBeforeNext()) {
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ReportMessage("newline_after_throw", Vector<const char*>::empty());
2660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *ok = false;
2661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return NULL;
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* exception = ParseExpression(true, CHECK_OK);
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectSemicolon(CHECK_OK);
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos));
2667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTryStatement* Parser::ParseTryStatement(bool* ok) {
2671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TryStatement ::
2672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'try' Block Catch
2673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'try' Block Finally
2674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'try' Block Catch Finally
2675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
2676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Catch ::
2677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'catch' '(' Identifier ')' Block
2678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Finally ::
2680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'finally' Block
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::TRY, CHECK_OK);
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TargetCollector try_collector;
2685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Block* try_block;
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  { Target target(&this->target_stack_, &try_collector);
2688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    try_block = ParseBlock(NULL, CHECK_OK);
2689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value tok = peek();
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tok != Token::CATCH && tok != Token::FINALLY) {
2693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ReportMessage("no_catch_or_finally", Vector<const char*>::empty());
2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *ok = false;
2695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return NULL;
2696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we can break out from the catch block and there is a finally block,
26993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // then we will need to collect escaping targets from the catch
27003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // block. Since we don't know yet if there will be a finally block, we
27013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // always collect the targets.
27023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TargetCollector catch_collector;
27033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* catch_scope = NULL;
27043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Variable* catch_variable = NULL;
27053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Block* catch_block = NULL;
27063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> name;
2707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tok == Token::CATCH) {
2708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Consume(Token::CATCH);
2709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::LPAREN, CHECK_OK);
27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    catch_scope = NewScope(top_scope_, CATCH_SCOPE);
27123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    catch_scope->set_start_position(scanner().location().beg_pos);
27133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    name = ParseIdentifier(CHECK_OK);
27141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) {
27161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ReportMessage("strict_catch_variable", Vector<const char*>::empty());
27171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      *ok = false;
27181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      return NULL;
27191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
27201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::RPAREN, CHECK_OK);
2722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (peek() == Token::LBRACE) {
272469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Target target(&this->target_stack_, &catch_collector);
27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      VariableMode mode = is_extended_mode() ? LET : VAR;
27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      catch_variable =
27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
272869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      BlockState block_state(this, catch_scope);
2730589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      catch_block = ParseBlock(NULL, CHECK_OK);
2731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Expect(Token::LBRACE, CHECK_OK);
2733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    catch_scope->set_end_position(scanner().location().end_pos);
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    tok = peek();
2736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Block* finally_block = NULL;
27393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (tok == Token::FINALLY || catch_block == NULL) {
2740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Consume(Token::FINALLY);
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    finally_block = ParseBlock(NULL, CHECK_OK);
2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Simplify the AST nodes by converting:
27453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //   'try B0 catch B1 finally B2'
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to:
27473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  //   'try { try B0 catch B1 } finally B2'
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27493e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (catch_block != NULL && finally_block != NULL) {
27503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If we have both, create an inner try/catch.
27513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(catch_scope != NULL && catch_variable != NULL);
27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index = current_function_state_->NextHandlerIndex();
27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    TryCatchStatement* statement = factory()->NewTryCatchStatement(
27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        index, try_block, catch_scope, catch_variable, catch_block);
27553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    statement->set_escaping_targets(try_collector.targets());
27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    try_block = factory()->NewBlock(NULL, 1, false);
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    try_block->AddStatement(statement);
27583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    catch_block = NULL;  // Clear to indicate it's been handled.
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TryStatement* result = NULL;
27623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (catch_block != NULL) {
27633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    ASSERT(finally_block == NULL);
27643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    ASSERT(catch_scope != NULL && catch_variable != NULL);
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index = current_function_state_->NextHandlerIndex();
27663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result = factory()->NewTryCatchStatement(
27673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        index, try_block, catch_scope, catch_variable, catch_block);
27683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  } else {
27693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    ASSERT(finally_block != NULL);
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int index = current_function_state_->NextHandlerIndex();
27713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result = factory()->NewTryFinallyStatement(index, try_block, finally_block);
27723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Combine the jump targets of the try block and the possible catch block.
27733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    try_collector.targets()->AddAll(*catch_collector.targets());
2774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  result->set_escaping_targets(try_collector.targets());
2777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
2778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockDoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
27823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                                bool* ok) {
2783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // DoStatement ::
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'do' Statement 'while' '(' Expression ')' ';'
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DoWhileStatement* loop = factory()->NewDoWhileStatement(labels);
27873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target target(&this->target_stack_, loop);
2788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::DO, CHECK_OK);
2790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* body = ParseStatement(NULL, CHECK_OK);
2791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::WHILE, CHECK_OK);
2792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
2793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2794d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (loop != NULL) {
2795d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    int position = scanner().location().beg_pos;
2796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    loop->set_condition_position(position);
2797d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
2798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
2799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* cond = ParseExpression(true, CHECK_OK);
2800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
2801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allow do-statements to be terminated with and without
2803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // semi-colons. This allows code such as 'do;while(0)return' to
2804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // parse, which would not be the case if we had used the
2805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ExpectSemicolon() functionality here.
2806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);
2807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (loop != NULL) loop->Initialize(cond, body);
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return loop;
2810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockWhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
2814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // WhileStatement ::
2815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'while' '(' Expression ')' Statement
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  WhileStatement* loop = factory()->NewWhileStatement(labels);
28183e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target target(&this->target_stack_, loop);
2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::WHILE, CHECK_OK);
2821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
2822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* cond = ParseExpression(true, CHECK_OK);
2823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
2824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* body = ParseStatement(NULL, CHECK_OK);
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (loop != NULL) loop->Initialize(cond, body);
2827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return loop;
2828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
2829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStatement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ForStatement ::
2833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
2834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* init = NULL;
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Create an in-between scope for let-bound iteration variables.
28383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* saved_scope = top_scope_;
28393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
28403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  top_scope_ = for_scope;
28413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::FOR, CHECK_OK);
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
28443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for_scope->set_start_position(scanner().location().beg_pos);
2845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() != Token::SEMICOLON) {
2846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (peek() == Token::VAR || peek() == Token::CONST) {
28473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Handle<String> name;
2848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Block* variable_statement =
28493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ParseVariableDeclarations(kForStatement, NULL, NULL, &name, CHECK_OK);
28503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
28513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (peek() == Token::IN && !name.is_null()) {
28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ForInStatement* loop = factory()->NewForInStatement(labels);
28543e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        Target target(&this->target_stack_, loop);
2855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expect(Token::IN, CHECK_OK);
2857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expression* enumerable = ParseExpression(true, CHECK_OK);
2858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expect(Token::RPAREN, CHECK_OK);
2859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Statement* body = ParseStatement(NULL, CHECK_OK);
28613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        loop->Initialize(each, enumerable, body);
28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Block* result = factory()->NewBlock(NULL, 2, false);
28633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        result->AddStatement(variable_statement);
28643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        result->AddStatement(loop);
28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        top_scope_ = saved_scope;
28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for_scope->set_end_position(scanner().location().end_pos);
28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for_scope = for_scope->FinalizeBlockScope();
28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(for_scope == NULL);
28693e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        // Parsed for-in loop w/ variable/const declaration.
28703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        return result;
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        init = variable_statement;
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (peek() == Token::LET) {
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Handle<String> name;
28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      VariableDeclarationProperties decl_props = kHasNoInitializers;
28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Block* variable_statement =
28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   CHECK_OK);
28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (peek() == Token::IN && accept_IN) {
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Rewrite a for-in statement of the form
28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
28843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   for (let x in e) b
28853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // into
28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //
28883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   <let x' be a temporary variable>
28893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   for (x' in e) {
28903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     let x;
28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     x = x';
28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //     b;
28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        //   }
28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // TODO(keuchel): Move the temporary variable to the block scope, after
28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // implementing stack allocated block scoped variables.
28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Variable* temp = top_scope_->DeclarationScope()->NewTemporary(name);
28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ForInStatement* loop = factory()->NewForInStatement(labels);
29013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Target target(&this->target_stack_, loop);
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Expect(Token::IN, CHECK_OK);
29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Expression* enumerable = ParseExpression(true, CHECK_OK);
29053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Expect(Token::RPAREN, CHECK_OK);
29063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Statement* body = ParseStatement(NULL, CHECK_OK);
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Block* body_block = factory()->NewBlock(NULL, 3, false);
29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Assignment* assignment = factory()->NewAssignment(
29103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
29113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Statement* assignment_statement =
29123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            factory()->NewExpressionStatement(assignment);
29133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        body_block->AddStatement(variable_statement);
29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        body_block->AddStatement(assignment_statement);
29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        body_block->AddStatement(body);
29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        loop->Initialize(temp_proxy, enumerable, body_block);
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        top_scope_ = saved_scope;
29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for_scope->set_end_position(scanner().location().end_pos);
29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for_scope = for_scope->FinalizeBlockScope();
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        body_block->set_block_scope(for_scope);
29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Parsed for-in loop w/ let declaration.
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return loop;
2923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
29253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        init = variable_statement;
29263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
2928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Expression* expression = ParseExpression(false, CHECK_OK);
2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (peek() == Token::IN) {
2930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Signal a reference error if the expression is an invalid
2931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // left-hand side expression.  We could report this as a syntax
2932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // error here but for compatibility with JSC we choose to report
2933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // the error at runtime.
2934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (expression == NULL || !expression->IsValidLeftHandSide()) {
293544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          Handle<String> type =
293644f0eee88ff00398ff7f715fab053374d808c90dSteve Block              isolate()->factory()->invalid_lhs_in_for_in_symbol();
2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          expression = NewThrowReferenceError(type);
2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
29393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ForInStatement* loop = factory()->NewForInStatement(labels);
29403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        Target target(&this->target_stack_, loop);
2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expect(Token::IN, CHECK_OK);
2943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expression* enumerable = ParseExpression(true, CHECK_OK);
2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expect(Token::RPAREN, CHECK_OK);
2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Statement* body = ParseStatement(NULL, CHECK_OK);
2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (loop) loop->Initialize(expression, enumerable, body);
29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        top_scope_ = saved_scope;
29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for_scope->set_end_position(scanner().location().end_pos);
29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for_scope = for_scope->FinalizeBlockScope();
29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(for_scope == NULL);
2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Parsed for-in loop.
2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return loop;
2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
29563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        init = factory()->NewExpressionStatement(expression);
2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Standard 'for' loop
29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ForStatement* loop = factory()->NewForStatement(labels);
29633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  Target target(&this->target_stack_, loop);
2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parsed initializer at this point.
2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::SEMICOLON, CHECK_OK);
2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* cond = NULL;
2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() != Token::SEMICOLON) {
2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cond = ParseExpression(true, CHECK_OK);
2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::SEMICOLON, CHECK_OK);
2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* next = NULL;
2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() != Token::RPAREN) {
2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* exp = ParseExpression(true, CHECK_OK);
29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    next = factory()->NewExpressionStatement(exp);
2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Statement* body = ParseStatement(NULL, CHECK_OK);
29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  top_scope_ = saved_scope;
29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for_scope->set_end_position(scanner().location().end_pos);
29843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for_scope = for_scope->FinalizeBlockScope();
29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (for_scope != NULL) {
29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Rewrite a for statement of the form
29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
29883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   for (let x = i; c; n) b
29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
29903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // into
29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //
29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   {
29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //     let x = i;
29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //     for (; c; n) b
29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   }
29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(init != NULL);
29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Block* result = factory()->NewBlock(NULL, 2, false);
29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result->AddStatement(init);
29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result->AddStatement(loop);
30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result->set_block_scope(for_scope);
30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (loop) loop->Initialize(NULL, cond, next, body);
30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return result;
30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (loop) loop->Initialize(init, cond, next, body);
30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return loop;
30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Precedence = 1
3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseExpression(bool accept_IN, bool* ok) {
3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Expression ::
3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   AssignmentExpression
3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   Expression ',' AssignmentExpression
3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() == Token::COMMA) {
3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::COMMA, CHECK_OK);
301980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int position = scanner().location().beg_pos;
3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
30213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result =
30223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        factory()->NewBinaryOperation(Token::COMMA, result, right, position);
3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Precedence = 2
3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // AssignmentExpression ::
3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ConditionalExpression
3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   LeftHandSideExpression AssignmentOperator AssignmentExpression
3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (fni_ != NULL) fni_->Enter();
3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!Token::IsAssignmentOp(peek())) {
303880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (fni_ != NULL) fni_->Leave();
3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Parsed conditional expression only (no assignment).
3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return expression;
3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Signal a reference error if the expression is an invalid left-hand
3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // side expression.  We could report this as a syntax error here but
3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for compatibility with JSC we choose to report the error at
3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // runtime.
3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expression == NULL || !expression->IsValidLeftHandSide()) {
304844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<String> type =
304944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->factory()->invalid_lhs_in_assignment_symbol();
3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expression = NewThrowReferenceError(type);
3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!top_scope_->is_classic_mode()) {
30541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Assignment to eval or arguments is disallowed in strict mode.
30551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
30561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
30573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MarkAsLValue(expression);
30581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value op = Next();  // Get assignment operator.
3060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int pos = scanner().location().beg_pos;
3061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // TODO(1231235): We try to estimate the set of properties set by
3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constructors. We define a new property whenever there is an
3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // assignment to a property of 'this'. We should probably only add
3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properties if we haven't seen them before. Otherwise we'll
3067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // probably overestimate the number of properties.
3068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Property* property = expression ? expression->AsProperty() : NULL;
3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (op == Token::ASSIGN &&
3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      property != NULL &&
3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      property->obj()->AsVariableProxy() != NULL &&
3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      property->obj()->AsVariableProxy()->is_this()) {
30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current_function_state_->AddProperty();
3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // If we assign a function literal to a property we pretenure the
30778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // literal so it can be added as a constant function property.
30788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (property != NULL && right->AsFunctionLiteral() != NULL) {
30793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    right->AsFunctionLiteral()->set_pretenure();
30808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
30818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
308280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (fni_ != NULL) {
308380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Check if the right hand side is a call to avoid inferring a
308480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // name if we're dealing with "a = function(){...}();"-like
308580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // expression.
308680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if ((op == Token::INIT_VAR
308780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         || op == Token::INIT_CONST
308880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen         || op == Token::ASSIGN)
30893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
309080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      fni_->Infer();
309169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
309269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      fni_->RemoveLastFunction();
309380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
309480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    fni_->Leave();
309580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
309680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
30973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewAssignment(op, expression, right, pos);
3098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Precedence = 3
3102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
3103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ConditionalExpression ::
3104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   LogicalOrExpression
3105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
3106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We start using the binary expression parser for prec >= 4 only!
3108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* expression = ParseBinaryExpression(4, accept_IN, CHECK_OK);
3109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() != Token::CONDITIONAL) return expression;
3110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Consume(Token::CONDITIONAL);
3111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In parsing the first assignment expression in conditional
3112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // expressions we always accept the 'in' keyword; see ECMA-262,
3113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // section 11.12, page 58.
31147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int left_position = scanner().peek_location().beg_pos;
3115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* left = ParseAssignmentExpression(true, CHECK_OK);
3116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::COLON, CHECK_OK);
31177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  int right_position = scanner().peek_location().beg_pos;
3118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
31193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewConditional(
31203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      expression, left, right, left_position, right_position);
3121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int Precedence(Token::Value tok, bool accept_IN) {
3125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tok == Token::IN && !accept_IN)
3126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 0;  // 0 precedence will terminate binary expression parsing
3127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Token::Precedence(tok);
3129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Precedence >= 4
3133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
3134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(prec >= 4);
3135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* x = ParseUnaryExpression(CHECK_OK);
3136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int prec1 = Precedence(peek(), accept_IN); prec1 >= prec; prec1--) {
3137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // prec1 >= 4
3138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (Precedence(peek(), accept_IN) == prec1) {
3139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Token::Value op = Next();
314080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      int position = scanner().location().beg_pos;
3141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Expression* y = ParseBinaryExpression(prec1 + 1, accept_IN, CHECK_OK);
3142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Compute some expressions involving only number literals.
3144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber() &&
3145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          y && y->AsLiteral() && y->AsLiteral()->handle()->IsNumber()) {
3146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        double x_val = x->AsLiteral()->handle()->Number();
3147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        double y_val = y->AsLiteral()->handle()->Number();
3148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (op) {
3150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::ADD:
31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(x_val + y_val);
3152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
3153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::SUB:
31543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(x_val - y_val);
3155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
3156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::MUL:
31573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(x_val * y_val);
3158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
3159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::DIV:
31603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(x_val / y_val);
3161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case Token::BIT_OR: {
31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
31643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(value);
3165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
31663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
31673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case Token::BIT_AND: {
31683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
31693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(value);
3170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
31713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
31723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          case Token::BIT_XOR: {
31733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
31743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(value);
3175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
31763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
3177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::SHL: {
3178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
31793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(value);
3180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
3181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
3182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::SHR: {
3183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
3184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            uint32_t value = DoubleToUint32(x_val) >> shift;
31853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(value);
3186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
3187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
3188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::SAR: {
3189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            uint32_t shift = DoubleToInt32(y_val) & 0x1f;
3190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
31913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            x = factory()->NewNumberLiteral(value);
3192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;
3193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
3194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
3195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
3196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
3197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // For now we distinguish between comparisons and other binary
3200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // operations.  (We could combine the two and get rid of this
320180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      // code and AST node eventually.)
3202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (Token::IsCompareOp(op)) {
3203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We have a comparison.
3204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Token::Value cmp = op;
3205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (op) {
3206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::NE: cmp = Token::EQ; break;
3207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
3208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default: break;
3209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
32103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        x = factory()->NewCompareOperation(cmp, x, y, position);
3211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (cmp != op) {
3212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // The comparison was negated - add a NOT.
32133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          x = factory()->NewUnaryOperation(Token::NOT, x, position);
3214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
3215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
3217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We have a "normal" binary operation.
32183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        x = factory()->NewBinaryOperation(op, x, y, position);
3219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return x;
3223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseUnaryExpression(bool* ok) {
3227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // UnaryExpression ::
3228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   PostfixExpression
3229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'delete' UnaryExpression
3230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'void' UnaryExpression
3231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'typeof' UnaryExpression
3232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '++' UnaryExpression
3233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '--' UnaryExpression
3234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '+' UnaryExpression
3235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '-' UnaryExpression
3236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '~' UnaryExpression
3237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '!' UnaryExpression
3238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value op = peek();
3240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (Token::IsUnaryOp(op)) {
3241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    op = Next();
3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int position = scanner().location().beg_pos;
3243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* expression = ParseUnaryExpression(CHECK_OK);
3244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (expression != NULL && (expression->AsLiteral() != NULL)) {
32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Handle<Object> literal = expression->AsLiteral()->handle();
32473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (op == Token::NOT) {
32483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Convert the literal to a boolean condition and negate it.
32493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        bool condition = literal->ToBoolean()->IsTrue();
32503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
32513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return factory()->NewLiteral(result);
32523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (literal->IsNumber()) {
32533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        // Compute some expressions involving only number literals.
32543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        double value = literal->Number();
32553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        switch (op) {
32563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          case Token::ADD:
32573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            return expression;
32583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          case Token::SUB:
32593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return factory()->NewNumberLiteral(-value);
32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          case Token::BIT_NOT:
32613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            return factory()->NewNumberLiteral(~DoubleToInt32(value));
32623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          default:
32633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            break;
32643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
3265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // "delete identifier" is a syntax error in strict mode.
32693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VariableProxy* operand = expression->AsVariableProxy();
3271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (operand != NULL && !operand->is_this()) {
3272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        ReportMessage("strict_delete", Vector<const char*>::empty());
3273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        *ok = false;
3274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        return NULL;
3275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      }
3276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
3277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return factory()->NewUnaryOperation(op, expression, position);
3279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (Token::IsCountOp(op)) {
3281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    op = Next();
3282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* expression = ParseUnaryExpression(CHECK_OK);
3283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Signal a reference error if the expression is an invalid
3284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // left-hand side expression.  We could report this as a syntax
3285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // error here but for compatibility with JSC we choose to report the
3286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // error at runtime.
3287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expression == NULL || !expression->IsValidLeftHandSide()) {
328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Handle<String> type =
328944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate()->factory()->invalid_lhs_in_prefix_op_symbol();
3290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      expression = NewThrowReferenceError(type);
3291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
32921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
32933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!top_scope_->is_classic_mode()) {
32941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Prefix expression operand in strict mode may not be eval or arguments.
32951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MarkAsLValue(expression);
32981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
329980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int position = scanner().location().beg_pos;
33003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return factory()->NewCountOperation(op,
33013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        true /* prefix */,
33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        expression,
33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        position);
3304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ParsePostfixExpression(ok);
3307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParsePostfixExpression(bool* ok) {
3312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // PostfixExpression ::
3313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   LeftHandSideExpression ('++' | '--')?
3314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!scanner().HasAnyLineTerminatorBeforeNext() &&
3317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Token::IsCountOp(peek())) {
3318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Signal a reference error if the expression is an invalid
3319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // left-hand side expression.  We could report this as a syntax
3320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // error here but for compatibility with JSC we choose to report the
3321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // error at runtime.
3322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expression == NULL || !expression->IsValidLeftHandSide()) {
332344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Handle<String> type =
332444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate()->factory()->invalid_lhs_in_postfix_op_symbol();
3325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      expression = NewThrowReferenceError(type);
3326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
33271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!top_scope_->is_classic_mode()) {
33291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Postfix expression operand in strict mode may not be eval or arguments.
33301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
33311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MarkAsLValue(expression);
33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Token::Value next = Next();
333580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int position = scanner().location().beg_pos;
33368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    expression =
33373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        factory()->NewCountOperation(next,
33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     false /* postfix */,
33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     expression,
33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     position);
3341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return expression;
3343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseLeftHandSideExpression(bool* ok) {
3347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // LeftHandSideExpression ::
3348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   (NewExpression | MemberExpression) ...
3349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* result;
3351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::NEW) {
3352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = ParseNewExpression(CHECK_OK);
3353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = ParseMemberExpression(CHECK_OK);
3355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
3358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (peek()) {
3359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::LBRACK: {
3360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Consume(Token::LBRACK);
3361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int pos = scanner().location().beg_pos;
3362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expression* index = ParseExpression(true, CHECK_OK);
33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = factory()->NewProperty(result, index, pos);
3364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expect(Token::RBRACK, CHECK_OK);
3365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::LPAREN: {
33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int pos;
33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (scanner().current_token() == Token::IDENTIFIER) {
33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // For call of an identifier we want to report position of
33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // the identifier as position of the call in the stack trace.
33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          pos = scanner().location().beg_pos;
33743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
33753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // For other kinds of calls we record position of the parenthesis as
33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // position of the call.  Note that this is extremely important for
33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // expressions of the form function(){...}() for which call position
33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // should not point to the closing brace otherwise it will intersect
33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // with positions recorded for function literal and confuse debugger.
33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          pos = scanner().peek_location().beg_pos;
33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
3382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Keep track of eval() calls since they disable all local variable
3385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // optimizations.
3386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // The calls that need special treatment are the
33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // direct eval calls. These calls are all of the form eval(...), with
33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // no explicit receiver.
3389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        // These calls are marked as potentially direct eval calls. Whether
3390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        // they are actually direct calls to eval is determined at run time.
33913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu        VariableProxy* callee = result->AsVariableProxy();
339244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (callee != NULL &&
339344f0eee88ff00398ff7f715fab053374d808c90dSteve Block            callee->IsVariable(isolate()->factory()->eval_symbol())) {
33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          top_scope_->DeclarationScope()->RecordEvalCall();
3395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = factory()->NewCall(result, args, pos);
3397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::PERIOD: {
3401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Consume(Token::PERIOD);
3402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int pos = scanner().location().beg_pos;
3403bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        Handle<String> name = ParseIdentifierName(CHECK_OK);
34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result =
34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            factory()->NewProperty(result, factory()->NewLiteral(name), pos);
340680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        if (fni_ != NULL) fni_->PushLiteralName(name);
3407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
3411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return result;
3412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
3418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NewExpression ::
3419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ('new')+ MemberExpression
3420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The grammar for new expressions is pretty warped. The keyword
3422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 'new' can either be a part of the new expression (where it isn't
3423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // followed by an argument list) or a part of the member expression,
3424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // where it must be followed by an argument list. To accommodate
3425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // this, we parse the 'new' keywords greedily and keep track of how
3426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // many we have parsed. This information is then passed on to the
3427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // member expression parser, which is only allowed to match argument
3428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // lists as long as it has 'new' prefixes left
3429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::NEW, CHECK_OK);
3430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PositionStack::Element pos(stack, scanner().location().beg_pos);
3431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* result;
3433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::NEW) {
3434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = ParseNewPrefix(stack, CHECK_OK);
3435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
3437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!stack->is_empty()) {
3440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int last = stack->pop();
34413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    result = factory()->NewCallNew(
34423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result, new(zone()) ZoneList<Expression*>(0), last);
3443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
3445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseNewExpression(bool* ok) {
3449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PositionStack stack(ok);
3450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ParseNewPrefix(&stack, ok);
3451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseMemberExpression(bool* ok) {
3455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ParseMemberWithNewPrefixesExpression(NULL, ok);
3456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
3460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                         bool* ok) {
3461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // MemberExpression ::
3462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   (PrimaryExpression | FunctionLiteral)
3463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //     ('[' Expression ']' | '.' Identifier | Arguments)*
3464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parse the initial primary or function expression.
3466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* result = NULL;
3467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (peek() == Token::FUNCTION) {
3468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::FUNCTION, CHECK_OK);
3469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int function_token_position = scanner().location().beg_pos;
3470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<String> name;
34713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool is_strict_reserved_name = false;
34721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (peek_any_identifier()) {
34733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
34743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                 CHECK_OK);
34751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
34763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    FunctionLiteral::Type type = name.is_null()
34773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        ? FunctionLiteral::ANONYMOUS_EXPRESSION
34783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        : FunctionLiteral::NAMED_EXPRESSION;
34793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    result = ParseFunctionLiteral(name,
34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  is_strict_reserved_name,
34813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  function_token_position,
34823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  type,
34833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                  CHECK_OK);
3484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = ParsePrimaryExpression(CHECK_OK);
3486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
3489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (peek()) {
3490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::LBRACK: {
3491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Consume(Token::LBRACK);
3492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int pos = scanner().location().beg_pos;
3493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expression* index = ParseExpression(true, CHECK_OK);
34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = factory()->NewProperty(result, index, pos);
34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (fni_ != NULL) {
34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          if (index->IsPropertyName()) {
34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          } else {
34993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            fni_->PushLiteralName(
35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                isolate()->factory()->anonymous_function_symbol());
35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
35023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
3503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Expect(Token::RBRACK, CHECK_OK);
3504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::PERIOD: {
3507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Consume(Token::PERIOD);
3508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int pos = scanner().location().beg_pos;
3509bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        Handle<String> name = ParseIdentifierName(CHECK_OK);
35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result =
35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            factory()->NewProperty(result, factory()->NewLiteral(name), pos);
351280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        if (fni_ != NULL) fni_->PushLiteralName(name);
3513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::LPAREN: {
3516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if ((stack == NULL) || stack->is_empty()) return result;
3517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Consume one of the new prefixes (already parsed).
3518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
3519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int last = stack->pop();
35203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = factory()->NewCallNew(result, args, last);
3521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
3524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return result;
3525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // contexts this is used as a statement which invokes the debugger as i a
3533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // break point is present.
3534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // DebuggerStatement ::
3535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'debugger' ';'
3536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::DEBUGGER, CHECK_OK);
3538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectSemicolon(CHECK_OK);
35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewDebuggerStatement();
3540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Parser::ReportUnexpectedToken(Token::Value token) {
3544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We don't report stack overflows here, to avoid increasing the
3545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack depth even further.  Instead we report it after parsing is
35464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // over, in ParseProgram/ParseJson.
3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (token == Token::ILLEGAL && stack_overflow_) return;
3548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Four of the tokens are treated specially
3549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (token) {
3550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::EOS:
3551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return ReportMessage("unexpected_eos", Vector<const char*>::empty());
3552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::NUMBER:
3553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return ReportMessage("unexpected_token_number",
3554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Vector<const char*>::empty());
3555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::STRING:
3556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return ReportMessage("unexpected_token_string",
3557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Vector<const char*>::empty());
3558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Token::IDENTIFIER:
3559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return ReportMessage("unexpected_token_identifier",
3560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                           Vector<const char*>::empty());
35611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case Token::FUTURE_RESERVED_WORD:
35623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return ReportMessage("unexpected_reserved",
35633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           Vector<const char*>::empty());
35643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::FUTURE_STRICT_RESERVED_WORD:
35653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ReportMessage(top_scope_->is_classic_mode() ?
35663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               "unexpected_token_identifier" :
35673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               "unexpected_strict_reserved",
35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                           Vector<const char*>::empty());
3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    default:
3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      const char* name = Token::String(token);
3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(name != NULL);
3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
3573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3577ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarkevoid Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
3578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
3579ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke  const char* element[1] = { *name_string };
3580ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke  ReportMessage("invalid_preparser_data",
3581ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke                Vector<const char*>(element, 1));
3582ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke  *ok = false;
3583ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke}
3584ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke
3585ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke
3586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParsePrimaryExpression(bool* ok) {
3587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // PrimaryExpression ::
3588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'this'
3589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'null'
3590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'true'
3591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   'false'
3592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   Identifier
3593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   Number
3594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   String
3595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ArrayLiteral
3596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   ObjectLiteral
3597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   RegExpLiteral
3598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '(' Expression ')'
3599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expression* result = NULL;
3601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (peek()) {
3602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::THIS: {
3603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::THIS);
36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewVariableProxy(top_scope_->receiver());
3605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::NULL_LITERAL:
3609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::NULL_LITERAL);
36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewLiteral(isolate()->factory()->null_value());
3611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::TRUE_LITERAL:
3614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::TRUE_LITERAL);
36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewLiteral(isolate()->factory()->true_value());
3616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::FALSE_LITERAL:
3619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::FALSE_LITERAL);
36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewLiteral(isolate()->factory()->false_value());
3621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    case Token::IDENTIFIER:
36243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    case Token::FUTURE_STRICT_RESERVED_WORD: {
3625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Handle<String> name = ParseIdentifier(CHECK_OK);
362680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (fni_ != NULL) fni_->PushVariableName(name);
36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The name may refer to a module instance object, so its type is unknown.
36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (FLAG_print_interface_details)
36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("# Variable %s ", name->ToAsciiArray());
36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Interface* interface = Interface::NewUnknown();
36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = top_scope_->NewUnresolved(
36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          factory(), name, scanner().location().beg_pos, interface);
3635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::NUMBER: {
3639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::NUMBER);
36409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      ASSERT(scanner().is_literal_ascii());
36418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      double value = StringToDouble(isolate()->unicode_cache(),
36428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                    scanner().literal_ascii_string(),
36439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                    ALLOW_HEX | ALLOW_OCTALS);
36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewNumberLiteral(value);
3645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::STRING: {
3649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::STRING);
36509ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick      Handle<String> symbol = GetSymbol(CHECK_OK);
36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = factory()->NewLiteral(symbol);
365280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (fni_ != NULL) fni_->PushLiteralName(symbol);
3653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::ASSIGN_DIV:
3657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      result = ParseRegExpLiteral(true, CHECK_OK);
3658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::DIV:
3661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      result = ParseRegExpLiteral(false, CHECK_OK);
3662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::LBRACK:
3665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      result = ParseArrayLiteral(CHECK_OK);
3666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::LBRACE:
3669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      result = ParseObjectLiteral(CHECK_OK);
3670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::LPAREN:
3673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Consume(Token::LPAREN);
3674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // Heuristically try to detect immediately called functions before
3675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      // seeing the call parentheses.
3676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      parenthesized_function_ = (peek() == Token::FUNCTION);
3677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      result = ParseExpression(true, CHECK_OK);
3678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Expect(Token::RPAREN, CHECK_OK);
3679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
3680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Token::MOD:
3682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (allow_natives_syntax_ || extension_ != NULL) {
3683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        result = ParseV8Intrinsic(CHECK_OK);
3684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
3685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
3686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // If we're not allowing special syntax we fall-through to the
3687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // default case.
3688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
3690bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      Token::Value tok = Next();
3691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ReportUnexpectedToken(tok);
3692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      *ok = false;
3693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return NULL;
3694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
3698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid Parser::BuildArrayLiteralBoilerplateLiterals(ZoneList<Expression*>* values,
37024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                  Handle<FixedArray> literals,
37034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                  bool* is_simple,
37044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                                  int* depth) {
37054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Fill in the literals.
37064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Accumulate output values in local variables.
37074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  bool is_simple_acc = true;
37084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int depth_acc = 1;
37094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  for (int i = 0; i < values->length(); i++) {
37104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
37114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (m_literal != NULL && m_literal->depth() >= depth_acc) {
37124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      depth_acc = m_literal->depth() + 1;
37134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
37144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
37154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (boilerplate_value->IsUndefined()) {
37164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      literals->set_the_hole(i);
37174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      is_simple_acc = false;
37184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    } else {
37194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      literals->set(i, *boilerplate_value);
37204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
37214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
37224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
37234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  *is_simple = is_simple_acc;
37244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  *depth = depth_acc;
37254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
37264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
37274515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
3728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseArrayLiteral(bool* ok) {
3729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ArrayLiteral ::
3730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '[' Expression? (',' Expression?)* ']'
3731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4);
3733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LBRACK, CHECK_OK);
3734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() != Token::RBRACK) {
3735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* elem;
3736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (peek() == Token::COMMA) {
3737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      elem = GetLiteralTheHole();
3738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
3739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      elem = ParseAssignmentExpression(true, CHECK_OK);
3740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
37413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    values->Add(elem);
3742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (peek() != Token::RBRACK) {
3743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Expect(Token::COMMA, CHECK_OK);
3744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RBRACK, CHECK_OK);
3747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Update the scope information before the pre-parsing bailout.
37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
3750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate a fixed array to hold all the object literals.
37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> object_literals =
375344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->NewFixedArray(values->length(), TENURED);
37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedDoubleArray> double_literals;
37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS;
37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_only_undefined_values = true;
3757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill in the literals.
3759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_simple = true;
3760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int depth = 1;
37613e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  for (int i = 0, n = values->length(); i < n; i++) {
37623e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    MaterializedLiteral* m_literal = values->at(i)->AsMaterializedLiteral();
3763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (m_literal != NULL && m_literal->depth() + 1 > depth) {
3764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      depth = m_literal->depth() + 1;
3765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
37663e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (boilerplate_value->IsUndefined()) {
37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object_literals->set_the_hole(i);
37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (elements_kind == FAST_DOUBLE_ELEMENTS) {
37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        double_literals->set_the_hole(i);
37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      is_simple = false;
3773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Examine each literal element, and adjust the ElementsKind if the
37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // literal element is not of a type that can be stored in the current
37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // ElementsKind.  Start with FAST_SMI_ONLY_ELEMENTS, and transition to
37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // FAST_DOUBLE_ELEMENTS and FAST_ELEMENTS as necessary.  Always remember
37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the tagged value, no matter what the ElementsKind is in case we
37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // ultimately end up in FAST_ELEMENTS.
37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      has_only_undefined_values = false;
37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      object_literals->set(i, *boilerplate_value);
37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Smi only elements. Notice if a transition to FAST_DOUBLE_ELEMENTS or
37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // FAST_ELEMENTS is required.
37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!boilerplate_value->IsSmi()) {
37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (boilerplate_value->IsNumber() && FLAG_smi_only_arrays) {
37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Allocate a double array on the FAST_DOUBLE_ELEMENTS transition to
37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // avoid over-allocating in TENURED space.
37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            double_literals = isolate()->factory()->NewFixedDoubleArray(
37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                values->length(), TENURED);
37913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // Copy the contents of the FAST_SMI_ONLY_ELEMENT array to the
37923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // FAST_DOUBLE_ELEMENTS array so that they are in sync.
37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            for (int j = 0; j < i; ++j) {
37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              Object* smi_value = object_literals->get(j);
37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              if (smi_value->IsTheHole()) {
37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                double_literals->set_the_hole(j);
37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              } else {
37983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                double_literals->set(j, Smi::cast(smi_value)->value());
37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              }
38003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
38013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            double_literals->set(i, boilerplate_value->Number());
38023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements_kind = FAST_DOUBLE_ELEMENTS;
38033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
38043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            elements_kind = FAST_ELEMENTS;
38053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
38063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
38073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else if (elements_kind == FAST_DOUBLE_ELEMENTS) {
38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Continue to store double values in to FAST_DOUBLE_ELEMENTS arrays
38093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // until the first value is seen that can't be stored as a double.
38103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (boilerplate_value->IsNumber()) {
38113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          double_literals->set(i, boilerplate_value->Number());
38123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
38133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          elements_kind = FAST_ELEMENTS;
38143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
38153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
3817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Very small array literals that don't have a concrete hint about their type
38203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // from a constant value should default to the slow case to avoid lots of
38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // elements transitions on really small objects.
38223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (has_only_undefined_values && values->length() <= 2) {
38233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    elements_kind = FAST_ELEMENTS;
38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3826756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Simple and shallow arrays can be lazily copied, we transform the
3827756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // elements array to a copy-on-write array.
38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_simple && depth == 1 && values->length() > 0 &&
38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      elements_kind != FAST_DOUBLE_ELEMENTS) {
38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    object_literals->set_map(isolate()->heap()->fixed_cow_array_map());
3831756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
3832756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArrayBase> element_values = elements_kind == FAST_DOUBLE_ELEMENTS
38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? Handle<FixedArrayBase>(double_literals)
38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : Handle<FixedArrayBase>(object_literals);
38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Remember both the literal's constant values as well as the ElementsKind
38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in a 2-element FixedArray.
38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<FixedArray> literals =
38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate()->factory()->NewFixedArray(2, TENURED);
38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  literals->set(0, Smi::FromInt(elements_kind));
38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  literals->set(1, *element_values);
38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewArrayLiteral(
38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      literals, values, literal_index, is_simple, depth);
3847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
3851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return property != NULL &&
3852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block         property->kind() != ObjectLiteral::Property::PROTOTYPE;
3853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
3857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (expression->AsLiteral() != NULL) return true;
3858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
3859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return lit != NULL && lit->is_simple();
3860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3862756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3863756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickbool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
3864756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    Expression* value) {
3865756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If value is a literal the property value is already set in the
3866756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // boilerplate object.
3867756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (value->AsLiteral() != NULL) return false;
3868756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // If value is a materialized literal the property value is already set
3869756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // in the boilerplate object if it is simple.
3870756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  if (CompileTimeValue::IsCompileTimeValue(value)) return false;
3871756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return true;
3872756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
3873756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3874756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
3876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(IsCompileTimeValue(expression));
387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<FixedArray> result = FACTORY->NewFixedArray(2, TENURED);
3878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ObjectLiteral* object_literal = expression->AsObjectLiteral();
3879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (object_literal != NULL) {
3880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(object_literal->is_simple());
38816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (object_literal->fast_elements()) {
38826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
38836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
38846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
38856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
3886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result->set(kElementsSlot, *object_literal->constant_properties());
3887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
3888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ArrayLiteral* array_literal = expression->AsArrayLiteral();
3889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(array_literal != NULL && array_literal->is_simple());
3890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
3891e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    result->set(kElementsSlot, *array_literal->constant_elements());
3892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
3894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
3898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Smi* type_value = Smi::cast(value->get(kTypeSlot));
3899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return static_cast<Type>(type_value->value());
3900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
3904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
3905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> Parser::GetBoilerplateValue(Expression* expression) {
3909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expression->AsLiteral() != NULL) {
3910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return expression->AsLiteral()->handle();
3911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
3912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (CompileTimeValue::IsCompileTimeValue(expression)) {
3913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CompileTimeValue::GetValue(expression);
3914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return isolate()->factory()->undefined_value();
3916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
3917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Validation per 11.1.5 Object Initialiser
39191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass ObjectLiteralPropertyChecker {
39201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) :
39223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    props_(Literal::Match),
39231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    parser_(parser),
39243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    language_mode_(language_mode) {
39251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
39261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void CheckProperty(
39281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ObjectLiteral::Property* property,
39291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Scanner::Location loc,
39301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bool* ok);
39311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
39331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum PropertyKind {
39341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    kGetAccessor = 0x01,
39351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    kSetAccessor = 0x02,
39361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    kAccessor = kGetAccessor | kSetAccessor,
39371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    kData = 0x04
39381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
39391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static intptr_t GetPropertyKind(ObjectLiteral::Property* property) {
39411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    switch (property->kind()) {
39421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case ObjectLiteral::Property::GETTER:
39431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return kGetAccessor;
39441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case ObjectLiteral::Property::SETTER:
39451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return kSetAccessor;
39461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      default:
39471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return kData;
39481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
39491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
39501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HashMap props_;
39521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Parser* parser_;
39533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LanguageMode language_mode_;
39541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
39551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid ObjectLiteralPropertyChecker::CheckProperty(
39581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ObjectLiteral::Property* property,
39591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Scanner::Location loc,
39601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    bool* ok) {
39611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(property != NULL);
39623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Literal* literal = property->key();
39633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HashMap::Entry* entry = props_.Lookup(literal, literal->Hash(), true);
39641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  intptr_t prev = reinterpret_cast<intptr_t> (entry->value);
39651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  intptr_t curr = GetPropertyKind(property);
39661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Duplicate data properties are illegal in strict or extended mode.
39683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (language_mode_ != CLASSIC_MODE && (curr & prev & kData) != 0) {
39691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    parser_->ReportMessageAt(loc, "strict_duplicate_property",
39701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             Vector<const char*>::empty());
39711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    *ok = false;
39721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return;
39731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
39741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Data property conflicting with an accessor.
39751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (((curr & kData) && (prev & kAccessor)) ||
39761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ((prev & kData) && (curr & kAccessor))) {
39771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    parser_->ReportMessageAt(loc, "accessor_data_property",
39781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             Vector<const char*>::empty());
39791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    *ok = false;
39801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return;
39811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
39821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Two accessors of the same type conflicting
39831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if ((curr & prev & kAccessor) != 0) {
39841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    parser_->ReportMessageAt(loc, "accessor_get_set",
39851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             Vector<const char*>::empty());
39861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    *ok = false;
39871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return;
39881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
39891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
39901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Update map
39911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  entry->value = reinterpret_cast<void*> (prev | curr);
39921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  *ok = true;
39931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
39941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkevoid Parser::BuildObjectLiteralConstantProperties(
39974515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    ZoneList<ObjectLiteral::Property*>* properties,
39984515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Handle<FixedArray> constant_properties,
39994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    bool* is_simple,
40006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool* fast_elements,
40014515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    int* depth) {
40024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int position = 0;
40034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Accumulate the value in local variables and store it at the end.
40044515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  bool is_simple_acc = true;
40054515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  int depth_acc = 1;
40066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  uint32_t max_element_index = 0;
40076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  uint32_t elements = 0;
40084515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  for (int i = 0; i < properties->length(); i++) {
40094515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    ObjectLiteral::Property* property = properties->at(i);
40104515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (!IsBoilerplateProperty(property)) {
40114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      is_simple_acc = false;
40124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      continue;
40134515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
40144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
40154515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (m_literal != NULL && m_literal->depth() >= depth_acc) {
40164515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke      depth_acc = m_literal->depth() + 1;
40174515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    }
40184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
40194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
40204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // value for COMPUTED properties, the real value is filled in at
40214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // runtime. The enumeration order is maintained.
40224515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Handle<Object> key = property->key()->handle();
40234515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Handle<Object> value = GetBoilerplateValue(property->value());
40244515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    is_simple_acc = is_simple_acc && !value->IsUndefined();
40254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
40266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Keep track of the number of elements in the object literal and
40276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // the largest element index.  If the largest element index is
40286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // much larger than the number of elements, creating an object
40296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // literal with fast elements will be a waste of space.
40306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    uint32_t element_index = 0;
40316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (key->IsString()
40326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        && Handle<String>::cast(key)->AsArrayIndex(&element_index)
40336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        && element_index > max_element_index) {
40346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      max_element_index = element_index;
40356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      elements++;
40366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if (key->IsSmi()) {
40376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      int key_value = Smi::cast(*key)->value();
40386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (key_value > 0
40396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          && static_cast<uint32_t>(key_value) > max_element_index) {
40406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        max_element_index = key_value;
40416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
40426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      elements++;
40436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
40446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
40454515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Add name, value pair to the fixed array.
40464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    constant_properties->set(position++, *key);
40474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    constant_properties->set(position++, *value);
40484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
40496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  *fast_elements =
40506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      (max_element_index <= 32) || ((2 * elements) >= max_element_index);
40514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  *is_simple = is_simple_acc;
40524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  *depth = depth_acc;
40534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
40544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
40554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4056bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
4057bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                                                          bool* ok) {
4058bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Special handling of getter and setter syntax:
4059bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
4060bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // We have already read the "get" or "set" keyword.
4061bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Token::Value next = Next();
40629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  bool is_keyword = Token::IsKeyword(next);
40639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (next == Token::IDENTIFIER || next == Token::NUMBER ||
40641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      next == Token::FUTURE_RESERVED_WORD ||
40653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      next == Token::FUTURE_STRICT_RESERVED_WORD ||
40669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      next == Token::STRING || is_keyword) {
40679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    Handle<String> name;
40689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    if (is_keyword) {
406944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      name = isolate_->factory()->LookupAsciiSymbol(Token::String(next));
40709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    } else {
40719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block      name = GetSymbol(CHECK_OK);
40729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    }
4073bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    FunctionLiteral* value =
4074bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        ParseFunctionLiteral(name,
40751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             false,   // reserved words are allowed here
4076bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                             RelocInfo::kNoPosition,
40773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                             FunctionLiteral::ANONYMOUS_EXPRESSION,
4078bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                             CHECK_OK);
40793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Allow any number of parameters for compatibilty with JSC.
40809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    // Specification only allows zero parameters for get and one for set.
40813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return factory()->NewObjectLiteralProperty(is_getter, value);
4082bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  } else {
4083bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    ReportUnexpectedToken(next);
4084bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    *ok = false;
4085bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    return NULL;
4086bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
4087bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4088bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4089bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseObjectLiteral(bool* ok) {
4091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ObjectLiteral ::
4092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '{' (
4093bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  //       ((IdentifierName | String | Number) ':' AssignmentExpression)
4094bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  //     | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
4095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //    )*[','] '}'
4096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40973e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  ZoneList<ObjectLiteral::Property*>* properties =
4098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      new(zone()) ZoneList<ObjectLiteral::Property*>(4);
4099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int number_of_boilerplate_properties = 0;
410044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool has_function = false;
4101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ObjectLiteralPropertyChecker checker(this, top_scope_->language_mode());
41031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LBRACE, CHECK_OK);
41051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (peek() != Token::RBRACE) {
410780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (fni_ != NULL) fni_->Enter();
410880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Literal* key = NULL;
4110bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    Token::Value next = peek();
41111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
41121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Location of the property name token
41131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Scanner::Location loc = scanner().peek_location();
41141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4115bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    switch (next) {
41161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case Token::FUTURE_RESERVED_WORD:
41173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      case Token::FUTURE_STRICT_RESERVED_WORD:
4118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::IDENTIFIER: {
4119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_getter = false;
4120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_setter = false;
4121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Handle<String> id =
41223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
412380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        if (fni_ != NULL) fni_->PushLiteralName(id);
412480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4125bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        if ((is_getter || is_setter) && peek() != Token::COLON) {
41261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            // Update loc to point to the identifier
41271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            loc = scanner().peek_location();
4128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            ObjectLiteral::Property* property =
4129bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch                ParseObjectLiteralGetSet(is_getter, CHECK_OK);
4130bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch            if (IsBoilerplateProperty(property)) {
4131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              number_of_boilerplate_properties++;
4132bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch            }
41331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            // Validate the property.
41341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            checker.CheckProperty(property, loc, CHECK_OK);
41353e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu            properties->Add(property);
4136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
413780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
413880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen            if (fni_ != NULL) {
413980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen              fni_->Infer();
414080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen              fni_->Leave();
414180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen            }
4142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            continue;  // restart the while
4143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
4144bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        // Failed to parse as get/set property, so it's just a property
4145bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        // called "get" or "set".
41463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        key = factory()->NewLiteral(id);
4147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
4148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
4149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::STRING: {
4150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Consume(Token::STRING);
41519ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick        Handle<String> string = GetSymbol(CHECK_OK);
415280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen        if (fni_ != NULL) fni_->PushLiteralName(string);
4153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uint32_t index;
4154756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick        if (!string.is_null() && string->AsArrayIndex(&index)) {
41553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          key = factory()->NewNumberLiteral(index);
4156bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          break;
4157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
41583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        key = factory()->NewLiteral(string);
4159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
4160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
4161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case Token::NUMBER: {
4162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Consume(Token::NUMBER);
41639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block        ASSERT(scanner().is_literal_ascii());
41648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        double value = StringToDouble(isolate()->unicode_cache(),
41658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                      scanner().literal_ascii_string(),
41669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                                      ALLOW_HEX | ALLOW_OCTALS);
41673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        key = factory()->NewNumberLiteral(value);
4168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
4169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
4170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
4171bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        if (Token::IsKeyword(next)) {
4172bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          Consume(next);
41739ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick          Handle<String> string = GetSymbol(CHECK_OK);
41743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          key = factory()->NewLiteral(string);
4175bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        } else {
4176bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          // Unexpected token.
4177bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          Token::Value next = Next();
4178bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          ReportUnexpectedToken(next);
4179bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          *ok = false;
4180bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          return NULL;
4181bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        }
4182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::COLON, CHECK_OK);
4185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* value = ParseAssignmentExpression(true, CHECK_OK);
4186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ObjectLiteral::Property* property =
41883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        new(zone()) ObjectLiteral::Property(key, value, isolate());
4189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Mark top-level object literals that contain function literals and
41913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // pretenure the literal so it can be added as a constant function
41923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // property.
41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (top_scope_->DeclarationScope()->is_global_scope() &&
41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        value->AsFunctionLiteral() != NULL) {
419544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      has_function = true;
41963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      value->AsFunctionLiteral()->set_pretenure();
419744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
419844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
4200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
42011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Validate the property
42021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    checker.CheckProperty(property, loc, CHECK_OK);
42033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    properties->Add(property);
4204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // TODO(1240767): Consider allowing trailing comma.
4206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
420780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
420880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    if (fni_ != NULL) {
420980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      fni_->Infer();
421080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      fni_->Leave();
421180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
4212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RBRACE, CHECK_OK);
42141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computation of literal_index must happen before pre parse bailout.
42163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
4217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
421844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<FixedArray> constant_properties = isolate()->factory()->NewFixedArray(
421944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      number_of_boilerplate_properties * 2, TENURED);
42204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_simple = true;
42226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  bool fast_elements = true;
4223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int depth = 1;
42243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  BuildObjectLiteralConstantProperties(properties,
42254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                       constant_properties,
42264515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                       &is_simple,
42276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                       &fast_elements,
42284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke                                       &depth);
42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewObjectLiteral(constant_properties,
42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     properties,
42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     literal_index,
42323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     is_simple,
42333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     fast_elements,
42343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     depth,
42353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     has_function);
4236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
4240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!scanner().ScanRegExpPattern(seen_equal)) {
4241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Next();
4242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ReportMessage("unterminated_regexp", Vector<const char*>::empty());
4243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    *ok = false;
4244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return NULL;
4245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int literal_index = current_function_state_->NextMaterializedLiteralIndex();
4248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Handle<String> js_pattern = NextLiteralString(TENURED);
4250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  scanner().ScanRegExpFlags();
42519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  Handle<String> js_flags = NextLiteralString(TENURED);
4252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Next();
4253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index);
4255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
4259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Arguments ::
4260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '(' (AssignmentExpression)*[','] ')'
4261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4);
4263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::LPAREN, CHECK_OK);
4264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done = (peek() == Token::RPAREN);
4265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!done) {
4266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
42673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    result->Add(argument);
4268053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    if (result->length() > kMaxNumFunctionParameters) {
4269053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      ReportMessageAt(scanner().location(), "too_many_arguments",
4270053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block                      Vector<const char*>::empty());
4271053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      *ok = false;
4272053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block      return NULL;
4273053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    }
4274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    done = (peek() == Token::RPAREN);
4275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!done) Expect(Token::COMMA, CHECK_OK);
4276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::RPAREN, CHECK_OK);
42783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  return result;
4279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass SingletonLogger : public ParserRecorder {
42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual ~SingletonLogger() { }
42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Reset() { has_error_ = false; }
42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void LogFunction(int start,
42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int end,
42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int literals,
42923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           int properties,
42933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           LanguageMode mode) {
42943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!has_error_);
42953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    start_ = start;
42963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    end_ = end;
42973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    literals_ = literals;
42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    properties_ = properties;
42993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mode_ = mode;
43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Logs a symbol creation of a literal or identifier.
43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void LogUtf16Symbol(int start, Vector<const uc16> literal) { }
43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Logs an error message and marks the log as containing an error.
43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Further logging will be ignored, and ExtractData will return a vector
43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // representing the error only.
43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void LogMessage(int start,
43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          int end,
43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          const char* message,
43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          const char* argument_opt) {
43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    has_error_ = true;
43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    start_ = start;
43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    end_ = end;
43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    message_ = message;
43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    argument_opt_ = argument_opt;
43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual int function_position() { return 0; }
43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual int symbol_position() { return 0; }
43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual int symbol_ids() { return -1; }
43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual Vector<unsigned> ExtractData() {
43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Vector<unsigned>();
43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void PauseRecording() { }
43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual void ResumeRecording() { }
43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_error() { return has_error_; }
43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int start() { return start_; }
43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int end() { return end_; }
43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int literals() {
43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!has_error_);
43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return literals_;
43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties() {
43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!has_error_);
43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return properties_;
43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LanguageMode language_mode() {
43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!has_error_);
43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return mode_;
43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* message() {
43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(has_error_);
43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return message_;
43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* argument_opt() {
43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(has_error_);
43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return argument_opt_;
43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool has_error_;
43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int start_;
43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int end_;
43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For function entries.
43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int literals_;
43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int properties_;
43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LanguageMode mode_;
43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // For error messages.
43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* message_;
43703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* argument_opt_;
43713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
43723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochFunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
43753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              bool name_is_strict_reserved,
4376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              int function_token_position,
43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              FunctionLiteral::Type type,
4378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                              bool* ok) {
4379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Function ::
4380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
4381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Anonymous functions were passed either the empty symbol or a null
43833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // handle as the function name.  Remember if we were passed a non-empty
43843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // handle to decide whether to invoke function name inference.
43853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool should_infer_name = function_name.is_null();
43863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
43873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // We want a non-null handle as the function name.
43883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (should_infer_name) {
43893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    function_name = isolate()->factory()->empty_symbol();
4390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int num_parameters = 0;
439369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Function declarations are function scoped in normal mode, so they are
439469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // hoisted. In harmony block scoping mode they are block scoped, so they
439569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // are not hoisted.
43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scope* scope = (type == FunctionLiteral::DECLARATION && !is_extended_mode())
43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE)
43983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : NewScope(top_scope_, FUNCTION_SCOPE);
43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ZoneList<Statement*>* body = NULL;
44003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int materialized_literal_count = -1;
44013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int expected_property_count = -1;
44023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int handler_count = 0;
44038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  bool only_simple_this_property_assignments;
44048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<FixedArray> this_property_assignments;
44053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FunctionLiteral::ParameterFlag duplicate_parameters =
44063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FunctionLiteral::kNoDuplicateParameters;
44073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AstProperties ast_properties;
4408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parse function body.
44093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { FunctionState function_state(this, scope, isolate());
44103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    top_scope_->SetScopeName(function_name);
4411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //  FormalParameterList ::
4413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //    '(' (Identifier)*[','] ')'
4414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::LPAREN, CHECK_OK);
44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope->set_start_position(scanner().location().beg_pos);
4416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Scanner::Location name_loc = Scanner::Location::invalid();
4417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Scanner::Location dupe_loc = Scanner::Location::invalid();
4418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    Scanner::Location reserved_loc = Scanner::Location::invalid();
44191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool done = (peek() == Token::RPAREN);
4421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (!done) {
44223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool is_strict_reserved = false;
44231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      Handle<String> param_name =
44243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
44253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                              CHECK_OK);
44261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
44271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      // Store locations for possible future error reports.
44281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
44291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        name_loc = scanner().location();
44301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
44311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
44331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        dupe_loc = scanner().location();
44341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
44353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!reserved_loc.IsValid() && is_strict_reserved) {
44361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        reserved_loc = scanner().location();
44371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
44381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
44393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      top_scope_->DeclareParameter(param_name, VAR);
44403e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu      num_parameters++;
44411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (num_parameters > kMaxNumFunctionParameters) {
44421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ReportMessageAt(scanner().location(), "too_many_parameters",
44431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        Vector<const char*>::empty());
44441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        *ok = false;
44451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return NULL;
44461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
4447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      done = (peek() == Token::RPAREN);
4448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!done) Expect(Token::COMMA, CHECK_OK);
4449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::RPAREN, CHECK_OK);
4451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Expect(Token::LBRACE, CHECK_OK);
4453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we have a named function expression, we add a local variable
4455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // declaration to the body of the function with the name of the
4456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // function and let it refer to the function itself (closure).
4457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // NOTE: We create a proxy and resolve it here so that in the
4458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // future we can change the AST to only refer to VariableProxies
4459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // instead of Variables and Proxis as is the case now.
44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Variable* fvar = NULL;
44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Token::Value fvar_init_op = Token::INIT_CONST;
44623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (type == FunctionLiteral::NAMED_EXPRESSION) {
44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      VariableMode fvar_mode;
44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (is_extended_mode()) {
44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        fvar_mode = CONST_HARMONY;
44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        fvar_init_op = Token::INIT_CONST_HARMONY;
44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
44683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        fvar_mode = CONST;
44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      fvar =
44713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          top_scope_->DeclareFunctionVar(function_name, fvar_mode, factory());
44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Determine whether the function will be lazily compiled.
44753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // The heuristics are:
44763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // - It must not have been prohibited by the caller to Parse (some callers
44773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   need a full AST).
44783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // - The outer scope must be trivial (only global variables in scope).
44793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // - The function mustn't be a function expression with an open parenthesis
44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   before; we consider that a hint that the function will be called
44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   immediately, and it would be a waste of time to make it lazily
44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    //   compiled.
44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // These are all things we can know at this point, without looking at the
44843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // function itself.
4485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
4486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               top_scope_->outer_scope()->is_global_scope() &&
4487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               top_scope_->HasTrivialOuterContext() &&
44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               !parenthesized_function_);
4489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    parenthesized_function_ = false;  // The bit was set for this function only.
4490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
44913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_lazily_compiled) {
44923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int function_block_pos = scanner().location().beg_pos;
44933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      FunctionEntry entry;
44943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (pre_data_ != NULL) {
44953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If we have pre_data_, we use it to skip parsing the function body.
44963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the preparser data contains the information we need to construct the
44973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // lazy function.
44983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        entry = pre_data()->GetFunctionEntry(function_block_pos);
44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (entry.is_valid()) {
45003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (entry.end_pos() <= function_block_pos) {
45013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // End position greater than end of stream is safe, and hard
45023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            // to check.
45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ReportInvalidPreparseData(function_name, CHECK_OK);
45043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scanner().SeekForward(entry.end_pos() - 1);
45063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
45073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          scope->set_end_position(entry.end_pos());
45083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Expect(Token::RBRACE, CHECK_OK);
45093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          isolate()->counters()->total_preparse_skipped()->Increment(
45103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              scope->end_position() - function_block_pos);
45113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          materialized_literal_count = entry.literal_count();
45123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          expected_property_count = entry.property_count();
45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          top_scope_->SetLanguageMode(entry.language_mode());
45143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          only_simple_this_property_assignments = false;
45153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          this_property_assignments = isolate()->factory()->empty_fixed_array();
45163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
45173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          is_lazily_compiled = false;
45183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
45193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else {
45203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // With no preparser data, we partially parse the function, without
45213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // building an AST. This gathers the data needed to build a lazy
45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // function.
45233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        SingletonLogger logger;
45243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        preparser::PreParser::PreParseResult result =
45253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            LazyParseFunctionLiteral(&logger);
45263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (result == preparser::PreParser::kPreParseStackOverflow) {
45273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          // Propagate stack overflow.
45283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          stack_overflow_ = true;
45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          *ok = false;
45303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return NULL;
4531592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
45323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (logger.has_error()) {
45333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          const char* arg = logger.argument_opt();
45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Vector<const char*> args;
45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (arg != NULL) {
45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            args = Vector<const char*>(&arg, 1);
45373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ReportMessageAt(Scanner::Location(logger.start(), logger.end()),
45393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          logger.message(), args);
45403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          *ok = false;
45413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return NULL;
45423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
45433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        scope->set_end_position(logger.end());
45443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Expect(Token::RBRACE, CHECK_OK);
45453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        isolate()->counters()->total_preparse_skipped()->Increment(
45463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            scope->end_position() - function_block_pos);
45473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        materialized_literal_count = logger.literals();
45483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        expected_property_count = logger.properties();
45493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        top_scope_->SetLanguageMode(logger.language_mode());
45503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        only_simple_this_property_assignments = false;
45513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        this_property_assignments = isolate()->factory()->empty_fixed_array();
4552ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke      }
45533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
45543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
45553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!is_lazily_compiled) {
45563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      body = new(zone()) ZoneList<Statement*>(8);
45573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (fvar != NULL) {
45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        VariableProxy* fproxy =
45593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            top_scope_->NewUnresolved(factory(), function_name);
45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        fproxy->BindTo(fvar);
45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        body->Add(factory()->NewExpressionStatement(
45623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            factory()->NewAssignment(fvar_init_op,
45633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     fproxy,
45643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     factory()->NewThisFunction(),
45653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     RelocInfo::kNoPosition)));
45663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
45673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ParseSourceElements(body, Token::RBRACE, false, CHECK_OK);
45683e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
45693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      materialized_literal_count = function_state.materialized_literal_count();
45703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      expected_property_count = function_state.expected_property_count();
45713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      handler_count = function_state.handler_count();
4572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      only_simple_this_property_assignments =
45733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          function_state.only_simple_this_property_assignments();
45743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      this_property_assignments = function_state.this_property_assignments();
4575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
457680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      Expect(Token::RBRACE, CHECK_OK);
45773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      scope->set_end_position(scanner().location().end_pos);
4578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
45801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Validate strict mode.
45813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!top_scope_->is_classic_mode()) {
45823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (IsEvalOrArguments(function_name)) {
45833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int start_pos = scope->start_position();
45841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        int position = function_token_position != RelocInfo::kNoPosition
45851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            ? function_token_position
45861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            : (start_pos > 0 ? start_pos - 1 : start_pos);
45871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Scanner::Location location = Scanner::Location(position, start_pos);
45881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ReportMessageAt(location,
45891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        "strict_function_name", Vector<const char*>::empty());
45901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        *ok = false;
45911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return NULL;
45921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
45931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (name_loc.IsValid()) {
45941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ReportMessageAt(name_loc, "strict_param_name",
45951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        Vector<const char*>::empty());
45961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        *ok = false;
45971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return NULL;
45981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
45991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (dupe_loc.IsValid()) {
46001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ReportMessageAt(dupe_loc, "strict_param_dupe",
46011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        Vector<const char*>::empty());
46021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        *ok = false;
46031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return NULL;
46041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
46053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (name_is_strict_reserved) {
46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int start_pos = scope->start_position();
46071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        int position = function_token_position != RelocInfo::kNoPosition
46081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            ? function_token_position
46091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block            : (start_pos > 0 ? start_pos - 1 : start_pos);
46101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        Scanner::Location location = Scanner::Location(position, start_pos);
46111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ReportMessageAt(location, "strict_reserved_word",
46121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        Vector<const char*>::empty());
46131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        *ok = false;
46141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return NULL;
46151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
46161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      if (reserved_loc.IsValid()) {
46171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        ReportMessageAt(reserved_loc, "strict_reserved_word",
46181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        Vector<const char*>::empty());
46191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        *ok = false;
46201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        return NULL;
46211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      }
46223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      CheckOctalLiteral(scope->start_position(),
46233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        scope->end_position(),
46243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                        CHECK_OK);
46251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
46263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ast_properties = *factory()->visitor()->ast_properties();
46278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
46281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
46293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (is_extended_mode()) {
4630589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    CheckConflictingVarDeclarations(scope, CHECK_OK);
4631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
4632589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
46338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  FunctionLiteral* function_literal =
46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewFunctionLiteral(function_name,
46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    scope,
46363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    body,
46373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    materialized_literal_count,
46383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    expected_property_count,
46393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    handler_count,
46403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    only_simple_this_property_assignments,
46413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    this_property_assignments,
46423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    num_parameters,
46433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    duplicate_parameters,
46443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    type,
46453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    FunctionLiteral::kIsFunction);
46468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  function_literal->set_function_token_position(function_token_position);
46473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  function_literal->set_ast_properties(&ast_properties);
46486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
46493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
46508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return function_literal;
4651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochpreparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
46553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SingletonLogger* logger) {
46563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
46573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_EQ(Token::LBRACE, scanner().current_token());
46583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (reusable_preparser_ == NULL) {
46603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    intptr_t stack_limit = isolate()->stack_guard()->real_climit();
46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool do_allow_lazy = true;
46623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    reusable_preparser_ = new preparser::PreParser(&scanner_,
46633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   NULL,
46643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   stack_limit,
46653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   do_allow_lazy,
46663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   allow_natives_syntax_,
46673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                   allow_modules_);
46683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
46693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  preparser::PreParser::PreParseResult result =
46703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
46713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                logger);
46723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return result;
46733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
46743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::ParseV8Intrinsic(bool* ok) {
4677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // CallRuntime ::
4678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   '%' Identifier Arguments
4679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::MOD, CHECK_OK);
4681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> name = ParseIdentifier(CHECK_OK);
4682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
46830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
46840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (extension_ != NULL) {
4685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The extension structures are only accessible while parsing the
4686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // very first time not when reparsing because of lazy compilation.
46873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    top_scope_->DeclarationScope()->ForceEagerCompilation();
4688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = Runtime::FunctionForSymbol(name);
4691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check for built-in IS_VAR macro.
46930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (function != NULL &&
46940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      function->intrinsic_type == Runtime::RUNTIME &&
46950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      function->function_id == Runtime::kIS_VAR) {
46960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // %IS_VAR(x) evaluates to x if x is a variable,
46970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // leads to a parse error otherwise.  Could be implemented as an
46980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // inline function %_IS_VAR(x) to eliminate this special case.
46990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
47000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      return args->at(0);
47010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
4702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ReportMessage("unable_to_parse", Vector<const char*>::empty());
47030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      *ok = false;
4704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return NULL;
4705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Check that the expected number of arguments are being passed.
47090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (function != NULL &&
47100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      function->nargs != -1 &&
47110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      function->nargs != args->length()) {
47120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ReportMessage("illegal_access", Vector<const char*>::empty());
47130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    *ok = false;
47140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return NULL;
47156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
47166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
47170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // We have a valid intrinsics call or a call to a builtin.
47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewCallRuntime(name, function, args);
4719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool Parser::peek_any_identifier() {
47231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Token::Value next = peek();
47241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return next == Token::IDENTIFIER ||
47253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         next == Token::FUTURE_RESERVED_WORD ||
47263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         next == Token::FUTURE_STRICT_RESERVED_WORD;
47271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
47281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
47291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Parser::Consume(Token::Value token) {
4731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value next = Next();
4732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  USE(next);
4733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  USE(token);
4734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(next == token);
4735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Parser::Expect(Token::Value token, bool* ok) {
4739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value next = Next();
4740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (next == token) return;
4741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ReportUnexpectedToken(next);
4742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *ok = false;
4743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkebool Parser::Check(Token::Value token) {
47474515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  Token::Value next = peek();
47484515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (next == token) {
47494515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Consume(next);
47504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    return true;
47514515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
47524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  return false;
47534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
47544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
47554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
4756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Parser::ExpectSemicolon(bool* ok) {
4757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check for automatic semicolon insertion according to
4758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the rules given in ECMA-262, section 7.9, page 21.
4759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Token::Value tok = peek();
4760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (tok == Token::SEMICOLON) {
4761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Next();
4762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
4763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
47643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (scanner().HasAnyLineTerminatorBeforeNext() ||
4765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      tok == Token::RBRACE ||
4766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      tok == Token::EOS) {
4767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
4768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Expect(Token::SEMICOLON, ok);
4770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Parser::ExpectContextualKeyword(const char* keyword, bool* ok) {
47743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expect(Token::IDENTIFIER, ok);
47753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!*ok) return;
47763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<String> symbol = GetSymbol(ok);
47773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!*ok) return;
47783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!symbol->IsEqualTo(CStrVector(keyword))) {
47793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *ok = false;
47803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ReportUnexpectedToken(scanner().current_token());
47813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLiteral* Parser::GetLiteralUndefined() {
47863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewLiteral(isolate()->factory()->undefined_value());
4787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLiteral* Parser::GetLiteralTheHole() {
47913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewLiteral(isolate()->factory()->the_hole_value());
4792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Parses an identifier that is valid for the current scope, in particular it
47963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// fails on strict mode future reserved keywords in a strict scope.
4797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<String> Parser::ParseIdentifier(bool* ok) {
47983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!top_scope_->is_classic_mode()) {
47993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Expect(Token::IDENTIFIER, ok);
48003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (!Check(Token::IDENTIFIER)) {
48013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
48023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
48033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!*ok) return Handle<String>();
48043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return GetSymbol(ok);
48051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
48061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// Parses and identifier or a strict mode future reserved word, and indicate
48093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// whether it is strict mode future reserved.
48103fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<String> Parser::ParseIdentifierOrStrictReservedWord(
48113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool* is_strict_reserved, bool* ok) {
48123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  *is_strict_reserved = false;
48133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (!Check(Token::IDENTIFIER)) {
48143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
48153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    *is_strict_reserved = true;
48161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
4817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!*ok) return Handle<String>();
48189ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  return GetSymbol(ok);
4819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4821bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4822bb769b257e753aafcbd96767abb2abc645eaa20cBen MurdochHandle<String> Parser::ParseIdentifierName(bool* ok) {
4823bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  Token::Value next = Next();
48241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (next != Token::IDENTIFIER &&
48253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      next != Token::FUTURE_RESERVED_WORD &&
48263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      next != Token::FUTURE_STRICT_RESERVED_WORD &&
48273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      !Token::IsKeyword(next)) {
4828bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    ReportUnexpectedToken(next);
4829bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    *ok = false;
4830bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    return Handle<String>();
4831bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  }
48329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  return GetSymbol(ok);
4833bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch}
4834bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
4835bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
48363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Parser::MarkAsLValue(Expression* expression) {
48373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableProxy* proxy = expression != NULL
48383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ? expression->AsVariableProxy()
48393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : NULL;
48403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (proxy != NULL) proxy->MarkAsLValue();
48423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
48433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
48451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Checks LHS expression for assignment and prefix/postfix increment/decrement
48461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// in strict mode.
48471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Parser::CheckStrictModeLValue(Expression* expression,
48481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   const char* error,
48491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                   bool* ok) {
48503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!top_scope_->is_classic_mode());
48511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  VariableProxy* lhs = expression != NULL
48521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ? expression->AsVariableProxy()
48531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : NULL;
48541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
48561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ReportMessage(error, Vector<const char*>::empty());
48571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    *ok = false;
48581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
48591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
48601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Checks whether an octal literal was last seen between beg_pos and end_pos.
4863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If so, reports an error. Only called for strict mode.
48641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
4865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Scanner::Location octal = scanner().octal_position();
4866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (octal.IsValid() &&
4867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      beg_pos <= octal.beg_pos &&
4868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      octal.end_pos <= end_pos) {
4869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ReportMessageAt(octal, "strict_octal_literal",
48701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                    Vector<const char*>::empty());
48711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    scanner().clear_octal_position();
48721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    *ok = false;
48731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
48741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
48751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
48761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4878589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Declaration* decl = scope->CheckConflictingVarDeclarations();
4879589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (decl != NULL) {
4880589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // In harmony mode we treat conflicting variable bindinds as early
4881589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // errors. See ES5 16 for a definition of early errors.
4882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Handle<String> name = decl->proxy()->name();
4883589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
4884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    const char* elms[2] = { "Variable", *c_string };
4885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Vector<const char*> args(elms, 2);
4886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    int position = decl->proxy()->position();
4887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    Scanner::Location location = position == RelocInfo::kNoPosition
4888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        ? Scanner::Location::invalid()
4889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        : Scanner::Location(position, position + 1);
4890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    ReportMessageAt(location, "redeclaration", args);
4891589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    *ok = false;
4892589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
4893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
4894589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
4895589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
48963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch// This function reads an identifier name and determines whether or not it
48971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// is 'get' or 'set'.
48983fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHandle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
48993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                     bool* is_set,
49003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                     bool* ok) {
49013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> result = ParseIdentifierName(ok);
4902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!*ok) return Handle<String>();
49039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
49049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    const char* token = scanner().literal_ascii_string().start();
49059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    *is_get = strncmp(token, "get", 3) == 0;
49069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block    *is_set = !*is_get && strncmp(token, "set", 3) == 0;
4907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
49081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return result;
4909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
4913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Parser support
4914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Parser::TargetStackContainsLabel(Handle<String> label) {
4917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BreakableStatement* stat = t->node()->AsBreakableStatement();
4919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (stat != NULL && ContainsLabel(stat->labels(), label))
4920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
4921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
4923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockBreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
4927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool anonymous = label.is_null();
4928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    BreakableStatement* stat = t->node()->AsBreakableStatement();
4930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (stat == NULL) continue;
4931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if ((anonymous && stat->is_target_for_anonymous()) ||
4932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        (!anonymous && ContainsLabel(stat->labels(), label))) {
4933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RegisterTargetUse(stat->break_target(), t->previous());
4934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return stat;
4935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
4938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockIterationStatement* Parser::LookupContinueTarget(Handle<String> label,
4942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                 bool* ok) {
4943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool anonymous = label.is_null();
4944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
4945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IterationStatement* stat = t->node()->AsIterationStatement();
4946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (stat == NULL) continue;
4947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(stat->is_target_for_anonymous());
4949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (anonymous || ContainsLabel(stat->labels(), label)) {
4950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RegisterTargetUse(stat->continue_target(), t->previous());
4951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return stat;
4952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
4955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Parser::RegisterTargetUse(Label* target, Target* stop) {
4959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register that a break target found at the given stop in the
4960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // target stack has been used from the top of the target stack. Add
4961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the break target to any TargetCollectors passed on the stack.
4962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Target* t = target_stack_; t != stop; t = t->previous()) {
4963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TargetCollector* collector = t->node()->AsTargetCollector();
4964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (collector != NULL) collector->AddTarget(target);
4965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
4966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::NewThrowReferenceError(Handle<String> type) {
497044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
4971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       type, HandleVector<Object>(NULL, 0));
4972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::NewThrowSyntaxError(Handle<String> type,
4976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Handle<Object> first) {
4977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int argc = first.is_null() ? 0 : 1;
4978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector< Handle<Object> > arguments = HandleVector<Object>(&first, argc);
497944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NewThrowError(
498044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->MakeSyntaxError_symbol(), type, arguments);
4981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::NewThrowTypeError(Handle<String> type,
4985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Handle<Object> first,
4986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Handle<Object> second) {
4987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!first.is_null() && !second.is_null());
4988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> elements[] = { first, second };
4989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector< Handle<Object> > arguments =
4990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      HandleVector<Object>(elements, ARRAY_SIZE(elements));
499144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NewThrowError(
499244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->MakeTypeError_symbol(), type, arguments);
4993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
4994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockExpression* Parser::NewThrowError(Handle<String> constructor,
4997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Handle<String> type,
4998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  Vector< Handle<Object> > arguments) {
4999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int argc = arguments.length();
500044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<FixedArray> elements = isolate()->factory()->NewFixedArray(argc,
500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                                    TENURED);
5002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < argc; i++) {
5003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Handle<Object> element = arguments[i];
5004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!element.is_null()) {
50051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      elements->set(i, *element);
5006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
50083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<JSArray> array = isolate()->factory()->NewJSArrayWithElements(
50093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      elements, FAST_ELEMENTS, TENURED);
50101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
50123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  args->Add(factory()->NewLiteral(type));
50133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  args->Add(factory()->NewLiteral(array));
50143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CallRuntime* call_constructor =
50153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      factory()->NewCallRuntime(constructor, NULL, args);
50163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return factory()->NewThrow(call_constructor, scanner().location().beg_pos);
5017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
50194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke// ----------------------------------------------------------------------------
5020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Regular expressions
5021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpParser::RegExpParser(FlatStringReader* in,
5024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           Handle<String>* error,
5025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           bool multiline)
502644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(Isolate::Current()),
502744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      error_(error),
502844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      captures_(NULL),
502944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      in_(in),
503044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current_(kEndMarker),
503144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      next_pos_(0),
503244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      capture_count_(0),
503344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      has_more_(true),
503444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      multiline_(multiline),
503544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      simple_(false),
503644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      contains_anchor_(false),
503744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      is_scanned_for_captures_(false),
503844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      failed_(false) {
5039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Advance();
5040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 RegExpParser::Next() {
5044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (has_next()) {
5045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return in()->Get(next_pos_);
5046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return kEndMarker;
5048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpParser::Advance() {
5053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (next_pos_ < in()->length()) {
505444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    StackLimitCheck check(isolate());
5055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (check.HasOverflowed()) {
505644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ReportError(CStrVector(Isolate::kStackOverflowMessage));
505744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (isolate()->zone()->excess_allocation()) {
5058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ReportError(CStrVector("Regular expression too large"));
5059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
5060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current_ = in()->Get(next_pos_);
5061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      next_pos_++;
5062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current_ = kEndMarker;
5065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    has_more_ = false;
5066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpParser::Reset(int pos) {
5071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_pos_ = pos;
5072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
5073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpParser::Advance(int dist) {
5077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  next_pos_ += dist - 1;
5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Advance();
5079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpParser::simple() {
5083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return simple_;
5084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpTree* RegExpParser::ReportError(Vector<const char> message) {
5087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  failed_ = true;
508844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  *error_ = isolate()->factory()->NewStringFromAscii(message, NOT_TENURED);
5089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Zip to the end to make sure the no more input is read.
5090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_ = kEndMarker;
5091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  next_pos_ = in()->length();
5092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
5093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Pattern ::
5097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Disjunction
5098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpTree* RegExpParser::ParsePattern() {
5099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpTree* result = ParseDisjunction(CHECK_FAILED);
5100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!has_more());
5101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the result of parsing is a literal string atom, and it has the
5102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // same length as the input, then the atom is identical to the input.
5103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (result->IsAtom() && result->AsAtom()->length() == in()->length()) {
5104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    simple_ = true;
5105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
5107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Disjunction ::
5111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Alternative
5112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Alternative | Disjunction
5113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Alternative ::
5114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   [empty]
5115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Term Alternative
5116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Term ::
5117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Assertion
5118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Atom
5119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Atom Quantifier
5120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpTree* RegExpParser::ParseDisjunction() {
5121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Used to store current state while parsing subexpressions.
5122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpParserState initial_state(NULL, INITIAL, 0);
5123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpParserState* stored_state = &initial_state;
5124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cache the builder in a local variable for quick access.
5125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpBuilder* builder = initial_state.builder();
5126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
5127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (current()) {
5128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case kEndMarker:
5129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (stored_state->IsSubexpression()) {
5130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Inside a parenthesized group when hitting end of input.
5131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ReportError(CStrVector("Unterminated group") CHECK_FAILED);
5132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT_EQ(INITIAL, stored_state->group_type());
5134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Parsing completed successfully.
5135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return builder->ToRegExp();
5136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case ')': {
5137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!stored_state->IsSubexpression()) {
5138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
5139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT_NE(INITIAL, stored_state->group_type());
5141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // End disjunction parsing and convert builder content to new single
5144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // regexp atom.
5145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RegExpTree* body = builder->ToRegExp();
5146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int end_capture_index = captures_started();
5148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int capture_index = stored_state->capture_index();
5150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      SubexpressionType type = stored_state->group_type();
5151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Restore previous state.
5153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      stored_state = stored_state->previous_state();
5154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder = stored_state->builder();
5155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Build result of subexpression.
5157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (type == CAPTURE) {
51588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        RegExpCapture* capture = new(zone()) RegExpCapture(body, capture_index);
5159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        captures_->at(capture_index - 1) = capture;
5160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        body = capture;
5161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (type != GROUPING) {
5162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT(type == POSITIVE_LOOKAHEAD || type == NEGATIVE_LOOKAHEAD);
5163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        bool is_positive = (type == POSITIVE_LOOKAHEAD);
51648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        body = new(zone()) RegExpLookahead(body,
5165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   is_positive,
5166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   end_capture_index - capture_index,
5167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   capture_index);
5168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder->AddAtom(body);
5170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // For compatability with JSC and ES3, we allow quantifiers after
5171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // lookaheads, and break in all cases.
5172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '|': {
5175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder->NewAlternative();
5177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
5178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '*':
5180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '+':
5181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '?':
5182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return ReportError(CStrVector("Nothing to repeat"));
5183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '^': {
5184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (multiline_) {
5186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddAssertion(
51878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) RegExpAssertion(RegExpAssertion::START_OF_LINE));
5188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
5189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddAssertion(
51908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) RegExpAssertion(RegExpAssertion::START_OF_INPUT));
5191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        set_contains_anchor();
5192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
5194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '$': {
5196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RegExpAssertion::Type type =
5198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          multiline_ ? RegExpAssertion::END_OF_LINE :
5199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       RegExpAssertion::END_OF_INPUT;
52008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      builder->AddAssertion(new(zone()) RegExpAssertion(type));
5201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
5202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '.': {
5204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // everything except \x0a, \x0d, \u2028 and \u2029
5206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ZoneList<CharacterRange>* ranges =
5207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          new(zone()) ZoneList<CharacterRange>(2);
5208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CharacterRange::AddClassEscape('.', ranges);
52098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
5210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder->AddAtom(atom);
5211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '(': {
5214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      SubexpressionType type = CAPTURE;
5215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (current() == '?') {
5217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        switch (Next()) {
5218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case ':':
5219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            type = GROUPING;
5220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
5221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case '=':
5222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            type = POSITIVE_LOOKAHEAD;
5223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
5224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          case '!':
5225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            type = NEGATIVE_LOOKAHEAD;
5226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
5227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          default:
5228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            ReportError(CStrVector("Invalid group") CHECK_FAILED);
5229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
5230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
5233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (captures_ == NULL) {
5234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          captures_ = new(zone()) ZoneList<RegExpCapture*>(2);
5235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (captures_started() >= kMaxCaptures) {
5237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ReportError(CStrVector("Too many captures") CHECK_FAILED);
5238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        captures_->Add(NULL);
5240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Store current state and begin new disjunction parsing.
52428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      stored_state = new(zone()) RegExpParserState(stored_state,
5243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           type,
5244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           captures_started());
5245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder = stored_state->builder();
5246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      continue;
5247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '[': {
5249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
5250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder->AddAtom(atom);
5251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Atom ::
5254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   \ AtomEscape
5255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '\\':
5256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      switch (Next()) {
5257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case kEndMarker:
5258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return ReportError(CStrVector("\\ at end of pattern"));
5259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'b':
5260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddAssertion(
52628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) RegExpAssertion(RegExpAssertion::BOUNDARY));
5263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
5264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'B':
5265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddAssertion(
52678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            new(zone()) RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
5268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
5269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // AtomEscape ::
5270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      //   CharacterClassEscape
5271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      //
5272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // CharacterClassEscape :: one of
5273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      //   d D s S w W
5274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'd': case 'D': case 's': case 'S': case 'w': case 'W': {
5275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uc32 c = Next();
5276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        ZoneList<CharacterRange>* ranges =
5278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch            new(zone()) ZoneList<CharacterRange>(2);
5279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CharacterRange::AddClassEscape(c, ranges);
52808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        RegExpTree* atom = new(zone()) RegExpCharacterClass(ranges, false);
5281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddAtom(atom);
5282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '1': case '2': case '3': case '4': case '5': case '6':
5285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '7': case '8': case '9': {
5286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int index = 0;
5287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (ParseBackReferenceIndex(&index)) {
5288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          RegExpCapture* capture = NULL;
5289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (captures_ != NULL && index <= captures_->length()) {
5290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            capture = captures_->at(index - 1);
5291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
5292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (capture == NULL) {
5293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            builder->AddEmpty();
5294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            break;
5295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
52968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          RegExpTree* atom = new(zone()) RegExpBackReference(capture);
5297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder->AddAtom(atom);
5298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
5299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uc32 first_digit = Next();
5301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (first_digit == '8' || first_digit == '9') {
5302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Treat as identity escape
5303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder->AddCharacter(first_digit);
5304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Advance(2);
5305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
5306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // FALLTHROUGH
5309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '0': {
5310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
5311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uc32 octal = ParseOctalLiteral();
5312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter(octal);
5313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // ControlEscape :: one of
5316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      //   f n r t v
5317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'f':
5318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter('\f');
5320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'n':
5322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter('\n');
5324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'r':
5326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter('\r');
5328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 't':
5330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter('\t');
5332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'v':
5334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter('\v');
5336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'c': {
5338086aeeaae12517475c22695a200be45495516549Ben Murdoch        Advance();
5339086aeeaae12517475c22695a200be45495516549Ben Murdoch        uc32 controlLetter = Next();
5340086aeeaae12517475c22695a200be45495516549Ben Murdoch        // Special case if it is an ASCII letter.
5341086aeeaae12517475c22695a200be45495516549Ben Murdoch        // Convert lower case letters to uppercase.
5342086aeeaae12517475c22695a200be45495516549Ben Murdoch        uc32 letter = controlLetter & ~('a' ^ 'A');
5343086aeeaae12517475c22695a200be45495516549Ben Murdoch        if (letter < 'A' || 'Z' < letter) {
5344086aeeaae12517475c22695a200be45495516549Ben Murdoch          // controlLetter is not in range 'A'-'Z' or 'a'-'z'.
5345086aeeaae12517475c22695a200be45495516549Ben Murdoch          // This is outside the specification. We match JSC in
5346086aeeaae12517475c22695a200be45495516549Ben Murdoch          // reading the backslash as a literal character instead
5347086aeeaae12517475c22695a200be45495516549Ben Murdoch          // of as starting an escape.
5348086aeeaae12517475c22695a200be45495516549Ben Murdoch          builder->AddCharacter('\\');
5349086aeeaae12517475c22695a200be45495516549Ben Murdoch        } else {
5350086aeeaae12517475c22695a200be45495516549Ben Murdoch          Advance(2);
5351086aeeaae12517475c22695a200be45495516549Ben Murdoch          builder->AddCharacter(controlLetter & 0x1f);
5352086aeeaae12517475c22695a200be45495516549Ben Murdoch        }
5353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'x': {
5356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uc32 value;
5358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (ParseHexEscape(2, &value)) {
5359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder->AddCharacter(value);
5360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
5361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder->AddCharacter('x');
5362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'u': {
5366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uc32 value;
5368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (ParseHexEscape(4, &value)) {
5369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder->AddCharacter(value);
5370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
5371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          builder->AddCharacter('u');
5372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
5376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Identity escape.
5377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        builder->AddCharacter(Next());
5378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '{': {
5383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int dummy;
5384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (ParseIntervalQuantifier(&dummy, &dummy)) {
5385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
5386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // fallthrough
5388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
5390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      builder->AddCharacter(current());
5391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }  // end switch(current())
5394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int min;
5396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int max;
5397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (current()) {
5398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // QuantifierPrefix ::
5399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   *
5400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   +
5401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   ?
5402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   {
5403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '*':
5404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      min = 0;
5405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      max = RegExpTree::kInfinity;
5406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '+':
5409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      min = 1;
5410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      max = RegExpTree::kInfinity;
5411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '?':
5414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      min = 0;
5415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      max = 1;
5416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '{':
5419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (ParseIntervalQuantifier(&min, &max)) {
5420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (max < min) {
5421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          ReportError(CStrVector("numbers out of order in {} quantifier.")
5422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      CHECK_FAILED);
5423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
5426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
5427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
5429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      continue;
5430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5431e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    RegExpQuantifier::Type type = RegExpQuantifier::GREEDY;
5432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current() == '?') {
5433e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      type = RegExpQuantifier::NON_GREEDY;
5434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      Advance();
5435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    } else if (FLAG_regexp_possessive_quantifier && current() == '+') {
5436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      // FLAG_regexp_possessive_quantifier is a debug-only flag.
5437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      type = RegExpQuantifier::POSSESSIVE;
5438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    builder->AddQuantifierToAtom(min, max, type);
5441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
5446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Currently only used in an ASSERT.
5447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IsSpecialClassEscape(uc32 c) {
5448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (c) {
5449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'd': case 'D':
5450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 's': case 'S':
5451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'w': case 'W':
5452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
5453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
5454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
5455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
5458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// In order to know whether an escape is a backreference or not we have to scan
5461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the entire regexp and find the number of capturing parentheses.  However we
5462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// don't want to scan the regexp twice unless it is necessary.  This mini-parser
5463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is called when needed.  It can see the difference between capturing and
5464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// noncapturing parentheses and can skip character classes and backslash-escaped
5465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// characters.
5466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpParser::ScanForCaptures() {
5467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Start with captures started previous to current position
5468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int capture_count = captures_started();
5469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add count of captures after this position.
5470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int n;
5471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while ((n = current()) != kEndMarker) {
5472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (n) {
5474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '\\':
5475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
5476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '[': {
5478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int c;
5479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        while ((c = current()) != kEndMarker) {
5480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          Advance();
5481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          if (c == '\\') {
5482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Advance();
5483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } else {
5484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            if (c == ']') break;
5485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
5486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case '(':
5490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (current() != '?') capture_count++;
5491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  capture_count_ = capture_count;
5495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  is_scanned_for_captures_ = true;
5496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpParser::ParseBackReferenceIndex(int* index_out) {
5500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ('\\', current());
5501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT('1' <= Next() && Next() <= '9');
5502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to parse a decimal literal that is no greater than the total number
5503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of left capturing parentheses in the input.
5504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int start = position();
5505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int value = Next() - '0';
5506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance(2);
5507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
5508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = current();
5509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsDecimalDigit(c)) {
5510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = 10 * value + (c - '0');
5511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (value > kMaxCaptures) {
5512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Reset(start);
5513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
5514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
5517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (value > captures_started()) {
5521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!is_scanned_for_captures_) {
5522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int saved_position = position();
5523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ScanForCaptures();
5524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Reset(saved_position);
5525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value > capture_count_) {
5527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Reset(start);
5528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
5529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *index_out = value;
5532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
5533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// QuantifierPrefix ::
5537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   { DecimalDigits }
5538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   { DecimalDigits , }
5539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   { DecimalDigits , DecimalDigits }
5540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
5541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns true if parsing succeeds, and set the min_out and max_out
5542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// values. Values are truncated to RegExpTree::kInfinity if they overflow.
5543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
5544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(current(), '{');
5545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int start = position();
5546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
5547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int min = 0;
5548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!IsDecimalDigit(current())) {
5549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Reset(start);
5550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
5551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (IsDecimalDigit(current())) {
5553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int next = current() - '0';
5554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (min > (RegExpTree::kInfinity - next) / 10) {
5555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Overflow. Skip past remaining decimal digits and return -1.
5556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      do {
5557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
5558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } while (IsDecimalDigit(current()));
5559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      min = RegExpTree::kInfinity;
5560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
5561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    min = 10 * min + next;
5563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int max = 0;
5566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (current() == '}') {
5567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    max = min;
5568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (current() == ',') {
5570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current() == '}') {
5572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      max = RegExpTree::kInfinity;
5573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
5575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (IsDecimalDigit(current())) {
5576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        int next = current() - '0';
5577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (max > (RegExpTree::kInfinity - next) / 10) {
5578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          do {
5579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            Advance();
5580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          } while (IsDecimalDigit(current()));
5581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          max = RegExpTree::kInfinity;
5582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          break;
5583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
5584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        max = 10 * max + next;
5585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance();
5586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (current() != '}') {
5588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Reset(start);
5589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return false;
5590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Reset(start);
5595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
5596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *min_out = min;
5598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *max_out = max;
5599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
5600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 RegExpParser::ParseOctalLiteral() {
5604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT('0' <= current() && current() <= '7');
5605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For compatibility with some other browsers (not all), we parse
5606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // up to three octal digits with a value below 256.
5607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 value = current() - '0';
5608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
5609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ('0' <= current() && current() <= '7') {
5610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    value = value * 8 + current() - '0';
5611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (value < 32 && '0' <= current() && current() <= '7') {
5613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      value = value * 8 + current() - '0';
5614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return value;
5618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpParser::ParseHexEscape(int length, uc32 *value) {
5622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int start = position();
5623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 val = 0;
5624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done = false;
5625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; !done; i++) {
5626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 c = current();
5627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int d = HexValue(c);
5628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (d < 0) {
5629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Reset(start);
5630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
5631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    val = val * 16 + d;
5633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i == length - 1) {
5635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      done = true;
5636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  *value = val;
5639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
5640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuc32 RegExpParser::ParseClassCharacterEscape() {
5644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(current() == '\\');
5645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(has_next() && !IsSpecialClassEscape(Next()));
5646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
5647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (current()) {
5648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'b':
5649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return '\b';
5651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // ControlEscape :: one of
5652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //   f n r t v
5653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'f':
5654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return '\f';
5656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'n':
5657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return '\n';
5659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'r':
5660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return '\r';
5662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 't':
5663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return '\t';
5665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'v':
5666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return '\v';
5668086aeeaae12517475c22695a200be45495516549Ben Murdoch    case 'c': {
5669086aeeaae12517475c22695a200be45495516549Ben Murdoch      uc32 controlLetter = Next();
5670086aeeaae12517475c22695a200be45495516549Ben Murdoch      uc32 letter = controlLetter & ~('A' ^ 'a');
5671086aeeaae12517475c22695a200be45495516549Ben Murdoch      // For compatibility with JSC, inside a character class
5672086aeeaae12517475c22695a200be45495516549Ben Murdoch      // we also accept digits and underscore as control characters.
5673086aeeaae12517475c22695a200be45495516549Ben Murdoch      if ((controlLetter >= '0' && controlLetter <= '9') ||
5674086aeeaae12517475c22695a200be45495516549Ben Murdoch          controlLetter == '_' ||
5675086aeeaae12517475c22695a200be45495516549Ben Murdoch          (letter >= 'A' && letter <= 'Z')) {
5676086aeeaae12517475c22695a200be45495516549Ben Murdoch        Advance(2);
5677086aeeaae12517475c22695a200be45495516549Ben Murdoch        // Control letters mapped to ASCII control characters in the range
5678086aeeaae12517475c22695a200be45495516549Ben Murdoch        // 0x00-0x1f.
5679086aeeaae12517475c22695a200be45495516549Ben Murdoch        return controlLetter & 0x1f;
5680086aeeaae12517475c22695a200be45495516549Ben Murdoch      }
5681086aeeaae12517475c22695a200be45495516549Ben Murdoch      // We match JSC in reading the backslash as a literal
5682086aeeaae12517475c22695a200be45495516549Ben Murdoch      // character instead of as starting an escape.
5683086aeeaae12517475c22695a200be45495516549Ben Murdoch      return '\\';
5684086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
5685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '0': case '1': case '2': case '3': case '4': case '5':
5686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case '6': case '7':
5687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // For compatibility, we interpret a decimal escape that isn't
5688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // a back reference (and therefore either \0 or not valid according
5689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // to the specification) as a 1..3 digit octal character code.
5690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return ParseOctalLiteral();
5691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'x': {
5692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 value;
5694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (ParseHexEscape(2, &value)) {
5695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return value;
5696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // If \x is not followed by a two-digit hexadecimal, treat it
5698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // as an identity escape.
5699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 'x';
5700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 'u': {
5702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 value;
5704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (ParseHexEscape(4, &value)) {
5705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return value;
5706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // If \u is not followed by a four-digit hexadecimal, treat it
5708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // as an identity escape.
5709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 'u';
5710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: {
5712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Extended identity escape. We accept any character that hasn't
5713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // been matched by a more specific case, not just the subset required
5714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // by the ECMAScript specification.
5715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc32 result = current();
5716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return result;
5718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 0;
5721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
5725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(0, *char_class);
5726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc32 first = current();
5727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (first == '\\') {
5728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    switch (Next()) {
5729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
5730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        *char_class = Next();
5731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Advance(2);
5732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return CharacterRange::Singleton(0);  // Return dummy value.
5733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      case kEndMarker:
5735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return ReportError(CStrVector("\\ at end of pattern"));
5736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      default:
5737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
5738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return CharacterRange::Singleton(c);
5739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return CharacterRange::Singleton(first);
5743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic const uc16 kNoCharClass = 0;
5748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Adds range or pre-defined character class to character ranges.
5750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// If char_class is not kInvalidClass, it's interpreted as a class
5751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// escape (i.e., 's' means whitespace, from '\s').
5752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic inline void AddRangeOrEscape(ZoneList<CharacterRange>* ranges,
5753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    uc16 char_class,
5754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                    CharacterRange range) {
5755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (char_class != kNoCharClass) {
5756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CharacterRange::AddClassEscape(char_class, ranges);
5757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
5758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ranges->Add(range);
5759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
5760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
5761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpTree* RegExpParser::ParseCharacterClass() {
5764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* kUnterminated = "Unterminated character class";
5765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const char* kRangeOutOfOrder = "Range out of order in character class";
5766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT_EQ(current(), '[');
5768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
5769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_negated = false;
5770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (current() == '^') {
5771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    is_negated = true;
5772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Advance();
5773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneList<CharacterRange>* ranges = new(zone()) ZoneList<CharacterRange>(2);
5775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (has_more() && current() != ']') {
5776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    uc16 char_class = kNoCharClass;
5777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
5778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current() == '-') {
5779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Advance();
5780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (current() == kEndMarker) {
5781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // If we reach the end we break out of the loop and let the
5782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // following code report an error.
5783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (current() == ']') {
5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddRangeOrEscape(ranges, char_class, first);
5786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ranges->Add(CharacterRange::Singleton('-'));
5787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
5788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      uc16 char_class_2 = kNoCharClass;
5790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      CharacterRange next = ParseClassAtom(&char_class_2 CHECK_FAILED);
5791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (char_class != kNoCharClass || char_class_2 != kNoCharClass) {
5792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // Either end is an escaped character class. Treat the '-' verbatim.
5793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddRangeOrEscape(ranges, char_class, first);
5794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ranges->Add(CharacterRange::Singleton('-'));
5795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        AddRangeOrEscape(ranges, char_class_2, next);
5796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        continue;
5797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (first.from() > next.to()) {
5799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
5800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
5801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ranges->Add(CharacterRange::Range(first.from(), next.to()));
5802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
5803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AddRangeOrEscape(ranges, char_class, first);
5804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!has_more()) {
5807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
5808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Advance();
5810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (ranges->length() == 0) {
5811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ranges->Add(CharacterRange::Everything());
5812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    is_negated = !is_negated;
5813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
58148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return new(zone()) RegExpCharacterClass(ranges, is_negated);
5815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
5819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The Parser interface.
5820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockParserMessage::~ParserMessage() {
5822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < args().length(); i++)
5823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DeleteArray(args()[i]);
5824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DeleteArray(args().start());
5825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScriptDataImpl::~ScriptDataImpl() {
58299ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  if (owns_store_) store_.Dispose();
5830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ScriptDataImpl::Length() {
5834f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return store_.length() * sizeof(unsigned);
5835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5838f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeconst char* ScriptDataImpl::Data() {
5839f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return reinterpret_cast<const char*>(store_.start());
5840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5843e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkebool ScriptDataImpl::HasError() {
5844e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return has_error();
5845e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
5846e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
5847e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
58480d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid ScriptDataImpl::Initialize() {
58490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Prepares state for use.
58508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (store_.length() >= PreparseDataConstants::kHeaderSize) {
58518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    function_index_ = PreparseDataConstants::kHeaderSize;
58528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    int symbol_data_offset = PreparseDataConstants::kHeaderSize
58538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        + store_[PreparseDataConstants::kFunctionsSizeOffset];
58540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (store_.length() > symbol_data_offset) {
58550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
58560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    } else {
58570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      // Partial preparse causes no symbol information.
58580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      symbol_data_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
58590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    }
58600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    symbol_data_end_ = reinterpret_cast<byte*>(&store_[0] + store_.length());
58610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
58620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
58630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
58640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
58650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenint ScriptDataImpl::ReadNumber(byte** source) {
58660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Reads a number from symbol_data_ in base 128. The most significant
58670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // bit marks that there are more digits.
58680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // If the first byte is 0x80 (kNumberTerminator), it would normally
58690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // represent a leading zero. Since that is useless, and therefore won't
58700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // appear as the first digit of any actual value, it is used to
58710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // mark the end of the input stream.
58720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  byte* data = *source;
58730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (data >= symbol_data_end_) return -1;
58740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  byte input = *data;
58758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  if (input == PreparseDataConstants::kNumberTerminator) {
58760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    // End of stream marker.
58770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return -1;
58780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
58790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int result = input & 0x7f;
58800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  data++;
58810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  while ((input & 0x80u) != 0) {
58820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (data >= symbol_data_end_) return -1;
58830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    input = *data;
58840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    result = (result << 7) | (input & 0x7f);
58850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    data++;
58860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
58870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *source = data;
58880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return result;
58890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
58900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
58910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
58928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Create a Scanner for the preparser to use as input, and preparse the source.
58933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic ScriptDataImpl* DoPreParse(Utf16CharacterStream* source,
58943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  int flags,
58953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ParserRecorder* recorder) {
589644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
58973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HistogramTimerScope timer(isolate->counters()->pre_parse());
58983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Scanner scanner(isolate->unicode_cache());
58993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scanner.SetHarmonyScoping(FLAG_harmony_scoping);
59009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  scanner.Initialize(source);
590144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t stack_limit = isolate->stack_guard()->real_climit();
59023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  preparser::PreParser::PreParseResult result =
59033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      preparser::PreParser::PreParseProgram(&scanner,
59043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            recorder,
59053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            flags,
59063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            stack_limit);
59073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (result == preparser::PreParser::kPreParseStackOverflow) {
590844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate->StackOverflow();
59098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    return NULL;
59108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  }
59118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
59128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Extract the accumulated data from the recorder as a single
59138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // contiguous vector that we are responsible for disposing.
59148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  Vector<unsigned> store = recorder->ExtractData();
59158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return new ScriptDataImpl(store);
59168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
59178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
59188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
59193e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// Preparse, but only collect data that is immediately useful,
59203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu// even if the preparser data is only used once.
59213ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochScriptDataImpl* ParserApi::PartialPreParse(Handle<String> source,
592269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           v8::Extension* extension,
59233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           int flags) {
59243e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  bool allow_lazy = FLAG_lazy && (extension == NULL);
59253e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (!allow_lazy) {
59263e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    // Partial preparsing is only about lazily compiled functions.
59273e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    // If we don't allow lazy compilation, the log data will be empty.
59283e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu    return NULL;
59293e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  }
59303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  flags |= kAllowLazy;
59313e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  PartialParserRecorder recorder;
59323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int source_length = source->length();
59333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (source->IsExternalTwoByteString()) {
59343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalTwoByteStringUtf16CharacterStream stream(
59353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Handle<ExternalTwoByteString>::cast(source), 0, source_length);
59363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return DoPreParse(&stream, flags, &recorder);
59373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
59383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GenericStringUtf16CharacterStream stream(source, 0, source_length);
59393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return DoPreParse(&stream, flags, &recorder);
59403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
59413e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu}
59423e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
59433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu
59443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochScriptDataImpl* ParserApi::PreParse(Utf16CharacterStream* source,
594569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                    v8::Extension* extension,
59463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int flags) {
5947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Script> no_script;
59483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_lazy && (extension == NULL)) {
59493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    flags |= kAllowLazy;
59503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
59513e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  CompleteParserRecorder recorder;
59523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return DoPreParse(source, flags, &recorder);
5953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhubool RegExpParser::ParseRegExp(FlatStringReader* input,
59573e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                               bool multiline,
59583e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                               RegExpCompileData* result) {
5959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(result != NULL);
5960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpParser parser(input, &result->error, multiline);
5961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpTree* tree = parser.ParsePattern();
5962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (parser.failed()) {
5963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(tree == NULL);
5964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!result->error.is_null());
5965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
5966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(tree != NULL);
5967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(result->error.is_null());
5968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result->tree = tree;
5969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int capture_count = parser.captures_started();
5970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result->simple = tree->IsAtom() && parser.simple() && capture_count == 0;
5971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result->contains_anchor = parser.contains_anchor();
5972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result->capture_count = capture_count;
5973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
5974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !parser.failed();
5975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
5976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
5979f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ASSERT(info->function() == NULL);
5980f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  FunctionLiteral* result = NULL;
5981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Handle<Script> script = info->script();
59823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((parsing_flags & kLanguageModeMask) == CLASSIC_MODE);
59833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info->is_native() && FLAG_harmony_scoping) {
59843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Harmony scoping is requested.
59853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    parsing_flags |= EXTENDED_MODE;
59863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
59873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info->is_native() && FLAG_harmony_modules) {
59883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    parsing_flags |= kAllowModules;
59893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
59903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_allow_natives_syntax || info->is_native()) {
59913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We require %identifier(..) syntax.
59923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    parsing_flags |= kAllowNativesSyntax;
59933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5994f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (info->is_lazy()) {
59953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!info->is_eval());
59963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Parser parser(script, parsing_flags, NULL, NULL);
59973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (info->shared_info()->is_function()) {
59983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = parser.ParseLazy(info);
59993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
60003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = parser.ParseProgram(info);
60013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
60024515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  } else {
6003f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    ScriptDataImpl* pre_data = info->pre_parse_data();
60043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Parser parser(script, parsing_flags, info->extension(), pre_data);
6005f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    if (pre_data != NULL && pre_data->has_error()) {
6006f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      Scanner::Location loc = pre_data->MessageLocation();
6007f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      const char* message = pre_data->BuildMessage();
6008f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      Vector<const char*> args = pre_data->BuildArgs();
6009f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      parser.ReportMessageAt(loc, message, args);
6010f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      DeleteArray(message);
6011f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      for (int i = 0; i < args.length(); i++) {
6012f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch        DeleteArray(args[i]);
6013f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      }
6014f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      DeleteArray(args.start());
601544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(info->isolate()->has_pending_exception());
6016f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    } else {
60173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      result = parser.ParseProgram(info);
6018f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    }
60194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  }
6020f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  info->SetFunction(result);
6021f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  return (result != NULL);
6022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
6023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
6025