Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(562)

Side by Side Diff: src/parser.cc

Issue 197653002: Move ParseAssignmentExpression to ParserBase. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 // Implementation of Parser 430 // Implementation of Parser
431 431
432 bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const { 432 bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
433 return identifier.is_identical_to( 433 return identifier.is_identical_to(
434 parser_->isolate()->factory()->eval_string()) || 434 parser_->isolate()->factory()->eval_string()) ||
435 identifier.is_identical_to( 435 identifier.is_identical_to(
436 parser_->isolate()->factory()->arguments_string()); 436 parser_->isolate()->factory()->arguments_string());
437 } 437 }
438 438
439 439
440 bool ParserTraits::IsThisProperty(Expression* expression) {
441 ASSERT(expression != NULL);
442 Property* property = expression->AsProperty();
443 return property != NULL &&
444 property->obj()->AsVariableProxy() != NULL &&
445 property->obj()->AsVariableProxy()->is_this();
446 }
447
448
449 void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
450 Expression* right) {
451 ASSERT(left != NULL);
452 if (left->AsProperty() != NULL &&
453 right->AsFunctionLiteral() != NULL) {
454 right->AsFunctionLiteral()->set_pretenure();
455 }
456 }
457
458
459 Expression* ParserTraits::ValidateAssignmentLeftHandSide(
460 Expression* expression) const {
461 ASSERT(expression != NULL);
462 if (!expression->IsValidLeftHandSide()) {
463 Handle<String> message =
464 parser_->isolate()->factory()->invalid_lhs_in_assignment_string();
465 expression = parser_->NewThrowReferenceError(message);
466 }
467 return expression;
468 }
469
470
471 Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) {
472 VariableProxy* proxy = expression != NULL
473 ? expression->AsVariableProxy()
474 : NULL;
475 if (proxy != NULL) proxy->MarkAsLValue();
476 return expression;
477 }
478
479
480 void ParserTraits::CheckStrictModeLValue(Expression* expression,
481 bool* ok) {
482 VariableProxy* lhs = expression != NULL
483 ? expression->AsVariableProxy()
484 : NULL;
485 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
486 parser_->ReportMessage("strict_eval_arguments",
487 Vector<const char*>::empty());
488 *ok = false;
489 }
490 }
491
492
440 void ParserTraits::ReportMessageAt(Scanner::Location source_location, 493 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
441 const char* message, 494 const char* message,
442 Vector<const char*> args) { 495 Vector<const char*> args) {
443 if (parser_->stack_overflow()) { 496 if (parser_->stack_overflow()) {
444 // Suppress the error message (syntax error or such) in the presence of a 497 // Suppress the error message (syntax error or such) in the presence of a
445 // stack overflow. The isolate allows only one pending exception at at time 498 // stack overflow. The isolate allows only one pending exception at at time
446 // and we want to report the stack overflow later. 499 // and we want to report the stack overflow later.
447 return; 500 return;
448 } 501 }
449 MessageLocation location(parser_->script_, 502 MessageLocation location(parser_->script_,
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 } 612 }
560 613
561 614
562 Literal* ParserTraits::GetLiteralTheHole( 615 Literal* ParserTraits::GetLiteralTheHole(
563 int position, AstNodeFactory<AstConstructionVisitor>* factory) { 616 int position, AstNodeFactory<AstConstructionVisitor>* factory) {
564 return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(), 617 return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
565 RelocInfo::kNoPosition); 618 RelocInfo::kNoPosition);
566 } 619 }
567 620
568 621
569 Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
570 return parser_->ParseAssignmentExpression(accept_IN, ok);
571 }
572
573
574 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) { 622 Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
575 return parser_->ParseV8Intrinsic(ok); 623 return parser_->ParseV8Intrinsic(ok);
576 } 624 }
577 625
578 626
579 FunctionLiteral* ParserTraits::ParseFunctionLiteral( 627 FunctionLiteral* ParserTraits::ParseFunctionLiteral(
580 Handle<String> name, 628 Handle<String> name,
581 Scanner::Location function_name_location, 629 Scanner::Location function_name_location,
582 bool name_is_strict_reserved, 630 bool name_is_strict_reserved,
583 bool is_generator, 631 bool is_generator,
584 int function_token_position, 632 int function_token_position,
585 FunctionLiteral::FunctionType type, 633 FunctionLiteral::FunctionType type,
586 bool* ok) { 634 bool* ok) {
587 return parser_->ParseFunctionLiteral(name, function_name_location, 635 return parser_->ParseFunctionLiteral(name, function_name_location,
588 name_is_strict_reserved, is_generator, 636 name_is_strict_reserved, is_generator,
589 function_token_position, type, ok); 637 function_token_position, type, ok);
590 } 638 }
591 639
592 640
641 Expression* ParserTraits::ParseYieldExpression(bool* ok) {
642 return parser_->ParseYieldExpression(ok);
643 }
644
645
646 Expression* ParserTraits::ParseConditionalExpression(bool accept_IN, bool* ok) {
647 return parser_->ParseConditionalExpression(accept_IN, ok);
648 }
649
650
593 Parser::Parser(CompilationInfo* info) 651 Parser::Parser(CompilationInfo* info)
594 : ParserBase<ParserTraits>(&scanner_, 652 : ParserBase<ParserTraits>(&scanner_,
595 info->isolate()->stack_guard()->real_climit(), 653 info->isolate()->stack_guard()->real_climit(),
596 info->extension(), 654 info->extension(),
597 info->zone(), 655 info->zone(),
598 this), 656 this),
599 isolate_(info->isolate()), 657 isolate_(info->isolate()),
600 symbol_cache_(0, info->zone()), 658 symbol_cache_(0, info->zone()),
601 script_(info->script()), 659 script_(info->script()),
602 scanner_(isolate_->unicode_cache()), 660 scanner_(isolate_->unicode_cache()),
(...skipping 2267 matching lines...) Expand 10 before | Expand all | Expand 10 after
2870 result->set_scope(for_scope); 2928 result->set_scope(for_scope);
2871 loop->Initialize(NULL, cond, next, body); 2929 loop->Initialize(NULL, cond, next, body);
2872 return result; 2930 return result;
2873 } else { 2931 } else {
2874 loop->Initialize(init, cond, next, body); 2932 loop->Initialize(init, cond, next, body);
2875 return loop; 2933 return loop;
2876 } 2934 }
2877 } 2935 }
2878 2936
2879 2937
2880 // Precedence = 2
2881 Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
2882 // AssignmentExpression ::
2883 // ConditionalExpression
2884 // YieldExpression
2885 // LeftHandSideExpression AssignmentOperator AssignmentExpression
2886
2887 if (peek() == Token::YIELD && is_generator()) {
2888 return ParseYieldExpression(ok);
2889 }
2890
2891 if (fni_ != NULL) fni_->Enter();
2892 Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
2893
2894 if (!Token::IsAssignmentOp(peek())) {
2895 if (fni_ != NULL) fni_->Leave();
2896 // Parsed conditional expression only (no assignment).
2897 return expression;
2898 }
2899
2900 // Signal a reference error if the expression is an invalid left-hand
2901 // side expression. We could report this as a syntax error here but
2902 // for compatibility with JSC we choose to report the error at
2903 // runtime.
2904 // TODO(ES5): Should change parsing for spec conformance.
2905 if (expression == NULL || !expression->IsValidLeftHandSide()) {
2906 Handle<String> message =
2907 isolate()->factory()->invalid_lhs_in_assignment_string();
2908 expression = NewThrowReferenceError(message);
2909 }
2910
2911 if (strict_mode() == STRICT) {
2912 // Assignment to eval or arguments is disallowed in strict mode.
2913 CheckStrictModeLValue(expression, CHECK_OK);
2914 }
2915 MarkAsLValue(expression);
2916
2917 Token::Value op = Next(); // Get assignment operator.
2918 int pos = position();
2919 Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
2920
2921 // TODO(1231235): We try to estimate the set of properties set by
2922 // constructors. We define a new property whenever there is an
2923 // assignment to a property of 'this'. We should probably only add
2924 // properties if we haven't seen them before. Otherwise we'll
2925 // probably overestimate the number of properties.
2926 Property* property = expression ? expression->AsProperty() : NULL;
2927 if (op == Token::ASSIGN &&
2928 property != NULL &&
2929 property->obj()->AsVariableProxy() != NULL &&
2930 property->obj()->AsVariableProxy()->is_this()) {
2931 function_state_->AddProperty();
2932 }
2933
2934 // If we assign a function literal to a property we pretenure the
2935 // literal so it can be added as a constant function property.
2936 if (property != NULL && right->AsFunctionLiteral() != NULL) {
2937 right->AsFunctionLiteral()->set_pretenure();
2938 }
2939
2940 if (fni_ != NULL) {
2941 // Check if the right hand side is a call to avoid inferring a
2942 // name if we're dealing with "a = function(){...}();"-like
2943 // expression.
2944 if ((op == Token::INIT_VAR
2945 || op == Token::INIT_CONST_LEGACY
2946 || op == Token::ASSIGN)
2947 && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
2948 fni_->Infer();
2949 } else {
2950 fni_->RemoveLastFunction();
2951 }
2952 fni_->Leave();
2953 }
2954
2955 return factory()->NewAssignment(op, expression, right, pos);
2956 }
2957
2958
2959 Expression* Parser::ParseYieldExpression(bool* ok) { 2938 Expression* Parser::ParseYieldExpression(bool* ok) {
2960 // YieldExpression :: 2939 // YieldExpression ::
2961 // 'yield' '*'? AssignmentExpression 2940 // 'yield' '*'? AssignmentExpression
2962 int pos = peek_position(); 2941 int pos = peek_position();
2963 Expect(Token::YIELD, CHECK_OK); 2942 Expect(Token::YIELD, CHECK_OK);
2964 Yield::Kind kind = 2943 Yield::Kind kind =
2965 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND; 2944 Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
2966 Expression* generator_object = factory()->NewVariableProxy( 2945 Expression* generator_object = factory()->NewVariableProxy(
2967 function_state_->generator_object_variable()); 2946 function_state_->generator_object_variable());
2968 Expression* expression = ParseAssignmentExpression(false, CHECK_OK); 2947 Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 if (expression == NULL || !expression->IsValidLeftHandSide()) { 3156 if (expression == NULL || !expression->IsValidLeftHandSide()) {
3178 Handle<String> message = 3157 Handle<String> message =
3179 isolate()->factory()->invalid_lhs_in_prefix_op_string(); 3158 isolate()->factory()->invalid_lhs_in_prefix_op_string();
3180 expression = NewThrowReferenceError(message); 3159 expression = NewThrowReferenceError(message);
3181 } 3160 }
3182 3161
3183 if (strict_mode() == STRICT) { 3162 if (strict_mode() == STRICT) {
3184 // Prefix expression operand in strict mode may not be eval or arguments. 3163 // Prefix expression operand in strict mode may not be eval or arguments.
3185 CheckStrictModeLValue(expression, CHECK_OK); 3164 CheckStrictModeLValue(expression, CHECK_OK);
3186 } 3165 }
3187 MarkAsLValue(expression); 3166 MarkExpressionAsLValue(expression);
3188 3167
3189 return factory()->NewCountOperation(op, 3168 return factory()->NewCountOperation(op,
3190 true /* prefix */, 3169 true /* prefix */,
3191 expression, 3170 expression,
3192 position()); 3171 position());
3193 3172
3194 } else { 3173 } else {
3195 return ParsePostfixExpression(ok); 3174 return ParsePostfixExpression(ok);
3196 } 3175 }
3197 } 3176 }
(...skipping 13 matching lines...) Expand all
3211 if (expression == NULL || !expression->IsValidLeftHandSide()) { 3190 if (expression == NULL || !expression->IsValidLeftHandSide()) {
3212 Handle<String> message = 3191 Handle<String> message =
3213 isolate()->factory()->invalid_lhs_in_postfix_op_string(); 3192 isolate()->factory()->invalid_lhs_in_postfix_op_string();
3214 expression = NewThrowReferenceError(message); 3193 expression = NewThrowReferenceError(message);
3215 } 3194 }
3216 3195
3217 if (strict_mode() == STRICT) { 3196 if (strict_mode() == STRICT) {
3218 // Postfix expression operand in strict mode may not be eval or arguments. 3197 // Postfix expression operand in strict mode may not be eval or arguments.
3219 CheckStrictModeLValue(expression, CHECK_OK); 3198 CheckStrictModeLValue(expression, CHECK_OK);
3220 } 3199 }
3221 MarkAsLValue(expression); 3200 MarkExpressionAsLValue(expression);
3222 3201
3223 Token::Value next = Next(); 3202 Token::Value next = Next();
3224 expression = 3203 expression =
3225 factory()->NewCountOperation(next, 3204 factory()->NewCountOperation(next,
3226 false /* postfix */, 3205 false /* postfix */,
3227 expression, 3206 expression,
3228 position()); 3207 position());
3229 } 3208 }
3230 return expression; 3209 return expression;
3231 } 3210 }
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
3967 return factory()->NewCallRuntime(name, function, args, pos); 3946 return factory()->NewCallRuntime(name, function, args, pos);
3968 } 3947 }
3969 3948
3970 3949
3971 Literal* Parser::GetLiteralUndefined(int position) { 3950 Literal* Parser::GetLiteralUndefined(int position) {
3972 return factory()->NewLiteral( 3951 return factory()->NewLiteral(
3973 isolate()->factory()->undefined_value(), position); 3952 isolate()->factory()->undefined_value(), position);
3974 } 3953 }
3975 3954
3976 3955
3977 void Parser::MarkAsLValue(Expression* expression) {
3978 VariableProxy* proxy = expression != NULL
3979 ? expression->AsVariableProxy()
3980 : NULL;
3981
3982 if (proxy != NULL) proxy->MarkAsLValue();
3983 }
3984
3985
3986 // Checks LHS expression for assignment and prefix/postfix increment/decrement
3987 // in strict mode.
3988 void Parser::CheckStrictModeLValue(Expression* expression,
3989 bool* ok) {
3990 ASSERT(strict_mode() == STRICT);
3991 VariableProxy* lhs = expression != NULL
3992 ? expression->AsVariableProxy()
3993 : NULL;
3994
3995 if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
3996 ReportMessage("strict_eval_arguments", Vector<const char*>::empty());
3997 *ok = false;
3998 }
3999 }
4000
4001
4002 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { 3956 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4003 Declaration* decl = scope->CheckConflictingVarDeclarations(); 3957 Declaration* decl = scope->CheckConflictingVarDeclarations();
4004 if (decl != NULL) { 3958 if (decl != NULL) {
4005 // In harmony mode we treat conflicting variable bindinds as early 3959 // In harmony mode we treat conflicting variable bindinds as early
4006 // errors. See ES5 16 for a definition of early errors. 3960 // errors. See ES5 16 for a definition of early errors.
4007 Handle<String> name = decl->proxy()->name(); 3961 Handle<String> name = decl->proxy()->name();
4008 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS); 3962 SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
4009 const char* elms[2] = { "Variable", c_string.get() }; 3963 const char* elms[2] = { "Variable", c_string.get() };
4010 Vector<const char*> args(elms, 2); 3964 Vector<const char*> args(elms, 2);
4011 int position = decl->proxy()->position(); 3965 int position = decl->proxy()->position();
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
5075 ASSERT(info()->isolate()->has_pending_exception()); 5029 ASSERT(info()->isolate()->has_pending_exception());
5076 } else { 5030 } else {
5077 result = ParseProgram(); 5031 result = ParseProgram();
5078 } 5032 }
5079 } 5033 }
5080 info()->SetFunction(result); 5034 info()->SetFunction(result);
5081 return (result != NULL); 5035 return (result != NULL);
5082 } 5036 }
5083 5037
5084 } } // namespace v8::internal 5038 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698