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