| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
| 6 | 6 |
| 7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
| 8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 token_kind_(Token::kILLEGAL), | 258 token_kind_(Token::kILLEGAL), |
| 259 current_block_(NULL), | 259 current_block_(NULL), |
| 260 is_top_level_(false), | 260 is_top_level_(false), |
| 261 current_member_(NULL), | 261 current_member_(NULL), |
| 262 allow_function_literals_(true), | 262 allow_function_literals_(true), |
| 263 current_function_(Function::Handle()), | 263 current_function_(Function::Handle()), |
| 264 innermost_function_(Function::Handle()), | 264 innermost_function_(Function::Handle()), |
| 265 current_class_(Class::Handle()), | 265 current_class_(Class::Handle()), |
| 266 library_(library), | 266 library_(library), |
| 267 try_blocks_list_(NULL), | 267 try_blocks_list_(NULL), |
| 268 expression_temp_(NULL) { | 268 expression_temp_(NULL), |
| 269 saved_current_context_(NULL) { |
| 269 ASSERT(tokens_iterator_.IsValid()); | 270 ASSERT(tokens_iterator_.IsValid()); |
| 270 ASSERT(!library.IsNull()); | 271 ASSERT(!library.IsNull()); |
| 271 } | 272 } |
| 272 | 273 |
| 273 | 274 |
| 274 // For parsing a function. | 275 // For parsing a function. |
| 275 Parser::Parser(const Script& script, | 276 Parser::Parser(const Script& script, |
| 276 const Function& function, | 277 const Function& function, |
| 277 intptr_t token_position) | 278 intptr_t token_position) |
| 278 : script_(script), | 279 : script_(script), |
| 279 tokens_iterator_(TokenStream::Handle(script.tokens()), token_position), | 280 tokens_iterator_(TokenStream::Handle(script.tokens()), token_position), |
| 280 token_kind_(Token::kILLEGAL), | 281 token_kind_(Token::kILLEGAL), |
| 281 current_block_(NULL), | 282 current_block_(NULL), |
| 282 is_top_level_(false), | 283 is_top_level_(false), |
| 283 current_member_(NULL), | 284 current_member_(NULL), |
| 284 allow_function_literals_(true), | 285 allow_function_literals_(true), |
| 285 current_function_(function), | 286 current_function_(function), |
| 286 innermost_function_(Function::Handle(function.raw())), | 287 innermost_function_(Function::Handle(function.raw())), |
| 287 current_class_(Class::Handle(current_function_.Owner())), | 288 current_class_(Class::Handle(current_function_.Owner())), |
| 288 library_(Library::Handle(current_class_.library())), | 289 library_(Library::Handle(current_class_.library())), |
| 289 try_blocks_list_(NULL), | 290 try_blocks_list_(NULL), |
| 290 expression_temp_(NULL) { | 291 expression_temp_(NULL), |
| 292 saved_current_context_(NULL) { |
| 291 ASSERT(tokens_iterator_.IsValid()); | 293 ASSERT(tokens_iterator_.IsValid()); |
| 292 ASSERT(!function.IsNull()); | 294 ASSERT(!function.IsNull()); |
| 293 if (FLAG_enable_type_checks) { | 295 if (FLAG_enable_type_checks) { |
| 294 EnsureExpressionTemp(); | 296 EnsureExpressionTemp(); |
| 295 } | 297 } |
| 296 } | 298 } |
| 297 | 299 |
| 298 | 300 |
| 299 bool Parser::SetAllowFunctionLiterals(bool value) { | 301 bool Parser::SetAllowFunctionLiterals(bool value) { |
| 300 bool current_value = allow_function_literals_; | 302 bool current_value = allow_function_literals_; |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 762 if (!HasReturnNode(node_sequence)) { | 764 if (!HasReturnNode(node_sequence)) { |
| 763 // Add implicit return node. | 765 // Add implicit return node. |
| 764 node_sequence->Add(new ReturnNode(func.end_token_pos())); | 766 node_sequence->Add(new ReturnNode(func.end_token_pos())); |
| 765 } | 767 } |
| 766 if (parser.expression_temp_ != NULL) { | 768 if (parser.expression_temp_ != NULL) { |
| 767 parsed_function->set_expression_temp_var(parser.expression_temp_); | 769 parsed_function->set_expression_temp_var(parser.expression_temp_); |
| 768 } | 770 } |
| 769 if (parsed_function->has_expression_temp_var()) { | 771 if (parsed_function->has_expression_temp_var()) { |
| 770 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); | 772 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); |
| 771 } | 773 } |
| 774 if (parser.saved_current_context_ != NULL) { |
| 775 parsed_function->set_saved_current_context_var( |
| 776 parser.saved_current_context_); |
| 777 node_sequence->scope()->AddVariable( |
| 778 parsed_function->saved_current_context_var()); |
| 779 } |
| 772 parsed_function->SetNodeSequence(node_sequence); | 780 parsed_function->SetNodeSequence(node_sequence); |
| 773 | 781 |
| 774 // The instantiator may be required at run time for generic type checks or | 782 // The instantiator may be required at run time for generic type checks or |
| 775 // allocation of generic types. | 783 // allocation of generic types. |
| 776 if (parser.IsInstantiatorRequired()) { | 784 if (parser.IsInstantiatorRequired()) { |
| 777 // In the case of a local function, only set the instantiator if the | 785 // In the case of a local function, only set the instantiator if the |
| 778 // receiver (or type arguments parameter of a factory) was captured. | 786 // receiver (or type arguments parameter of a factory) was captured. |
| 779 LocalVariable* instantiator = NULL; | 787 LocalVariable* instantiator = NULL; |
| 780 const bool kTestOnly = true; | 788 const bool kTestOnly = true; |
| 781 if (parser.current_function().IsInFactoryScope()) { | 789 if (parser.current_function().IsInFactoryScope()) { |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 kResolveGetter, | 1453 kResolveGetter, |
| 1446 &is_no_such_method)); | 1454 &is_no_such_method)); |
| 1447 if (super_function.IsGetterFunction() || | 1455 if (super_function.IsGetterFunction() || |
| 1448 super_function.IsImplicitGetterFunction()) { | 1456 super_function.IsImplicitGetterFunction()) { |
| 1449 const Class& super_class = Class::ZoneHandle(current_class().SuperClass()); | 1457 const Class& super_class = Class::ZoneHandle(current_class().SuperClass()); |
| 1450 AstNode* closure = new StaticGetterNode(supercall_pos, | 1458 AstNode* closure = new StaticGetterNode(supercall_pos, |
| 1451 LoadReceiver(supercall_pos), | 1459 LoadReceiver(supercall_pos), |
| 1452 /* is_super_getter */ true, | 1460 /* is_super_getter */ true, |
| 1453 super_class, | 1461 super_class, |
| 1454 function_name); | 1462 function_name); |
| 1455 EnsureExpressionTemp(); | 1463 EnsureSavedCurrentContext(); |
| 1456 // 'this' is not passed as parameter to the closure. | 1464 // 'this' is not passed as parameter to the closure. |
| 1457 ArgumentListNode* closure_arguments = new ArgumentListNode(supercall_pos); | 1465 ArgumentListNode* closure_arguments = new ArgumentListNode(supercall_pos); |
| 1458 for (int i = 1; i < arguments->length(); i++) { | 1466 for (int i = 1; i < arguments->length(); i++) { |
| 1459 closure_arguments->Add(arguments->NodeAt(i)); | 1467 closure_arguments->Add(arguments->NodeAt(i)); |
| 1460 } | 1468 } |
| 1461 return new ClosureCallNode(supercall_pos, closure, closure_arguments); | 1469 return new ClosureCallNode(supercall_pos, closure, closure_arguments); |
| 1462 } | 1470 } |
| 1463 if (is_no_such_method) { | 1471 if (is_no_such_method) { |
| 1464 arguments = BuildNoSuchMethodArguments( | 1472 arguments = BuildNoSuchMethodArguments( |
| 1465 supercall_pos, function_name, *arguments); | 1473 supercall_pos, function_name, *arguments); |
| (...skipping 4326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5792 return MakeStaticCall(Symbols::AssertionError(), | 5800 return MakeStaticCall(Symbols::AssertionError(), |
| 5793 PrivateCoreLibName(Symbols::ThrowNew()), | 5801 PrivateCoreLibName(Symbols::ThrowNew()), |
| 5794 arguments); | 5802 arguments); |
| 5795 } | 5803 } |
| 5796 | 5804 |
| 5797 | 5805 |
| 5798 AstNode* Parser::InsertClosureCallNodes(AstNode* condition) { | 5806 AstNode* Parser::InsertClosureCallNodes(AstNode* condition) { |
| 5799 if (condition->IsClosureNode() || | 5807 if (condition->IsClosureNode() || |
| 5800 (condition->IsStoreLocalNode() && | 5808 (condition->IsStoreLocalNode() && |
| 5801 condition->AsStoreLocalNode()->value()->IsClosureNode())) { | 5809 condition->AsStoreLocalNode()->value()->IsClosureNode())) { |
| 5802 EnsureExpressionTemp(); | 5810 EnsureSavedCurrentContext(); |
| 5803 // Function literal in assert implies a call. | 5811 // Function literal in assert implies a call. |
| 5804 const intptr_t pos = condition->token_pos(); | 5812 const intptr_t pos = condition->token_pos(); |
| 5805 condition = new ClosureCallNode(pos, condition, new ArgumentListNode(pos)); | 5813 condition = new ClosureCallNode(pos, condition, new ArgumentListNode(pos)); |
| 5806 } else if (condition->IsConditionalExprNode()) { | 5814 } else if (condition->IsConditionalExprNode()) { |
| 5807 ConditionalExprNode* cond_expr = condition->AsConditionalExprNode(); | 5815 ConditionalExprNode* cond_expr = condition->AsConditionalExprNode(); |
| 5808 cond_expr->set_true_expr(InsertClosureCallNodes(cond_expr->true_expr())); | 5816 cond_expr->set_true_expr(InsertClosureCallNodes(cond_expr->true_expr())); |
| 5809 cond_expr->set_false_expr(InsertClosureCallNodes(cond_expr->false_expr())); | 5817 cond_expr->set_false_expr(InsertClosureCallNodes(cond_expr->false_expr())); |
| 5810 } | 5818 } |
| 5811 return condition; | 5819 return condition; |
| 5812 } | 5820 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5931 ASSERT(node->IsJumpNode()); | 5939 ASSERT(node->IsJumpNode()); |
| 5932 node->AsJumpNode()->AddInlinedFinallyNode(finally_node); | 5940 node->AsJumpNode()->AddInlinedFinallyNode(finally_node); |
| 5933 } | 5941 } |
| 5934 } | 5942 } |
| 5935 | 5943 |
| 5936 | 5944 |
| 5937 AstNode* Parser::ParseTryStatement(String* label_name) { | 5945 AstNode* Parser::ParseTryStatement(String* label_name) { |
| 5938 TRACE_PARSER("ParseTryStatement"); | 5946 TRACE_PARSER("ParseTryStatement"); |
| 5939 | 5947 |
| 5940 // We create three stack slots for exceptions here: | 5948 // We create three stack slots for exceptions here: |
| 5941 // ':saved_context_var' - Used to save the context before start of the try | 5949 // ':saved_try_context_var' - Used to save the context before start of the try |
| 5942 // block. The context register is restored from this | 5950 // block. The context register is restored from |
| 5943 // slot before processing the catch block handler. | 5951 // this slot before processing the catch block |
| 5952 // handler. |
| 5944 // ':exception_var' - Used to save the current exception object that was | 5953 // ':exception_var' - Used to save the current exception object that was |
| 5945 // thrown. | 5954 // thrown. |
| 5946 // ':stacktrace_var' - Used to save the current stack trace object into which | 5955 // ':stacktrace_var' - Used to save the current stack trace object into which |
| 5947 // the stack trace was copied into when an exception was | 5956 // the stack trace was copied into when an exception was |
| 5948 // thrown. | 5957 // thrown. |
| 5949 // :exception_var and :stacktrace_var get set with the exception object | 5958 // :exception_var and :stacktrace_var get set with the exception object |
| 5950 // and the stacktrace object when an exception is thrown. | 5959 // and the stacktrace object when an exception is thrown. |
| 5951 // These three implicit variables can never be captured variables. | 5960 // These three implicit variables can never be captured variables. |
| 5952 LocalVariable* context_var = | 5961 LocalVariable* context_var = |
| 5953 current_block_->scope->LocalLookupVariable(Symbols::SavedContextVar()); | 5962 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 5954 if (context_var == NULL) { | 5963 if (context_var == NULL) { |
| 5955 context_var = new LocalVariable(TokenPos(), | 5964 context_var = new LocalVariable(TokenPos(), |
| 5956 Symbols::SavedContextVar(), | 5965 Symbols::SavedTryContextVar(), |
| 5957 Type::ZoneHandle(Type::DynamicType())); | 5966 Type::ZoneHandle(Type::DynamicType())); |
| 5958 current_block_->scope->AddVariable(context_var); | 5967 current_block_->scope->AddVariable(context_var); |
| 5959 } | 5968 } |
| 5960 LocalVariable* catch_excp_var = | 5969 LocalVariable* catch_excp_var = |
| 5961 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); | 5970 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); |
| 5962 if (catch_excp_var == NULL) { | 5971 if (catch_excp_var == NULL) { |
| 5963 catch_excp_var = new LocalVariable(TokenPos(), | 5972 catch_excp_var = new LocalVariable(TokenPos(), |
| 5964 Symbols::ExceptionVar(), | 5973 Symbols::ExceptionVar(), |
| 5965 Type::ZoneHandle(Type::DynamicType())); | 5974 Type::ZoneHandle(Type::DynamicType())); |
| 5966 current_block_->scope->AddVariable(catch_excp_var); | 5975 current_block_->scope->AddVariable(catch_excp_var); |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6782 return expression_temp_; | 6791 return expression_temp_; |
| 6783 } | 6792 } |
| 6784 | 6793 |
| 6785 | 6794 |
| 6786 void Parser::EnsureExpressionTemp() { | 6795 void Parser::EnsureExpressionTemp() { |
| 6787 // Temporary used later by the flow_graph_builder. | 6796 // Temporary used later by the flow_graph_builder. |
| 6788 GetIncrementTempLocal(); | 6797 GetIncrementTempLocal(); |
| 6789 } | 6798 } |
| 6790 | 6799 |
| 6791 | 6800 |
| 6801 void Parser::EnsureSavedCurrentContext() { |
| 6802 // Used later by the flow_graph_builder to save current context. |
| 6803 if (saved_current_context_ == NULL) { |
| 6804 // Allocate a local variable to save the current context when we call into |
| 6805 // any closure function as the call will destroy the current context. |
| 6806 saved_current_context_ = |
| 6807 new LocalVariable(current_function().token_pos(), |
| 6808 Symbols::SavedCurrentContextVar(), |
| 6809 Type::ZoneHandle(Type::DynamicType())); |
| 6810 } |
| 6811 } |
| 6812 |
| 6813 |
| 6792 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos, | 6814 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos, |
| 6793 const char* s) { | 6815 const char* s) { |
| 6794 char name[64]; | 6816 char name[64]; |
| 6795 OS::SNPrint(name, 64, ":%s%"Pd, s, token_pos); | 6817 OS::SNPrint(name, 64, ":%s%"Pd, s, token_pos); |
| 6796 LocalVariable* temp = | 6818 LocalVariable* temp = |
| 6797 new LocalVariable(token_pos, | 6819 new LocalVariable(token_pos, |
| 6798 String::ZoneHandle(Symbols::New(name)), | 6820 String::ZoneHandle(Symbols::New(name)), |
| 6799 Type::ZoneHandle(Type::DynamicType())); | 6821 Type::ZoneHandle(Type::DynamicType())); |
| 6800 temp->set_is_final(); | 6822 temp->set_is_final(); |
| 6801 current_block_->scope->AddVariable(temp); | 6823 current_block_->scope->AddVariable(temp); |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7222 const String& getter_name = | 7244 const String& getter_name = |
| 7223 String::ZoneHandle(Field::GetterName(func_name)); | 7245 String::ZoneHandle(Field::GetterName(func_name)); |
| 7224 const int kNumArguments = 0; // no arguments. | 7246 const int kNumArguments = 0; // no arguments. |
| 7225 func = Resolver::ResolveStatic(cls, | 7247 func = Resolver::ResolveStatic(cls, |
| 7226 getter_name, | 7248 getter_name, |
| 7227 kNumArguments, | 7249 kNumArguments, |
| 7228 Object::empty_array(), | 7250 Object::empty_array(), |
| 7229 Resolver::kIsQualified); | 7251 Resolver::kIsQualified); |
| 7230 if (!func.IsNull()) { | 7252 if (!func.IsNull()) { |
| 7231 ASSERT(func.kind() != RawFunction::kConstImplicitGetter); | 7253 ASSERT(func.kind() != RawFunction::kConstImplicitGetter); |
| 7232 EnsureExpressionTemp(); | 7254 EnsureSavedCurrentContext(); |
| 7233 closure = new StaticGetterNode(call_pos, | 7255 closure = new StaticGetterNode(call_pos, |
| 7234 NULL, | 7256 NULL, |
| 7235 false, | 7257 false, |
| 7236 Class::ZoneHandle(cls.raw()), | 7258 Class::ZoneHandle(cls.raw()), |
| 7237 func_name); | 7259 func_name); |
| 7238 return new ClosureCallNode(call_pos, closure, arguments); | 7260 return new ClosureCallNode(call_pos, closure, arguments); |
| 7239 } | 7261 } |
| 7240 } else { | 7262 } else { |
| 7241 EnsureExpressionTemp(); | 7263 EnsureSavedCurrentContext(); |
| 7242 closure = GenerateStaticFieldLookup(field, call_pos); | 7264 closure = GenerateStaticFieldLookup(field, call_pos); |
| 7243 return new ClosureCallNode(call_pos, closure, arguments); | 7265 return new ClosureCallNode(call_pos, closure, arguments); |
| 7244 } | 7266 } |
| 7245 // Could not resolve static method: throw a NoSuchMethodError. | 7267 // Could not resolve static method: throw a NoSuchMethodError. |
| 7246 return ThrowNoSuchMethodError(ident_pos, cls, func_name); | 7268 return ThrowNoSuchMethodError(ident_pos, cls, func_name); |
| 7247 } | 7269 } |
| 7248 return new StaticCallNode(call_pos, func, arguments); | 7270 return new StaticCallNode(call_pos, func, arguments); |
| 7249 } | 7271 } |
| 7250 | 7272 |
| 7251 | 7273 |
| 7252 AstNode* Parser::ParseInstanceCall(AstNode* receiver, const String& func_name) { | 7274 AstNode* Parser::ParseInstanceCall(AstNode* receiver, const String& func_name) { |
| 7253 TRACE_PARSER("ParseInstanceCall"); | 7275 TRACE_PARSER("ParseInstanceCall"); |
| 7254 const intptr_t call_pos = TokenPos(); | 7276 const intptr_t call_pos = TokenPos(); |
| 7255 if (CurrentToken() != Token::kLPAREN) { | 7277 if (CurrentToken() != Token::kLPAREN) { |
| 7256 ErrorMsg(call_pos, "left parenthesis expected"); | 7278 ErrorMsg(call_pos, "left parenthesis expected"); |
| 7257 } | 7279 } |
| 7258 ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); | 7280 ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); |
| 7259 return new InstanceCallNode(call_pos, receiver, func_name, arguments); | 7281 return new InstanceCallNode(call_pos, receiver, func_name, arguments); |
| 7260 } | 7282 } |
| 7261 | 7283 |
| 7262 | 7284 |
| 7263 AstNode* Parser::ParseClosureCall(AstNode* closure) { | 7285 AstNode* Parser::ParseClosureCall(AstNode* closure) { |
| 7264 TRACE_PARSER("ParseClosureCall"); | 7286 TRACE_PARSER("ParseClosureCall"); |
| 7265 const intptr_t call_pos = TokenPos(); | 7287 const intptr_t call_pos = TokenPos(); |
| 7266 ASSERT(CurrentToken() == Token::kLPAREN); | 7288 ASSERT(CurrentToken() == Token::kLPAREN); |
| 7267 EnsureExpressionTemp(); | 7289 EnsureSavedCurrentContext(); |
| 7268 ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); | 7290 ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); |
| 7269 return new ClosureCallNode(call_pos, closure, arguments); | 7291 return new ClosureCallNode(call_pos, closure, arguments); |
| 7270 } | 7292 } |
| 7271 | 7293 |
| 7272 | 7294 |
| 7273 AstNode* Parser::GenerateStaticFieldLookup(const Field& field, | 7295 AstNode* Parser::GenerateStaticFieldLookup(const Field& field, |
| 7274 intptr_t ident_pos) { | 7296 intptr_t ident_pos) { |
| 7275 // If the static field has an initializer, initialize the field at compile | 7297 // If the static field has an initializer, initialize the field at compile |
| 7276 // time, which is only possible if the field is const. | 7298 // time, which is only possible if the field is const. |
| 7277 AstNode* initializing_getter = RunStaticFieldInitializer(field); | 7299 AstNode* initializing_getter = RunStaticFieldInitializer(field); |
| (...skipping 2481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9759 void Parser::SkipQualIdent() { | 9781 void Parser::SkipQualIdent() { |
| 9760 ASSERT(IsIdentifier()); | 9782 ASSERT(IsIdentifier()); |
| 9761 ConsumeToken(); | 9783 ConsumeToken(); |
| 9762 if (CurrentToken() == Token::kPERIOD) { | 9784 if (CurrentToken() == Token::kPERIOD) { |
| 9763 ConsumeToken(); // Consume the kPERIOD token. | 9785 ConsumeToken(); // Consume the kPERIOD token. |
| 9764 ExpectIdentifier("identifier expected after '.'"); | 9786 ExpectIdentifier("identifier expected after '.'"); |
| 9765 } | 9787 } |
| 9766 } | 9788 } |
| 9767 | 9789 |
| 9768 } // namespace dart | 9790 } // namespace dart |
| OLD | NEW |