Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(244)

Side by Side Diff: runtime/vm/parser.cc

Issue 735723003: Implement enum types in VM (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 714 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 725
726 void Parser::ParseClass(const Class& cls) { 726 void Parser::ParseClass(const Class& cls) {
727 if (!cls.is_synthesized_class()) { 727 if (!cls.is_synthesized_class()) {
728 Isolate* isolate = Isolate::Current(); 728 Isolate* isolate = Isolate::Current();
729 TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer); 729 TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
730 ASSERT(isolate->long_jump_base()->IsSafeToJump()); 730 ASSERT(isolate->long_jump_base()->IsSafeToJump());
731 const Script& script = Script::Handle(isolate, cls.script()); 731 const Script& script = Script::Handle(isolate, cls.script());
732 const Library& lib = Library::Handle(isolate, cls.library()); 732 const Library& lib = Library::Handle(isolate, cls.library());
733 Parser parser(script, lib, cls.token_pos()); 733 Parser parser(script, lib, cls.token_pos());
734 parser.ParseClassDefinition(cls); 734 parser.ParseClassDefinition(cls);
735 } else if (cls.is_enum_class()) {
736 Isolate* isolate = Isolate::Current();
737 TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
738 ASSERT(isolate->long_jump_base()->IsSafeToJump());
739 const Script& script = Script::Handle(isolate, cls.script());
740 const Library& lib = Library::Handle(isolate, cls.library());
741 Parser parser(script, lib, cls.token_pos());
742 parser.ParseEnumDefinition(cls);
735 } 743 }
736 } 744 }
737 745
738 746
739 RawObject* Parser::ParseFunctionParameters(const Function& func) { 747 RawObject* Parser::ParseFunctionParameters(const Function& func) {
740 ASSERT(!func.IsNull()); 748 ASSERT(!func.IsNull());
741 Isolate* isolate = Isolate::Current(); 749 Isolate* isolate = Isolate::Current();
742 StackZone zone(isolate); 750 StackZone zone(isolate);
743 LongJumpScope jump; 751 LongJumpScope jump;
744 if (setjmp(*jump.Set()) == 0) { 752 if (setjmp(*jump.Set()) == 0) {
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 ASSERT(!func.HasOptionalParameters()); 1126 ASSERT(!func.HasOptionalParameters());
1119 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved()); 1127 ASSERT(AbstractType::Handle(I, func.result_type()).IsResolved());
1120 1128
1121 // Build local scope for function and populate with the formal parameters. 1129 // Build local scope for function and populate with the formal parameters.
1122 OpenFunctionBlock(func); 1130 OpenFunctionBlock(func);
1123 AddFormalParamsToScope(&params, current_block_->scope); 1131 AddFormalParamsToScope(&params, current_block_->scope);
1124 1132
1125 // Receiver is local 0. 1133 // Receiver is local 0.
1126 LocalVariable* receiver = current_block_->scope->VariableAt(0); 1134 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1127 LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver); 1135 LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver);
1128 ASSERT(IsIdentifier()); 1136 String& field_name = String::Handle(I, func.name());
1129 const String& field_name = *CurrentLiteral(); 1137 field_name = Field::NameFromGetter(field_name);
1138
1130 const Class& field_class = Class::Handle(I, func.Owner()); 1139 const Class& field_class = Class::Handle(I, func.Owner());
1131 const Field& field = 1140 const Field& field =
1132 Field::ZoneHandle(I, field_class.LookupInstanceField(field_name)); 1141 Field::ZoneHandle(I, field_class.LookupInstanceField(field_name));
1142 ASSERT(!field.IsNull());
1133 1143
1134 LoadInstanceFieldNode* load_field = 1144 LoadInstanceFieldNode* load_field =
1135 new LoadInstanceFieldNode(ident_pos, load_receiver, field); 1145 new LoadInstanceFieldNode(ident_pos, load_receiver, field);
1136 1146
1137 ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, load_field); 1147 ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, load_field);
1138 current_block_->statements->Add(return_node); 1148 current_block_->statements->Add(return_node);
1139 return CloseBlock(); 1149 return CloseBlock();
1140 } 1150 }
1141 1151
1142 1152
(...skipping 1901 matching lines...) Expand 10 before | Expand all | Expand 10 after
3044 } else if (func.is_async_closure()) { 3054 } else if (func.is_async_closure()) {
3045 OpenAsyncClosure(); 3055 OpenAsyncClosure();
3046 } 3056 }
3047 3057
3048 bool saved_await_is_keyword = await_is_keyword_; 3058 bool saved_await_is_keyword = await_is_keyword_;
3049 await_is_keyword_ = func.IsAsyncFunction() || func.is_async_closure(); 3059 await_is_keyword_ = func.IsAsyncFunction() || func.is_async_closure();
3050 3060
3051 intptr_t end_token_pos = 0; 3061 intptr_t end_token_pos = 0;
3052 if (CurrentToken() == Token::kLBRACE) { 3062 if (CurrentToken() == Token::kLBRACE) {
3053 ConsumeToken(); 3063 ConsumeToken();
3054 if (String::Handle(I, func.name()).Equals( 3064 if (String::Handle(I, func.name()).Equals(Symbols::EqualOperator())) {
3055 Symbols::EqualOperator())) {
3056 const Class& owner = Class::Handle(I, func.Owner()); 3065 const Class& owner = Class::Handle(I, func.Owner());
3057 if (!owner.IsObjectClass()) { 3066 if (!owner.IsObjectClass()) {
3058 AddEqualityNullCheck(); 3067 AddEqualityNullCheck();
3059 } 3068 }
3060 } 3069 }
3061 ParseStatementSequence(); 3070 ParseStatementSequence();
3062 end_token_pos = TokenPos(); 3071 end_token_pos = TokenPos();
3063 ExpectToken(Token::kRBRACE); 3072 ExpectToken(Token::kRBRACE);
3064 } else if (CurrentToken() == Token::kARROW) { 3073 } else if (CurrentToken() == Token::kARROW) {
3065 ConsumeToken(); 3074 ConsumeToken();
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after
3995 ParseFieldDefinition(members, &member); 4004 ParseFieldDefinition(members, &member);
3996 } else { 4005 } else {
3997 UnexpectedToken(); 4006 UnexpectedToken();
3998 } 4007 }
3999 current_member_ = NULL; 4008 current_member_ = NULL;
4000 CheckMemberNameConflict(members, &member); 4009 CheckMemberNameConflict(members, &member);
4001 members->AddMember(member); 4010 members->AddMember(member);
4002 } 4011 }
4003 4012
4004 4013
4014 void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes,
4015 const Class& toplevel_class,
4016 intptr_t metadata_pos) {
4017 TRACE_PARSER("ParseEnumDeclaration");
4018 ConsumeToken();
4019 const intptr_t enum_pos = TokenPos();
4020 String* enum_name =
4021 ExpectUserDefinedTypeIdentifier("enum type name expected");
4022 if (FLAG_trace_parser) {
4023 OS::Print("TopLevel parsing enum '%s'\n", enum_name->ToCString());
4024 }
4025 ExpectToken(Token::kLBRACE);
4026 if (!IsIdentifier()) {
4027 ReportError("Enumeration must have at least one name");
4028 }
4029 while (IsIdentifier()) {
4030 ConsumeToken();
4031 if (CurrentToken() == Token::kCOMMA) {
4032 ConsumeToken();
4033 if (CurrentToken() == Token::kRBRACE) {
4034 break;
4035 }
4036 } else if (CurrentToken() == Token::kRBRACE) {
4037 break;
4038 } else {
4039 ReportError(", or } expected");
4040 }
4041 }
4042 ExpectToken(Token::kRBRACE);
4043
4044 Object& obj = Object::Handle(I, library_.LookupLocalObject(*enum_name));
4045 if (!obj.IsNull()) {
4046 ReportError(enum_pos, "'%s' is already defined", enum_name->ToCString());
4047 }
4048 Class& cls = Class::Handle(I);
4049 cls = Class::New(*enum_name, script_, enum_pos);
4050 cls.set_library(library_);
4051 library_.AddClass(cls);
4052 cls.set_is_synthesized_class();
4053 cls.set_is_enum_class();
4054 if (metadata_pos >= 0) {
4055 library_.AddClassMetadata(cls, toplevel_class, metadata_pos);
4056 }
4057 cls.set_super_type(Type::Handle(I, Type::ObjectType()));
4058 pending_classes.Add(cls, Heap::kOld);
4059 }
4060
4061
4005 void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, 4062 void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
4006 const Class& toplevel_class, 4063 const Class& toplevel_class,
4007 intptr_t metadata_pos) { 4064 intptr_t metadata_pos) {
4008 TRACE_PARSER("ParseClassDeclaration"); 4065 TRACE_PARSER("ParseClassDeclaration");
4009 bool is_patch = false; 4066 bool is_patch = false;
4010 bool is_abstract = false; 4067 bool is_abstract = false;
4011 if (is_patch_source() && 4068 if (is_patch_source() &&
4012 (CurrentToken() == Token::kIDENT) && 4069 (CurrentToken() == Token::kIDENT) &&
4013 CurrentLiteral()->Equals("patch")) { 4070 CurrentLiteral()->Equals("patch")) {
4014 ConsumeToken(); 4071 ConsumeToken();
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
4237 const Class& orig_class = Class::Cast(obj); 4294 const Class& orig_class = Class::Cast(obj);
4238 ASSERT(!orig_class.is_finalized()); 4295 ASSERT(!orig_class.is_finalized());
4239 Error& error = Error::Handle(I); 4296 Error& error = Error::Handle(I);
4240 if (!orig_class.ApplyPatch(cls, &error)) { 4297 if (!orig_class.ApplyPatch(cls, &error)) {
4241 Report::LongJumpF(error, script_, class_pos, "applying patch failed"); 4298 Report::LongJumpF(error, script_, class_pos, "applying patch failed");
4242 } 4299 }
4243 } 4300 }
4244 } 4301 }
4245 4302
4246 4303
4304 void Parser::ParseEnumDefinition(const Class& cls) {
4305 TRACE_PARSER("ParseEnumDefinition");
4306 CompilerStats::num_classes_compiled++;
4307
4308 const String& enum_name = String::Handle(I, cls.Name());
4309 ClassDesc enum_members(cls, enum_name, false, cls.token_pos());
4310
4311 // Add instance field 'final int index'.
4312 Field& index_field = Field::ZoneHandle(I);
4313 const Type& int_type = Type::Handle(I, Type::IntType());
4314 const Type& dynamic_type = Type::Handle(Type::DynamicType());
4315 index_field = Field::New(Symbols::Index(),
4316 false, // Not static.
4317 true, // Field is final.
4318 false, // Not const.
4319 false, // Not synthetic.
4320 cls,
4321 cls.token_pos());
4322 index_field.set_type(int_type);
4323 enum_members.AddField(index_field);
4324
4325 // Add implicit getter for index field.
4326 const String& getter_name =
4327 String::Handle(I, Field::GetterSymbol(Symbols::Index()));
4328 Function& getter = Function::Handle(I);
4329 getter = Function::New(getter_name,
4330 RawFunction::kImplicitGetter,
4331 /* is_static = */ false,
4332 /* is_const = */ true,
4333 /* is_abstract = */ false,
4334 /* is_external = */ false,
4335 /* is_native = */ false,
4336 cls,
4337 cls.token_pos());
4338 getter.set_result_type(int_type);
4339 ParamList params;
4340 params.AddReceiver(&dynamic_type, cls.token_pos());
4341 AddFormalParamsToFunction(&params, getter);
4342 enum_members.AddFunction(getter);
4343
4344 GrowableObjectArray& enum_names = GrowableObjectArray::Handle(I,
4345 GrowableObjectArray::New(8, Heap::kOld));
4346 const String& name_prefix =
4347 String::Handle(String::Concat(enum_name, Symbols::Dot()));
4348
4349 ASSERT(IsIdentifier());
4350 ASSERT(CurrentLiteral()->raw() == cls.Name());
4351
4352 ConsumeToken(); // Enum type name.
4353 ExpectToken(Token::kLBRACE);
4354 Field& enum_value = Field::Handle(I);
4355 String& enum_value_name = String::Handle(I);
4356 intptr_t i = 0;
4357 GrowableArray<String*> declared_names(8);
4358
4359 while (IsIdentifier()) {
4360 String* enum_ident = CurrentLiteral();
4361
4362 // Check for name conflicts.
4363 if (enum_ident->raw() == cls.Name()) {
4364 ReportError("enum identifier '%s' cannot be equal to enum type name",
4365 CurrentLiteral()->ToCString());
4366 } else if (enum_ident->raw() == Symbols::Index().raw()) {
4367 ReportError("enum identifier conflicts with "
4368 "implicit instance field 'index'");
4369 } else if (enum_ident->raw() == Symbols::Values().raw()) {
4370 ReportError("enum identifier conflicts with "
4371 "implicit static field 'values'");
4372 } else if (enum_ident->raw() == Symbols::toString().raw()) {
4373 ReportError("enum identifier conflicts with "
4374 "implicit instance method 'toString()'");
4375 }
4376 for (intptr_t i = 0; i < declared_names.length(); i++) {
4377 if (enum_ident->Equals(*declared_names[i])) {
4378 ReportError("Duplicate name '%s' in enum definition '%s'",
4379 enum_ident->ToCString(),
4380 enum_name.ToCString());
4381 }
4382 }
4383 declared_names.Add(enum_ident);
4384
4385 // Create the static const field for the enumeration value.
4386 enum_value = Field::New(*enum_ident,
4387 /* is_static = */ true,
4388 /* is_final = */ true,
4389 /* is_const = */ true,
4390 /* is_synthetic = */ false,
4391 cls,
4392 cls.token_pos());
4393 enum_value.set_type(dynamic_type);
4394 enum_value.set_has_initializer(false);
4395 enum_members.AddField(enum_value);
4396 // Initialize the field with the ordinal value. It will be patched
4397 // later with the enum constant instance.
4398 Smi& ordinal_value = Smi::Handle(I, Smi::New(i));
srdjan 2014/11/18 21:19:18 const Smi&
hausner 2014/11/18 23:14:07 Done.
4399 enum_value.set_value(ordinal_value);
4400 enum_value.RecordStore(ordinal_value);
4401 i++;
4402
4403 // For the user-visible name of the enumeration value, we need to
4404 // unmangle private names.
4405 if (enum_ident->CharAt(0) == '_') {
4406 *enum_ident = String::IdentifierPrettyName(*enum_ident);
4407 }
4408 enum_value_name = Symbols::FromConcat(name_prefix, *enum_ident);
4409 enum_names.Add(enum_value_name, Heap::kOld);
4410
4411 ConsumeToken(); // Enum value name.
4412 if (CurrentToken() == Token::kCOMMA) {
4413 ConsumeToken();
4414 }
4415 }
4416 ExpectToken(Token::kRBRACE);
4417
4418 const Class& helper_class =
4419 Class::Handle(I, Library::LookupCoreClass(Symbols::_EnumHelper()));
4420 ASSERT(!helper_class.IsNull());
4421
4422 // Add static field 'const List values'.
4423 Field& values_field = Field::ZoneHandle(I);
4424 values_field = Field::New(Symbols::Values(),
4425 /* is_static = */ true,
4426 /* is_final = */ true,
4427 /* is_const = */ true,
4428 /* is_synthetic = */ false,
4429 cls,
4430 cls.token_pos());
4431 values_field.set_type(Type::Handle(I, Type::ArrayType()));
4432 enum_members.AddField(values_field);
4433
4434 // Allocate the immutable array containing the enumeration values.
4435 // The actual enum instance values will be patched in later.
4436 const Array& values_array = Array::Handle(I, Array::New(i, Heap::kOld));
4437 values_field.set_value(values_array);
4438 values_field.RecordStore(values_array);
4439
4440 // Create a static field that contains the list of enumeration names.
4441 // Clone the _enum_names field from the helper class.
4442 Field& names_field = Field::Handle(I,
4443 helper_class.LookupStaticField(Symbols::_EnumNames()));
4444 ASSERT(!names_field.IsNull());
4445 names_field = names_field.Clone(cls);
4446 enum_members.AddField(names_field);
4447 const Array& names_array = Array::Handle(Array::MakeArray(enum_names));
4448 names_field.set_value(names_array);
4449 names_field.RecordStore(names_array);
4450
4451 // Clone the toString() function from the helper class.
4452 Function& to_string_func = Function::Handle(I,
4453 helper_class.LookupDynamicFunctionAllowPrivate(Symbols::toString()));
4454 ASSERT(!to_string_func.IsNull());
4455 to_string_func = to_string_func.Clone(cls);
4456 to_string_func.set_is_visible(false);
4457 enum_members.AddFunction(to_string_func);
4458
4459 cls.AddFields(enum_members.fields());
4460 const Array& functions =
4461 Array::Handle(I, Array::MakeArray(enum_members.functions()));
4462 cls.SetFunctions(functions);
4463 }
4464
4465
4247 // Add an implicit constructor to the given class. 4466 // Add an implicit constructor to the given class.
4248 void Parser::AddImplicitConstructor(const Class& cls) { 4467 void Parser::AddImplicitConstructor(const Class& cls) {
4249 // The implicit constructor is unnamed, has no explicit parameter. 4468 // The implicit constructor is unnamed, has no explicit parameter.
4250 String& ctor_name = String::ZoneHandle(I, cls.Name()); 4469 String& ctor_name = String::ZoneHandle(I, cls.Name());
4251 ctor_name = String::Concat(ctor_name, Symbols::Dot()); 4470 ctor_name = String::Concat(ctor_name, Symbols::Dot());
4252 ctor_name = Symbols::New(ctor_name); 4471 ctor_name = Symbols::New(ctor_name);
4253 // To indicate that this is an implicit constructor, we set the 4472 // To indicate that this is an implicit constructor, we set the
4254 // token position and end token position of the function 4473 // token position and end token position of the function
4255 // to the token position of the class. 4474 // to the token position of the class.
4256 Function& ctor = Function::Handle(I, 4475 Function& ctor = Function::Handle(I,
(...skipping 1162 matching lines...) Expand 10 before | Expand all | Expand 10 after
5419 } else if (is_part_source()) { 5638 } else if (is_part_source()) {
5420 ParsePartHeader(); 5639 ParsePartHeader();
5421 } 5640 }
5422 5641
5423 const Class& cls = Class::Handle(I); 5642 const Class& cls = Class::Handle(I);
5424 while (true) { 5643 while (true) {
5425 set_current_class(cls); // No current class. 5644 set_current_class(cls); // No current class.
5426 intptr_t metadata_pos = SkipMetadata(); 5645 intptr_t metadata_pos = SkipMetadata();
5427 if (CurrentToken() == Token::kCLASS) { 5646 if (CurrentToken() == Token::kCLASS) {
5428 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); 5647 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos);
5648 } else if (CurrentToken() == Token::kENUM) {
5649 ParseEnumDeclaration(pending_classes, toplevel_class, metadata_pos);
5429 } else if ((CurrentToken() == Token::kTYPEDEF) && 5650 } else if ((CurrentToken() == Token::kTYPEDEF) &&
5430 (LookaheadToken(1) != Token::kLPAREN)) { 5651 (LookaheadToken(1) != Token::kLPAREN)) {
5431 set_current_class(toplevel_class); 5652 set_current_class(toplevel_class);
5432 ParseTypedef(pending_classes, toplevel_class, metadata_pos); 5653 ParseTypedef(pending_classes, toplevel_class, metadata_pos);
5433 } else if ((CurrentToken() == Token::kABSTRACT) && 5654 } else if ((CurrentToken() == Token::kABSTRACT) &&
5434 (LookaheadToken(1) == Token::kCLASS)) { 5655 (LookaheadToken(1) == Token::kCLASS)) {
5435 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); 5656 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos);
5436 } else if (is_patch_source() && IsLiteral("patch") && 5657 } else if (is_patch_source() && IsLiteral("patch") &&
5437 (LookaheadToken(1) == Token::kCLASS)) { 5658 (LookaheadToken(1) == Token::kCLASS)) {
5438 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos); 5659 ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos);
(...skipping 6453 matching lines...) Expand 10 before | Expand all | Expand 10 after
11892 void Parser::SkipQualIdent() { 12113 void Parser::SkipQualIdent() {
11893 ASSERT(IsIdentifier()); 12114 ASSERT(IsIdentifier());
11894 ConsumeToken(); 12115 ConsumeToken();
11895 if (CurrentToken() == Token::kPERIOD) { 12116 if (CurrentToken() == Token::kPERIOD) {
11896 ConsumeToken(); // Consume the kPERIOD token. 12117 ConsumeToken(); // Consume the kPERIOD token.
11897 ExpectIdentifier("identifier expected after '.'"); 12118 ExpectIdentifier("identifier expected after '.'");
11898 } 12119 }
11899 } 12120 }
11900 12121
11901 } // namespace dart 12122 } // namespace dart
OLDNEW
« runtime/vm/class_finalizer.cc ('K') | « runtime/vm/parser.h ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698