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

Unified Diff: runtime/vm/parser.cc

Issue 8585004: Support correct factory syntax in the VM as decribed in the spec. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 1585)
+++ runtime/vm/parser.cc (working copy)
@@ -25,7 +25,7 @@
DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
-DEFINE_FLAG(bool, silent_warnings, true, "Silence warnings.");
+DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
// All references to Dart names are listed here.
static const char* kAssertionErrorName = "AssertionError";
@@ -280,13 +280,13 @@
Clear();
}
void Clear() {
- local_scope_ident = false;
+ is_local_scope_ident = false;
lib_prefix = NULL;
qualifier = NULL;
ident_pos = 0;
ident = NULL;
}
- bool local_scope_ident;
+ bool is_local_scope_ident;
LibraryPrefix* lib_prefix;
String* qualifier;
intptr_t ident_pos;
@@ -572,6 +572,7 @@
case RawFunction::kGetterFunction:
case RawFunction::kSetterFunction:
case RawFunction::kConstructor:
+ ASSERT(!func.IsFactory() || (func.signature_class() != Class::null()));
node_sequence = parser.ParseFunc(func, default_parameter_values);
break;
case RawFunction::kImplicitGetter:
@@ -641,7 +642,7 @@
// fragment to evaluate the expression. Instead, we just make sure
// the static const field initializer is a constant expression and
// leave the evaluation to the getter function.
- intptr_t expr_pos = token_index_;
+ const intptr_t expr_pos = token_index_;
AstNode* expr = ParseExpr(kAllowConst);
if (expr->EvalConstExpr() == NULL) {
ErrorMsg(expr_pos, "initializer must be a compile time constant");
@@ -731,7 +732,7 @@
void Parser::SkipBlock() {
ASSERT(CurrentToken() == Token::kLBRACE);
GrowableArray<Token::Kind> token_stack(8);
- intptr_t block_start_pos = token_index_;
+ const intptr_t block_start_pos = token_index_;
bool is_match = true;
bool unexpected_token_found = false;
Token::Kind token;
@@ -1372,7 +1373,7 @@
GrowableArray<FieldInitExpression>* initializers) {
const Array& fields = Array::Handle(cls.fields());
Field& f = Field::Handle();
- intptr_t saved_pos = token_index_;
+ const intptr_t saved_pos = token_index_;
for (int i = 0; i < fields.Length(); i++) {
f ^= fields.At(i);
if (!f.is_static() && f.has_initializer()) {
@@ -1416,7 +1417,7 @@
AstNode* init_statement;
if (CurrentToken() == Token::kSUPER) {
if (super_init_seen) {
- ErrorMsg("Duplicate call to super constructor");
+ ErrorMsg("duplicate call to super constructor");
}
init_statement = ParseSuperInitializer(cls, receiver);
super_init_seen = true;
@@ -1438,7 +1439,7 @@
void Parser::ParseConstructorRedirection(const Class& cls,
LocalVariable* receiver) {
ASSERT(CurrentToken() == Token::kTHIS);
- intptr_t call_pos = token_index_;
+ const intptr_t call_pos = token_index_;
ConsumeToken();
String& ctor_name = String::Handle(cls.Name());
String& ctor_suffix = String::Handle(String::NewSymbol("."));
@@ -1481,7 +1482,7 @@
SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
ASSERT(func.IsConstructor());
- intptr_t ctor_pos = token_index_;
+ const intptr_t ctor_pos = token_index_;
// Implicit 'this' is the only parameter/local variable.
OpenFunctionBlock(func);
@@ -1843,7 +1844,7 @@
ExpectToken(Token::kRBRACE);
} else if (CurrentToken() == Token::kARROW) {
ConsumeToken();
- intptr_t expr_pos = token_index_;
+ const intptr_t expr_pos = token_index_;
AstNode* expr = ParseExpr(kAllowConst);
ASSERT(expr != NULL);
current_block_->statements->Add(new ReturnNode(expr_pos, expr));
@@ -1910,16 +1911,16 @@
void Parser::ParseQualIdent(QualIdent* qual_ident) {
ASSERT(CurrentToken() == Token::kIDENT);
if (!is_top_level_) {
- bool local_ident = ResolveIdentInLocalScope(token_index_,
- *CurrentLiteral(),
- NULL);
+ bool is_local_ident = ResolveIdentInLocalScope(token_index_,
+ *CurrentLiteral(),
+ NULL);
qual_ident->ident_pos = token_index_;
qual_ident->ident = CurrentLiteral();
qual_ident->lib_prefix = NULL;
qual_ident->qualifier = NULL;
- qual_ident->local_scope_ident = local_ident;
+ qual_ident->is_local_scope_ident = is_local_ident;
ConsumeToken();
- if (!local_ident && (CurrentToken() == Token::kPERIOD)) {
+ if (!is_local_ident && (CurrentToken() == Token::kPERIOD)) {
LibraryPrefix& lib_prefix = LibraryPrefix::ZoneHandle();
lib_prefix = current_class().LookupLibraryPrefix(*(qual_ident->ident));
if (!lib_prefix.IsNull()) {
@@ -1936,7 +1937,7 @@
qual_ident->ident = CurrentLiteral();
qual_ident->lib_prefix = NULL;
qual_ident->qualifier = NULL;
- qual_ident->local_scope_ident = false;
+ qual_ident->is_local_scope_ident = false;
ConsumeToken();
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken(); // Consume the kPERIOD token.
@@ -2291,10 +2292,7 @@
ConsumeToken();
member.has_factory = true;
member.has_static = true;
- // The member result type is the type of this class.
- // TODO(regis): What are the type arguments?
- member.type =
- &Type::ZoneHandle(Type::NewRawType(Class::Handle(members->clazz())));
+ // The result type depends on the name of the factory method.
}
// Optionally parse a type.
if (CurrentToken() == Token::kVOID) {
@@ -2306,7 +2304,7 @@
member.type = &Type::ZoneHandle(Type::VoidType());
} else if (CurrentToken() == Token::kIDENT) {
// This is either a type name or the name of a method/constructor/field.
- if (member.type == NULL) {
+ if ((member.type == NULL) && !member.has_factory) {
// We have not seen a member type yet, so we check if the next
// identifier could represent a type before parsing it.
Token::Kind follower = LookaheadToken(1);
@@ -2329,18 +2327,26 @@
(CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) {
member.name = CurrentLiteral();
member.name_pos = this->token_index_;
- // Factory result type is the same as the type name of the factory.
- // TODO(srdjan): Implement checks in class finalization when all types have
- // been resolved.
- if (member.has_factory && !member.name->Equals(members->class_name())) {
- const UnresolvedClass& type =
+ ConsumeToken();
+ // Resolution of the factory result type is always postponed until class
+ // finalization, so that the list of type parameters in the factory
+ // signature can be checked at the same time.
+ if (member.has_factory) {
+ const UnresolvedClass& unresolved_factory_class =
UnresolvedClass::Handle(UnresolvedClass::New(member.name_pos,
String::Handle(),
*(member.name)));
+ const Class& signature_class = Class::Handle(
+ Class::New(String::Handle(String::NewSymbol(":factory_signature")),
+ Script::Handle()));
+ signature_class.set_is_finalized();
+ unresolved_factory_class.set_factory_signature_class(signature_class);
+ // The type arguments of the result type are set during finalization.
const TypeArguments& args = TypeArguments::Handle();
- member.type = &Type::ZoneHandle(Type::NewParameterizedType(type, args));
+ member.type = &Type::ZoneHandle(
+ Type::NewParameterizedType(unresolved_factory_class, args));
+ ParseTypeParameters(signature_class);
}
- ConsumeToken();
// We must be dealing with a constructor or named constructor.
member.kind = RawFunction::kConstructor;
String& ctor_suffix = String::ZoneHandle(String::NewSymbol("."));
@@ -2354,9 +2360,11 @@
// Ensure that names are symbols.
*member.name = String::NewSymbol(*member.name);
if (member.type == NULL) {
- // TODO(regis): What are the type arguments?
- member.type =
- &Type::ZoneHandle(Type::NewRawType(Class::Handle(members->clazz())));
+ ASSERT(!member.has_factory);
+ // The body of the constructor cannot modify the type arguments of the
+ // constructed instance, which is passed in as an hidden parameter.
srdjan 2011/11/16 23:02:26 a hidden
regis 2011/11/16 23:38:08 Merci :-)
+ // Therefore, there is no need to set the result type to be checked.
+ member.type = &Type::ZoneHandle(Type::DynamicType());
} else {
// The type can only be already set in the factory case.
if (!member.has_factory) {
@@ -2442,9 +2450,9 @@
void Parser::ParseClassDefinition(GrowableArray<const Class*>* classes) {
TRACE_PARSER("ParseClassDefinition");
- intptr_t class_pos = token_index_;
+ const intptr_t class_pos = token_index_;
ExpectToken(Token::kCLASS);
- intptr_t classname_pos = token_index_;
+ const intptr_t classname_pos = token_index_;
String& class_name = *ExpectIdentifier("class name expected");
if (FLAG_trace_parser) {
OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString());
@@ -2537,9 +2545,10 @@
&Type::ZoneHandle(Type::DynamicType()));
AddFormalParamsToFunction(&params, ctor);
- // TODO(regis): What are the type arguments?
- Type& result_type = Type::ZoneHandle(
- Type::NewRawType(Class::Handle(class_desc->clazz())));
+ // The body of the constructor cannot modify the type arguments of the
+ // constructed instance, which is passed in as an hidden parameter.
srdjan 2011/11/16 23:02:26 a hidden
regis 2011/11/16 23:38:08 Done.
+ // Therefore, there is no need to set the result type to be checked.
+ const Type& result_type = Type::ZoneHandle(Type::DynamicType());
ctor.set_result_type(result_type);
class_desc->AddFunction(&ctor);
}
@@ -2598,7 +2607,7 @@
ExpectToken(Token::kTYPEDEF);
Type& result_type = Type::Handle(Type::DynamicType());
- intptr_t result_type_pos = token_index_;
+ const intptr_t result_type_pos = token_index_;
if (CurrentToken() == Token::kVOID) {
ConsumeToken();
result_type = Type::VoidType();
@@ -2627,8 +2636,8 @@
// At this point, the type parameters have been parsed, so we can resolve the
// result type.
- if (!result_type.IsNull() && !result_type.IsResolved()) {
- ResolveTypeFromClass(result_type_pos, alias_owner, &result_type);
+ if (!result_type.IsNull()) {
+ TryResolveTypeFromClass(result_type_pos, alias_owner, &result_type);
}
ParamList func_params;
const bool no_explicit_default_values = false;
@@ -2685,9 +2694,9 @@
void Parser::ParseInterfaceDefinition(GrowableArray<const Class*>* classes) {
TRACE_PARSER("ParseInterfaceDefinition");
- intptr_t interface_pos = token_index_;
+ const intptr_t interface_pos = token_index_;
ExpectToken(Token::kINTERFACE);
- intptr_t interfacename_pos = token_index_;
+ const intptr_t interfacename_pos = token_index_;
String& interface_name = *ExpectIdentifier("interface name expected");
if (FLAG_trace_parser) {
OS::Print("TopLevel parsing interface '%s'\n", interface_name.ToCString());
@@ -2727,17 +2736,27 @@
if (CurrentToken() == Token::kFACTORY) {
ConsumeToken();
- Type& factory_type = Type::Handle();
- const intptr_t factory_type_pos = token_index_;
- factory_type = ParseType(kCanResolve);
- if (factory_type.IsInterfaceType()) {
- ErrorMsg(factory_type_pos,
- "interface '%s' must have a factory class "
- "but '%s' is an interface",
- interface_name.ToCString(),
- String::Handle(factory_type.Name()).ToCString());
+ const intptr_t factory_pos = token_index_;
+ QualIdent factory_name;
+ ParseQualIdent(&factory_name);
+ if (factory_name.is_local_scope_ident) {
+ ErrorMsg(factory_pos,
+ "using '%s' in this context is invalid",
+ factory_name.ident->ToCString());
}
- interface.set_factory_type(factory_type);
+ String& qualifier = String::Handle();
+ if (factory_name.qualifier != NULL) {
+ qualifier ^= factory_name.qualifier->raw();
+ }
+ const UnresolvedClass& unresolved_factory_class = UnresolvedClass::Handle(
+ UnresolvedClass::New(factory_pos, qualifier, *(factory_name.ident)));
+ const Class& signature_class = Class::Handle(
+ Class::New(String::Handle(String::NewSymbol(":factory_signature")),
+ Script::Handle()));
+ signature_class.set_is_finalized();
+ ParseTypeParameters(signature_class);
+ unresolved_factory_class.set_factory_signature_class(signature_class);
+ interface.set_factory_class(unresolved_factory_class);
}
ExpectToken(Token::kLBRACE);
@@ -2810,6 +2829,7 @@
void Parser::ParseTypeParameters(const Class& cls) {
if (CurrentToken() == Token::kLT) {
+ const intptr_t type_pos = token_index_;
GrowableArray<String*> type_parameters;
GrowableArray<Type*> type_parameter_extends;
do {
@@ -2836,8 +2856,18 @@
ErrorMsg("right angle bracket expected");
}
cls.set_type_parameters(Array::Handle(NewArray<String>(type_parameters)));
- cls.set_type_parameter_extends(
- TypeArray::Handle(NewTypeArray(type_parameter_extends)));
+ const TypeArray& extends_array =
+ TypeArray::Handle(NewTypeArray(type_parameter_extends));
+ cls.set_type_parameter_extends(extends_array);
+ // Try to resolve the upper bounds, which will at least resolve the
+ // referenced type parameters.
+ Type& type_extends = Type::Handle();
+ const intptr_t num_types = extends_array.Length();
+ for (intptr_t i = 0; i < num_types; i++) {
+ type_extends = extends_array.TypeAt(i);
+ TryResolveTypeFromClass(type_pos, cls, &type_extends);
+ extends_array.SetTypeAt(i, type_extends);
+ }
}
}
@@ -3026,13 +3056,13 @@
UnexpectedToken();
}
}
- intptr_t name_pos = token_index_;
+ const intptr_t name_pos = token_index_;
const String* field_name = ExpectIdentifier("accessor name expected");
if (CurrentToken() != Token::kLPAREN) {
ErrorMsg("'(' expected");
}
- intptr_t accessor_pos = token_index_;
+ const intptr_t accessor_pos = token_index_;
ParamList params;
const bool allow_explicit_default_values = true;
ParseFormalParameterList(allow_explicit_default_values, &params);
@@ -3114,7 +3144,7 @@
void Parser::ParseLibraryImport() {
while (CurrentToken() == Token::kIMPORT) {
- intptr_t import_pos = token_index_;
+ const intptr_t import_pos = token_index_;
ConsumeToken();
ExpectToken(Token::kLPAREN);
if (CurrentToken() != Token::kSTRING) {
@@ -3171,7 +3201,7 @@
void Parser::ParseLibraryInclude() {
while (CurrentToken() == Token::kSOURCE) {
- intptr_t source_pos = token_index_;
+ const intptr_t source_pos = token_index_;
ConsumeToken();
ExpectToken(Token::kLPAREN);
if (CurrentToken() != Token::kSTRING) {
@@ -3385,7 +3415,7 @@
const int num_parameters = params->parameters->length();
// Parse the function name out.
- intptr_t native_pos = token_index_;
+ const intptr_t native_pos = token_index_;
const String& native_name = ParseNativeDeclaration();
// Now resolve the native function to the corresponding native entrypoint.
@@ -3579,7 +3609,7 @@
(LookaheadToken(1) != Token::kLPAREN)) {
result_type = ParseType(kMustResolve);
}
- intptr_t ident_pos = token_index_;
+ const intptr_t ident_pos = token_index_;
if (CurrentToken() == Token::kIDENT) {
variable_name = CurrentLiteral();
function_name = variable_name;
@@ -3779,7 +3809,7 @@
ParseQualIdent(&type_name);
// Check if the type_name has been defined as a variable in a local scope,
// hiding the type.
- if (type_name.local_scope_ident) {
+ if (type_name.is_local_scope_ident) {
return false;
}
if (CurrentToken() == Token::kLT && !IsTypeParameter()) {
@@ -3816,7 +3846,7 @@
if (CurrentToken() != Token::kIDENT) {
return false;
}
- intptr_t saved_pos = token_index_;
+ const intptr_t saved_pos = token_index_;
bool is_var_decl = false;
if (IsOptionalType()) {
if (CurrentToken() == Token::kIDENT) {
@@ -3853,7 +3883,7 @@
if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
return true;
}
- intptr_t saved_pos = token_index_;
+ const intptr_t saved_pos = token_index_;
if (IsReturnType()) {
if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
if (LookaheadToken(1) == Token::kIDENT) { // Accessor name.
@@ -3871,7 +3901,7 @@
if (!allow_function_literals_) {
return false;
}
- intptr_t saved_pos = token_index_;
+ const intptr_t saved_pos = token_index_;
bool is_function_literal = false;
if ((CurrentToken() == Token::kIDENT) &&
(LookaheadToken(1) == Token::kLPAREN)) {
@@ -3899,7 +3929,7 @@
// statement. Returns true if we recognize a for ( .. in expr)
// statement.
bool Parser::IsForInStatement() {
- intptr_t saved_pos = token_index_;
+ const intptr_t saved_pos = token_index_;
bool result = false;
if (CurrentToken() == Token::kVAR || CurrentToken() == Token::kFINAL) {
ConsumeToken();
@@ -3945,7 +3975,7 @@
const bool dead_code_allowed = true;
bool abrupt_completing_seen = false;
while (CurrentToken() != Token::kRBRACE) {
- intptr_t statement_pos = token_index_;
+ const intptr_t statement_pos = token_index_;
AstNode* statement = ParseStatement();
if (statement != NULL) {
if (!dead_code_allowed && abrupt_completing_seen) {
@@ -3990,7 +4020,7 @@
AstNode* Parser::ParseIfStatement(String* label_name) {
TRACE_PARSER("ParseIfStatement");
ASSERT(CurrentToken() == Token::kIF);
- intptr_t if_pos = token_index_;
+ const intptr_t if_pos = token_index_;
SourceLabel* label = NULL;
if (label_name != NULL) {
label = SourceLabel::New(if_pos, label_name, SourceLabel::kStatement);
@@ -4023,7 +4053,7 @@
SourceLabel* case_label) {
TRACE_PARSER("ParseCaseStatement");
bool default_seen = false;
- intptr_t case_pos = token_index_;
+ const intptr_t case_pos = token_index_;
SequenceNode* case_expressions =
new SequenceNode(case_pos, current_block_->scope);
while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) {
@@ -4032,7 +4062,7 @@
ErrorMsg("default clause must be last case");
}
ConsumeToken(); // Keyword case.
- intptr_t expr_pos = token_index_;
+ const intptr_t expr_pos = token_index_;
AstNode* expr = ParseExpr(kAllowConst);
AstNode* switch_expr_load = new LoadLocalNode(case_pos,
*switch_expr_value);
@@ -4097,7 +4127,7 @@
AstNode* Parser::ParseSwitchStatement(String* label_name) {
TRACE_PARSER("ParseSwitchStatement");
ASSERT(CurrentToken() == Token::kSWITCH);
- intptr_t switch_pos = token_index_;
+ const intptr_t switch_pos = token_index_;
SourceLabel* label =
SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch);
ConsumeToken();
@@ -4109,7 +4139,7 @@
} else if (parens_are_mandatory) {
ErrorMsg("'(' expected");
}
- intptr_t expr_pos = token_index_;
+ const intptr_t expr_pos = token_index_;
AstNode* switch_expr = ParseExpr(kAllowConst);
if (paren_found) {
ExpectToken(Token::kRPAREN);
@@ -4137,7 +4167,7 @@
LookaheadToken(1) == Token::kCOLON) {
// Case statements start with a label.
String* label_name = CurrentLiteral();
- intptr_t label_pos = token_index_;
+ const intptr_t label_pos = token_index_;
ConsumeToken(); // Consume label identifier.
ConsumeToken(); // Consume colon.
case_label = current_block_->scope->LocalLookupLabel(*label_name);
@@ -4189,7 +4219,7 @@
AstNode* Parser::ParseWhileStatement(String* label_name) {
TRACE_PARSER("ParseWhileStatement");
- intptr_t while_pos = token_index_;
+ const intptr_t while_pos = token_index_;
SourceLabel* label =
SourceLabel::New(while_pos, label_name, SourceLabel::kWhile);
ConsumeToken();
@@ -4204,7 +4234,7 @@
AstNode* Parser::ParseDoWhileStatement(String* label_name) {
TRACE_PARSER("ParseDoWhileStatement");
- intptr_t do_pos = token_index_;
+ const intptr_t do_pos = token_index_;
SourceLabel* label =
SourceLabel::New(do_pos, label_name, SourceLabel::kDoWhile);
ConsumeToken();
@@ -4240,7 +4270,7 @@
}
}
ExpectToken(Token::kIN);
- intptr_t collection_pos = token_index_;
+ const intptr_t collection_pos = token_index_;
AstNode* collection_expr = ParseExpr(kAllowConst);
ExpectToken(Token::kRPAREN);
@@ -4332,7 +4362,7 @@
AstNode* Parser::ParseForStatement(String* label_name) {
TRACE_PARSER("ParseForStatement");
- intptr_t for_pos = token_index_;
+ const intptr_t for_pos = token_index_;
ConsumeToken();
ExpectToken(Token::kLPAREN);
SourceLabel* label = SourceLabel::New(for_pos, label_name, SourceLabel::kFor);
@@ -4344,7 +4374,7 @@
// the loop variable declarations.
current_block_->scope->AddLabel(label);
AstNode* initializer = NULL;
- intptr_t init_pos = token_index_;
+ const intptr_t init_pos = token_index_;
LocalScope* init_scope = current_block_->scope;
if (CurrentToken() != Token::kSEMICOLON) {
if (IsVariableDeclaration()) {
@@ -4360,7 +4390,7 @@
}
ExpectSemicolon();
AstNode* increment = NULL;
- intptr_t incr_pos = token_index_;
+ const intptr_t incr_pos = token_index_;
LocalScope* incr_scope = current_block_->scope;
if (CurrentToken() != Token::kRPAREN) {
increment = ParseExprList();
@@ -4628,7 +4658,7 @@
current_block_->scope->AddVariable(catch_trace_var);
}
- intptr_t try_pos = token_index_;
+ const intptr_t try_pos = token_index_;
ConsumeToken(); // Consume the 'try'.
SourceLabel* try_label = NULL;
@@ -4658,12 +4688,12 @@
bool catch_seen = false;
bool generic_catch_seen = false;
SequenceNode* catch_handler_list = NULL;
- intptr_t handler_pos = token_index_;
+ const intptr_t handler_pos = token_index_;
OpenBlock(); // Start the catch block sequence.
current_block_->scope->AddLabel(end_catch_label);
while (CurrentToken() == Token::kCATCH) {
catch_seen = true;
- intptr_t catch_pos = token_index_;
+ const intptr_t catch_pos = token_index_;
ConsumeToken(); // Consume the 'catch'.
ExpectToken(Token::kLPAREN);
CatchParamDesc exception_param;
@@ -4679,7 +4709,7 @@
// subsequent catch statements are dead. We issue an error for now,
// it might make sense to turn this into a warning.
if (generic_catch_seen) {
- ErrorMsg("A generic 'catch all' statement already exists for this "
+ ErrorMsg("a generic 'catch all' statement already exists for this "
"try block. All subsequent catch statements are dead code");
}
OpenBlock();
@@ -4755,7 +4785,7 @@
if (CurrentToken() == Token::kFINALLY) {
current_function_.set_is_optimizable(false);
ConsumeToken(); // Consume the 'finally'.
- intptr_t finally_pos = token_index_;
+ const intptr_t finally_pos = token_index_;
// Add the finally block to the exit points recorded so far.
intptr_t node_index = 0;
AstNode* node_to_inline =
@@ -4818,7 +4848,7 @@
AstNode* Parser::ParseJump(String* label_name) {
ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE);
Token::Kind jump_kind = CurrentToken();
- intptr_t jump_pos = token_index_;
+ const intptr_t jump_pos = token_index_;
SourceLabel* target = NULL;
ConsumeToken();
if (CurrentToken() == Token::kIDENT) {
@@ -5041,6 +5071,8 @@
if (FLAG_warning_as_error) {
Isolate::Current()->long_jump_base()->Jump(1, error_msg_);
UNREACHABLE();
+ } else {
+ OS::Print(error_msg_);
}
}
@@ -5338,7 +5370,7 @@
case Token::kASSIGN_XOR:
return new BinaryOpNode(op_pos, Token::kBIT_XOR, lhs, rhs);
default:
- ErrorMsg(op_pos, "Internal error: ExpandAssignableOp '%s' unimplemented",
+ ErrorMsg(op_pos, "internal error: ExpandAssignableOp '%s' unimplemented",
Token::Name(assignment_op));
UNIMPLEMENTED();
return NULL;
@@ -5386,7 +5418,7 @@
AstNode* assign_expr = expr->MakeAssignmentNode(right_expr);
if (assign_expr == NULL) {
ErrorMsg(assignment_pos,
- "Left hand side of '%s' is not assignable",
+ "left hand side of '%s' is not assignable",
Token::Str(assignment_op));
}
return assign_expr;
@@ -5430,7 +5462,7 @@
ConsumeToken();
expr = ParseUnaryExpr();
if (!IsAssignableExpr(expr)) {
- ErrorMsg("Expression is not assignable");
+ ErrorMsg("expression is not assignable");
}
// is_prefix.
AstNode* incr_op_node = expr->MakeIncrOpNode(op_pos, incr_op, true);
@@ -5781,7 +5813,7 @@
// Dynamic function call on implicit "this" parameter.
if (current_function().is_static()) {
ErrorMsg(primary_pos,
- "Cannot access instance method '%s' "
+ "cannot access instance method '%s' "
"from static function",
func_name.ToCString());
}
@@ -5801,7 +5833,7 @@
}
} else if (primary->primary().IsClass()) {
ErrorMsg(left->token_index(),
- "must use 'new' or 'const' to construct new instance");
+ "must use 'new' or 'const' to construct new instance");
} else {
// Internal parser error.
UNREACHABLE();
@@ -5882,9 +5914,13 @@
}
-bool Parser::ResolveTypeFromClass(intptr_t type_pos,
- const Class& cls,
- Type* type) {
+// Try to resolve the given type and its type arguments from the given class.
+// Not all involved type classes may get resolved yet, but at least the type
+// parameters of the given class will get resolved, thereby relieving the class
+// finalizer from resolving type parameters out of context.
+void Parser::TryResolveTypeFromClass(intptr_t type_pos,
+ const Class& cls,
+ Type* type) {
ASSERT(type != NULL);
// Resolve class.
if (!type->HasResolvedTypeClass()) {
@@ -5896,42 +5932,36 @@
const TypeParameter& type_parameter = TypeParameter::Handle(
cls.LookupTypeParameter(unresolved_class_name));
if (!type_parameter.IsNull()) {
- CheckTypeParameterReference(type_pos, unresolved_class_name);
// A type parameter cannot be parameterized, so report an error if type
// arguments have previously been parsed.
if (type->arguments() != TypeArguments::null()) {
ErrorMsg(type_pos, "type parameter '%s' cannot be parameterized",
type_parameter.ToCString());
- return false;
}
*type = type_parameter.raw();
- return true;
+ return;
}
const Class& resolved_type_class =
Class::Handle(LookupClass(unresolved_class_name));
- if (resolved_type_class.IsNull()) {
- return false;
+ if (!resolved_type_class.IsNull()) {
+ Object& type_class = Object::Handle(resolved_type_class.raw());
+ ASSERT(type->IsParameterizedType());
+ // Replace unresolved class with resolved type class.
+ ParameterizedType& parameterized_type = ParameterizedType::Handle();
+ parameterized_type ^= type->raw();
+ parameterized_type.set_type_class(type_class);
}
- Object& type_class = Object::Handle(resolved_type_class.raw());
- ASSERT(type->IsParameterizedType());
- // Replace unresolved class with resolved type class.
- ParameterizedType& parameterized_type = ParameterizedType::Handle();
- parameterized_type ^= type->raw();
- parameterized_type.set_type_class(type_class);
}
// Resolve type arguments, if any.
const TypeArguments& arguments = TypeArguments::Handle(type->arguments());
if (!arguments.IsNull()) {
- intptr_t num_arguments = arguments.Length();
+ const intptr_t num_arguments = arguments.Length();
for (intptr_t i = 0; i < num_arguments; i++) {
Type& type_argument = Type::Handle(arguments.TypeAt(i));
- if (!ResolveTypeFromClass(type_pos, cls, &type_argument)) {
- return false;
- }
+ TryResolveTypeFromClass(type_pos, cls, &type_argument);
arguments.SetTypeAt(i, type_argument);
}
}
- return true;
}
@@ -5990,22 +6020,51 @@
}
-void Parser::CheckTypeParameterReference(intptr_t type_parameter_pos,
- const String& type_parameter_name) {
+// If type parameters are currently in scope, return their declaring class,
+// otherwise return null.
+RawClass* Parser::TypeParametersScopeClass() {
// Type parameters cannot be referred to from a static function, except from
// a constructor or from a factory.
// A constructor is considered as non-static by the compiler.
- if ((is_top_level_ &&
- (current_member_ != NULL) &&
- current_member_->has_static &&
- !current_member_->has_factory) ||
- (!current_function().IsNull() &&
- current_function().is_static() &&
- !current_function().IsInFactoryScope())) {
- ErrorMsg(type_parameter_pos,
- "cannot refer to type parameter '%s' from a static function",
- type_parameter_name.ToCString());
+ if (is_top_level_) {
+ if ((current_member_ != NULL) && current_member_->has_factory) {
+ const Type& factory_result_type = *current_member_->type;
+ ASSERT(!factory_result_type.IsNull());
+ const UnresolvedClass& unresolved_factory_class =
+ UnresolvedClass::Handle(factory_result_type.unresolved_class());
+ // TODO(regis): For now, and until the core lib is fixed, we accept a
+ // factory method with missing list of type parameters and use the
+ // list of the enclosing class.
+ // See bug 5408808.
+ // Therefore, we temporarily return the current class instead of the
+ // factory signature class if the latter one does not declare any type
+ // parameters.
+ const Class& factory_signature_class =
+ Class::Handle(unresolved_factory_class.factory_signature_class());
+ if (factory_signature_class.NumTypeParameters() == 0) {
+ return current_class().raw();
+ } else {
+ return factory_signature_class.raw();
+ }
+ }
+ if ((current_member_ == NULL) || !current_member_->has_static) {
+ return current_class().raw();
+ }
+ } else {
+ if (!current_function().IsNull()) {
+ Function& outer_function = Function::Handle(current_function().raw());
+ while (outer_function.IsLocalFunction()) {
+ outer_function = outer_function.parent_function();
+ }
+ if (outer_function.IsFactory()) {
+ return outer_function.signature_class();
+ }
+ if (!outer_function.is_static()) {
+ return current_class().raw();
+ }
+ }
}
+ return Class::null();
}
@@ -6013,7 +6072,7 @@
ASSERT(field.is_static());
const Instance& value = Instance::Handle(field.value());
if (value.raw() == Object::transition_sentinel()) {
- ErrorMsg("Circular dependency while initializing static field '%s'",
+ ErrorMsg("circular dependency while initializing static field '%s'",
String::Handle(field.name()).ToCString());
} else if (value.raw() == Object::sentinel()) {
@@ -6040,7 +6099,7 @@
Instance& const_value = Instance::Handle(
DartEntry::InvokeStatic(func, arguments, kNoArgumentNames));
if (const_value.IsUnhandledException()) {
- ErrorMsg("Exception thrown in Parser::RunStaticFieldInitializer");
+ ErrorMsg("exception thrown in Parser::RunStaticFieldInitializer");
}
if (!const_value.IsNull()) {
const_value ^= const_value.Canonicalize();
@@ -6339,10 +6398,10 @@
ErrorMsg("type name expected");
}
QualIdent type_name;
- intptr_t type_pos = token_index_;
+ const intptr_t type_pos = token_index_;
ParseQualIdent(&type_name);
- if (type_name.local_scope_ident) {
- ErrorMsg(type_pos, "Using '%s' in this context is invalid",
+ if (type_name.is_local_scope_ident) {
+ ErrorMsg(type_pos, "using '%s' in this context is invalid",
type_name.ident->ToCString());
}
Object& type_class = Object::Handle();
@@ -6353,26 +6412,27 @@
}
type_class = UnresolvedClass::New(type_pos, qualifier, *(type_name.ident));
} else {
- TypeParameter& type_parameter = TypeParameter::Handle();
- // Check if qualifier is a type parameter of the class we are parsing.
- if (type_name.qualifier != NULL) {
- type_parameter =
- current_class().LookupTypeParameter(*type_name.qualifier);
- if (!type_parameter.IsNull()) {
- ErrorMsg(type_pos, "Use of '%s' in this context is invalid",
- type_name.qualifier->ToCString());
- }
- } else {
- // Check if ident is a type parameter of the class we are parsing.
- type_parameter = current_class().LookupTypeParameter(*type_name.ident);
- if (!type_parameter.IsNull()) {
- CheckTypeParameterReference(type_name.ident_pos, *type_name.ident);
- if (CurrentToken() == Token::kLT) {
- // A type parameter cannot be parameterized.
- ErrorMsg(type_pos, "type parameter '%s' cannot be parameterized",
- String::Handle(type_parameter.Name()).ToCString());
+ const Class& scope_class = Class::Handle(TypeParametersScopeClass());
+ if (!scope_class.IsNull()) {
+ TypeParameter& type_parameter = TypeParameter::Handle();
+ // Check if qualifier is a type parameter in scope.
+ if (type_name.qualifier != NULL) {
+ type_parameter = scope_class.LookupTypeParameter(*type_name.qualifier);
+ if (!type_parameter.IsNull()) {
+ ErrorMsg(type_pos, "type Parameter '%s' cannot be used as qualifier",
+ type_name.qualifier->ToCString());
}
- return type_parameter.raw();
+ } else {
+ // Check if ident is a type parameter in scope.
+ type_parameter = scope_class.LookupTypeParameter(*type_name.ident);
+ if (!type_parameter.IsNull()) {
+ if (CurrentToken() == Token::kLT) {
+ // A type parameter cannot be parameterized.
+ ErrorMsg(type_pos, "type parameter '%s' cannot be parameterized",
+ String::Handle(type_parameter.Name()).ToCString());
+ }
+ return type_parameter.raw();
+ }
}
}
// Try to resolve the type class.
@@ -6396,12 +6456,20 @@
void Parser::CheckConstructorCallTypeArguments(
intptr_t pos, Function& constructor, const TypeArguments& type_arguments) {
- if (!type_arguments.IsNull() &&
- (type_arguments.Length() !=
- Class::Handle(constructor.owner()).NumTypeArguments())) {
- ErrorMsg(pos, "Incorrect number of type arguments, expected %d got %d",
- Class::Handle(constructor.owner()).NumTypeArguments(),
- type_arguments.Length());
+ if (!type_arguments.IsNull()) {
+ Class& signature_class = Class::Handle();
+ if (constructor.IsFactory()) {
+ signature_class = constructor.signature_class();
+ } else {
+ signature_class = constructor.owner();
+ }
+ ASSERT(!signature_class.IsNull());
+ ASSERT(signature_class.is_finalized());
+ if (type_arguments.Length() != signature_class.NumTypeArguments()) {
+ ErrorMsg(pos, "incorrect number of type arguments, expected %d got %d",
+ signature_class.NumTypeArguments(),
+ type_arguments.Length());
+ }
}
}
@@ -6414,7 +6482,7 @@
bool is_const,
const TypeArguments& type_arguments) {
ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
- intptr_t literal_pos = token_index_;
+ const intptr_t literal_pos = token_index_;
bool is_empty_literal = CurrentToken() == Token::kINDEX;
ConsumeToken();
@@ -6523,7 +6591,7 @@
const TypeArguments& type_arguments) {
TRACE_PARSER("ParseMapLiteral");
ASSERT(CurrentToken() == Token::kLBRACE);
- intptr_t literal_pos = token_index_;
+ const intptr_t literal_pos = token_index_;
ConsumeToken();
String& map_class_name = String::Handle(
@@ -6635,7 +6703,7 @@
is_const = true;
ConsumeToken();
}
- intptr_t type_pos = token_index_;
+ const intptr_t type_pos = token_index_;
TypeArguments& type_arguments =
TypeArguments::ZoneHandle(ParseTypeArguments(kMustResolve));
AstNode* primary = NULL;
@@ -6645,7 +6713,7 @@
} else if (CurrentToken() == Token::kLBRACE) {
primary = ParseMapLiteral(type_pos, is_const, type_arguments);
} else {
- ErrorMsg("Unexpected token %s", Token::Str(CurrentToken()));
+ ErrorMsg("unexpected token %s", Token::Str(CurrentToken()));
}
return primary;
}
@@ -6688,36 +6756,35 @@
String& type_class_name = String::Handle();
TypeArguments& type_arguments = TypeArguments::ZoneHandle();
String* named_constructor = NULL;
- intptr_t type_pos = token_index_;
+ const intptr_t type_pos = token_index_;
QualIdent type_name;
ParseQualIdent(&type_name);
- if (type_name.local_scope_ident) {
- ErrorMsg(type_pos, "Using '%s' in this context is invalid",
+ if (type_name.is_local_scope_ident) {
+ ErrorMsg(type_pos, "using '%s' in this context is invalid",
type_name.ident->ToCString());
}
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
named_constructor = ExpectIdentifier("identifier expected after '.'");
}
- TypeParameter& type_parameter = TypeParameter::Handle();
- if (type_name.lib_prefix != NULL) {
- // TODO(regis): Ascertain that this check for shadowing is valid
- // See bug (490270).
- // Check if qualifier is a type parameter of the class we are parsing.
- type_parameter ^= current_class().LookupTypeParameter(*type_name.qualifier);
+ const Class& scope_class = Class::Handle(TypeParametersScopeClass());
+ if (!scope_class.IsNull()) {
+ TypeParameter& type_parameter = TypeParameter::Handle();
+ if (type_name.lib_prefix != NULL) {
+ // Check if qualifier is a type parameter in scope.
+ type_parameter ^= scope_class.LookupTypeParameter(*type_name.qualifier);
+ if (!type_parameter.IsNull()) {
+ ErrorMsg(type_pos, "type parameter '%s' cannot be used as qualifier",
+ String::Handle(type_parameter.Name()).ToCString());
+ }
+ }
+ // Check if ident is a type parameter in scope.
+ type_parameter = scope_class.LookupTypeParameter(*type_name.ident);
if (!type_parameter.IsNull()) {
- CheckTypeParameterReference(type_pos, *type_name.qualifier);
ErrorMsg(type_pos, "type parameter '%s' cannot be instantiated",
String::Handle(type_parameter.Name()).ToCString());
}
}
- // Check if ident is a type parameter of the class we are parsing.
- type_parameter = current_class().LookupTypeParameter(*type_name.ident);
- if (!type_parameter.IsNull()) {
- CheckTypeParameterReference(type_name.ident_pos, *type_name.ident);
- ErrorMsg(type_pos, "type parameter '%s' cannot be instantiated",
- String::Handle(type_parameter.Name()).ToCString());
- }
type_class ^= LookupTypeClass(type_name, kMustResolve);
type_class_name = type_class.Name();
// Type arguments are not allowed after the optional constructor name.
@@ -6769,37 +6836,29 @@
external_constructor_name.ToCString(),
type_class_name.ToCString());
}
-
- // TODO(srdjan): Evaluate if the mapping should occur during code
- // generation or here in the parser.
- const Type& factory_type = Type::Handle(type_class.factory_type());
- if (factory_type.IsNull()) {
+ if (!type_class.HasFactoryClass()) {
ErrorMsg("cannot allocate interface '%s' without factory class",
type_class_name.ToCString());
}
- if (!factory_type.HasResolvedTypeClass()) {
+ if (!type_class.HasResolvedFactoryClass()) {
// This error can occur only with bootstrap classes.
const UnresolvedClass& unresolved =
- UnresolvedClass::Handle(factory_type.unresolved_class());
+ UnresolvedClass::Handle(type_class.UnresolvedFactoryClass());
const String& missing_class_name = String::Handle(unresolved.ident());
- ErrorMsg("Unresolved factory class '%s'", missing_class_name.ToCString());
+ ErrorMsg("unresolved factory class '%s'", missing_class_name.ToCString());
}
-
// Only change the class of the constructor to the factory class if the
// factory class implements the interface 'type'.
- Class& factory_type_class = Class::Handle(factory_type.type_class());
- // TODO(regis): Verify in the guide/spec that a factory class must have
- // identical type parameters as the interface.
- // TODO(regis): Do we check that in the parser?
- // Assuming that it has been checked, it is sufficient to test if the
- // raw factory type implements the raw interface type.
- if (factory_type_class.IsSubtypeOf(TypeArguments::Handle(),
- type_class,
- TypeArguments::Handle())) {
- type_class_name = factory_type_class.Name();
+ const Class& factory_class = Class::Handle(type_class.FactoryClass());
+ if (factory_class.IsSubtypeOf(TypeArguments::Handle(),
+ type_class,
+ TypeArguments::Handle())) {
+ // Class finalization verifies that the factory class has identical type
+ // parameters as the interface.
+ type_class_name = factory_class.Name();
}
// Always change the result type of the constructor to the factory type.
- type_class = factory_type_class.raw();
+ type_class = factory_class.raw();
ASSERT(!type_class.is_interface());
}
@@ -6868,7 +6927,7 @@
// there are never two kSTRING tokens next to each other.
AstNode* Parser::ParseStringLiteral() {
AstNode* primary = NULL;
- intptr_t literal_start = token_index_;
+ const intptr_t literal_start = token_index_;
if ((CurrentToken() == Token::kSTRING) &&
(LookaheadToken(1) != Token::kINTERPOL_VAR) &&
(LookaheadToken(1) != Token::kINTERPOL_START)) {
@@ -6927,7 +6986,7 @@
} else if (CurrentToken() == Token::kIDENT) {
QualIdent qual_ident;
ParseQualIdent(&qual_ident);
- if (qual_ident.local_scope_ident) {
+ if (qual_ident.is_local_scope_ident) {
ResolveIdentInLocalScope(qual_ident.ident_pos,
*qual_ident.ident,
&primary);
@@ -7028,7 +7087,7 @@
Token::CanBeOverloaded(CurrentToken())) {
primary = ParseSuperOperator();
} else {
- ErrorMsg("Illegal super call");
+ ErrorMsg("illegal super call");
}
} else {
UnexpectedToken();

Powered by Google App Engine
This is Rietveld 408576698