| 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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/class_finalizer.h" | 9 #include "vm/class_finalizer.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 LocalScope* scope; | 197 LocalScope* scope; |
| 198 SequenceNode* statements; | 198 SequenceNode* statements; |
| 199 }; | 199 }; |
| 200 | 200 |
| 201 | 201 |
| 202 // Class which describes an inlined finally block which is used to generate | 202 // Class which describes an inlined finally block which is used to generate |
| 203 // inlined code for the finally blocks when there is an exit from a try | 203 // inlined code for the finally blocks when there is an exit from a try |
| 204 // block using 'return', 'break' or 'continue'. | 204 // block using 'return', 'break' or 'continue'. |
| 205 class Parser::TryBlocks : public ZoneAllocated { | 205 class Parser::TryBlocks : public ZoneAllocated { |
| 206 public: | 206 public: |
| 207 TryBlocks(Block* try_block, TryBlocks* outer_try_block) | 207 TryBlocks(Block* try_block, TryBlocks* outer_try_block, intptr_t try_index) |
| 208 : try_block_(try_block), | 208 : try_block_(try_block), |
| 209 inlined_finally_nodes_(), | 209 inlined_finally_nodes_(), |
| 210 outer_try_block_(outer_try_block) { } | 210 outer_try_block_(outer_try_block), |
| 211 try_index_(try_index) { } |
| 211 | 212 |
| 212 TryBlocks* outer_try_block() const { return outer_try_block_; } | 213 TryBlocks* outer_try_block() const { return outer_try_block_; } |
| 213 Block* try_block() const { return try_block_; } | 214 Block* try_block() const { return try_block_; } |
| 215 intptr_t try_index() const { return try_index_; } |
| 214 | 216 |
| 215 void AddNodeForFinallyInlining(AstNode* node); | 217 void AddNodeForFinallyInlining(AstNode* node); |
| 216 AstNode* GetNodeToInlineFinally(int index) { | 218 AstNode* GetNodeToInlineFinally(int index) { |
| 217 if (0 <= index && index < inlined_finally_nodes_.length()) { | 219 if (0 <= index && index < inlined_finally_nodes_.length()) { |
| 218 return inlined_finally_nodes_[index]; | 220 return inlined_finally_nodes_[index]; |
| 219 } | 221 } |
| 220 return NULL; | 222 return NULL; |
| 221 } | 223 } |
| 222 | 224 |
| 223 private: | 225 private: |
| 224 Block* try_block_; | 226 Block* try_block_; |
| 225 GrowableArray<AstNode*> inlined_finally_nodes_; | 227 GrowableArray<AstNode*> inlined_finally_nodes_; |
| 226 TryBlocks* outer_try_block_; | 228 TryBlocks* outer_try_block_; |
| 229 const intptr_t try_index_; |
| 227 | 230 |
| 228 DISALLOW_COPY_AND_ASSIGN(TryBlocks); | 231 DISALLOW_COPY_AND_ASSIGN(TryBlocks); |
| 229 }; | 232 }; |
| 230 | 233 |
| 231 | 234 |
| 232 void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) { | 235 void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) { |
| 233 inlined_finally_nodes_.Add(node); | 236 inlined_finally_nodes_.Add(node); |
| 234 } | 237 } |
| 235 | 238 |
| 236 | 239 |
| 237 // For parsing a compilation unit. | 240 // For parsing a compilation unit. |
| 238 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) | 241 Parser::Parser(const Script& script, const Library& library, intptr_t token_pos) |
| 239 : isolate_(Isolate::Current()), | 242 : isolate_(Isolate::Current()), |
| 240 script_(Script::Handle(isolate_, script.raw())), | 243 script_(Script::Handle(isolate_, script.raw())), |
| 241 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), | 244 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), |
| 242 token_pos), | 245 token_pos), |
| 243 token_kind_(Token::kILLEGAL), | 246 token_kind_(Token::kILLEGAL), |
| 244 current_block_(NULL), | 247 current_block_(NULL), |
| 245 is_top_level_(false), | 248 is_top_level_(false), |
| 246 current_member_(NULL), | 249 current_member_(NULL), |
| 247 allow_function_literals_(true), | 250 allow_function_literals_(true), |
| 248 parsed_function_(NULL), | 251 parsed_function_(NULL), |
| 249 innermost_function_(Function::Handle(isolate_)), | 252 innermost_function_(Function::Handle(isolate_)), |
| 250 literal_token_(LiteralToken::Handle(isolate_)), | 253 literal_token_(LiteralToken::Handle(isolate_)), |
| 251 current_class_(Class::Handle(isolate_)), | 254 current_class_(Class::Handle(isolate_)), |
| 252 library_(Library::Handle(isolate_, library.raw())), | 255 library_(Library::Handle(isolate_, library.raw())), |
| 253 try_blocks_list_(NULL) { | 256 try_blocks_list_(NULL), |
| 257 last_used_try_index_(CatchClauseNode::kInvalidTryIndex) { |
| 254 ASSERT(tokens_iterator_.IsValid()); | 258 ASSERT(tokens_iterator_.IsValid()); |
| 255 ASSERT(!library.IsNull()); | 259 ASSERT(!library.IsNull()); |
| 256 } | 260 } |
| 257 | 261 |
| 258 | 262 |
| 259 // For parsing a function. | 263 // For parsing a function. |
| 260 Parser::Parser(const Script& script, | 264 Parser::Parser(const Script& script, |
| 261 ParsedFunction* parsed_function, | 265 ParsedFunction* parsed_function, |
| 262 intptr_t token_position) | 266 intptr_t token_position) |
| 263 : isolate_(Isolate::Current()), | 267 : isolate_(Isolate::Current()), |
| 264 script_(Script::Handle(isolate_, script.raw())), | 268 script_(Script::Handle(isolate_, script.raw())), |
| 265 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), | 269 tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()), |
| 266 token_position), | 270 token_position), |
| 267 token_kind_(Token::kILLEGAL), | 271 token_kind_(Token::kILLEGAL), |
| 268 current_block_(NULL), | 272 current_block_(NULL), |
| 269 is_top_level_(false), | 273 is_top_level_(false), |
| 270 current_member_(NULL), | 274 current_member_(NULL), |
| 271 allow_function_literals_(true), | 275 allow_function_literals_(true), |
| 272 parsed_function_(parsed_function), | 276 parsed_function_(parsed_function), |
| 273 innermost_function_(Function::Handle(isolate_, | 277 innermost_function_(Function::Handle(isolate_, |
| 274 parsed_function->function().raw())), | 278 parsed_function->function().raw())), |
| 275 literal_token_(LiteralToken::Handle(isolate_)), | 279 literal_token_(LiteralToken::Handle(isolate_)), |
| 276 current_class_(Class::Handle(isolate_, | 280 current_class_(Class::Handle(isolate_, |
| 277 parsed_function->function().Owner())), | 281 parsed_function->function().Owner())), |
| 278 library_(Library::Handle(Class::Handle( | 282 library_(Library::Handle(Class::Handle( |
| 279 isolate_, | 283 isolate_, |
| 280 parsed_function->function().origin()).library())), | 284 parsed_function->function().origin()).library())), |
| 281 try_blocks_list_(NULL) { | 285 try_blocks_list_(NULL), |
| 286 last_used_try_index_(CatchClauseNode::kInvalidTryIndex) { |
| 282 ASSERT(tokens_iterator_.IsValid()); | 287 ASSERT(tokens_iterator_.IsValid()); |
| 283 ASSERT(!current_function().IsNull()); | 288 ASSERT(!current_function().IsNull()); |
| 284 if (FLAG_enable_type_checks) { | 289 if (FLAG_enable_type_checks) { |
| 285 EnsureExpressionTemp(); | 290 EnsureExpressionTemp(); |
| 286 } | 291 } |
| 287 } | 292 } |
| 288 | 293 |
| 289 | 294 |
| 290 void Parser::SetScript(const Script & script, intptr_t token_pos) { | 295 void Parser::SetScript(const Script & script, intptr_t token_pos) { |
| 291 script_ = script.raw(); | 296 script_ = script.raw(); |
| (...skipping 5999 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6291 OpenBlock(); | 6296 OpenBlock(); |
| 6292 ExpectToken(Token::kLBRACE); | 6297 ExpectToken(Token::kLBRACE); |
| 6293 ParseStatementSequence(); | 6298 ParseStatementSequence(); |
| 6294 ExpectToken(Token::kRBRACE); | 6299 ExpectToken(Token::kRBRACE); |
| 6295 SequenceNode* finally_block = CloseBlock(); | 6300 SequenceNode* finally_block = CloseBlock(); |
| 6296 return finally_block; | 6301 return finally_block; |
| 6297 } | 6302 } |
| 6298 | 6303 |
| 6299 | 6304 |
| 6300 void Parser::PushTryBlock(Block* try_block) { | 6305 void Parser::PushTryBlock(Block* try_block) { |
| 6301 TryBlocks* block = new TryBlocks(try_block, try_blocks_list_); | 6306 intptr_t try_index = AllocateTryIndex(); |
| 6307 TryBlocks* block = new TryBlocks(try_block, try_blocks_list_, try_index); |
| 6302 try_blocks_list_ = block; | 6308 try_blocks_list_ = block; |
| 6303 } | 6309 } |
| 6304 | 6310 |
| 6305 | 6311 |
| 6306 Parser::TryBlocks* Parser::PopTryBlock() { | 6312 Parser::TryBlocks* Parser::PopTryBlock() { |
| 6307 TryBlocks* innermost_try_block = try_blocks_list_; | 6313 TryBlocks* innermost_try_block = try_blocks_list_; |
| 6308 try_blocks_list_ = try_blocks_list_->outer_try_block(); | 6314 try_blocks_list_ = try_blocks_list_->outer_try_block(); |
| 6309 return innermost_try_block; | 6315 return innermost_try_block; |
| 6310 } | 6316 } |
| 6311 | 6317 |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6543 handler_types.SetLength(0); | 6549 handler_types.SetLength(0); |
| 6544 handler_types.Add(*exception_param.type); | 6550 handler_types.Add(*exception_param.type); |
| 6545 } | 6551 } |
| 6546 SequenceNode* catch_clause = CloseBlock(); | 6552 SequenceNode* catch_clause = CloseBlock(); |
| 6547 | 6553 |
| 6548 // Add this individual catch handler to the catch handlers list. | 6554 // Add this individual catch handler to the catch handlers list. |
| 6549 current_block_->statements->Add(catch_clause); | 6555 current_block_->statements->Add(catch_clause); |
| 6550 } | 6556 } |
| 6551 catch_handler_list = CloseBlock(); | 6557 catch_handler_list = CloseBlock(); |
| 6552 TryBlocks* inner_try_block = PopTryBlock(); | 6558 TryBlocks* inner_try_block = PopTryBlock(); |
| 6559 intptr_t try_index = inner_try_block->try_index(); |
| 6560 TryBlocks* outer_try_block = try_blocks_list_; |
| 6561 intptr_t outer_try_index = (outer_try_block != NULL) |
| 6562 ? outer_try_block->try_index() |
| 6563 : CatchClauseNode::kInvalidTryIndex; |
| 6553 | 6564 |
| 6554 // Finally parse the 'finally' block. | 6565 // Finally parse the 'finally' block. |
| 6555 SequenceNode* finally_block = NULL; | 6566 SequenceNode* finally_block = NULL; |
| 6556 if (CurrentToken() == Token::kFINALLY) { | 6567 if (CurrentToken() == Token::kFINALLY) { |
| 6557 current_function().set_has_finally(true); | 6568 current_function().set_has_finally(true); |
| 6558 ConsumeToken(); // Consume the 'finally'. | 6569 ConsumeToken(); // Consume the 'finally'. |
| 6559 const intptr_t finally_pos = TokenPos(); | 6570 const intptr_t finally_pos = TokenPos(); |
| 6560 // Add the finally block to the exit points recorded so far. | 6571 // Add the finally block to the exit points recorded so far. |
| 6561 intptr_t node_index = 0; | 6572 intptr_t node_index = 0; |
| 6562 AstNode* node_to_inline = | 6573 AstNode* node_to_inline = |
| 6563 inner_try_block->GetNodeToInlineFinally(node_index); | 6574 inner_try_block->GetNodeToInlineFinally(node_index); |
| 6564 while (node_to_inline != NULL) { | 6575 while (node_to_inline != NULL) { |
| 6565 finally_block = ParseFinallyBlock(); | 6576 finally_block = ParseFinallyBlock(); |
| 6566 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, | 6577 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, |
| 6567 finally_block, | 6578 finally_block, |
| 6568 context_var); | 6579 context_var, |
| 6580 outer_try_index); |
| 6569 AddFinallyBlockToNode(node_to_inline, node); | 6581 AddFinallyBlockToNode(node_to_inline, node); |
| 6570 node_index += 1; | 6582 node_index += 1; |
| 6571 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); | 6583 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); |
| 6572 tokens_iterator_.SetCurrentPosition(finally_pos); | 6584 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 6573 } | 6585 } |
| 6574 finally_block = ParseFinallyBlock(); | 6586 finally_block = ParseFinallyBlock(); |
| 6575 } else { | 6587 } else { |
| 6576 if (!catch_seen) { | 6588 if (!catch_seen) { |
| 6577 ErrorMsg("catch or finally clause expected"); | 6589 ErrorMsg("catch or finally clause expected"); |
| 6578 } | 6590 } |
| 6579 } | 6591 } |
| 6580 | 6592 |
| 6581 if (!generic_catch_seen) { | 6593 if (!generic_catch_seen) { |
| 6582 // No generic catch handler exists so rethrow the exception so that | 6594 // No generic catch handler exists so rethrow the exception so that |
| 6583 // the next catch handler can deal with it. | 6595 // the next catch handler can deal with it. |
| 6584 catch_handler_list->Add( | 6596 catch_handler_list->Add( |
| 6585 new ThrowNode(handler_pos, | 6597 new ThrowNode(handler_pos, |
| 6586 new LoadLocalNode(handler_pos, catch_excp_var), | 6598 new LoadLocalNode(handler_pos, catch_excp_var), |
| 6587 new LoadLocalNode(handler_pos, catch_trace_var))); | 6599 new LoadLocalNode(handler_pos, catch_trace_var))); |
| 6588 } | 6600 } |
| 6589 CatchClauseNode* catch_block = | 6601 CatchClauseNode* catch_block = |
| 6590 new CatchClauseNode(handler_pos, | 6602 new CatchClauseNode(handler_pos, |
| 6591 catch_handler_list, | 6603 catch_handler_list, |
| 6592 Array::ZoneHandle(Array::MakeArray(handler_types)), | 6604 Array::ZoneHandle(Array::MakeArray(handler_types)), |
| 6593 context_var, | 6605 context_var, |
| 6594 catch_excp_var, | 6606 catch_excp_var, |
| 6595 catch_trace_var); | 6607 catch_trace_var, |
| 6608 (finally_block != NULL) |
| 6609 ? AllocateTryIndex() |
| 6610 : CatchClauseNode::kInvalidTryIndex); |
| 6596 | 6611 |
| 6597 // Now create the try/catch ast node and return it. If there is a label | 6612 // Now create the try/catch ast node and return it. If there is a label |
| 6598 // on the try/catch, close the block that's embedding the try statement | 6613 // on the try/catch, close the block that's embedding the try statement |
| 6599 // and attach the label to it. | 6614 // and attach the label to it. |
| 6600 AstNode* try_catch_node = | 6615 AstNode* try_catch_node = |
| 6601 new TryCatchNode(try_pos, try_block, end_catch_label, | 6616 new TryCatchNode(try_pos, try_block, end_catch_label, |
| 6602 context_var, catch_block, finally_block); | 6617 context_var, catch_block, finally_block, try_index); |
| 6603 | 6618 |
| 6604 if (try_label != NULL) { | 6619 if (try_label != NULL) { |
| 6605 current_block_->statements->Add(try_catch_node); | 6620 current_block_->statements->Add(try_catch_node); |
| 6606 SequenceNode* sequence = CloseBlock(); | 6621 SequenceNode* sequence = CloseBlock(); |
| 6607 sequence->set_label(try_label); | 6622 sequence->set_label(try_label); |
| 6608 try_catch_node = sequence; | 6623 try_catch_node = sequence; |
| 6609 } | 6624 } |
| 6610 return try_catch_node; | 6625 return try_catch_node; |
| 6611 } | 6626 } |
| 6612 | 6627 |
| (...skipping 3645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10258 void Parser::SkipQualIdent() { | 10273 void Parser::SkipQualIdent() { |
| 10259 ASSERT(IsIdentifier()); | 10274 ASSERT(IsIdentifier()); |
| 10260 ConsumeToken(); | 10275 ConsumeToken(); |
| 10261 if (CurrentToken() == Token::kPERIOD) { | 10276 if (CurrentToken() == Token::kPERIOD) { |
| 10262 ConsumeToken(); // Consume the kPERIOD token. | 10277 ConsumeToken(); // Consume the kPERIOD token. |
| 10263 ExpectIdentifier("identifier expected after '.'"); | 10278 ExpectIdentifier("identifier expected after '.'"); |
| 10264 } | 10279 } |
| 10265 } | 10280 } |
| 10266 | 10281 |
| 10267 } // namespace dart | 10282 } // namespace dart |
| OLD | NEW |