OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
7 | 7 |
8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 | 94 |
95 #define CHECK_OK_CUSTOM(x, ...) ok); \ | 95 #define CHECK_OK_CUSTOM(x, ...) ok); \ |
96 if (!*ok) return impl()->x(__VA_ARGS__); \ | 96 if (!*ok) return impl()->x(__VA_ARGS__); \ |
97 ((void)0 | 97 ((void)0 |
98 #define DUMMY ) // to make indentation work | 98 #define DUMMY ) // to make indentation work |
99 #undef DUMMY | 99 #undef DUMMY |
100 | 100 |
101 // Used in functions where the return type is ExpressionT. | 101 // Used in functions where the return type is ExpressionT. |
102 #define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression) | 102 #define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression) |
103 | 103 |
| 104 #define CHECK_OK_VOID ok); \ |
| 105 if (!*ok) return; \ |
| 106 ((void)0 |
| 107 #define DUMMY ) // to make indentation work |
| 108 #undef DUMMY |
| 109 |
104 // Common base class template shared between parser and pre-parser. | 110 // Common base class template shared between parser and pre-parser. |
105 // The Impl parameter is the actual class of the parser/pre-parser, | 111 // The Impl parameter is the actual class of the parser/pre-parser, |
106 // following the Curiously Recurring Template Pattern (CRTP). | 112 // following the Curiously Recurring Template Pattern (CRTP). |
107 // The structure of the parser objects is roughly the following: | 113 // The structure of the parser objects is roughly the following: |
108 // | 114 // |
109 // // A structure template containing type definitions, needed to | 115 // // A structure template containing type definitions, needed to |
110 // // avoid a cyclic dependency. | 116 // // avoid a cyclic dependency. |
111 // template <typename Impl> | 117 // template <typename Impl> |
112 // struct ParserTypes; | 118 // struct ParserTypes; |
113 // | 119 // |
(...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 StatementT ParseFunctionDeclaration(bool* ok); | 1222 StatementT ParseFunctionDeclaration(bool* ok); |
1217 StatementT ParseHoistableDeclaration(ZoneList<const AstRawString*>* names, | 1223 StatementT ParseHoistableDeclaration(ZoneList<const AstRawString*>* names, |
1218 bool default_export, bool* ok); | 1224 bool default_export, bool* ok); |
1219 StatementT ParseHoistableDeclaration(int pos, ParseFunctionFlags flags, | 1225 StatementT ParseHoistableDeclaration(int pos, ParseFunctionFlags flags, |
1220 ZoneList<const AstRawString*>* names, | 1226 ZoneList<const AstRawString*>* names, |
1221 bool default_export, bool* ok); | 1227 bool default_export, bool* ok); |
1222 StatementT ParseClassDeclaration(ZoneList<const AstRawString*>* names, | 1228 StatementT ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
1223 bool default_export, bool* ok); | 1229 bool default_export, bool* ok); |
1224 StatementT ParseNativeDeclaration(bool* ok); | 1230 StatementT ParseNativeDeclaration(bool* ok); |
1225 | 1231 |
| 1232 // Consumes the ending }. |
| 1233 void ParseFunctionBody(StatementListT result, IdentifierT function_name, |
| 1234 int pos, const FormalParametersT& parameters, |
| 1235 FunctionKind kind, |
| 1236 FunctionLiteral::FunctionType function_type, bool* ok); |
| 1237 |
1226 // Under some circumstances, we allow preparsing to abort if the preparsed | 1238 // Under some circumstances, we allow preparsing to abort if the preparsed |
1227 // function is "long and trivial", and fully parse instead. Our current | 1239 // function is "long and trivial", and fully parse instead. Our current |
1228 // definition of "long and trivial" is: | 1240 // definition of "long and trivial" is: |
1229 // - over kLazyParseTrialLimit statements | 1241 // - over kLazyParseTrialLimit statements |
1230 // - all starting with an identifier (i.e., no if, for, while, etc.) | 1242 // - all starting with an identifier (i.e., no if, for, while, etc.) |
1231 static const int kLazyParseTrialLimit = 200; | 1243 static const int kLazyParseTrialLimit = 200; |
1232 | 1244 |
1233 // TODO(nikolaos, marja): The first argument should not really be passed | 1245 // TODO(nikolaos, marja): The first argument should not really be passed |
1234 // by value. The method is expected to add the parsed statements to the | 1246 // by value. The method is expected to add the parsed statements to the |
1235 // list. This works because in the case of the parser, StatementListT is | 1247 // list. This works because in the case of the parser, StatementListT is |
(...skipping 2642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3878 *ok = false; | 3890 *ok = false; |
3879 impl()->ReportUnexpectedToken(scanner()->current_token()); | 3891 impl()->ReportUnexpectedToken(scanner()->current_token()); |
3880 return impl()->NullStatement(); | 3892 return impl()->NullStatement(); |
3881 } | 3893 } |
3882 Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement)); | 3894 Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement)); |
3883 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; | 3895 ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; |
3884 return ParseHoistableDeclaration(pos, flags, names, default_export, ok); | 3896 return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
3885 } | 3897 } |
3886 | 3898 |
3887 template <typename Impl> | 3899 template <typename Impl> |
| 3900 void ParserBase<Impl>::ParseFunctionBody( |
| 3901 typename ParserBase<Impl>::StatementListT result, IdentifierT function_name, |
| 3902 int pos, const FormalParametersT& parameters, FunctionKind kind, |
| 3903 FunctionLiteral::FunctionType function_type, bool* ok) { |
| 3904 static const int kFunctionNameAssignmentIndex = 0; |
| 3905 if (function_type == FunctionLiteral::kNamedExpression) { |
| 3906 DCHECK(!impl()->IsEmptyIdentifier(function_name)); |
| 3907 // If we have a named function expression, we add a local variable |
| 3908 // declaration to the body of the function with the name of the |
| 3909 // function and let it refer to the function itself (closure). |
| 3910 // Not having parsed the function body, the language mode may still change, |
| 3911 // so we reserve a spot and create the actual const assignment later. |
| 3912 DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); |
| 3913 result->Add(impl()->NullStatement(), zone()); |
| 3914 } |
| 3915 |
| 3916 DeclarationScope* function_scope = scope()->AsDeclarationScope(); |
| 3917 DeclarationScope* inner_scope = function_scope; |
| 3918 BlockT inner_block = impl()->NullBlock(); |
| 3919 |
| 3920 StatementListT body = result; |
| 3921 if (!parameters.is_simple) { |
| 3922 inner_scope = NewVarblockScope(); |
| 3923 inner_scope->set_start_position(scanner()->location().beg_pos); |
| 3924 inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); |
| 3925 inner_block->set_scope(inner_scope); |
| 3926 body = inner_block->statements(); |
| 3927 } |
| 3928 |
| 3929 { |
| 3930 BlockState block_state(&scope_state_, inner_scope); |
| 3931 |
| 3932 if (IsGeneratorFunction(kind)) { |
| 3933 impl()->ParseAndRewriteGeneratorFunctionBody(pos, kind, body, ok); |
| 3934 } else if (IsAsyncFunction(kind)) { |
| 3935 const bool accept_IN = true; |
| 3936 ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal, |
| 3937 accept_IN, pos, CHECK_OK_VOID); |
| 3938 } else { |
| 3939 ParseStatementList(body, Token::RBRACE, CHECK_OK_VOID); |
| 3940 } |
| 3941 |
| 3942 if (IsDerivedConstructor(kind)) { |
| 3943 body->Add(factory()->NewReturnStatement(impl()->ThisExpression(), |
| 3944 kNoSourcePosition), |
| 3945 zone()); |
| 3946 } |
| 3947 } |
| 3948 |
| 3949 Expect(Token::RBRACE, CHECK_OK_VOID); |
| 3950 scope()->set_end_position(scanner()->location().end_pos); |
| 3951 |
| 3952 if (!parameters.is_simple) { |
| 3953 DCHECK_NOT_NULL(inner_scope); |
| 3954 DCHECK_EQ(function_scope, scope()); |
| 3955 DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
| 3956 impl()->SetLanguageMode(function_scope, inner_scope->language_mode()); |
| 3957 BlockT init_block = |
| 3958 impl()->BuildParameterInitializationBlock(parameters, CHECK_OK_VOID); |
| 3959 |
| 3960 if (is_sloppy(inner_scope->language_mode())) { |
| 3961 impl()->InsertSloppyBlockFunctionVarBindings(inner_scope); |
| 3962 } |
| 3963 |
| 3964 // TODO(littledan): Merge the two rejection blocks into one |
| 3965 if (IsAsyncFunction(kind)) { |
| 3966 init_block = impl()->BuildRejectPromiseOnException(init_block); |
| 3967 } |
| 3968 |
| 3969 inner_scope->set_end_position(scanner()->location().end_pos); |
| 3970 if (inner_scope->FinalizeBlockScope() != nullptr) { |
| 3971 impl()->CheckConflictingVarDeclarations(inner_scope, CHECK_OK_VOID); |
| 3972 impl()->InsertShadowingVarBindingInitializers(inner_block); |
| 3973 } |
| 3974 inner_scope = nullptr; |
| 3975 |
| 3976 result->Add(init_block, zone()); |
| 3977 result->Add(inner_block, zone()); |
| 3978 } else { |
| 3979 DCHECK_EQ(inner_scope, function_scope); |
| 3980 if (is_sloppy(function_scope->language_mode())) { |
| 3981 impl()->InsertSloppyBlockFunctionVarBindings(function_scope); |
| 3982 } |
| 3983 } |
| 3984 |
| 3985 if (!IsArrowFunction(kind)) { |
| 3986 // Declare arguments after parsing the function since lexical 'arguments' |
| 3987 // masks the arguments object. Declare arguments before declaring the |
| 3988 // function var since the arguments object masks 'function arguments'. |
| 3989 function_scope->DeclareArguments(ast_value_factory()); |
| 3990 } |
| 3991 |
| 3992 impl()->CreateFunctionNameAssignment(function_name, pos, function_type, |
| 3993 function_scope, result, |
| 3994 kFunctionNameAssignmentIndex); |
| 3995 impl()->MarkCollectedTailCallExpressions(); |
| 3996 } |
| 3997 |
| 3998 template <typename Impl> |
3888 void ParserBase<Impl>::CheckArityRestrictions(int param_count, | 3999 void ParserBase<Impl>::CheckArityRestrictions(int param_count, |
3889 FunctionKind function_kind, | 4000 FunctionKind function_kind, |
3890 bool has_rest, | 4001 bool has_rest, |
3891 int formals_start_pos, | 4002 int formals_start_pos, |
3892 int formals_end_pos, bool* ok) { | 4003 int formals_end_pos, bool* ok) { |
3893 if (IsGetterFunction(function_kind)) { | 4004 if (IsGetterFunction(function_kind)) { |
3894 if (param_count != 0) { | 4005 if (param_count != 0) { |
3895 impl()->ReportMessageAt( | 4006 impl()->ReportMessageAt( |
3896 Scanner::Location(formals_start_pos, formals_end_pos), | 4007 Scanner::Location(formals_start_pos, formals_end_pos), |
3897 MessageTemplate::kBadGetterArity); | 4008 MessageTemplate::kBadGetterArity); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4040 | 4151 |
4041 // This is probably an initialization function. Inform the compiler it | 4152 // This is probably an initialization function. Inform the compiler it |
4042 // should also eager-compile this function, and that we expect it to | 4153 // should also eager-compile this function, and that we expect it to |
4043 // be used once. | 4154 // be used once. |
4044 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; | 4155 eager_compile_hint = FunctionLiteral::kShouldEagerCompile; |
4045 should_be_used_once_hint = true; | 4156 should_be_used_once_hint = true; |
4046 } | 4157 } |
4047 } | 4158 } |
4048 if (!is_lazy_top_level_function) { | 4159 if (!is_lazy_top_level_function) { |
4049 Consume(Token::LBRACE); | 4160 Consume(Token::LBRACE); |
4050 body = impl()->ParseEagerFunctionBody( | 4161 body = impl()->NewStatementList(8); |
4051 impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters, | 4162 impl()->ParseFunctionBody(body, impl()->EmptyIdentifier(), |
4052 kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); | 4163 kNoSourcePosition, formal_parameters, kind, |
| 4164 FunctionLiteral::kAnonymousExpression, |
| 4165 CHECK_OK); |
4053 materialized_literal_count = | 4166 materialized_literal_count = |
4054 function_state.materialized_literal_count(); | 4167 function_state.materialized_literal_count(); |
4055 expected_property_count = function_state.expected_property_count(); | 4168 expected_property_count = function_state.expected_property_count(); |
4056 } | 4169 } |
4057 } else { | 4170 } else { |
4058 // Single-expression body | 4171 // Single-expression body |
4059 has_braces = false; | 4172 has_braces = false; |
4060 int pos = position(); | 4173 int pos = position(); |
4061 DCHECK(ReturnExprContext::kInsideValidBlock == | 4174 DCHECK(ReturnExprContext::kInsideValidBlock == |
4062 function_state_->return_expr_context()); | 4175 function_state_->return_expr_context()); |
(...skipping 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5539 if (has_seen_constructor_) { | 5652 if (has_seen_constructor_) { |
5540 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); | 5653 this->parser()->ReportMessage(MessageTemplate::kDuplicateConstructor); |
5541 *ok = false; | 5654 *ok = false; |
5542 return; | 5655 return; |
5543 } | 5656 } |
5544 has_seen_constructor_ = true; | 5657 has_seen_constructor_ = true; |
5545 return; | 5658 return; |
5546 } | 5659 } |
5547 } | 5660 } |
5548 | 5661 |
| 5662 #undef CHECK_OK_VOID |
5549 | 5663 |
5550 } // namespace internal | 5664 } // namespace internal |
5551 } // namespace v8 | 5665 } // namespace v8 |
5552 | 5666 |
5553 #endif // V8_PARSING_PARSER_BASE_H | 5667 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |