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 || |