| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 779)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -790,17 +790,19 @@
|
| parameter.type = &Type::ZoneHandle(Type::VoidType());
|
| }
|
| if (parameter.type == NULL) {
|
| - // At this point, we must see an identifier for the type or the
|
| + // At this point, we must see 'Dynamic' or an identifier for the type or the
|
| // function parameter.
|
| - if (CurrentToken() != Token::kIDENT) {
|
| + if ((CurrentToken() != Token::kIDENT) &&
|
| + (CurrentToken() != Token::kDYNAMIC)) {
|
| ErrorMsg("parameter name or type expected");
|
| }
|
| // We have not seen a parameter type yet, so we check if the next
|
| - // identifier could represent a type before parsing it.
|
| + // token could represent a type before parsing it.
|
| Token::Kind follower = LookaheadToken(1);
|
| - // We have an identifier followed by a 'follower' token.
|
| + // We have 'Dynamic' or an identifier followed by a 'follower' token.
|
| // We either parse a type or assume that no type is specified.
|
| - if ((follower == Token::kLT) || // Parameterized type.
|
| + if ((CurrentToken() == Token::kDYNAMIC) || // Dynamic type.
|
| + (follower == Token::kLT) || // Parameterized type.
|
| (follower == Token::kPERIOD) || // Qualified class name of type.
|
| (follower == Token::kIDENT) || // Parameter name following a type.
|
| (follower == Token::kTHIS)) { // Field parameter following a type.
|
| @@ -2082,15 +2084,17 @@
|
| ConsumeToken();
|
| ASSERT(member.type == NULL);
|
| member.type = &Type::ZoneHandle(Type::VoidType());
|
| - } else if (CurrentToken() == Token::kIDENT) {
|
| + } else if ((CurrentToken() == Token::kIDENT) ||
|
| + (CurrentToken() == Token::kDYNAMIC)) {
|
| // This is either a type name or the name of a method/constructor/field.
|
| if (member.type == NULL) {
|
| // 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);
|
| - // We have an identifier followed by a 'follower' token.
|
| + // We have 'Dynamic' or an identifier followed by a 'follower' token.
|
| // We either parse a type or assume that no type is specified.
|
| - if ((follower == Token::kLT) || // Parameterized type.
|
| + if ((CurrentToken() == Token::kDYNAMIC) || // Dynamic type.
|
| + (follower == Token::kLT) || // Parameterized type.
|
| (follower == Token::kGET) || // Getter following a type.
|
| (follower == Token::kSET) || // Setter following a type.
|
| (follower == Token::kOPERATOR) || // Operator following a type.
|
| @@ -2346,6 +2350,9 @@
|
| // and the alias name of a function type alias.
|
| // Token position remains unchanged.
|
| bool Parser::IsFunctionTypeAliasName() {
|
| + if (CurrentToken() == Token::kDYNAMIC) {
|
| + return false;
|
| + }
|
| if ((CurrentToken() == Token::kIDENT) &&
|
| (LookaheadToken(1) == Token::kLPAREN)) {
|
| return true;
|
| @@ -2584,7 +2591,8 @@
|
| GrowableArray<Type*> type_parameter_extends;
|
| do {
|
| ConsumeToken();
|
| - if (CurrentToken() != Token::kIDENT) {
|
| + if ((CurrentToken() != Token::kDYNAMIC) &&
|
| + (CurrentToken() != Token::kIDENT)) {
|
| ErrorMsg("type parameter name expected");
|
| }
|
| String& type_parameter_name = *CurrentLiteral();
|
| @@ -2733,8 +2741,9 @@
|
| result_type = Type::VoidType();
|
| } else {
|
| // Parse optional type.
|
| - if ((CurrentToken() == Token::kIDENT) &&
|
| - (LookaheadToken(1) != Token::kLPAREN)) {
|
| + if ((CurrentToken() == Token::kDYNAMIC) ||
|
| + ((CurrentToken() == Token::kIDENT) &&
|
| + (LookaheadToken(1) != Token::kLPAREN))) {
|
| result_type = ParseType(kCanResolve);
|
| }
|
| }
|
| @@ -3269,6 +3278,10 @@
|
| ConsumeToken();
|
| type_specification = kIsOptional;
|
| }
|
| + if (CurrentToken() == Token::kDYNAMIC) {
|
| + ConsumeToken();
|
| + return Type::DynamicType();
|
| + }
|
| if (CurrentToken() != Token::kIDENT) {
|
| if (type_specification == kIsOptional) {
|
| return Type::DynamicType();
|
| @@ -3337,8 +3350,9 @@
|
| if (CurrentToken() == Token::kVOID) {
|
| ConsumeToken();
|
| result_type = Type::VoidType();
|
| - } else if ((CurrentToken() == Token::kIDENT) &&
|
| - (LookaheadToken(1) != Token::kLPAREN)) {
|
| + } else if ((CurrentToken() == Token::kDYNAMIC) ||
|
| + ((CurrentToken() == Token::kIDENT) &&
|
| + (LookaheadToken(1) != Token::kLPAREN))) {
|
| result_type = ParseType(kMustResolve);
|
| }
|
| intptr_t ident_pos = token_index_;
|
| @@ -6064,11 +6078,15 @@
|
| }
|
|
|
|
|
| -// Parses type = [ident "."] ident ["<" type { "," type } ">"].
|
| +// Parses type = "Dynamic" | ([ident "."] ident ["<" type { "," type } ">"]).
|
| // Returns the class object if the type can be resolved. Otherwise, either give
|
| // an error if type resolution was required, or return the unresolved name as a
|
| // string object.
|
| RawType* Parser::ParseType(TypeResolution type_resolution) {
|
| + if (CurrentToken() == Token::kDYNAMIC) {
|
| + ConsumeToken();
|
| + return Type::DynamicType();
|
| + }
|
| if (CurrentToken() != Token::kIDENT) {
|
| ErrorMsg("type name expected");
|
| }
|
| @@ -6397,6 +6415,7 @@
|
| // constructor would be misinterpreted as a qualified type name.
|
| // TODO(regis): Revisit once we correctly support qualified identifiers.
|
| // For now, we inline a customized version of ParseType(kMustResolve).
|
| + // Note that the inline version of ParseType correctly refuses 'Dynamic'.
|
| Type& type = Type::Handle();
|
| Class& type_class = Class::ZoneHandle();
|
| String& type_class_name = String::Handle();
|
|
|