| 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 "platform/utils.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/ast.h" | |
| 10 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 11 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| 12 #include "vm/compiler.h" | 11 #include "vm/compiler.h" |
| 13 #include "vm/compiler_stats.h" | 12 #include "vm/compiler_stats.h" |
| 14 #include "vm/dart_api_impl.h" | 13 #include "vm/dart_api_impl.h" |
| 15 #include "vm/dart_entry.h" | 14 #include "vm/dart_entry.h" |
| 16 #include "vm/flags.h" | 15 #include "vm/flags.h" |
| 17 #include "vm/growable_array.h" | 16 #include "vm/growable_array.h" |
| 18 #include "vm/handles.h" | |
| 19 #include "vm/heap.h" | |
| 20 #include "vm/isolate.h" | |
| 21 #include "vm/longjump.h" | 17 #include "vm/longjump.h" |
| 22 #include "vm/native_arguments.h" | |
| 23 #include "vm/native_entry.h" | 18 #include "vm/native_entry.h" |
| 24 #include "vm/object.h" | 19 #include "vm/object.h" |
| 25 #include "vm/object_store.h" | 20 #include "vm/object_store.h" |
| 26 #include "vm/os.h" | |
| 27 #include "vm/resolver.h" | 21 #include "vm/resolver.h" |
| 28 #include "vm/scanner.h" | |
| 29 #include "vm/scopes.h" | 22 #include "vm/scopes.h" |
| 30 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
| 31 #include "vm/timer.h" | |
| 32 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
| 33 #include "vm/zone.h" | |
| 34 | 25 |
| 35 namespace dart { | 26 namespace dart { |
| 36 | 27 |
| 37 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); | 28 DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements."); |
| 38 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); | 29 DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks."); |
| 39 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); | 30 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations."); |
| 40 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); | 31 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); |
| 41 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); | 32 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); |
| 42 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef"); | 33 DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef"); |
| 43 DECLARE_FLAG(bool, error_on_bad_type); | 34 DECLARE_FLAG(bool, error_on_bad_type); |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 // Generate code returning the field value. | 1033 // Generate code returning the field value. |
| 1043 ReturnNode* return_node = | 1034 ReturnNode* return_node = |
| 1044 new ReturnNode(ident_pos, | 1035 new ReturnNode(ident_pos, |
| 1045 new LoadStaticFieldNode(ident_pos, field)); | 1036 new LoadStaticFieldNode(ident_pos, field)); |
| 1046 current_block_->statements->Add(return_node); | 1037 current_block_->statements->Add(return_node); |
| 1047 } | 1038 } |
| 1048 return CloseBlock(); | 1039 return CloseBlock(); |
| 1049 } | 1040 } |
| 1050 | 1041 |
| 1051 | 1042 |
| 1052 LocalVariable* Parser::EnsureLocalVariable(const String& name) { | |
| 1053 LocalVariable* variable = current_block_->scope->LocalLookupVariable(name); | |
| 1054 if (variable == NULL) { | |
| 1055 variable = new LocalVariable(TokenPos(), name, | |
| 1056 Type::ZoneHandle(Type::DynamicType())); | |
| 1057 current_block_->scope->AddVariable(variable); | |
| 1058 } | |
| 1059 return variable; | |
| 1060 } | |
| 1061 | |
| 1062 | |
| 1063 SequenceNode* Parser::ParseStaticInitializer(const Function& func) { | 1043 SequenceNode* Parser::ParseStaticInitializer(const Function& func) { |
| 1064 TRACE_PARSER("ParseStaticInitializer"); | 1044 TRACE_PARSER("ParseStaticInitializer"); |
| 1065 ParamList params; | 1045 ParamList params; |
| 1066 ASSERT(func.num_fixed_parameters() == 0); // static. | 1046 ASSERT(func.num_fixed_parameters() == 0); // static. |
| 1067 ASSERT(!func.HasOptionalParameters()); | 1047 ASSERT(!func.HasOptionalParameters()); |
| 1068 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 1048 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 1069 | 1049 |
| 1070 // Build local scope for function and populate with the formal parameters. | 1050 // Build local scope for function and populate with the formal parameters. |
| 1071 OpenFunctionBlock(func); | 1051 OpenFunctionBlock(func); |
| 1072 AddFormalParamsToScope(¶ms, current_block_->scope); | 1052 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 1073 | 1053 |
| 1074 // Move forward to the start of the initializer expression. | 1054 // Move forward to the start of the initializer expression. |
| 1075 ExpectIdentifier("identifier expected"); | 1055 ExpectIdentifier("identifier expected"); |
| 1076 ExpectToken(Token::kASSIGN); | 1056 ExpectToken(Token::kASSIGN); |
| 1077 intptr_t token_pos = TokenPos(); | 1057 intptr_t token_pos = TokenPos(); |
| 1078 | 1058 |
| 1079 // Synthesize a try-catch block to wrap the initializer expression. | 1059 // Synthesize a try-catch block to wrap the initializer expression. |
| 1080 LocalVariable* context_var = | 1060 LocalVariable* context_var = |
| 1081 EnsureLocalVariable(Symbols::SavedTryContextVar()); | 1061 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 1082 LocalVariable* exception_var = EnsureLocalVariable(Symbols::ExceptionVar()); | 1062 if (context_var == NULL) { |
| 1083 LocalVariable* stack_trace_var = | 1063 context_var = new LocalVariable(token_pos, |
| 1084 EnsureLocalVariable(Symbols::StackTraceVar()); | 1064 Symbols::SavedTryContextVar(), |
| 1065 Type::ZoneHandle(Type::DynamicType())); |
| 1066 current_block_->scope->AddVariable(context_var); |
| 1067 } |
| 1068 LocalVariable* catch_excp_var = |
| 1069 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); |
| 1070 if (catch_excp_var == NULL) { |
| 1071 catch_excp_var = new LocalVariable(token_pos, |
| 1072 Symbols::ExceptionVar(), |
| 1073 Type::ZoneHandle(Type::DynamicType())); |
| 1074 current_block_->scope->AddVariable(catch_excp_var); |
| 1075 } |
| 1076 LocalVariable* catch_trace_var = |
| 1077 current_block_->scope->LocalLookupVariable(Symbols::StacktraceVar()); |
| 1078 if (catch_trace_var == NULL) { |
| 1079 catch_trace_var = new LocalVariable(token_pos, |
| 1080 Symbols::StacktraceVar(), |
| 1081 Type::ZoneHandle(Type::DynamicType())); |
| 1082 current_block_->scope->AddVariable(catch_trace_var); |
| 1083 } |
| 1085 | 1084 |
| 1086 OpenBlock(); // Start try block. | 1085 OpenBlock(); // Start try block. |
| 1087 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 1086 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 1088 const Field& field = Field::ZoneHandle(func.saved_static_field()); | 1087 const Field& field = Field::ZoneHandle(func.saved_static_field()); |
| 1089 ASSERT(!field.is_const()); | 1088 ASSERT(!field.is_const()); |
| 1090 StoreStaticFieldNode* store = new StoreStaticFieldNode(field.token_pos(), | 1089 StoreStaticFieldNode* store = new StoreStaticFieldNode(field.token_pos(), |
| 1091 field, | 1090 field, |
| 1092 expr); | 1091 expr); |
| 1093 current_block_->statements->Add(store); | 1092 current_block_->statements->Add(store); |
| 1094 SequenceNode* try_block = CloseBlock(); // End try block. | 1093 SequenceNode* try_block = CloseBlock(); // End try block. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1109 store_null->Add(new StoreStaticFieldNode( | 1108 store_null->Add(new StoreStaticFieldNode( |
| 1110 field.token_pos(), | 1109 field.token_pos(), |
| 1111 field, | 1110 field, |
| 1112 new LiteralNode(token_pos, Instance::ZoneHandle()))); | 1111 new LiteralNode(token_pos, Instance::ZoneHandle()))); |
| 1113 AstNode* transition_sentinel_check = | 1112 AstNode* transition_sentinel_check = |
| 1114 new IfNode(token_pos, compare_transition_sentinel, store_null, NULL); | 1113 new IfNode(token_pos, compare_transition_sentinel, store_null, NULL); |
| 1115 current_block_->statements->Add(transition_sentinel_check); | 1114 current_block_->statements->Add(transition_sentinel_check); |
| 1116 | 1115 |
| 1117 current_block_->statements->Add( | 1116 current_block_->statements->Add( |
| 1118 new ThrowNode(token_pos, | 1117 new ThrowNode(token_pos, |
| 1119 new LoadLocalNode(token_pos, exception_var), | 1118 new LoadLocalNode(token_pos, catch_excp_var), |
| 1120 new LoadLocalNode(token_pos, stack_trace_var))); | 1119 new LoadLocalNode(token_pos, catch_trace_var))); |
| 1121 current_block_->statements->Add( | 1120 current_block_->statements->Add( |
| 1122 new JumpNode(token_pos, Token::kCONTINUE, end_catch_label)); | 1121 new JumpNode(token_pos, Token::kCONTINUE, end_catch_label)); |
| 1123 SequenceNode* catch_clause = CloseBlock(); // End catch clause. | 1122 SequenceNode* catch_clause = CloseBlock(); // End catch clause. |
| 1124 | 1123 |
| 1125 current_block_->statements->Add(catch_clause); | 1124 current_block_->statements->Add(catch_clause); |
| 1126 SequenceNode* catch_handler_list = CloseBlock(); // End catch handler list. | 1125 SequenceNode* catch_handler_list = CloseBlock(); // End catch handler list. |
| 1127 CatchClauseNode* catch_block = | 1126 CatchClauseNode* catch_block = |
| 1128 new CatchClauseNode(token_pos, | 1127 new CatchClauseNode(token_pos, |
| 1129 catch_handler_list, | 1128 catch_handler_list, |
| 1130 Array::ZoneHandle(Object::empty_array().raw()), | 1129 Array::ZoneHandle(Object::empty_array().raw()), |
| 1131 context_var, | 1130 context_var, |
| 1132 exception_var, | 1131 catch_excp_var, |
| 1133 stack_trace_var, | 1132 catch_trace_var, |
| 1134 CatchClauseNode::kInvalidTryIndex, | 1133 CatchClauseNode::kInvalidTryIndex, |
| 1135 false); // No stack trace needed. | 1134 false); // No stack trace needed. |
| 1136 | 1135 |
| 1137 AstNode* try_catch_node = new TryCatchNode(token_pos, | 1136 AstNode* try_catch_node = new TryCatchNode(token_pos, |
| 1138 try_block, | 1137 try_block, |
| 1139 end_catch_label, | 1138 end_catch_label, |
| 1140 context_var, | 1139 context_var, |
| 1141 catch_block, | 1140 catch_block, |
| 1142 NULL, // No finally block. | 1141 NULL, // No finally block. |
| 1143 AllocateTryIndex()); | 1142 AllocateTryIndex()); |
| (...skipping 5532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6676 condition = InsertClosureCallNodes(condition); | 6675 condition = InsertClosureCallNodes(condition); |
| 6677 condition = new UnaryOpNode(condition_pos, Token::kNOT, condition); | 6676 condition = new UnaryOpNode(condition_pos, Token::kNOT, condition); |
| 6678 AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end); | 6677 AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end); |
| 6679 return new IfNode(condition_pos, | 6678 return new IfNode(condition_pos, |
| 6680 condition, | 6679 condition, |
| 6681 NodeAsSequenceNode(condition_pos, assert_throw, NULL), | 6680 NodeAsSequenceNode(condition_pos, assert_throw, NULL), |
| 6682 NULL); | 6681 NULL); |
| 6683 } | 6682 } |
| 6684 | 6683 |
| 6685 | 6684 |
| 6686 struct CatchParameter { | 6685 struct CatchParamDesc { |
| 6687 CatchParameter() | 6686 CatchParamDesc() |
| 6688 : token_pos(0), type(AbstractType::ZoneHandle()), name(NULL), var(NULL) { | 6687 : token_pos(0), type(NULL), var(NULL) { } |
| 6689 } | |
| 6690 intptr_t token_pos; | 6688 intptr_t token_pos; |
| 6691 AbstractType& type; | 6689 const AbstractType* type; |
| 6692 const String* name; | 6690 const String* var; |
| 6693 LocalVariable* var; | |
| 6694 }; | 6691 }; |
| 6695 | 6692 |
| 6696 | 6693 |
| 6697 // Populate local scope of the catch block with the catch parameters. | 6694 // Populate local scope of the catch block with the catch parameters. |
| 6698 void Parser::AddCatchParametersToScope(CatchParameter* exception_param, | 6695 void Parser::AddCatchParamsToScope(const CatchParamDesc& exception_param, |
| 6699 CatchParameter* stack_trace_param, | 6696 const CatchParamDesc& stack_trace_param, |
| 6700 LocalScope* scope) { | 6697 LocalScope* scope) { |
| 6701 if (exception_param->name != NULL) { | 6698 if (exception_param.var != NULL) { |
| 6702 LocalVariable* var = new LocalVariable(exception_param->token_pos, | 6699 LocalVariable* var = new LocalVariable(exception_param.token_pos, |
| 6703 *exception_param->name, | 6700 *exception_param.var, |
| 6704 exception_param->type); | 6701 *exception_param.type); |
| 6705 var->set_is_final(); | 6702 var->set_is_final(); |
| 6706 bool added_to_scope = scope->AddVariable(var); | 6703 bool added_to_scope = scope->AddVariable(var); |
| 6707 ASSERT(added_to_scope); | 6704 ASSERT(added_to_scope); |
| 6708 exception_param->var = var; | |
| 6709 } | 6705 } |
| 6710 if (stack_trace_param->name != NULL) { | 6706 if (stack_trace_param.var != NULL) { |
| 6711 LocalVariable* var = new LocalVariable(stack_trace_param->token_pos, | 6707 LocalVariable* var = new LocalVariable(TokenPos(), |
| 6712 *stack_trace_param->name, | 6708 *stack_trace_param.var, |
| 6713 stack_trace_param->type); | 6709 *stack_trace_param.type); |
| 6714 var->set_is_final(); | 6710 var->set_is_final(); |
| 6715 bool added_to_scope = scope->AddVariable(var); | 6711 bool added_to_scope = scope->AddVariable(var); |
| 6716 if (!added_to_scope) { | 6712 if (!added_to_scope) { |
| 6717 ErrorMsg(stack_trace_param->token_pos, | 6713 ErrorMsg(stack_trace_param.token_pos, |
| 6718 "name '%s' already exists in scope", | 6714 "name '%s' already exists in scope", |
| 6719 stack_trace_param->name->ToCString()); | 6715 stack_trace_param.var->ToCString()); |
| 6720 } | 6716 } |
| 6721 stack_trace_param->var = var; | |
| 6722 } | 6717 } |
| 6723 } | 6718 } |
| 6724 | 6719 |
| 6725 | 6720 |
| 6726 SequenceNode* Parser::ParseFinallyBlock() { | 6721 SequenceNode* Parser::ParseFinallyBlock() { |
| 6727 TRACE_PARSER("ParseFinallyBlock"); | 6722 TRACE_PARSER("ParseFinallyBlock"); |
| 6728 OpenBlock(); | 6723 OpenBlock(); |
| 6729 ExpectToken(Token::kLBRACE); | 6724 ExpectToken(Token::kLBRACE); |
| 6730 ParseStatementSequence(); | 6725 ParseStatementSequence(); |
| 6731 ExpectToken(Token::kRBRACE); | 6726 ExpectToken(Token::kRBRACE); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6783 } else { | 6778 } else { |
| 6784 ASSERT(node->IsJumpNode()); | 6779 ASSERT(node->IsJumpNode()); |
| 6785 node->AsJumpNode()->AddInlinedFinallyNode(finally_node); | 6780 node->AsJumpNode()->AddInlinedFinallyNode(finally_node); |
| 6786 } | 6781 } |
| 6787 } | 6782 } |
| 6788 | 6783 |
| 6789 | 6784 |
| 6790 AstNode* Parser::ParseTryStatement(String* label_name) { | 6785 AstNode* Parser::ParseTryStatement(String* label_name) { |
| 6791 TRACE_PARSER("ParseTryStatement"); | 6786 TRACE_PARSER("ParseTryStatement"); |
| 6792 | 6787 |
| 6793 // We create three local variables for exceptions here: | 6788 // We create three stack slots for exceptions here: |
| 6794 // ':saved_try_context_var' - Used to save the context before start of the | 6789 // ':saved_try_context_var' - Used to save the context before start of the try |
| 6795 // try block. The context register is restored | 6790 // block. The context register is restored from |
| 6796 // from this slot before processing the catch | 6791 // this slot before processing the catch block |
| 6797 // block handler. | 6792 // handler. |
| 6798 // ':exception_var' - Used to save the current exception object that was | 6793 // ':exception_var' - Used to save the current exception object that was |
| 6799 // thrown. | 6794 // thrown. |
| 6800 // ':stack_trace_var' - Used to save the current stack trace object into | 6795 // ':stacktrace_var' - Used to save the current stack trace object into which |
| 6801 // which the stack trace was copied into when an | 6796 // the stack trace was copied into when an exception was |
| 6802 // exception was thrown. | 6797 // thrown. |
| 6803 // :exception_var and :stack_trace_var get set with the exception object | 6798 // :exception_var and :stacktrace_var get set with the exception object |
| 6804 // and the stack trace object when an exception is thrown. These three | 6799 // and the stacktrace object when an exception is thrown. |
| 6805 // implicit variables can never be captured variables. | 6800 // These three implicit variables can never be captured variables. |
| 6806 LocalVariable* context_var = | 6801 LocalVariable* context_var = |
| 6807 EnsureLocalVariable(Symbols::SavedTryContextVar()); | 6802 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); |
| 6808 LocalVariable* exception_var = EnsureLocalVariable(Symbols::ExceptionVar()); | 6803 if (context_var == NULL) { |
| 6809 LocalVariable* stack_trace_var = | 6804 context_var = new LocalVariable(TokenPos(), |
| 6810 EnsureLocalVariable(Symbols::StackTraceVar()); | 6805 Symbols::SavedTryContextVar(), |
| 6806 Type::ZoneHandle(Type::DynamicType())); |
| 6807 current_block_->scope->AddVariable(context_var); |
| 6808 } |
| 6809 LocalVariable* catch_excp_var = |
| 6810 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); |
| 6811 if (catch_excp_var == NULL) { |
| 6812 catch_excp_var = new LocalVariable(TokenPos(), |
| 6813 Symbols::ExceptionVar(), |
| 6814 Type::ZoneHandle(Type::DynamicType())); |
| 6815 current_block_->scope->AddVariable(catch_excp_var); |
| 6816 } |
| 6817 LocalVariable* catch_trace_var = |
| 6818 current_block_->scope->LocalLookupVariable(Symbols::StacktraceVar()); |
| 6819 if (catch_trace_var == NULL) { |
| 6820 catch_trace_var = new LocalVariable(TokenPos(), |
| 6821 Symbols::StacktraceVar(), |
| 6822 Type::ZoneHandle(Type::DynamicType())); |
| 6823 current_block_->scope->AddVariable(catch_trace_var); |
| 6824 } |
| 6811 | 6825 |
| 6812 const intptr_t try_pos = TokenPos(); | 6826 const intptr_t try_pos = TokenPos(); |
| 6813 ConsumeToken(); // Consume the 'try'. | 6827 ConsumeToken(); // Consume the 'try'. |
| 6814 | 6828 |
| 6815 SourceLabel* try_label = NULL; | 6829 SourceLabel* try_label = NULL; |
| 6816 if (label_name != NULL) { | 6830 if (label_name != NULL) { |
| 6817 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); | 6831 try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement); |
| 6818 OpenBlock(); | 6832 OpenBlock(); |
| 6819 current_block_->scope->AddLabel(try_label); | 6833 current_block_->scope->AddLabel(try_label); |
| 6820 } | 6834 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 6831 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && | 6845 if ((CurrentToken() != Token::kCATCH) && !IsLiteral("on") && |
| 6832 (CurrentToken() != Token::kFINALLY)) { | 6846 (CurrentToken() != Token::kFINALLY)) { |
| 6833 ErrorMsg("catch or finally clause expected"); | 6847 ErrorMsg("catch or finally clause expected"); |
| 6834 } | 6848 } |
| 6835 | 6849 |
| 6836 // Now create a label for the end of catch block processing so that we can | 6850 // Now create a label for the end of catch block processing so that we can |
| 6837 // jump over the catch block code after executing the try block. | 6851 // jump over the catch block code after executing the try block. |
| 6838 SourceLabel* end_catch_label = | 6852 SourceLabel* end_catch_label = |
| 6839 SourceLabel::New(TokenPos(), NULL, SourceLabel::kCatch); | 6853 SourceLabel::New(TokenPos(), NULL, SourceLabel::kCatch); |
| 6840 | 6854 |
| 6841 // Now parse the 'catch' blocks if any and merge all of them into an | 6855 // Now parse the 'catch' blocks if any and merge all of them into |
| 6842 // if-then sequence of the different types specified using the 'is' | 6856 // an if-then sequence of the different types specified using the 'is' |
| 6843 // operator. | 6857 // operator. |
| 6844 bool generic_catch_seen = false; | 6858 bool generic_catch_seen = false; |
| 6845 const intptr_t handler_pos = TokenPos(); | 6859 const intptr_t handler_pos = TokenPos(); |
| 6846 OpenBlock(); // Start the catch block sequence. | 6860 OpenBlock(); // Start the catch block sequence. |
| 6847 current_block_->scope->AddLabel(end_catch_label); | 6861 current_block_->scope->AddLabel(end_catch_label); |
| 6848 const GrowableObjectArray& handler_types = | 6862 const GrowableObjectArray& handler_types = |
| 6849 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 6863 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 6850 bool needs_stack_trace = false; | 6864 bool needs_stacktrace = false; |
| 6851 while ((CurrentToken() == Token::kCATCH) || IsLiteral("on")) { | 6865 while ((CurrentToken() == Token::kCATCH) || IsLiteral("on")) { |
| 6852 const intptr_t catch_pos = TokenPos(); | 6866 const intptr_t catch_pos = TokenPos(); |
| 6853 CatchParameter exception_param; | 6867 CatchParamDesc exception_param; |
| 6854 CatchParameter stack_trace_param; | 6868 CatchParamDesc stack_trace_param; |
| 6855 if (IsLiteral("on")) { | 6869 if (IsLiteral("on")) { |
| 6856 ConsumeToken(); | 6870 ConsumeToken(); |
| 6857 exception_param.type = ParseType(ClassFinalizer::kCanonicalize); | 6871 exception_param.type = &AbstractType::ZoneHandle( |
| 6872 ParseType(ClassFinalizer::kCanonicalize)); |
| 6858 } else { | 6873 } else { |
| 6859 exception_param.type = Type::DynamicType(); | 6874 exception_param.type = |
| 6875 &AbstractType::ZoneHandle(Type::DynamicType()); |
| 6860 } | 6876 } |
| 6861 if (CurrentToken() == Token::kCATCH) { | 6877 if (CurrentToken() == Token::kCATCH) { |
| 6862 ConsumeToken(); // Consume the 'catch'. | 6878 ConsumeToken(); // Consume the 'catch'. |
| 6863 ExpectToken(Token::kLPAREN); | 6879 ExpectToken(Token::kLPAREN); |
| 6864 exception_param.token_pos = TokenPos(); | 6880 exception_param.token_pos = TokenPos(); |
| 6865 exception_param.name = ExpectIdentifier("identifier expected"); | 6881 exception_param.var = ExpectIdentifier("identifier expected"); |
| 6866 if (CurrentToken() == Token::kCOMMA) { | 6882 if (CurrentToken() == Token::kCOMMA) { |
| 6867 ConsumeToken(); | 6883 ConsumeToken(); |
| 6868 // TODO(hausner): Make implicit type be StackTrace, not dynamic. | 6884 // TODO(hausner): Make implicit type be StackTrace, not dynamic. |
| 6869 stack_trace_param.type = Type::DynamicType(); | 6885 stack_trace_param.type = |
| 6886 &AbstractType::ZoneHandle(Type::DynamicType()); |
| 6870 stack_trace_param.token_pos = TokenPos(); | 6887 stack_trace_param.token_pos = TokenPos(); |
| 6871 stack_trace_param.name = ExpectIdentifier("identifier expected"); | 6888 stack_trace_param.var = ExpectIdentifier("identifier expected"); |
| 6872 } | 6889 } |
| 6873 ExpectToken(Token::kRPAREN); | 6890 ExpectToken(Token::kRPAREN); |
| 6874 } | 6891 } |
| 6875 | 6892 |
| 6876 // Parse the individual catch handler code and add an unconditional JUMP | 6893 // Parse the individual catch handler code and add an unconditional |
| 6877 // to the end of the try block. | 6894 // JUMP to the end of the try block. |
| 6878 ExpectToken(Token::kLBRACE); | 6895 ExpectToken(Token::kLBRACE); |
| 6879 OpenBlock(); | 6896 OpenBlock(); |
| 6880 AddCatchParametersToScope(&exception_param, &stack_trace_param, | 6897 AddCatchParamsToScope(exception_param, |
| 6881 current_block_->scope); | 6898 stack_trace_param, |
| 6899 current_block_->scope); |
| 6882 | 6900 |
| 6883 if (exception_param.var != NULL) { | 6901 if (exception_param.var != NULL) { |
| 6884 // Generate code to load the exception object (:exception_var) into | 6902 // Generate code to load the exception object (:exception_var) into |
| 6885 // the exception variable specified in this block. | 6903 // the exception variable specified in this block. |
| 6886 ASSERT(exception_var != NULL); | 6904 LocalVariable* var = LookupLocalScope(*exception_param.var); |
| 6905 ASSERT(var != NULL); |
| 6906 ASSERT(catch_excp_var != NULL); |
| 6887 current_block_->statements->Add( | 6907 current_block_->statements->Add( |
| 6888 new StoreLocalNode(catch_pos, exception_param.var, | 6908 new StoreLocalNode(catch_pos, var, |
| 6889 new LoadLocalNode(catch_pos, exception_var))); | 6909 new LoadLocalNode(catch_pos, catch_excp_var))); |
| 6890 } | 6910 } |
| 6891 if (stack_trace_param.var != NULL) { | 6911 if (stack_trace_param.var != NULL) { |
| 6892 // A stack trace variable is specified in this block, so generate code | 6912 // A stack trace variable is specified in this block, so generate code |
| 6893 // to load the stack trace object (:stack_trace_var) into the stack | 6913 // to load the stack trace object (:stacktrace_var) into the stack trace |
| 6894 // trace variable specified in this block. | 6914 // variable specified in this block. |
| 6895 needs_stack_trace = true; | 6915 needs_stacktrace = true; |
| 6896 ArgumentListNode* no_args = new ArgumentListNode(catch_pos); | 6916 ArgumentListNode* no_args = new ArgumentListNode(catch_pos); |
| 6897 ASSERT(stack_trace_var != NULL); | 6917 LocalVariable* trace = LookupLocalScope(*stack_trace_param.var); |
| 6918 ASSERT(catch_trace_var != NULL); |
| 6898 current_block_->statements->Add( | 6919 current_block_->statements->Add( |
| 6899 new StoreLocalNode(catch_pos, stack_trace_param.var, | 6920 new StoreLocalNode(catch_pos, trace, |
| 6900 new LoadLocalNode(catch_pos, stack_trace_var))); | 6921 new LoadLocalNode(catch_pos, catch_trace_var))); |
| 6901 current_block_->statements->Add( | 6922 current_block_->statements->Add( |
| 6902 new InstanceCallNode( | 6923 new InstanceCallNode( |
| 6903 catch_pos, | 6924 catch_pos, |
| 6904 new LoadLocalNode(catch_pos, stack_trace_param.var), | 6925 new LoadLocalNode(catch_pos, trace), |
| 6905 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), | 6926 Library::PrivateCoreLibName(Symbols::_setupFullStackTrace()), |
| 6906 no_args)); | 6927 no_args)); |
| 6907 } | 6928 } |
| 6908 | 6929 |
| 6909 ParseStatementSequence(); // Parse the catch handler code. | 6930 ParseStatementSequence(); // Parse the catch handler code. |
| 6910 current_block_->statements->Add( | 6931 current_block_->statements->Add( |
| 6911 new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); | 6932 new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); |
| 6912 SequenceNode* catch_handler = CloseBlock(); | 6933 SequenceNode* catch_handler = CloseBlock(); |
| 6913 ExpectToken(Token::kRBRACE); | 6934 ExpectToken(Token::kRBRACE); |
| 6914 | 6935 |
| 6915 const bool is_bad_type = exception_param.type.IsMalformed() || | 6936 const bool is_bad_type = exception_param.type->IsMalformed() || |
| 6916 exception_param.type.IsMalbounded(); | 6937 exception_param.type->IsMalbounded(); |
| 6917 if (!is_bad_type && !exception_param.type.IsDynamicType()) { | 6938 if (!is_bad_type && !exception_param.type->IsDynamicType()) { |
| 6918 // Has a type specification that is not malformed or malbounded. | 6939 // Has a type specification that is not malformed or malbounded. |
| 6919 // Now form an 'if type check' as an exception type exists in the | 6940 // Now form an 'if type check' as an exception type exists in the |
| 6920 // catch specifier. | 6941 // catch specifier. |
| 6921 if (!exception_param.type.IsInstantiated() && | 6942 if (!exception_param.type->IsInstantiated() && |
| 6922 (current_block_->scope->function_level() > 0)) { | 6943 (current_block_->scope->function_level() > 0)) { |
| 6923 // Make sure that the instantiator is captured. | 6944 // Make sure that the instantiator is captured. |
| 6924 CaptureInstantiator(); | 6945 CaptureInstantiator(); |
| 6925 } | 6946 } |
| 6926 TypeNode* exception_type = new TypeNode(catch_pos, exception_param.type); | 6947 TypeNode* exception_type = new TypeNode(catch_pos, *exception_param.type); |
| 6927 AstNode* exception_value = new LoadLocalNode(catch_pos, exception_var); | 6948 AstNode* exception_var = new LoadLocalNode(catch_pos, catch_excp_var); |
| 6928 if (!exception_type->type().IsInstantiated()) { | 6949 if (!exception_type->type().IsInstantiated()) { |
| 6929 EnsureExpressionTemp(); | 6950 EnsureExpressionTemp(); |
| 6930 } | 6951 } |
| 6931 AstNode* type_cond_expr = new ComparisonNode( | 6952 AstNode* type_cond_expr = new ComparisonNode( |
| 6932 catch_pos, Token::kIS, exception_value, exception_type); | 6953 catch_pos, Token::kIS, exception_var, exception_type); |
| 6933 current_block_->statements->Add( | 6954 current_block_->statements->Add( |
| 6934 new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); | 6955 new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); |
| 6935 | 6956 |
| 6936 // Do not add uninstantiated types (e.g. type parameter T or generic | 6957 // Do not add uninstantiated types (e.g. type parameter T or |
| 6937 // type List<T>), since the debugger won't be able to instantiate it | 6958 // generic type List<T>), since the debugger won't be able to |
| 6938 // when walking the stack. This means that the debugger is not able | 6959 // instantiate it when walking the stack. |
| 6939 // to determine whether an exception is caught if the catch clause | 6960 // This means that the debugger is not able to determine whether |
| 6940 // uses generic types. It will report the exception as uncaught when | 6961 // an exception is caught if the catch clause uses generic types. |
| 6941 // in fact it might be caught and handled when we unwind the stack. | 6962 // It will report the exception as uncaught when in fact it might |
| 6942 if (exception_param.type.IsInstantiated()) { | 6963 // be caught and handled when we unwind the stack. |
| 6943 handler_types.Add(exception_param.type); | 6964 if (exception_param.type->IsInstantiated()) { |
| 6965 handler_types.Add(*exception_param.type); |
| 6944 } | 6966 } |
| 6945 } else { | 6967 } else { |
| 6946 if (is_bad_type) { | 6968 if (is_bad_type) { |
| 6947 current_block_->statements->Add(ThrowTypeError(catch_pos, | 6969 current_block_->statements->Add(ThrowTypeError(catch_pos, |
| 6948 exception_param.type)); | 6970 *exception_param.type)); |
| 6949 // We still add the dead code below to satisfy the code generator. | 6971 // We still add the dead code below to satisfy the code generator. |
| 6950 } | 6972 } |
| 6951 // No exception type exists in the catch specifier so execute the | 6973 // No exception type exists in the catch specifier so execute the |
| 6952 // catch handler code unconditionally. | 6974 // catch handler code unconditionally. |
| 6953 current_block_->statements->Add(catch_handler); | 6975 current_block_->statements->Add(catch_handler); |
| 6954 generic_catch_seen = true; | 6976 generic_catch_seen = true; |
| 6955 // This catch clause will handle all exceptions. We can safely forget | 6977 // This catch clause will handle all exceptions. We can safely forget |
| 6956 // all previous catch clause types. | 6978 // all previous catch clause types. |
| 6957 handler_types.SetLength(0); | 6979 handler_types.SetLength(0); |
| 6958 handler_types.Add(exception_param.type); | 6980 handler_types.Add(*exception_param.type); |
| 6959 } | 6981 } |
| 6960 } | 6982 } |
| 6961 SequenceNode* catch_handler_list = CloseBlock(); | 6983 SequenceNode* catch_handler_list = CloseBlock(); |
| 6962 TryBlocks* inner_try_block = PopTryBlock(); | 6984 TryBlocks* inner_try_block = PopTryBlock(); |
| 6963 const intptr_t try_index = inner_try_block->try_index(); | 6985 const intptr_t try_index = inner_try_block->try_index(); |
| 6964 TryBlocks* outer_try_block = try_blocks_list_; | 6986 TryBlocks* outer_try_block = try_blocks_list_; |
| 6965 const intptr_t outer_try_index = (outer_try_block != NULL) | 6987 const intptr_t outer_try_index = (outer_try_block != NULL) |
| 6966 ? outer_try_block->try_index() | 6988 ? outer_try_block->try_index() |
| 6967 : CatchClauseNode::kInvalidTryIndex; | 6989 : CatchClauseNode::kInvalidTryIndex; |
| 6968 | 6990 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6984 outer_try_index); | 7006 outer_try_index); |
| 6985 AddFinallyBlockToNode(node_to_inline, node); | 7007 AddFinallyBlockToNode(node_to_inline, node); |
| 6986 node_index += 1; | 7008 node_index += 1; |
| 6987 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); | 7009 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); |
| 6988 tokens_iterator_.SetCurrentPosition(finally_pos); | 7010 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 6989 } | 7011 } |
| 6990 finally_block = ParseFinallyBlock(); | 7012 finally_block = ParseFinallyBlock(); |
| 6991 } | 7013 } |
| 6992 | 7014 |
| 6993 if (!generic_catch_seen) { | 7015 if (!generic_catch_seen) { |
| 6994 // No generic catch handler exists so rethrow the exception so that the | 7016 // No generic catch handler exists so rethrow the exception so that |
| 6995 // next catch handler can deal with it. | 7017 // the next catch handler can deal with it. |
| 6996 catch_handler_list->Add( | 7018 catch_handler_list->Add( |
| 6997 new ThrowNode(handler_pos, | 7019 new ThrowNode(handler_pos, |
| 6998 new LoadLocalNode(handler_pos, exception_var), | 7020 new LoadLocalNode(handler_pos, catch_excp_var), |
| 6999 new LoadLocalNode(handler_pos, stack_trace_var))); | 7021 new LoadLocalNode(handler_pos, catch_trace_var))); |
| 7000 } | 7022 } |
| 7001 CatchClauseNode* catch_block = | 7023 CatchClauseNode* catch_block = |
| 7002 new CatchClauseNode(handler_pos, | 7024 new CatchClauseNode(handler_pos, |
| 7003 catch_handler_list, | 7025 catch_handler_list, |
| 7004 Array::ZoneHandle(Array::MakeArray(handler_types)), | 7026 Array::ZoneHandle(Array::MakeArray(handler_types)), |
| 7005 context_var, | 7027 context_var, |
| 7006 exception_var, | 7028 catch_excp_var, |
| 7007 stack_trace_var, | 7029 catch_trace_var, |
| 7008 (finally_block != NULL) | 7030 (finally_block != NULL) |
| 7009 ? AllocateTryIndex() | 7031 ? AllocateTryIndex() |
| 7010 : CatchClauseNode::kInvalidTryIndex, | 7032 : CatchClauseNode::kInvalidTryIndex, |
| 7011 needs_stack_trace); | 7033 needs_stacktrace); |
| 7012 | 7034 |
| 7013 // Now create the try/catch ast node and return it. If there is a label on | 7035 // Now create the try/catch ast node and return it. If there is a label |
| 7014 // the try/catch, close the block that's embedding the try statement and | 7036 // on the try/catch, close the block that's embedding the try statement |
| 7015 // attach the label to it. | 7037 // and attach the label to it. |
| 7016 AstNode* try_catch_node = | 7038 AstNode* try_catch_node = |
| 7017 new TryCatchNode(try_pos, try_block, end_catch_label, | 7039 new TryCatchNode(try_pos, try_block, end_catch_label, |
| 7018 context_var, catch_block, finally_block, try_index); | 7040 context_var, catch_block, finally_block, try_index); |
| 7019 | 7041 |
| 7020 if (try_label != NULL) { | 7042 if (try_label != NULL) { |
| 7021 current_block_->statements->Add(try_catch_node); | 7043 current_block_->statements->Add(try_catch_node); |
| 7022 SequenceNode* sequence = CloseBlock(); | 7044 SequenceNode* sequence = CloseBlock(); |
| 7023 sequence->set_label(try_label); | 7045 sequence->set_label(try_label); |
| 7024 try_catch_node = sequence; | 7046 try_catch_node = sequence; |
| 7025 } | 7047 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7173 ExpectSemicolon(); | 7195 ExpectSemicolon(); |
| 7174 // Check if it is ok to do a rethrow. | 7196 // Check if it is ok to do a rethrow. |
| 7175 SourceLabel* label = current_block_->scope->LookupInnermostCatchLabel(); | 7197 SourceLabel* label = current_block_->scope->LookupInnermostCatchLabel(); |
| 7176 if (label == NULL || | 7198 if (label == NULL || |
| 7177 label->FunctionLevel() != current_block_->scope->function_level()) { | 7199 label->FunctionLevel() != current_block_->scope->function_level()) { |
| 7178 ErrorMsg(statement_pos, "rethrow of an exception is not valid here"); | 7200 ErrorMsg(statement_pos, "rethrow of an exception is not valid here"); |
| 7179 } | 7201 } |
| 7180 ASSERT(label->owner() != NULL); | 7202 ASSERT(label->owner() != NULL); |
| 7181 LocalScope* scope = label->owner()->parent(); | 7203 LocalScope* scope = label->owner()->parent(); |
| 7182 ASSERT(scope != NULL); | 7204 ASSERT(scope != NULL); |
| 7183 LocalVariable* exception_var = | 7205 LocalVariable* excp_var = |
| 7184 scope->LocalLookupVariable(Symbols::ExceptionVar()); | 7206 scope->LocalLookupVariable(Symbols::ExceptionVar()); |
| 7185 ASSERT(exception_var != NULL); | 7207 ASSERT(excp_var != NULL); |
| 7186 LocalVariable* stack_trace_var = | 7208 LocalVariable* trace_var = |
| 7187 scope->LocalLookupVariable(Symbols::StackTraceVar()); | 7209 scope->LocalLookupVariable(Symbols::StacktraceVar()); |
| 7188 ASSERT(stack_trace_var != NULL); | 7210 ASSERT(trace_var != NULL); |
| 7189 statement = | 7211 statement = new ThrowNode(statement_pos, |
| 7190 new ThrowNode(statement_pos, | 7212 new LoadLocalNode(statement_pos, excp_var), |
| 7191 new LoadLocalNode(statement_pos, exception_var), | 7213 new LoadLocalNode(statement_pos, trace_var)); |
| 7192 new LoadLocalNode(statement_pos, stack_trace_var)); | |
| 7193 } else { | 7214 } else { |
| 7194 statement = ParseExpr(kAllowConst, kConsumeCascades); | 7215 statement = ParseExpr(kAllowConst, kConsumeCascades); |
| 7195 ExpectSemicolon(); | 7216 ExpectSemicolon(); |
| 7196 } | 7217 } |
| 7197 return statement; | 7218 return statement; |
| 7198 } | 7219 } |
| 7199 | 7220 |
| 7200 | 7221 |
| 7201 RawError* Parser::FormatErrorWithAppend(const Error& prev_error, | 7222 RawError* Parser::FormatErrorWithAppend(const Error& prev_error, |
| 7202 const Script& script, | 7223 const Script& script, |
| (...skipping 3535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10738 void Parser::SkipQualIdent() { | 10759 void Parser::SkipQualIdent() { |
| 10739 ASSERT(IsIdentifier()); | 10760 ASSERT(IsIdentifier()); |
| 10740 ConsumeToken(); | 10761 ConsumeToken(); |
| 10741 if (CurrentToken() == Token::kPERIOD) { | 10762 if (CurrentToken() == Token::kPERIOD) { |
| 10742 ConsumeToken(); // Consume the kPERIOD token. | 10763 ConsumeToken(); // Consume the kPERIOD token. |
| 10743 ExpectIdentifier("identifier expected after '.'"); | 10764 ExpectIdentifier("identifier expected after '.'"); |
| 10744 } | 10765 } |
| 10745 } | 10766 } |
| 10746 | 10767 |
| 10747 } // namespace dart | 10768 } // namespace dart |
| OLD | NEW |