| 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 "platform/utils.h" |
| 9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
| 10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
| (...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 node_sequence = parser.ParseInstanceGetter(func); | 821 node_sequence = parser.ParseInstanceGetter(func); |
| 822 break; | 822 break; |
| 823 case RawFunction::kImplicitSetter: | 823 case RawFunction::kImplicitSetter: |
| 824 ASSERT(!func.is_static()); | 824 ASSERT(!func.is_static()); |
| 825 node_sequence = parser.ParseInstanceSetter(func); | 825 node_sequence = parser.ParseInstanceSetter(func); |
| 826 break; | 826 break; |
| 827 case RawFunction::kImplicitStaticFinalGetter: | 827 case RawFunction::kImplicitStaticFinalGetter: |
| 828 node_sequence = parser.ParseStaticFinalGetter(func); | 828 node_sequence = parser.ParseStaticFinalGetter(func); |
| 829 CompilerStats::num_implicit_final_getters++; | 829 CompilerStats::num_implicit_final_getters++; |
| 830 break; | 830 break; |
| 831 case RawFunction::kStaticInitializer: | |
| 832 node_sequence = parser.ParseStaticInitializer(func); | |
| 833 CompilerStats::num_static_initializer_funcs++; | |
| 834 break; | |
| 835 case RawFunction::kMethodExtractor: | 831 case RawFunction::kMethodExtractor: |
| 836 node_sequence = parser.ParseMethodExtractor(func); | 832 node_sequence = parser.ParseMethodExtractor(func); |
| 837 break; | 833 break; |
| 838 case RawFunction::kNoSuchMethodDispatcher: | 834 case RawFunction::kNoSuchMethodDispatcher: |
| 839 node_sequence = | 835 node_sequence = |
| 840 parser.ParseNoSuchMethodDispatcher(func, &default_parameter_values); | 836 parser.ParseNoSuchMethodDispatcher(func, &default_parameter_values); |
| 841 break; | 837 break; |
| 842 case RawFunction::kInvokeFieldDispatcher: | 838 case RawFunction::kInvokeFieldDispatcher: |
| 843 node_sequence = | 839 node_sequence = |
| 844 parser.ParseInvokeFieldDispatcher(func, &default_parameter_values); | 840 parser.ParseInvokeFieldDispatcher(func, &default_parameter_values); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 996 if (expr->EvalConstExpr() == NULL) { | 992 if (expr->EvalConstExpr() == NULL) { |
| 997 ReportError(expr_pos, "expression must be a compile-time constant"); | 993 ReportError(expr_pos, "expression must be a compile-time constant"); |
| 998 } | 994 } |
| 999 const Instance& val = EvaluateConstExpr(expr_pos, expr); | 995 const Instance& val = EvaluateConstExpr(expr_pos, expr); |
| 1000 meta_values.Add(val); | 996 meta_values.Add(val); |
| 1001 } | 997 } |
| 1002 return Array::MakeArray(meta_values); | 998 return Array::MakeArray(meta_values); |
| 1003 } | 999 } |
| 1004 | 1000 |
| 1005 | 1001 |
| 1002 SequenceNode* Parser::ParseStaticInitializer() { |
| 1003 ExpectIdentifier("field name expected"); |
| 1004 CheckToken(Token::kASSIGN, "field initialier expected"); |
| 1005 ConsumeToken(); |
| 1006 OpenFunctionBlock(parsed_function()->function()); |
| 1007 intptr_t expr_pos = TokenPos(); |
| 1008 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 1009 ReturnNode* ret = new(I) ReturnNode(expr_pos, expr); |
| 1010 current_block_->statements->Add(ret); |
| 1011 return CloseBlock(); |
| 1012 } |
| 1013 |
| 1014 |
| 1015 ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) { |
| 1016 ASSERT(field.is_static()); |
| 1017 ASSERT(field.value() == Object::transition_sentinel().raw()); |
| 1018 Isolate* isolate = Isolate::Current(); |
| 1019 |
| 1020 const Class& script_cls = Class::Handle(isolate, field.origin()); |
| 1021 const Script& script = Script::Handle(isolate, script_cls.script()); |
| 1022 |
| 1023 const String& field_name = String::Handle(isolate, field.name()); |
| 1024 String& init_name = String::Handle(isolate, |
| 1025 String::Concat(Symbols::InitPrefix(), field_name)); |
| 1026 init_name = Symbols::New(init_name); |
| 1027 |
| 1028 const Function& initializer = Function::ZoneHandle(isolate, |
| 1029 Function::New(init_name, |
| 1030 RawFunction::kRegularFunction, |
| 1031 true, // static |
| 1032 false, // !const |
| 1033 false, // !abstract |
| 1034 false, // !external |
| 1035 false, // !native |
| 1036 Class::Handle(field.owner()), |
| 1037 field.token_pos())); |
| 1038 initializer.set_result_type(AbstractType::Handle(isolate, field.type())); |
| 1039 // Static initializer functions are hidden from the user. |
| 1040 // Since they are only executed once, we avoid optimizing |
| 1041 // and inlining them. After the field is initialized, the |
| 1042 // compiler can eliminate the call to the static initializer. |
| 1043 initializer.set_is_visible(false); |
| 1044 initializer.SetIsOptimizable(false); |
| 1045 initializer.set_is_inlinable(false); |
| 1046 |
| 1047 ParsedFunction* parsed_function = new ParsedFunction(isolate, initializer); |
| 1048 Parser parser(script, parsed_function, field.token_pos()); |
| 1049 |
| 1050 SequenceNode* body = parser.ParseStaticInitializer(); |
| 1051 parsed_function->SetNodeSequence(body); |
| 1052 parsed_function->set_default_parameter_values(Object::null_array()); |
| 1053 |
| 1054 if (parsed_function->has_expression_temp_var()) { |
| 1055 body->scope()->AddVariable(parsed_function->expression_temp_var()); |
| 1056 } |
| 1057 if (parsed_function->has_saved_current_context_var()) { |
| 1058 body->scope()->AddVariable(parsed_function->saved_current_context_var()); |
| 1059 } |
| 1060 if (parsed_function->has_finally_return_temp_var()) { |
| 1061 body->scope()->AddVariable(parsed_function->finally_return_temp_var()); |
| 1062 } |
| 1063 // The instantiator is not required in a static expression. |
| 1064 ASSERT(!parser.IsInstantiatorRequired()); |
| 1065 |
| 1066 return parsed_function; |
| 1067 } |
| 1068 |
| 1069 |
| 1006 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { | 1070 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { |
| 1007 TRACE_PARSER("ParseStaticFinalGetter"); | 1071 TRACE_PARSER("ParseStaticFinalGetter"); |
| 1008 ParamList params; | 1072 ParamList params; |
| 1009 ASSERT(func.num_fixed_parameters() == 0); // static. | 1073 ASSERT(func.num_fixed_parameters() == 0); // static. |
| 1010 ASSERT(!func.HasOptionalParameters()); | 1074 ASSERT(!func.HasOptionalParameters()); |
| 1011 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); | 1075 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); |
| 1012 | 1076 |
| 1013 // Build local scope for function and populate with the formal parameters. | 1077 // Build local scope for function and populate with the formal parameters. |
| 1014 OpenFunctionBlock(func); | 1078 OpenFunctionBlock(func); |
| 1015 AddFormalParamsToScope(¶ms, current_block_->scope); | 1079 AddFormalParamsToScope(¶ms, current_block_->scope); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1032 // leave the evaluation to the getter function. | 1096 // leave the evaluation to the getter function. |
| 1033 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 1097 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 1034 // This getter will only be called once at compile time. | 1098 // This getter will only be called once at compile time. |
| 1035 if (expr->EvalConstExpr() == NULL) { | 1099 if (expr->EvalConstExpr() == NULL) { |
| 1036 ReportError(expr_pos, "initializer is not a valid compile-time constant"); | 1100 ReportError(expr_pos, "initializer is not a valid compile-time constant"); |
| 1037 } | 1101 } |
| 1038 ReturnNode* return_node = new ReturnNode(ident_pos, expr); | 1102 ReturnNode* return_node = new ReturnNode(ident_pos, expr); |
| 1039 current_block_->statements->Add(return_node); | 1103 current_block_->statements->Add(return_node); |
| 1040 } else { | 1104 } else { |
| 1041 // This getter may be called each time the static field is accessed. | 1105 // This getter may be called each time the static field is accessed. |
| 1042 // The following generated code lazily initializes the field: | 1106 // Call runtime support to parse and evaluate the initializer expression. |
| 1043 // if (field.value === transition_sentinel) { | 1107 // The runtime function will detect circular dependencies in expressions |
| 1044 // field.value = null; | 1108 // and handle errors while evaluating the expression. |
| 1045 // throw("circular dependency in field initialization"); | 1109 current_block_->statements->Add( |
| 1046 // } | 1110 new (I) InitStaticFieldNode(ident_pos, field)); |
| 1047 // if (field.value === sentinel) { | |
| 1048 // field.value = transition_sentinel; | |
| 1049 // field.value = expr; | |
| 1050 // } | |
| 1051 // return field.value; // Type check is executed here in checked mode. | |
| 1052 | |
| 1053 // Generate code checking for circular dependency in field initialization. | |
| 1054 AstNode* compare_circular = new ComparisonNode( | |
| 1055 ident_pos, | |
| 1056 Token::kEQ_STRICT, | |
| 1057 new LoadStaticFieldNode(ident_pos, field), | |
| 1058 new LiteralNode(ident_pos, Object::transition_sentinel())); | |
| 1059 // Set field to null prior to throwing exception, so that subsequent | |
| 1060 // accesses to the field do not throw again, since initializers should only | |
| 1061 // be executed once. | |
| 1062 SequenceNode* report_circular = new SequenceNode(ident_pos, NULL); | |
| 1063 report_circular->Add( | |
| 1064 new StoreStaticFieldNode( | |
| 1065 ident_pos, | |
| 1066 field, | |
| 1067 new LiteralNode(ident_pos, Instance::ZoneHandle(I)))); | |
| 1068 // Call CyclicInitializationError._throwNew(field_name). | |
| 1069 ArgumentListNode* error_arguments = new ArgumentListNode(ident_pos); | |
| 1070 error_arguments->Add(new LiteralNode(ident_pos, field_name)); | |
| 1071 report_circular->Add( | |
| 1072 MakeStaticCall(Symbols::CyclicInitializationError(), | |
| 1073 Library::PrivateCoreLibName(Symbols::ThrowNew()), | |
| 1074 error_arguments)); | |
| 1075 AstNode* circular_check = | |
| 1076 new IfNode(ident_pos, compare_circular, report_circular, NULL); | |
| 1077 current_block_->statements->Add(circular_check); | |
| 1078 | |
| 1079 // Generate code checking for uninitialized field. | |
| 1080 AstNode* compare_uninitialized = new ComparisonNode( | |
| 1081 ident_pos, | |
| 1082 Token::kEQ_STRICT, | |
| 1083 new LoadStaticFieldNode(ident_pos, field), | |
| 1084 new LiteralNode(ident_pos, Object::sentinel())); | |
| 1085 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL); | |
| 1086 initialize_field->Add( | |
| 1087 new StoreStaticFieldNode( | |
| 1088 ident_pos, | |
| 1089 field, | |
| 1090 new LiteralNode(ident_pos, Object::transition_sentinel()))); | |
| 1091 const String& init_name = String::Handle(I, Symbols::New( | |
| 1092 String::Handle(I, String::Concat( | |
| 1093 Symbols::InitPrefix(), String::Handle(I, field.name()))))); | |
| 1094 const Function& init_function = Function::ZoneHandle(I, | |
| 1095 field_class.LookupStaticFunction(init_name)); | |
| 1096 ASSERT(!init_function.IsNull()); | |
| 1097 ArgumentListNode* arguments = new ArgumentListNode(expr_pos); | |
| 1098 StaticCallNode* init_call = | |
| 1099 new StaticCallNode(expr_pos, init_function, arguments); | |
| 1100 initialize_field->Add(init_call); | |
| 1101 | |
| 1102 AstNode* uninitialized_check = | |
| 1103 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL); | |
| 1104 current_block_->statements->Add(uninitialized_check); | |
| 1105 | |
| 1106 // Generate code returning the field value. | |
| 1107 ReturnNode* return_node = | 1111 ReturnNode* return_node = |
| 1108 new ReturnNode(ident_pos, new LoadStaticFieldNode(ident_pos, field)); | 1112 new ReturnNode(ident_pos, |
| 1113 new LoadStaticFieldNode(ident_pos, field)); |
| 1109 current_block_->statements->Add(return_node); | 1114 current_block_->statements->Add(return_node); |
| 1110 } | 1115 } |
| 1111 return CloseBlock(); | 1116 return CloseBlock(); |
| 1112 } | 1117 } |
| 1113 | 1118 |
| 1114 | 1119 |
| 1115 SequenceNode* Parser::ParseStaticInitializer(const Function& func) { | |
| 1116 TRACE_PARSER("ParseStaticInitializer"); | |
| 1117 ParamList params; | |
| 1118 ASSERT(func.num_fixed_parameters() == 0); // static. | |
| 1119 ASSERT(!func.HasOptionalParameters()); | |
| 1120 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); | |
| 1121 | |
| 1122 // Build local scope for function and populate with the formal parameters. | |
| 1123 OpenFunctionBlock(func); | |
| 1124 AddFormalParamsToScope(¶ms, current_block_->scope); | |
| 1125 | |
| 1126 // Move forward to the start of the initializer expression. | |
| 1127 intptr_t ident_pos = TokenPos(); | |
| 1128 ExpectIdentifier("identifier expected"); | |
| 1129 ExpectToken(Token::kASSIGN); | |
| 1130 intptr_t token_pos = TokenPos(); | |
| 1131 | |
| 1132 // Synthesize a try-catch block to wrap the initializer expression. | |
| 1133 LocalVariable* context_var = | |
| 1134 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); | |
| 1135 if (context_var == NULL) { | |
| 1136 context_var = new(I) LocalVariable( | |
| 1137 token_pos, | |
| 1138 Symbols::SavedTryContextVar(), | |
| 1139 Type::ZoneHandle(I, Type::DynamicType())); | |
| 1140 current_block_->scope->AddVariable(context_var); | |
| 1141 } | |
| 1142 LocalVariable* catch_excp_var = | |
| 1143 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); | |
| 1144 if (catch_excp_var == NULL) { | |
| 1145 catch_excp_var = new (I) LocalVariable( | |
| 1146 token_pos, | |
| 1147 Symbols::ExceptionVar(), | |
| 1148 Type::ZoneHandle(I, Type::DynamicType())); | |
| 1149 current_block_->scope->AddVariable(catch_excp_var); | |
| 1150 } | |
| 1151 LocalVariable* catch_trace_var = | |
| 1152 current_block_->scope->LocalLookupVariable(Symbols::StackTraceVar()); | |
| 1153 if (catch_trace_var == NULL) { | |
| 1154 catch_trace_var = new (I) LocalVariable( | |
| 1155 token_pos, | |
| 1156 Symbols::StackTraceVar(), | |
| 1157 Type::ZoneHandle(I, Type::DynamicType())); | |
| 1158 current_block_->scope->AddVariable(catch_trace_var); | |
| 1159 } | |
| 1160 | |
| 1161 OpenBlock(); // Start try block. | |
| 1162 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | |
| 1163 const Field& field = Field::ZoneHandle(I, func.saved_static_field()); | |
| 1164 ASSERT(!field.is_const()); | |
| 1165 if (FLAG_enable_type_checks) { | |
| 1166 expr = new AssignableNode( | |
| 1167 field.token_pos(), | |
| 1168 expr, | |
| 1169 AbstractType::ZoneHandle(I, field.type()), | |
| 1170 String::ZoneHandle(I, field.name())); | |
| 1171 } | |
| 1172 StoreStaticFieldNode* store = new StoreStaticFieldNode(field.token_pos(), | |
| 1173 field, | |
| 1174 expr); | |
| 1175 current_block_->statements->Add(store); | |
| 1176 SequenceNode* try_block = CloseBlock(); // End try block. | |
| 1177 | |
| 1178 OpenBlock(); // Start catch handler list. | |
| 1179 OpenBlock(); // Start catch clause. | |
| 1180 AstNode* compare_transition_sentinel = new ComparisonNode( | |
| 1181 token_pos, | |
| 1182 Token::kEQ_STRICT, | |
| 1183 new LoadStaticFieldNode(ident_pos, field), | |
| 1184 new LiteralNode(field.token_pos(), Object::transition_sentinel())); | |
| 1185 | |
| 1186 SequenceNode* store_null = new SequenceNode(token_pos, NULL); | |
| 1187 store_null->Add(new StoreStaticFieldNode( | |
| 1188 field.token_pos(), | |
| 1189 field, | |
| 1190 new LiteralNode(token_pos, Instance::ZoneHandle(I)))); | |
| 1191 AstNode* transition_sentinel_check = | |
| 1192 new IfNode(token_pos, compare_transition_sentinel, store_null, NULL); | |
| 1193 current_block_->statements->Add(transition_sentinel_check); | |
| 1194 | |
| 1195 current_block_->statements->Add( | |
| 1196 new ThrowNode(token_pos, | |
| 1197 new LoadLocalNode(token_pos, catch_excp_var), | |
| 1198 new LoadLocalNode(token_pos, catch_trace_var))); | |
| 1199 SequenceNode* catch_clause = CloseBlock(); // End catch clause. | |
| 1200 | |
| 1201 current_block_->statements->Add(catch_clause); | |
| 1202 SequenceNode* catch_handler_list = CloseBlock(); // End catch handler list. | |
| 1203 CatchClauseNode* catch_block = | |
| 1204 new CatchClauseNode(token_pos, | |
| 1205 catch_handler_list, | |
| 1206 Array::ZoneHandle(I, Object::empty_array().raw()), | |
| 1207 context_var, | |
| 1208 catch_excp_var, | |
| 1209 catch_trace_var, | |
| 1210 CatchClauseNode::kInvalidTryIndex, | |
| 1211 false); // No stack trace needed. | |
| 1212 | |
| 1213 AstNode* try_catch_node = new TryCatchNode(token_pos, | |
| 1214 try_block, | |
| 1215 context_var, | |
| 1216 catch_block, | |
| 1217 NULL, // No finally block. | |
| 1218 AllocateTryIndex()); | |
| 1219 current_block_->statements->Add(try_catch_node); | |
| 1220 return CloseBlock(); | |
| 1221 } | |
| 1222 | |
| 1223 | |
| 1224 // Create AstNodes for an implicit instance getter method: | 1120 // Create AstNodes for an implicit instance getter method: |
| 1225 // LoadLocalNode 0 ('this'); | 1121 // LoadLocalNode 0 ('this'); |
| 1226 // LoadInstanceFieldNode (field_name); | 1122 // LoadInstanceFieldNode (field_name); |
| 1227 // ReturnNode (field's value); | 1123 // ReturnNode (field's value); |
| 1228 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { | 1124 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { |
| 1229 TRACE_PARSER("ParseInstanceGetter"); | 1125 TRACE_PARSER("ParseInstanceGetter"); |
| 1230 ParamList params; | 1126 ParamList params; |
| 1231 // func.token_pos() points to the name of the field. | 1127 // func.token_pos() points to the name of the field. |
| 1232 const intptr_t ident_pos = func.token_pos(); | 1128 const intptr_t ident_pos = func.token_pos(); |
| 1233 ASSERT(current_class().raw() == func.Owner()); | 1129 ASSERT(current_class().raw() == func.Owner()); |
| (...skipping 2454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3688 RawFunction::kImplicitStaticFinalGetter, | 3584 RawFunction::kImplicitStaticFinalGetter, |
| 3689 field->has_static, | 3585 field->has_static, |
| 3690 field->has_const, | 3586 field->has_const, |
| 3691 /* is_abstract = */ false, | 3587 /* is_abstract = */ false, |
| 3692 /* is_external = */ false, | 3588 /* is_external = */ false, |
| 3693 /* is_native = */ false, | 3589 /* is_native = */ false, |
| 3694 current_class(), | 3590 current_class(), |
| 3695 field->name_pos); | 3591 field->name_pos); |
| 3696 getter.set_result_type(*field->type); | 3592 getter.set_result_type(*field->type); |
| 3697 members->AddFunction(getter); | 3593 members->AddFunction(getter); |
| 3698 | |
| 3699 // Create initializer function for non-const fields. | |
| 3700 if (!class_field.is_const()) { | |
| 3701 const Function& init_function = Function::ZoneHandle(I, | |
| 3702 Function::NewStaticInitializer(class_field)); | |
| 3703 members->AddFunction(init_function); | |
| 3704 } | |
| 3705 } | 3594 } |
| 3706 } | 3595 } |
| 3707 | 3596 |
| 3708 // For instance fields, we create implicit getter and setter methods. | 3597 // For instance fields, we create implicit getter and setter methods. |
| 3709 if (!field->has_static) { | 3598 if (!field->has_static) { |
| 3710 String& getter_name = String::Handle(I, | 3599 String& getter_name = String::Handle(I, |
| 3711 Field::GetterSymbol(*field->name)); | 3600 Field::GetterSymbol(*field->name)); |
| 3712 getter = Function::New(getter_name, RawFunction::kImplicitGetter, | 3601 getter = Function::New(getter_name, RawFunction::kImplicitGetter, |
| 3713 field->has_static, | 3602 field->has_static, |
| 3714 field->has_final, | 3603 field->has_final, |
| (...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4853 RawFunction::kImplicitStaticFinalGetter, | 4742 RawFunction::kImplicitStaticFinalGetter, |
| 4854 is_static, | 4743 is_static, |
| 4855 is_const, | 4744 is_const, |
| 4856 /* is_abstract = */ false, | 4745 /* is_abstract = */ false, |
| 4857 /* is_external = */ false, | 4746 /* is_external = */ false, |
| 4858 /* is_native = */ false, | 4747 /* is_native = */ false, |
| 4859 current_class(), | 4748 current_class(), |
| 4860 name_pos); | 4749 name_pos); |
| 4861 getter.set_result_type(type); | 4750 getter.set_result_type(type); |
| 4862 top_level->functions.Add(getter); | 4751 top_level->functions.Add(getter); |
| 4863 | |
| 4864 // Create initializer function. | |
| 4865 if (!field.is_const()) { | |
| 4866 const Function& init_function = Function::ZoneHandle(I, | |
| 4867 Function::NewStaticInitializer(field)); | |
| 4868 top_level->functions.Add(init_function); | |
| 4869 } | |
| 4870 } | 4752 } |
| 4871 } else if (is_final) { | 4753 } else if (is_final) { |
| 4872 ReportError(name_pos, "missing initializer for final or const variable"); | 4754 ReportError(name_pos, "missing initializer for final or const variable"); |
| 4873 } | 4755 } |
| 4874 | 4756 |
| 4875 if (CurrentToken() == Token::kCOMMA) { | 4757 if (CurrentToken() == Token::kCOMMA) { |
| 4876 ConsumeToken(); | 4758 ConsumeToken(); |
| 4877 } else if (CurrentToken() == Token::kSEMICOLON) { | 4759 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 4878 ConsumeToken(); | 4760 ConsumeToken(); |
| 4879 break; | 4761 break; |
| (...skipping 6143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11023 ASSERT(field.is_const()); | 10905 ASSERT(field.is_const()); |
| 11024 ASSERT(field.value() != Object::sentinel().raw()); | 10906 ASSERT(field.value() != Object::sentinel().raw()); |
| 11025 ASSERT(field.value() != Object::transition_sentinel().raw()); | 10907 ASSERT(field.value() != Object::transition_sentinel().raw()); |
| 11026 return Instance::ZoneHandle(I, field.value()); | 10908 return Instance::ZoneHandle(I, field.value()); |
| 11027 } else { | 10909 } else { |
| 11028 ASSERT(expr->EvalConstExpr() != NULL); | 10910 ASSERT(expr->EvalConstExpr() != NULL); |
| 11029 ReturnNode* ret = new(I) ReturnNode(expr->token_pos(), expr); | 10911 ReturnNode* ret = new(I) ReturnNode(expr->token_pos(), expr); |
| 11030 // Compile time constant expressions cannot reference anything from a | 10912 // Compile time constant expressions cannot reference anything from a |
| 11031 // local scope. | 10913 // local scope. |
| 11032 LocalScope* empty_scope = new(I) LocalScope(NULL, 0, 0); | 10914 LocalScope* empty_scope = new(I) LocalScope(NULL, 0, 0); |
| 11033 SequenceNode* seq = new(I) SequenceNode(expr->token_pos(), | 10915 SequenceNode* seq = new(I) SequenceNode(expr->token_pos(), empty_scope); |
| 11034 empty_scope); | |
| 11035 seq->Add(ret); | 10916 seq->Add(ret); |
| 11036 | 10917 |
| 11037 Object& result = Object::Handle(I, Compiler::ExecuteOnce(seq)); | 10918 Object& result = Object::Handle(I, Compiler::ExecuteOnce(seq)); |
| 11038 if (result.IsError()) { | 10919 if (result.IsError()) { |
| 11039 ReportErrors(Error::Cast(result), | 10920 ReportErrors(Error::Cast(result), |
| 11040 script_, expr_pos, | 10921 script_, expr_pos, |
| 11041 "error evaluating constant expression"); | 10922 "error evaluating constant expression"); |
| 11042 } | 10923 } |
| 11043 ASSERT(result.IsInstance()); | 10924 ASSERT(result.IsInstance()); |
| 11044 Instance& value = Instance::ZoneHandle(I); | 10925 Instance& value = Instance::ZoneHandle(I); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11377 void Parser::SkipQualIdent() { | 11258 void Parser::SkipQualIdent() { |
| 11378 ASSERT(IsIdentifier()); | 11259 ASSERT(IsIdentifier()); |
| 11379 ConsumeToken(); | 11260 ConsumeToken(); |
| 11380 if (CurrentToken() == Token::kPERIOD) { | 11261 if (CurrentToken() == Token::kPERIOD) { |
| 11381 ConsumeToken(); // Consume the kPERIOD token. | 11262 ConsumeToken(); // Consume the kPERIOD token. |
| 11382 ExpectIdentifier("identifier expected after '.'"); | 11263 ExpectIdentifier("identifier expected after '.'"); |
| 11383 } | 11264 } |
| 11384 } | 11265 } |
| 11385 | 11266 |
| 11386 } // namespace dart | 11267 } // namespace dart |
| OLD | NEW |