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/bootstrap.h" | 9 #include "vm/bootstrap.h" |
10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
(...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 node_sequence = parser.ParseInstanceGetter(func); | 820 node_sequence = parser.ParseInstanceGetter(func); |
821 break; | 821 break; |
822 case RawFunction::kImplicitSetter: | 822 case RawFunction::kImplicitSetter: |
823 ASSERT(!func.is_static()); | 823 ASSERT(!func.is_static()); |
824 node_sequence = parser.ParseInstanceSetter(func); | 824 node_sequence = parser.ParseInstanceSetter(func); |
825 break; | 825 break; |
826 case RawFunction::kImplicitStaticFinalGetter: | 826 case RawFunction::kImplicitStaticFinalGetter: |
827 node_sequence = parser.ParseStaticFinalGetter(func); | 827 node_sequence = parser.ParseStaticFinalGetter(func); |
828 CompilerStats::num_implicit_final_getters++; | 828 CompilerStats::num_implicit_final_getters++; |
829 break; | 829 break; |
830 case RawFunction::kStaticInitializer: | |
831 node_sequence = parser.ParseStaticInitializer(func); | |
832 CompilerStats::num_static_initializer_funcs++; | |
833 break; | |
834 case RawFunction::kMethodExtractor: | 830 case RawFunction::kMethodExtractor: |
835 node_sequence = parser.ParseMethodExtractor(func); | 831 node_sequence = parser.ParseMethodExtractor(func); |
836 break; | 832 break; |
837 case RawFunction::kNoSuchMethodDispatcher: | 833 case RawFunction::kNoSuchMethodDispatcher: |
838 node_sequence = | 834 node_sequence = |
839 parser.ParseNoSuchMethodDispatcher(func, &default_parameter_values); | 835 parser.ParseNoSuchMethodDispatcher(func, &default_parameter_values); |
840 break; | 836 break; |
841 case RawFunction::kInvokeFieldDispatcher: | 837 case RawFunction::kInvokeFieldDispatcher: |
842 node_sequence = | 838 node_sequence = |
843 parser.ParseInvokeFieldDispatcher(func, &default_parameter_values); | 839 parser.ParseInvokeFieldDispatcher(func, &default_parameter_values); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 if (expr->EvalConstExpr() == NULL) { | 991 if (expr->EvalConstExpr() == NULL) { |
996 ReportError(expr_pos, "expression must be a compile-time constant"); | 992 ReportError(expr_pos, "expression must be a compile-time constant"); |
997 } | 993 } |
998 const Instance& val = EvaluateConstExpr(expr_pos, expr); | 994 const Instance& val = EvaluateConstExpr(expr_pos, expr); |
999 meta_values.Add(val); | 995 meta_values.Add(val); |
1000 } | 996 } |
1001 return Array::MakeArray(meta_values); | 997 return Array::MakeArray(meta_values); |
1002 } | 998 } |
1003 | 999 |
1004 | 1000 |
| 1001 SequenceNode* Parser::ParseStaticInitializer() { |
| 1002 ExpectIdentifier("field name expected"); |
| 1003 CheckToken(Token::kASSIGN, "field initialier expected"); |
| 1004 ConsumeToken(); |
| 1005 OpenFunctionBlock(parsed_function()->function()); |
| 1006 intptr_t expr_pos = TokenPos(); |
| 1007 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 1008 ReturnNode* ret = new(I) ReturnNode(expr_pos, expr); |
| 1009 current_block_->statements->Add(ret); |
| 1010 return CloseBlock(); |
| 1011 } |
| 1012 |
| 1013 |
| 1014 ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) { |
| 1015 ASSERT(field.is_static()); |
| 1016 ASSERT(field.value() == Object::transition_sentinel().raw()); |
| 1017 Isolate* isolate = Isolate::Current(); |
| 1018 |
| 1019 const Class& script_cls = Class::Handle(isolate, field.origin()); |
| 1020 const Script& script = Script::Handle(isolate, script_cls.script()); |
| 1021 |
| 1022 const String& field_name = String::Handle(isolate, field.name()); |
| 1023 String& init_name = String::Handle(isolate, |
| 1024 String::Concat(Symbols::InitPrefix(), field_name)); |
| 1025 init_name = Symbols::New(init_name); |
| 1026 |
| 1027 const Function& initializer = Function::ZoneHandle(isolate, |
| 1028 Function::New(init_name, |
| 1029 RawFunction::kRegularFunction, |
| 1030 true, // static |
| 1031 false, // !const |
| 1032 false, // !abstract |
| 1033 false, // !external |
| 1034 false, // !native |
| 1035 Class::Handle(field.owner()), |
| 1036 field.token_pos())); |
| 1037 initializer.set_result_type(AbstractType::Handle(isolate, field.type())); |
| 1038 // Static initializer functions are hidden from the user. |
| 1039 // Since they are only executed once, we avoid optimizing |
| 1040 // and inlining them. After the field is initialized, the |
| 1041 // compiler can eliminate the call to the static initializer. |
| 1042 initializer.set_is_visible(false); |
| 1043 initializer.SetIsOptimizable(false); |
| 1044 initializer.set_is_inlinable(false); |
| 1045 |
| 1046 ParsedFunction* parsed_function = new ParsedFunction(isolate, initializer); |
| 1047 Parser parser(script, parsed_function, field.token_pos()); |
| 1048 |
| 1049 SequenceNode* body = parser.ParseStaticInitializer(); |
| 1050 parsed_function->SetNodeSequence(body); |
| 1051 parsed_function->set_default_parameter_values(Object::null_array()); |
| 1052 |
| 1053 if (parsed_function->has_expression_temp_var()) { |
| 1054 body->scope()->AddVariable(parsed_function->expression_temp_var()); |
| 1055 } |
| 1056 if (parsed_function->has_saved_current_context_var()) { |
| 1057 body->scope()->AddVariable(parsed_function->saved_current_context_var()); |
| 1058 } |
| 1059 if (parsed_function->has_finally_return_temp_var()) { |
| 1060 body->scope()->AddVariable(parsed_function->finally_return_temp_var()); |
| 1061 } |
| 1062 // The instantiator is not required in a static expression. |
| 1063 ASSERT(!parser.IsInstantiatorRequired()); |
| 1064 |
| 1065 return parsed_function; |
| 1066 } |
| 1067 |
| 1068 |
1005 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { | 1069 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { |
1006 TRACE_PARSER("ParseStaticFinalGetter"); | 1070 TRACE_PARSER("ParseStaticFinalGetter"); |
1007 ParamList params; | 1071 ParamList params; |
1008 ASSERT(func.num_fixed_parameters() == 0); // static. | 1072 ASSERT(func.num_fixed_parameters() == 0); // static. |
1009 ASSERT(!func.HasOptionalParameters()); | 1073 ASSERT(!func.HasOptionalParameters()); |
1010 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); | 1074 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); |
1011 | 1075 |
1012 // Build local scope for function and populate with the formal parameters. | 1076 // Build local scope for function and populate with the formal parameters. |
1013 OpenFunctionBlock(func); | 1077 OpenFunctionBlock(func); |
1014 AddFormalParamsToScope(¶ms, current_block_->scope); | 1078 AddFormalParamsToScope(¶ms, current_block_->scope); |
(...skipping 16 matching lines...) Expand all Loading... |
1031 // leave the evaluation to the getter function. | 1095 // leave the evaluation to the getter function. |
1032 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 1096 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
1033 // This getter will only be called once at compile time. | 1097 // This getter will only be called once at compile time. |
1034 if (expr->EvalConstExpr() == NULL) { | 1098 if (expr->EvalConstExpr() == NULL) { |
1035 ReportError(expr_pos, "initializer is not a valid compile-time constant"); | 1099 ReportError(expr_pos, "initializer is not a valid compile-time constant"); |
1036 } | 1100 } |
1037 ReturnNode* return_node = new ReturnNode(ident_pos, expr); | 1101 ReturnNode* return_node = new ReturnNode(ident_pos, expr); |
1038 current_block_->statements->Add(return_node); | 1102 current_block_->statements->Add(return_node); |
1039 } else { | 1103 } else { |
1040 // This getter may be called each time the static field is accessed. | 1104 // This getter may be called each time the static field is accessed. |
1041 // The following generated code lazily initializes the field: | 1105 // Call runtime support to parse and evaluate the initializer expression. |
1042 // if (field.value === transition_sentinel) { | 1106 // The runtime function will detect circular dependencies in expressions |
1043 // field.value = null; | 1107 // and handle errors while evaluating the expression. |
1044 // throw("circular dependency in field initialization"); | 1108 current_block_->statements->Add( |
1045 // } | 1109 new (I) InitStaticFieldNode(ident_pos, field)); |
1046 // if (field.value === sentinel) { | |
1047 // field.value = transition_sentinel; | |
1048 // field.value = expr; | |
1049 // } | |
1050 // return field.value; // Type check is executed here in checked mode. | |
1051 | |
1052 // Generate code checking for circular dependency in field initialization. | |
1053 AstNode* compare_circular = new ComparisonNode( | |
1054 ident_pos, | |
1055 Token::kEQ_STRICT, | |
1056 new LoadStaticFieldNode(ident_pos, field), | |
1057 new LiteralNode(ident_pos, Object::transition_sentinel())); | |
1058 // Set field to null prior to throwing exception, so that subsequent | |
1059 // accesses to the field do not throw again, since initializers should only | |
1060 // be executed once. | |
1061 SequenceNode* report_circular = new SequenceNode(ident_pos, NULL); | |
1062 report_circular->Add( | |
1063 new StoreStaticFieldNode( | |
1064 ident_pos, | |
1065 field, | |
1066 new LiteralNode(ident_pos, Instance::ZoneHandle(I)))); | |
1067 // Call CyclicInitializationError._throwNew(field_name). | |
1068 ArgumentListNode* error_arguments = new ArgumentListNode(ident_pos); | |
1069 error_arguments->Add(new LiteralNode(ident_pos, field_name)); | |
1070 report_circular->Add( | |
1071 MakeStaticCall(Symbols::CyclicInitializationError(), | |
1072 Library::PrivateCoreLibName(Symbols::ThrowNew()), | |
1073 error_arguments)); | |
1074 AstNode* circular_check = | |
1075 new IfNode(ident_pos, compare_circular, report_circular, NULL); | |
1076 current_block_->statements->Add(circular_check); | |
1077 | |
1078 // Generate code checking for uninitialized field. | |
1079 AstNode* compare_uninitialized = new ComparisonNode( | |
1080 ident_pos, | |
1081 Token::kEQ_STRICT, | |
1082 new LoadStaticFieldNode(ident_pos, field), | |
1083 new LiteralNode(ident_pos, Object::sentinel())); | |
1084 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL); | |
1085 initialize_field->Add( | |
1086 new StoreStaticFieldNode( | |
1087 ident_pos, | |
1088 field, | |
1089 new LiteralNode(ident_pos, Object::transition_sentinel()))); | |
1090 const String& init_name = String::Handle(I, Symbols::New( | |
1091 String::Handle(I, String::Concat( | |
1092 Symbols::InitPrefix(), String::Handle(I, field.name()))))); | |
1093 const Function& init_function = Function::ZoneHandle(I, | |
1094 field_class.LookupStaticFunction(init_name)); | |
1095 ASSERT(!init_function.IsNull()); | |
1096 ArgumentListNode* arguments = new ArgumentListNode(expr_pos); | |
1097 StaticCallNode* init_call = | |
1098 new StaticCallNode(expr_pos, init_function, arguments); | |
1099 initialize_field->Add(init_call); | |
1100 | |
1101 AstNode* uninitialized_check = | |
1102 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL); | |
1103 current_block_->statements->Add(uninitialized_check); | |
1104 | |
1105 // Generate code returning the field value. | |
1106 ReturnNode* return_node = | 1110 ReturnNode* return_node = |
1107 new ReturnNode(ident_pos, new LoadStaticFieldNode(ident_pos, field)); | 1111 new ReturnNode(ident_pos, |
| 1112 new LoadStaticFieldNode(ident_pos, field)); |
1108 current_block_->statements->Add(return_node); | 1113 current_block_->statements->Add(return_node); |
1109 } | 1114 } |
1110 return CloseBlock(); | 1115 return CloseBlock(); |
1111 } | 1116 } |
1112 | 1117 |
1113 | 1118 |
1114 SequenceNode* Parser::ParseStaticInitializer(const Function& func) { | |
1115 TRACE_PARSER("ParseStaticInitializer"); | |
1116 ParamList params; | |
1117 ASSERT(func.num_fixed_parameters() == 0); // static. | |
1118 ASSERT(!func.HasOptionalParameters()); | |
1119 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); | |
1120 | |
1121 // Build local scope for function and populate with the formal parameters. | |
1122 OpenFunctionBlock(func); | |
1123 AddFormalParamsToScope(¶ms, current_block_->scope); | |
1124 | |
1125 // Move forward to the start of the initializer expression. | |
1126 intptr_t ident_pos = TokenPos(); | |
1127 ExpectIdentifier("identifier expected"); | |
1128 ExpectToken(Token::kASSIGN); | |
1129 intptr_t token_pos = TokenPos(); | |
1130 | |
1131 // Synthesize a try-catch block to wrap the initializer expression. | |
1132 LocalVariable* context_var = | |
1133 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); | |
1134 if (context_var == NULL) { | |
1135 context_var = new(I) LocalVariable( | |
1136 token_pos, | |
1137 Symbols::SavedTryContextVar(), | |
1138 Type::ZoneHandle(I, Type::DynamicType())); | |
1139 current_block_->scope->AddVariable(context_var); | |
1140 } | |
1141 LocalVariable* catch_excp_var = | |
1142 current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar()); | |
1143 if (catch_excp_var == NULL) { | |
1144 catch_excp_var = new (I) LocalVariable( | |
1145 token_pos, | |
1146 Symbols::ExceptionVar(), | |
1147 Type::ZoneHandle(I, Type::DynamicType())); | |
1148 current_block_->scope->AddVariable(catch_excp_var); | |
1149 } | |
1150 LocalVariable* catch_trace_var = | |
1151 current_block_->scope->LocalLookupVariable(Symbols::StackTraceVar()); | |
1152 if (catch_trace_var == NULL) { | |
1153 catch_trace_var = new (I) LocalVariable( | |
1154 token_pos, | |
1155 Symbols::StackTraceVar(), | |
1156 Type::ZoneHandle(I, Type::DynamicType())); | |
1157 current_block_->scope->AddVariable(catch_trace_var); | |
1158 } | |
1159 | |
1160 OpenBlock(); // Start try block. | |
1161 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | |
1162 const Field& field = Field::ZoneHandle(I, func.saved_static_field()); | |
1163 ASSERT(!field.is_const()); | |
1164 if (FLAG_enable_type_checks) { | |
1165 expr = new AssignableNode( | |
1166 field.token_pos(), | |
1167 expr, | |
1168 AbstractType::ZoneHandle(I, field.type()), | |
1169 String::ZoneHandle(I, field.name())); | |
1170 } | |
1171 StoreStaticFieldNode* store = new StoreStaticFieldNode(field.token_pos(), | |
1172 field, | |
1173 expr); | |
1174 current_block_->statements->Add(store); | |
1175 SequenceNode* try_block = CloseBlock(); // End try block. | |
1176 | |
1177 OpenBlock(); // Start catch handler list. | |
1178 OpenBlock(); // Start catch clause. | |
1179 AstNode* compare_transition_sentinel = new ComparisonNode( | |
1180 token_pos, | |
1181 Token::kEQ_STRICT, | |
1182 new LoadStaticFieldNode(ident_pos, field), | |
1183 new LiteralNode(field.token_pos(), Object::transition_sentinel())); | |
1184 | |
1185 SequenceNode* store_null = new SequenceNode(token_pos, NULL); | |
1186 store_null->Add(new StoreStaticFieldNode( | |
1187 field.token_pos(), | |
1188 field, | |
1189 new LiteralNode(token_pos, Instance::ZoneHandle(I)))); | |
1190 AstNode* transition_sentinel_check = | |
1191 new IfNode(token_pos, compare_transition_sentinel, store_null, NULL); | |
1192 current_block_->statements->Add(transition_sentinel_check); | |
1193 | |
1194 current_block_->statements->Add( | |
1195 new ThrowNode(token_pos, | |
1196 new LoadLocalNode(token_pos, catch_excp_var), | |
1197 new LoadLocalNode(token_pos, catch_trace_var))); | |
1198 SequenceNode* catch_clause = CloseBlock(); // End catch clause. | |
1199 | |
1200 current_block_->statements->Add(catch_clause); | |
1201 SequenceNode* catch_handler_list = CloseBlock(); // End catch handler list. | |
1202 CatchClauseNode* catch_block = | |
1203 new CatchClauseNode(token_pos, | |
1204 catch_handler_list, | |
1205 Array::ZoneHandle(I, Object::empty_array().raw()), | |
1206 context_var, | |
1207 catch_excp_var, | |
1208 catch_trace_var, | |
1209 CatchClauseNode::kInvalidTryIndex, | |
1210 false); // No stack trace needed. | |
1211 | |
1212 AstNode* try_catch_node = new TryCatchNode(token_pos, | |
1213 try_block, | |
1214 context_var, | |
1215 catch_block, | |
1216 NULL, // No finally block. | |
1217 AllocateTryIndex()); | |
1218 current_block_->statements->Add(try_catch_node); | |
1219 return CloseBlock(); | |
1220 } | |
1221 | |
1222 | |
1223 // Create AstNodes for an implicit instance getter method: | 1119 // Create AstNodes for an implicit instance getter method: |
1224 // LoadLocalNode 0 ('this'); | 1120 // LoadLocalNode 0 ('this'); |
1225 // LoadInstanceFieldNode (field_name); | 1121 // LoadInstanceFieldNode (field_name); |
1226 // ReturnNode (field's value); | 1122 // ReturnNode (field's value); |
1227 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { | 1123 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { |
1228 TRACE_PARSER("ParseInstanceGetter"); | 1124 TRACE_PARSER("ParseInstanceGetter"); |
1229 ParamList params; | 1125 ParamList params; |
1230 // func.token_pos() points to the name of the field. | 1126 // func.token_pos() points to the name of the field. |
1231 const intptr_t ident_pos = func.token_pos(); | 1127 const intptr_t ident_pos = func.token_pos(); |
1232 ASSERT(current_class().raw() == func.Owner()); | 1128 ASSERT(current_class().raw() == func.Owner()); |
(...skipping 2440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3673 RawFunction::kImplicitStaticFinalGetter, | 3569 RawFunction::kImplicitStaticFinalGetter, |
3674 field->has_static, | 3570 field->has_static, |
3675 field->has_const, | 3571 field->has_const, |
3676 /* is_abstract = */ false, | 3572 /* is_abstract = */ false, |
3677 /* is_external = */ false, | 3573 /* is_external = */ false, |
3678 /* is_native = */ false, | 3574 /* is_native = */ false, |
3679 current_class(), | 3575 current_class(), |
3680 field->name_pos); | 3576 field->name_pos); |
3681 getter.set_result_type(*field->type); | 3577 getter.set_result_type(*field->type); |
3682 members->AddFunction(getter); | 3578 members->AddFunction(getter); |
3683 | |
3684 // Create initializer function for non-const fields. | |
3685 if (!class_field.is_const()) { | |
3686 const Function& init_function = Function::ZoneHandle(I, | |
3687 Function::NewStaticInitializer(class_field)); | |
3688 members->AddFunction(init_function); | |
3689 } | |
3690 } | 3579 } |
3691 } | 3580 } |
3692 | 3581 |
3693 // For instance fields, we create implicit getter and setter methods. | 3582 // For instance fields, we create implicit getter and setter methods. |
3694 if (!field->has_static) { | 3583 if (!field->has_static) { |
3695 String& getter_name = String::Handle(I, | 3584 String& getter_name = String::Handle(I, |
3696 Field::GetterSymbol(*field->name)); | 3585 Field::GetterSymbol(*field->name)); |
3697 getter = Function::New(getter_name, RawFunction::kImplicitGetter, | 3586 getter = Function::New(getter_name, RawFunction::kImplicitGetter, |
3698 field->has_static, | 3587 field->has_static, |
3699 field->has_final, | 3588 field->has_final, |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4838 RawFunction::kImplicitStaticFinalGetter, | 4727 RawFunction::kImplicitStaticFinalGetter, |
4839 is_static, | 4728 is_static, |
4840 is_const, | 4729 is_const, |
4841 /* is_abstract = */ false, | 4730 /* is_abstract = */ false, |
4842 /* is_external = */ false, | 4731 /* is_external = */ false, |
4843 /* is_native = */ false, | 4732 /* is_native = */ false, |
4844 current_class(), | 4733 current_class(), |
4845 name_pos); | 4734 name_pos); |
4846 getter.set_result_type(type); | 4735 getter.set_result_type(type); |
4847 top_level->functions.Add(getter); | 4736 top_level->functions.Add(getter); |
4848 | |
4849 // Create initializer function. | |
4850 if (!field.is_const()) { | |
4851 const Function& init_function = Function::ZoneHandle(I, | |
4852 Function::NewStaticInitializer(field)); | |
4853 top_level->functions.Add(init_function); | |
4854 } | |
4855 } | 4737 } |
4856 } else if (is_final) { | 4738 } else if (is_final) { |
4857 ReportError(name_pos, "missing initializer for final or const variable"); | 4739 ReportError(name_pos, "missing initializer for final or const variable"); |
4858 } | 4740 } |
4859 | 4741 |
4860 if (CurrentToken() == Token::kCOMMA) { | 4742 if (CurrentToken() == Token::kCOMMA) { |
4861 ConsumeToken(); | 4743 ConsumeToken(); |
4862 } else if (CurrentToken() == Token::kSEMICOLON) { | 4744 } else if (CurrentToken() == Token::kSEMICOLON) { |
4863 ConsumeToken(); | 4745 ConsumeToken(); |
4864 break; | 4746 break; |
(...skipping 6089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10954 ASSERT(field.is_const()); | 10836 ASSERT(field.is_const()); |
10955 ASSERT(field.value() != Object::sentinel().raw()); | 10837 ASSERT(field.value() != Object::sentinel().raw()); |
10956 ASSERT(field.value() != Object::transition_sentinel().raw()); | 10838 ASSERT(field.value() != Object::transition_sentinel().raw()); |
10957 return Instance::ZoneHandle(I, field.value()); | 10839 return Instance::ZoneHandle(I, field.value()); |
10958 } else { | 10840 } else { |
10959 ASSERT(expr->EvalConstExpr() != NULL); | 10841 ASSERT(expr->EvalConstExpr() != NULL); |
10960 ReturnNode* ret = new(I) ReturnNode(expr->token_pos(), expr); | 10842 ReturnNode* ret = new(I) ReturnNode(expr->token_pos(), expr); |
10961 // Compile time constant expressions cannot reference anything from a | 10843 // Compile time constant expressions cannot reference anything from a |
10962 // local scope. | 10844 // local scope. |
10963 LocalScope* empty_scope = new(I) LocalScope(NULL, 0, 0); | 10845 LocalScope* empty_scope = new(I) LocalScope(NULL, 0, 0); |
10964 SequenceNode* seq = new(I) SequenceNode(expr->token_pos(), | 10846 SequenceNode* seq = new(I) SequenceNode(expr->token_pos(), empty_scope); |
10965 empty_scope); | |
10966 seq->Add(ret); | 10847 seq->Add(ret); |
10967 | 10848 |
10968 Object& result = Object::Handle(I, Compiler::ExecuteOnce(seq)); | 10849 Object& result = Object::Handle(I, Compiler::ExecuteOnce(seq)); |
10969 if (result.IsError()) { | 10850 if (result.IsError()) { |
10970 ReportErrors(Error::Cast(result), | 10851 ReportErrors(Error::Cast(result), |
10971 script_, expr_pos, | 10852 script_, expr_pos, |
10972 "error evaluating constant expression"); | 10853 "error evaluating constant expression"); |
10973 } | 10854 } |
10974 ASSERT(result.IsInstance()); | 10855 ASSERT(result.IsInstance()); |
10975 Instance& value = Instance::ZoneHandle(I); | 10856 Instance& value = Instance::ZoneHandle(I); |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11308 void Parser::SkipQualIdent() { | 11189 void Parser::SkipQualIdent() { |
11309 ASSERT(IsIdentifier()); | 11190 ASSERT(IsIdentifier()); |
11310 ConsumeToken(); | 11191 ConsumeToken(); |
11311 if (CurrentToken() == Token::kPERIOD) { | 11192 if (CurrentToken() == Token::kPERIOD) { |
11312 ConsumeToken(); // Consume the kPERIOD token. | 11193 ConsumeToken(); // Consume the kPERIOD token. |
11313 ExpectIdentifier("identifier expected after '.'"); | 11194 ExpectIdentifier("identifier expected after '.'"); |
11314 } | 11195 } |
11315 } | 11196 } |
11316 | 11197 |
11317 } // namespace dart | 11198 } // namespace dart |
OLD | NEW |