Chromium Code Reviews| Index: runtime/vm/parser.cc |
| =================================================================== |
| --- runtime/vm/parser.cc (revision 23883) |
| +++ runtime/vm/parser.cc (working copy) |
| @@ -511,6 +511,7 @@ |
| has_var = false; |
| has_factory = false; |
| has_operator = false; |
| + metadata_pos = -1; |
| operator_token = Token::kILLEGAL; |
| type = NULL; |
| name_pos = 0; |
| @@ -543,6 +544,7 @@ |
| bool has_var; |
| bool has_factory; |
| bool has_operator; |
| + intptr_t metadata_pos; |
| Token::Kind operator_token; |
| const AbstractType* type; |
| intptr_t name_pos; |
| @@ -647,8 +649,8 @@ |
| return fields_; |
| } |
| - RawClass* clazz() const { |
| - return clazz_.raw(); |
| + const Class& clazz() const { |
| + return clazz_; |
| } |
| const String& class_name() const { |
| @@ -841,6 +843,63 @@ |
| } |
| +RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) { |
| + Isolate* isolate = Isolate::Current(); |
| + StackZone zone(isolate); |
| + LongJump* base = isolate->long_jump_base(); |
| + LongJump jump; |
| + isolate->set_long_jump_base(&jump); |
| + if (setjmp(*jump.Set()) == 0) { |
| + const Script& script = Script::Handle(cls.script()); |
| + const Library& lib = Library::Handle(cls.library()); |
| + Parser parser(script, lib, token_pos); |
| + parser.set_current_class(cls); |
| + return parser.EvaluateMetadata(); |
| + } else { |
| + Error& error = Error::Handle(); |
| + error = isolate->object_store()->sticky_error(); |
| + isolate->object_store()->clear_sticky_error(); |
| + isolate->set_long_jump_base(base); |
| + return error.raw(); |
| + } |
| + UNREACHABLE(); |
| + return Object::null(); |
| +} |
| + |
| + |
| +RawArray* Parser::EvaluateMetadata() { |
| + if (CurrentToken() != Token::kAT) { |
| + ErrorMsg("Metadata character '@' expected"); |
| + } |
| + GrowableObjectArray& meta_values = |
| + GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| + while (CurrentToken() == Token::kAT) { |
| + ConsumeToken(); |
| + intptr_t expr_pos = TokenPos(); |
| + if (!IsIdentifier()) { |
| + ExpectIdentifier("identifier expected"); |
| + } |
| + AstNode* expr = NULL; |
| + if ((LookaheadToken(1) == Token::kLPAREN) || |
| + ((LookaheadToken(1) == Token::kPERIOD) && |
| + (LookaheadToken(3) == Token::kLPAREN)) || |
| + ((LookaheadToken(1) == Token::kPERIOD) && |
| + (LookaheadToken(3) == Token::kPERIOD) && |
| + (LookaheadToken(5) == Token::kLPAREN))) { |
| + expr = ParseNewOperator(Token::kCONST); |
| + } else { |
| + expr = ParsePrimary(); |
| + } |
| + if (expr->EvalConstExpr() == NULL) { |
| + ErrorMsg(expr_pos, "expression must be a compile-time constant"); |
| + } |
| + const Instance& val = EvaluateConstExpr(expr); |
| + meta_values.Add(val); |
| + } |
|
siva
2013/06/12 00:16:52
ASSERT(meta_values.Length() > 0); ?
We don't expe
|
| + return Array::MakeArray(meta_values); |
| +} |
| + |
| + |
| // TODO(regis): Since a const variable is implicitly final, |
| // rename ParseStaticConstGetter to ParseStaticFinalGetter and |
| // rename kConstImplicitGetter to kImplicitFinalGetter. |
| @@ -2824,6 +2883,9 @@ |
| method_pos)); |
| func.set_result_type(*method->type); |
| func.set_end_token_pos(method_end_pos); |
| + if (method->metadata_pos > 0) { |
| + library_.AddFunctionMetadata(func, method->metadata_pos); |
| + } |
| // If this method is a redirecting factory, set the redirection information. |
| if (!redirection_type.IsNull()) { |
| @@ -2911,6 +2973,9 @@ |
| class_field.set_type(*field->type); |
| class_field.set_has_initializer(has_initializer); |
| members->AddField(class_field); |
| + if (field->metadata_pos >= 0) { |
| + library_.AddFieldMetadata(class_field, field->metadata_pos); |
| + } |
| // For static const fields, set value to "uninitialized" and |
| // create a kConstImplicitGetter getter method. |
| @@ -3001,10 +3066,12 @@ |
| } |
| -void Parser::ParseClassMemberDefinition(ClassDesc* members) { |
| +void Parser::ParseClassMemberDefinition(ClassDesc* members, |
| + intptr_t metadata_pos) { |
| TRACE_PARSER("ParseClassMemberDefinition"); |
| MemberDesc member; |
| current_member_ = &member; |
| + member.metadata_pos = metadata_pos; |
| if ((CurrentToken() == Token::kEXTERNAL) && |
| (LookaheadToken(1) != Token::kLPAREN)) { |
| ConsumeToken(); |
| @@ -3217,7 +3284,8 @@ |
| } |
| -void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes) { |
| +void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes, |
| + intptr_t metadata_pos) { |
| TRACE_PARSER("ParseClassDeclaration"); |
| bool is_patch = false; |
| bool is_abstract = false; |
| @@ -3359,6 +3427,9 @@ |
| cls.set_is_patch(); |
| } |
| pending_classes.Add(cls, Heap::kOld); |
| + if (metadata_pos >= 0) { |
| + library_.AddClassMetadata(cls, metadata_pos); |
| + } |
| if (CurrentToken() != Token::kLBRACE) { |
| ErrorMsg("{ expected"); |
| @@ -3379,8 +3450,8 @@ |
| } |
| ExpectToken(Token::kLBRACE); |
| while (CurrentToken() != Token::kRBRACE) { |
| - SkipMetadata(); |
| - ParseClassMemberDefinition(&members); |
| + intptr_t metadata_pos = SkipMetadata(); |
| + ParseClassMemberDefinition(&members, metadata_pos); |
| } |
| ExpectToken(Token::kRBRACE); |
| @@ -3719,7 +3790,11 @@ |
| } |
| -void Parser::SkipMetadata() { |
| +intptr_t Parser::SkipMetadata() { |
| + if (CurrentToken() != Token::kAT) { |
| + return -1; |
| + } |
| + intptr_t metadata_pos = TokenPos(); |
| while (CurrentToken() == Token::kAT) { |
| ConsumeToken(); |
| ExpectIdentifier("identifier expected"); |
| @@ -3735,6 +3810,7 @@ |
| SkipToMatchingParenthesis(); |
| } |
| } |
| + return metadata_pos; |
| } |
| @@ -3973,7 +4049,8 @@ |
| } |
| -void Parser::ParseTopLevelVariable(TopLevel* top_level) { |
| +void Parser::ParseTopLevelVariable(TopLevel* top_level, |
| + intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelVariable"); |
| const bool is_const = (CurrentToken() == Token::kCONST); |
| // Const fields are implicitly final. |
| @@ -4013,6 +4090,9 @@ |
| field.set_value(Instance::Handle(Instance::null())); |
| top_level->fields.Add(field); |
| library_.AddObject(field, var_name); |
| + if (metadata_pos >= 0) { |
| + library_.AddFieldMetadata(field, metadata_pos); |
| + } |
| if (CurrentToken() == Token::kASSIGN) { |
| ConsumeToken(); |
| Instance& field_value = Instance::Handle(Object::sentinel().raw()); |
| @@ -4052,7 +4132,8 @@ |
| } |
| -void Parser::ParseTopLevelFunction(TopLevel* top_level) { |
| +void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| + intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelFunction"); |
| AbstractType& result_type = Type::Handle(Type::DynamicType()); |
| const bool is_static = true; |
| @@ -4137,10 +4218,14 @@ |
| } else { |
| library_.ReplaceObject(func, func_name); |
| } |
| + if (metadata_pos >= 0) { |
| + library_.AddFunctionMetadata(func, metadata_pos); |
| + } |
| } |
| -void Parser::ParseTopLevelAccessor(TopLevel* top_level) { |
| +void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
| + intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelAccessor"); |
| const bool is_static = true; |
| bool is_external = false; |
| @@ -4258,6 +4343,9 @@ |
| } else { |
| library_.ReplaceObject(func, accessor_name); |
| } |
| + if (metadata_pos >= 0) { |
| + library_.AddFunctionMetadata(func, metadata_pos); |
| + } |
| } |
| @@ -4528,27 +4616,27 @@ |
| const Class& cls = Class::Handle(isolate()); |
| while (true) { |
| set_current_class(cls); // No current class. |
| - SkipMetadata(); |
| + intptr_t metadata_pos = SkipMetadata(); |
| if (CurrentToken() == Token::kCLASS) { |
| - ParseClassDeclaration(pending_classes); |
| + ParseClassDeclaration(pending_classes, metadata_pos); |
| } else if ((CurrentToken() == Token::kTYPEDEF) && |
| (LookaheadToken(1) != Token::kLPAREN)) { |
| set_current_class(toplevel_class); |
| ParseTypedef(pending_classes); |
| } else if ((CurrentToken() == Token::kABSTRACT) && |
| (LookaheadToken(1) == Token::kCLASS)) { |
| - ParseClassDeclaration(pending_classes); |
| + ParseClassDeclaration(pending_classes, metadata_pos); |
| } else if (is_patch_source() && IsLiteral("patch") && |
| (LookaheadToken(1) == Token::kCLASS)) { |
| - ParseClassDeclaration(pending_classes); |
| + ParseClassDeclaration(pending_classes, metadata_pos); |
| } else { |
| set_current_class(toplevel_class); |
| if (IsVariableDeclaration()) { |
| - ParseTopLevelVariable(&top_level); |
| + ParseTopLevelVariable(&top_level, metadata_pos); |
| } else if (IsFunctionDeclaration()) { |
| - ParseTopLevelFunction(&top_level); |
| + ParseTopLevelFunction(&top_level, metadata_pos); |
| } else if (IsTopLevelAccessor()) { |
| - ParseTopLevelAccessor(&top_level); |
| + ParseTopLevelAccessor(&top_level, metadata_pos); |
| } else if (CurrentToken() == Token::kEOS) { |
| break; |
| } else { |
| @@ -9146,12 +9234,11 @@ |
| } |
| -AstNode* Parser::ParseNewOperator() { |
| +AstNode* Parser::ParseNewOperator(Token::Kind op_kind) { |
| TRACE_PARSER("ParseNewOperator"); |
| const intptr_t new_pos = TokenPos(); |
| - ASSERT((CurrentToken() == Token::kNEW) || (CurrentToken() == Token::kCONST)); |
| - bool is_const = (CurrentToken() == Token::kCONST); |
| - ConsumeToken(); |
| + ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST)); |
| + bool is_const = (op_kind == Token::kCONST); |
| if (!IsIdentifier()) { |
| ErrorMsg("type name expected"); |
| } |
| @@ -9619,7 +9706,8 @@ |
| } else if (CurrentToken() == Token::kSTRING) { |
| primary = ParseStringLiteral(); |
| } else if (CurrentToken() == Token::kNEW) { |
| - primary = ParseNewOperator(); |
| + ConsumeToken(); |
| + primary = ParseNewOperator(Token::kNEW); |
| } else if (CurrentToken() == Token::kCONST) { |
| if ((LookaheadToken(1) == Token::kLT) || |
| (LookaheadToken(1) == Token::kLBRACK) || |
| @@ -9627,7 +9715,8 @@ |
| (LookaheadToken(1) == Token::kLBRACE)) { |
| primary = ParseCompoundLiteral(); |
| } else { |
| - primary = ParseNewOperator(); |
| + ConsumeToken(); |
| + primary = ParseNewOperator(Token::kCONST); |
| } |
| } else if (CurrentToken() == Token::kLT || |
| CurrentToken() == Token::kLBRACK || |