• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "ast.h"
31 #include "parser.h"
32 #include "scopes.h"
33 #include "string-stream.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 
39 VariableProxySentinel VariableProxySentinel::this_proxy_(true);
40 VariableProxySentinel VariableProxySentinel::identifier_proxy_(false);
41 ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_;
42 Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0);
43 Call Call::sentinel_(NULL, NULL, 0);
44 
45 
46 // ----------------------------------------------------------------------------
47 // All the Accept member functions for each syntax tree node type.
48 
49 #define DECL_ACCEPT(type)                \
50   void type::Accept(AstVisitor* v) {        \
51     if (v->CheckStackOverflow()) return; \
52     v->Visit##type(this);                \
53   }
AST_NODE_LIST(DECL_ACCEPT)54 AST_NODE_LIST(DECL_ACCEPT)
55 #undef DECL_ACCEPT
56 
57 
58 // ----------------------------------------------------------------------------
59 // Implementation of other node functionality.
60 
61 VariableProxy::VariableProxy(Handle<String> name,
62                              bool is_this,
63                              bool inside_with)
64   : name_(name),
65     var_(NULL),
66     is_this_(is_this),
67     inside_with_(inside_with) {
68   // names must be canonicalized for fast equality checks
69   ASSERT(name->IsSymbol());
70   // at least one access, otherwise no need for a VariableProxy
71   var_uses_.RecordRead(1);
72 }
73 
74 
VariableProxy(bool is_this)75 VariableProxy::VariableProxy(bool is_this)
76   : is_this_(is_this) {
77 }
78 
79 
BindTo(Variable * var)80 void VariableProxy::BindTo(Variable* var) {
81   ASSERT(var_ == NULL);  // must be bound only once
82   ASSERT(var != NULL);  // must bind
83   ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
84   // Ideally CONST-ness should match. However, this is very hard to achieve
85   // because we don't know the exact semantics of conflicting (const and
86   // non-const) multiple variable declarations, const vars introduced via
87   // eval() etc.  Const-ness and variable declarations are a complete mess
88   // in JS. Sigh...
89   var_ = var;
90   var->var_uses()->RecordUses(&var_uses_);
91   var->obj_uses()->RecordUses(&obj_uses_);
92 }
93 
94 
binary_op() const95 Token::Value Assignment::binary_op() const {
96   switch (op_) {
97     case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
98     case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
99     case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
100     case Token::ASSIGN_SHL: return Token::SHL;
101     case Token::ASSIGN_SAR: return Token::SAR;
102     case Token::ASSIGN_SHR: return Token::SHR;
103     case Token::ASSIGN_ADD: return Token::ADD;
104     case Token::ASSIGN_SUB: return Token::SUB;
105     case Token::ASSIGN_MUL: return Token::MUL;
106     case Token::ASSIGN_DIV: return Token::DIV;
107     case Token::ASSIGN_MOD: return Token::MOD;
108     default: UNREACHABLE();
109   }
110   return Token::ILLEGAL;
111 }
112 
113 
AllowsLazyCompilation()114 bool FunctionLiteral::AllowsLazyCompilation() {
115   return scope()->AllowsLazyCompilation();
116 }
117 
118 
Property(Literal * key,Expression * value)119 ObjectLiteral::Property::Property(Literal* key, Expression* value) {
120   key_ = key;
121   value_ = value;
122   Object* k = *key->handle();
123   if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
124     kind_ = PROTOTYPE;
125   } else if (value_->AsMaterializedLiteral() != NULL) {
126     kind_ = MATERIALIZED_LITERAL;
127   } else if (value_->AsLiteral() != NULL) {
128     kind_ = CONSTANT;
129   } else {
130     kind_ = COMPUTED;
131   }
132 }
133 
134 
Property(bool is_getter,FunctionLiteral * value)135 ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
136   key_ = new Literal(value->name());
137   value_ = value;
138   kind_ = is_getter ? GETTER : SETTER;
139 }
140 
141 
IsCompileTimeValue()142 bool ObjectLiteral::Property::IsCompileTimeValue() {
143   return kind_ == CONSTANT ||
144       (kind_ == MATERIALIZED_LITERAL &&
145        CompileTimeValue::IsCompileTimeValue(value_));
146 }
147 
148 
AddTarget(BreakTarget * target)149 void TargetCollector::AddTarget(BreakTarget* target) {
150   // Add the label to the collector, but discard duplicates.
151   int length = targets_->length();
152   for (int i = 0; i < length; i++) {
153     if (targets_->at(i) == target) return;
154   }
155   targets_->Add(target);
156 }
157 
158 
159 // ----------------------------------------------------------------------------
160 // Implementation of AstVisitor
161 
162 
VisitDeclarations(ZoneList<Declaration * > * declarations)163 void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
164   for (int i = 0; i < declarations->length(); i++) {
165     Visit(declarations->at(i));
166   }
167 }
168 
169 
VisitStatements(ZoneList<Statement * > * statements)170 void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
171   for (int i = 0; i < statements->length(); i++) {
172     Visit(statements->at(i));
173   }
174 }
175 
176 
VisitExpressions(ZoneList<Expression * > * expressions)177 void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
178   for (int i = 0; i < expressions->length(); i++) {
179     // The variable statement visiting code may pass NULL expressions
180     // to this code. Maybe this should be handled by introducing an
181     // undefined expression or literal?  Revisit this code if this
182     // changes
183     Expression* expression = expressions->at(i);
184     if (expression != NULL) Visit(expression);
185   }
186 }
187 
188 
189 // ----------------------------------------------------------------------------
190 // Regular expressions
191 
192 #define MAKE_ACCEPT(Name)                                            \
193   void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) {   \
194     return visitor->Visit##Name(this, data);                         \
195   }
196 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
197 #undef MAKE_ACCEPT
198 
199 #define MAKE_TYPE_CASE(Name)                                         \
200   RegExp##Name* RegExpTree::As##Name() {                             \
201     return NULL;                                                     \
202   }                                                                  \
203   bool RegExpTree::Is##Name() { return false; }
204 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
205 #undef MAKE_TYPE_CASE
206 
207 #define MAKE_TYPE_CASE(Name)                                        \
208   RegExp##Name* RegExp##Name::As##Name() {                          \
209     return this;                                                    \
210   }                                                                 \
211   bool RegExp##Name::Is##Name() { return true; }
212 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
213 #undef MAKE_TYPE_CASE
214 
215 RegExpEmpty RegExpEmpty::kInstance;
216 
217 
ListCaptureRegisters(ZoneList<RegExpTree * > * children)218 static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
219   Interval result = Interval::Empty();
220   for (int i = 0; i < children->length(); i++)
221     result = result.Union(children->at(i)->CaptureRegisters());
222   return result;
223 }
224 
225 
CaptureRegisters()226 Interval RegExpAlternative::CaptureRegisters() {
227   return ListCaptureRegisters(nodes());
228 }
229 
230 
CaptureRegisters()231 Interval RegExpDisjunction::CaptureRegisters() {
232   return ListCaptureRegisters(alternatives());
233 }
234 
235 
CaptureRegisters()236 Interval RegExpLookahead::CaptureRegisters() {
237   return body()->CaptureRegisters();
238 }
239 
240 
CaptureRegisters()241 Interval RegExpCapture::CaptureRegisters() {
242   Interval self(StartRegister(index()), EndRegister(index()));
243   return self.Union(body()->CaptureRegisters());
244 }
245 
246 
CaptureRegisters()247 Interval RegExpQuantifier::CaptureRegisters() {
248   return body()->CaptureRegisters();
249 }
250 
251 
IsAnchored()252 bool RegExpAssertion::IsAnchored() {
253   return type() == RegExpAssertion::START_OF_INPUT;
254 }
255 
256 
IsAnchored()257 bool RegExpAlternative::IsAnchored() {
258   ZoneList<RegExpTree*>* nodes = this->nodes();
259   for (int i = 0; i < nodes->length(); i++) {
260     RegExpTree* node = nodes->at(i);
261     if (node->IsAnchored()) { return true; }
262     if (node->max_match() > 0) { return false; }
263   }
264   return false;
265 }
266 
267 
IsAnchored()268 bool RegExpDisjunction::IsAnchored() {
269   ZoneList<RegExpTree*>* alternatives = this->alternatives();
270   for (int i = 0; i < alternatives->length(); i++) {
271     if (!alternatives->at(i)->IsAnchored())
272       return false;
273   }
274   return true;
275 }
276 
277 
IsAnchored()278 bool RegExpLookahead::IsAnchored() {
279   return is_positive() && body()->IsAnchored();
280 }
281 
282 
IsAnchored()283 bool RegExpCapture::IsAnchored() {
284   return body()->IsAnchored();
285 }
286 
287 
288 // Convert regular expression trees to a simple sexp representation.
289 // This representation should be different from the input grammar
290 // in as many cases as possible, to make it more difficult for incorrect
291 // parses to look as correct ones which is likely if the input and
292 // output formats are alike.
293 class RegExpUnparser: public RegExpVisitor {
294  public:
295   RegExpUnparser();
296   void VisitCharacterRange(CharacterRange that);
ToString()297   SmartPointer<const char> ToString() { return stream_.ToCString(); }
298 #define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
299   FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
300 #undef MAKE_CASE
301  private:
stream()302   StringStream* stream() { return &stream_; }
303   HeapStringAllocator alloc_;
304   StringStream stream_;
305 };
306 
307 
RegExpUnparser()308 RegExpUnparser::RegExpUnparser() : stream_(&alloc_) {
309 }
310 
311 
VisitDisjunction(RegExpDisjunction * that,void * data)312 void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
313   stream()->Add("(|");
314   for (int i = 0; i <  that->alternatives()->length(); i++) {
315     stream()->Add(" ");
316     that->alternatives()->at(i)->Accept(this, data);
317   }
318   stream()->Add(")");
319   return NULL;
320 }
321 
322 
VisitAlternative(RegExpAlternative * that,void * data)323 void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
324   stream()->Add("(:");
325   for (int i = 0; i <  that->nodes()->length(); i++) {
326     stream()->Add(" ");
327     that->nodes()->at(i)->Accept(this, data);
328   }
329   stream()->Add(")");
330   return NULL;
331 }
332 
333 
VisitCharacterRange(CharacterRange that)334 void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
335   stream()->Add("%k", that.from());
336   if (!that.IsSingleton()) {
337     stream()->Add("-%k", that.to());
338   }
339 }
340 
341 
342 
VisitCharacterClass(RegExpCharacterClass * that,void * data)343 void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
344                                           void* data) {
345   if (that->is_negated())
346     stream()->Add("^");
347   stream()->Add("[");
348   for (int i = 0; i < that->ranges()->length(); i++) {
349     if (i > 0) stream()->Add(" ");
350     VisitCharacterRange(that->ranges()->at(i));
351   }
352   stream()->Add("]");
353   return NULL;
354 }
355 
356 
VisitAssertion(RegExpAssertion * that,void * data)357 void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
358   switch (that->type()) {
359     case RegExpAssertion::START_OF_INPUT:
360       stream()->Add("@^i");
361       break;
362     case RegExpAssertion::END_OF_INPUT:
363       stream()->Add("@$i");
364       break;
365     case RegExpAssertion::START_OF_LINE:
366       stream()->Add("@^l");
367       break;
368     case RegExpAssertion::END_OF_LINE:
369       stream()->Add("@$l");
370        break;
371     case RegExpAssertion::BOUNDARY:
372       stream()->Add("@b");
373       break;
374     case RegExpAssertion::NON_BOUNDARY:
375       stream()->Add("@B");
376       break;
377   }
378   return NULL;
379 }
380 
381 
VisitAtom(RegExpAtom * that,void * data)382 void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
383   stream()->Add("'");
384   Vector<const uc16> chardata = that->data();
385   for (int i = 0; i < chardata.length(); i++) {
386     stream()->Add("%k", chardata[i]);
387   }
388   stream()->Add("'");
389   return NULL;
390 }
391 
392 
VisitText(RegExpText * that,void * data)393 void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
394   if (that->elements()->length() == 1) {
395     that->elements()->at(0).data.u_atom->Accept(this, data);
396   } else {
397     stream()->Add("(!");
398     for (int i = 0; i < that->elements()->length(); i++) {
399       stream()->Add(" ");
400       that->elements()->at(i).data.u_atom->Accept(this, data);
401     }
402     stream()->Add(")");
403   }
404   return NULL;
405 }
406 
407 
VisitQuantifier(RegExpQuantifier * that,void * data)408 void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
409   stream()->Add("(# %i ", that->min());
410   if (that->max() == RegExpTree::kInfinity) {
411     stream()->Add("- ");
412   } else {
413     stream()->Add("%i ", that->max());
414   }
415   stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
416   that->body()->Accept(this, data);
417   stream()->Add(")");
418   return NULL;
419 }
420 
421 
VisitCapture(RegExpCapture * that,void * data)422 void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
423   stream()->Add("(^ ");
424   that->body()->Accept(this, data);
425   stream()->Add(")");
426   return NULL;
427 }
428 
429 
VisitLookahead(RegExpLookahead * that,void * data)430 void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
431   stream()->Add("(-> ");
432   stream()->Add(that->is_positive() ? "+ " : "- ");
433   that->body()->Accept(this, data);
434   stream()->Add(")");
435   return NULL;
436 }
437 
438 
VisitBackReference(RegExpBackReference * that,void * data)439 void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
440                                          void* data) {
441   stream()->Add("(<- %i)", that->index());
442   return NULL;
443 }
444 
445 
VisitEmpty(RegExpEmpty * that,void * data)446 void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
447   stream()->Put('%');
448   return NULL;
449 }
450 
451 
ToString()452 SmartPointer<const char> RegExpTree::ToString() {
453   RegExpUnparser unparser;
454   Accept(&unparser, NULL);
455   return unparser.ToString();
456 }
457 
458 
RegExpDisjunction(ZoneList<RegExpTree * > * alternatives)459 RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
460     : alternatives_(alternatives) {
461   ASSERT(alternatives->length() > 1);
462   RegExpTree* first_alternative = alternatives->at(0);
463   min_match_ = first_alternative->min_match();
464   max_match_ = first_alternative->max_match();
465   for (int i = 1; i < alternatives->length(); i++) {
466     RegExpTree* alternative = alternatives->at(i);
467     min_match_ = Min(min_match_, alternative->min_match());
468     max_match_ = Max(max_match_, alternative->max_match());
469   }
470 }
471 
472 
RegExpAlternative(ZoneList<RegExpTree * > * nodes)473 RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
474     : nodes_(nodes) {
475   ASSERT(nodes->length() > 1);
476   min_match_ = 0;
477   max_match_ = 0;
478   for (int i = 0; i < nodes->length(); i++) {
479     RegExpTree* node = nodes->at(i);
480     min_match_ += node->min_match();
481     int node_max_match = node->max_match();
482     if (kInfinity - max_match_ < node_max_match) {
483       max_match_ = kInfinity;
484     } else {
485       max_match_ += node->max_match();
486     }
487   }
488 }
489 
490 
491 } }  // namespace v8::internal
492