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 |