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

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

Issue 106843002: Detect illegal assignable expressions (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years 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
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/assignable_expression_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/bootstrap.h" 9 #include "vm/bootstrap.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 "Class '%s' has no field '%s'", 925 "Class '%s' has no field '%s'",
926 cls.ToCString(), 926 cls.ToCString(),
927 ident->ToCString()); 927 ident->ToCString());
928 } 928 }
929 if (!field.is_const()) { 929 if (!field.is_const()) {
930 ErrorMsg(ident_pos, 930 ErrorMsg(ident_pos,
931 "Field '%s' of class '%s' is not const", 931 "Field '%s' of class '%s' is not const",
932 ident->ToCString(), 932 ident->ToCString(),
933 cls.ToCString()); 933 cls.ToCString());
934 } 934 }
935 expr = GenerateStaticFieldLookup(field, TokenPos()); 935 expr = GenerateStaticFieldLookup(field, ident_pos);
936 } 936 }
937 } 937 }
938 if (expr->EvalConstExpr() == NULL) { 938 if (expr->EvalConstExpr() == NULL) {
939 ErrorMsg(expr_pos, "expression must be a compile-time constant"); 939 ErrorMsg(expr_pos, "expression must be a compile-time constant");
940 } 940 }
941 const Instance& val = EvaluateConstExpr(expr_pos, expr); 941 const Instance& val = EvaluateConstExpr(expr_pos, expr);
942 meta_values.Add(val); 942 meta_values.Add(val);
943 } 943 }
944 return Array::MakeArray(meta_values); 944 return Array::MakeArray(meta_values);
945 } 945 }
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 ParamList params; 1060 ParamList params;
1061 ASSERT(func.num_fixed_parameters() == 0); // static. 1061 ASSERT(func.num_fixed_parameters() == 0); // static.
1062 ASSERT(!func.HasOptionalParameters()); 1062 ASSERT(!func.HasOptionalParameters());
1063 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 1063 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
1064 1064
1065 // Build local scope for function and populate with the formal parameters. 1065 // Build local scope for function and populate with the formal parameters.
1066 OpenFunctionBlock(func); 1066 OpenFunctionBlock(func);
1067 AddFormalParamsToScope(&params, current_block_->scope); 1067 AddFormalParamsToScope(&params, current_block_->scope);
1068 1068
1069 // Move forward to the start of the initializer expression. 1069 // Move forward to the start of the initializer expression.
1070 intptr_t ident_pos = TokenPos();
1070 ExpectIdentifier("identifier expected"); 1071 ExpectIdentifier("identifier expected");
1071 ExpectToken(Token::kASSIGN); 1072 ExpectToken(Token::kASSIGN);
1072 intptr_t token_pos = TokenPos(); 1073 intptr_t token_pos = TokenPos();
1073 1074
1074 // Synthesize a try-catch block to wrap the initializer expression. 1075 // Synthesize a try-catch block to wrap the initializer expression.
1075 LocalVariable* context_var = 1076 LocalVariable* context_var =
1076 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar()); 1077 current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar());
1077 if (context_var == NULL) { 1078 if (context_var == NULL) {
1078 context_var = new LocalVariable(token_pos, 1079 context_var = new LocalVariable(token_pos,
1079 Symbols::SavedTryContextVar(), 1080 Symbols::SavedTryContextVar(),
(...skipping 25 matching lines...) Expand all
1105 field, 1106 field,
1106 expr); 1107 expr);
1107 current_block_->statements->Add(store); 1108 current_block_->statements->Add(store);
1108 SequenceNode* try_block = CloseBlock(); // End try block. 1109 SequenceNode* try_block = CloseBlock(); // End try block.
1109 1110
1110 OpenBlock(); // Start catch handler list. 1111 OpenBlock(); // Start catch handler list.
1111 OpenBlock(); // Start catch clause. 1112 OpenBlock(); // Start catch clause.
1112 AstNode* compare_transition_sentinel = new ComparisonNode( 1113 AstNode* compare_transition_sentinel = new ComparisonNode(
1113 token_pos, 1114 token_pos,
1114 Token::kEQ_STRICT, 1115 Token::kEQ_STRICT,
1115 new LoadStaticFieldNode(token_pos, field), 1116 new LoadStaticFieldNode(ident_pos, field),
1116 new LiteralNode(field.token_pos(), Object::transition_sentinel())); 1117 new LiteralNode(field.token_pos(), Object::transition_sentinel()));
1117 1118
1118 SequenceNode* store_null = new SequenceNode(token_pos, NULL); 1119 SequenceNode* store_null = new SequenceNode(token_pos, NULL);
1119 store_null->Add(new StoreStaticFieldNode( 1120 store_null->Add(new StoreStaticFieldNode(
1120 field.token_pos(), 1121 field.token_pos(),
1121 field, 1122 field,
1122 new LiteralNode(token_pos, Instance::ZoneHandle()))); 1123 new LiteralNode(token_pos, Instance::ZoneHandle())));
1123 AstNode* transition_sentinel_check = 1124 AstNode* transition_sentinel_check =
1124 new IfNode(token_pos, compare_transition_sentinel, store_null, NULL); 1125 new IfNode(token_pos, compare_transition_sentinel, store_null, NULL);
1125 current_block_->statements->Add(transition_sentinel_check); 1126 current_block_->statements->Add(transition_sentinel_check);
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 implicit_closure_function.signature_class()); 1994 implicit_closure_function.signature_class());
1994 if (signature_class.NumTypeParameters() > 0) { 1995 if (signature_class.NumTypeParameters() > 0) {
1995 CaptureInstantiator(); 1996 CaptureInstantiator();
1996 } 1997 }
1997 } 1998 }
1998 } 1999 }
1999 return new ClosureNode(token_pos, implicit_closure_function, receiver, NULL); 2000 return new ClosureNode(token_pos, implicit_closure_function, receiver, NULL);
2000 } 2001 }
2001 2002
2002 2003
2003 AstNode* Parser::ParseSuperFieldAccess(const String& field_name) { 2004 AstNode* Parser::ParseSuperFieldAccess(const String& field_name,
2005 intptr_t field_pos) {
2004 TRACE_PARSER("ParseSuperFieldAccess"); 2006 TRACE_PARSER("ParseSuperFieldAccess");
2005 const intptr_t field_pos = TokenPos();
2006 const Class& super_class = Class::ZoneHandle(current_class().SuperClass()); 2007 const Class& super_class = Class::ZoneHandle(current_class().SuperClass());
2007 if (super_class.IsNull()) { 2008 if (super_class.IsNull()) {
2008 ErrorMsg("class '%s' does not have a superclass", 2009 ErrorMsg("class '%s' does not have a superclass",
2009 String::Handle(current_class().Name()).ToCString()); 2010 String::Handle(current_class().Name()).ToCString());
2010 } 2011 }
2011 AstNode* implicit_argument = LoadReceiver(field_pos); 2012 AstNode* implicit_argument = LoadReceiver(field_pos);
2012 2013
2013 const String& getter_name = 2014 const String& getter_name =
2014 String::ZoneHandle(Field::GetterName(field_name)); 2015 String::ZoneHandle(Field::GetterName(field_name));
2015 const Function& super_getter = Function::ZoneHandle( 2016 const Function& super_getter = Function::ZoneHandle(
(...skipping 5769 matching lines...) Expand 10 before | Expand all | Expand 10 after
7785 } 7786 }
7786 *expr = new InstanceGetterNode(token_pos, 7787 *expr = new InstanceGetterNode(token_pos,
7787 receiver, 7788 receiver,
7788 getter->field_name()); 7789 getter->field_name());
7789 return result; 7790 return result;
7790 } 7791 }
7791 return result; 7792 return result;
7792 } 7793 }
7793 7794
7794 7795
7796 // Check whether the syntax of expression expr is a grammatically legal
7797 // assignable expression. This check is used to detect situations where
7798 // the expression itself is assignable, but the source is grammatically
7799 // wrong. The AST representation of an expression cannot distinguish
7800 // between x = 0 and (x) = 0. The latter is illegal.
7801 // A syntactically legal assignable expression always ends with an
7802 // identifier token or a ] token. We rewind the token iterator and
7803 // check whether the token before end_pos is an identifier or ].
7804 bool Parser::IsLegalAssignableSyntax(AstNode* expr, intptr_t end_pos) {
7805 ASSERT(expr->token_pos() >= 0);
7806 ASSERT(expr->token_pos() < end_pos);
7807 SetPosition(expr->token_pos());
7808 Token::Kind token = Token::kILLEGAL;
7809 while (TokenPos() < end_pos) {
7810 token = CurrentToken();
7811 ConsumeToken();
7812 }
7813 ASSERT(TokenPos() == end_pos);
7814 return Token::IsIdentifier(token) || (token == Token::kRBRACK);
7815 }
7816
7817
7795 AstNode* Parser::CreateAssignmentNode(AstNode* original, 7818 AstNode* Parser::CreateAssignmentNode(AstNode* original,
7796 AstNode* rhs, 7819 AstNode* rhs,
7797 const String* left_ident, 7820 const String* left_ident,
7798 intptr_t left_pos) { 7821 intptr_t left_pos) {
7799 AstNode* result = original->MakeAssignmentNode(rhs); 7822 AstNode* result = original->MakeAssignmentNode(rhs);
7800 if (result == NULL) { 7823 if (result == NULL) {
7801 String& name = String::ZoneHandle(); 7824 String& name = String::ZoneHandle();
7802 const Class* target_cls = &current_class(); 7825 const Class* target_cls = &current_class();
7803 if (original->IsTypeNode()) { 7826 if (original->IsTypeNode()) {
7804 name = Symbols::New(original->AsTypeNode()->TypeName()); 7827 name = Symbols::New(original->AsTypeNode()->TypeName());
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
7925 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { 7948 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) {
7926 return ParseCascades(expr); 7949 return ParseCascades(expr);
7927 } 7950 }
7928 expr = LiteralIfStaticConst(expr); 7951 expr = LiteralIfStaticConst(expr);
7929 if (require_compiletime_const) { 7952 if (require_compiletime_const) {
7930 expr = FoldConstExpr(expr_pos, expr); 7953 expr = FoldConstExpr(expr_pos, expr);
7931 } 7954 }
7932 return expr; 7955 return expr;
7933 } 7956 }
7934 // Assignment expressions. 7957 // Assignment expressions.
7958 if (!IsLegalAssignableSyntax(expr, TokenPos())) {
7959 ErrorMsg(expr_pos, "expression is not assignable");
7960 }
7935 const Token::Kind assignment_op = CurrentToken(); 7961 const Token::Kind assignment_op = CurrentToken();
7936 const intptr_t assignment_pos = TokenPos(); 7962 const intptr_t assignment_pos = TokenPos();
7937 ConsumeToken(); 7963 ConsumeToken();
7938 const intptr_t right_expr_pos = TokenPos(); 7964 const intptr_t right_expr_pos = TokenPos();
7939 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { 7965 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) {
7940 ErrorMsg(right_expr_pos, "expression is not a valid compile-time constant"); 7966 ErrorMsg(right_expr_pos, "expression is not a valid compile-time constant");
7941 } 7967 }
7942 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); 7968 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades);
7943 if (assignment_op != Token::kASSIGN) { 7969 if (assignment_op != Token::kASSIGN) {
7944 // Compound assignment: store inputs with side effects into temp. locals. 7970 // Compound assignment: store inputs with side effects into temp. locals.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
8003 } else { 8029 } else {
8004 expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr); 8030 expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr);
8005 } 8031 }
8006 } else if (IsIncrementOperator(CurrentToken())) { 8032 } else if (IsIncrementOperator(CurrentToken())) {
8007 Token::Kind incr_op = CurrentToken(); 8033 Token::Kind incr_op = CurrentToken();
8008 ConsumeToken(); 8034 ConsumeToken();
8009 String* expr_ident = 8035 String* expr_ident =
8010 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; 8036 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
8011 const intptr_t expr_pos = TokenPos(); 8037 const intptr_t expr_pos = TokenPos();
8012 expr = ParseUnaryExpr(); 8038 expr = ParseUnaryExpr();
8039 if (!IsLegalAssignableSyntax(expr, TokenPos())) {
8040 ErrorMsg(expr_pos, "expression is not assignable");
8041 }
8013 // Is prefix. 8042 // Is prefix.
8014 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr); 8043 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
8015 Token::Kind binary_op = 8044 Token::Kind binary_op =
8016 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; 8045 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
8017 BinaryOpNode* add = new BinaryOpNode( 8046 BinaryOpNode* add = new BinaryOpNode(
8018 op_pos, 8047 op_pos,
8019 binary_op, 8048 binary_op,
8020 expr, 8049 expr,
8021 new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1)))); 8050 new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1))));
8022 AstNode* store = CreateAssignmentNode(expr, add, expr_ident, expr_pos); 8051 AstNode* store = CreateAssignmentNode(expr, add, expr_ident, expr_pos);
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
8165 EnsureSavedCurrentContext(); 8194 EnsureSavedCurrentContext();
8166 ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst); 8195 ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
8167 return new ClosureCallNode(call_pos, closure, arguments); 8196 return new ClosureCallNode(call_pos, closure, arguments);
8168 } 8197 }
8169 8198
8170 8199
8171 AstNode* Parser::GenerateStaticFieldLookup(const Field& field, 8200 AstNode* Parser::GenerateStaticFieldLookup(const Field& field,
8172 intptr_t ident_pos) { 8201 intptr_t ident_pos) {
8173 // If the static field has an initializer, initialize the field at compile 8202 // If the static field has an initializer, initialize the field at compile
8174 // time, which is only possible if the field is const. 8203 // time, which is only possible if the field is const.
8175 AstNode* initializing_getter = RunStaticFieldInitializer(field); 8204 AstNode* initializing_getter = RunStaticFieldInitializer(field, ident_pos);
8176 if (initializing_getter != NULL) { 8205 if (initializing_getter != NULL) {
8177 // The field is not yet initialized and could not be initialized at compile 8206 // The field is not yet initialized and could not be initialized at compile
8178 // time. The getter will initialize the field. 8207 // time. The getter will initialize the field.
8179 return initializing_getter; 8208 return initializing_getter;
8180 } 8209 }
8181 // The field is initialized. 8210 // The field is initialized.
8182 ASSERT(field.is_static()); 8211 ASSERT(field.is_static());
8183 const Class& field_owner = Class::ZoneHandle(field.owner()); 8212 const Class& field_owner = Class::ZoneHandle(field.owner());
8184 const String& field_name = String::ZoneHandle(field.name()); 8213 const String& field_name = String::ZoneHandle(field.name());
8185 const String& getter_name = String::Handle(Field::GetterName(field_name)); 8214 const String& getter_name = String::Handle(Field::GetterName(field_name));
(...skipping 12 matching lines...) Expand all
8198 } 8227 }
8199 } 8228 }
8200 8229
8201 8230
8202 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, 8231 AstNode* Parser::ParseStaticFieldAccess(const Class& cls,
8203 const String& field_name, 8232 const String& field_name,
8204 intptr_t ident_pos, 8233 intptr_t ident_pos,
8205 bool consume_cascades) { 8234 bool consume_cascades) {
8206 TRACE_PARSER("ParseStaticFieldAccess"); 8235 TRACE_PARSER("ParseStaticFieldAccess");
8207 AstNode* access = NULL; 8236 AstNode* access = NULL;
8208 const intptr_t call_pos = TokenPos();
8209 const Field& field = Field::ZoneHandle(cls.LookupStaticField(field_name)); 8237 const Field& field = Field::ZoneHandle(cls.LookupStaticField(field_name));
8210 Function& func = Function::ZoneHandle(); 8238 Function& func = Function::ZoneHandle();
8211 if (field.IsNull()) { 8239 if (field.IsNull()) {
8212 // No field, check if we have an explicit getter function. 8240 // No field, check if we have an explicit getter function.
8213 const String& getter_name = 8241 const String& getter_name =
8214 String::ZoneHandle(Field::GetterName(field_name)); 8242 String::ZoneHandle(Field::GetterName(field_name));
8215 const int kNumArguments = 0; // no arguments. 8243 const int kNumArguments = 0; // no arguments.
8216 func = Resolver::ResolveStatic(cls, 8244 func = Resolver::ResolveStatic(cls,
8217 getter_name, 8245 getter_name,
8218 kNumArguments, 8246 kNumArguments,
8219 Object::empty_array()); 8247 Object::empty_array());
8220 if (func.IsNull()) { 8248 if (func.IsNull()) {
8221 // We might be referring to an implicit closure, check to see if 8249 // We might be referring to an implicit closure, check to see if
8222 // there is a function of the same name. 8250 // there is a function of the same name.
8223 func = cls.LookupStaticFunction(field_name); 8251 func = cls.LookupStaticFunction(field_name);
8224 if (!func.IsNull()) { 8252 if (!func.IsNull()) {
8225 access = CreateImplicitClosureNode(func, call_pos, NULL); 8253 access = CreateImplicitClosureNode(func, ident_pos, NULL);
8226 } else { 8254 } else {
8227 // No function to closurize found found. 8255 // No function to closurize found found.
8228 // This field access may turn out to be a call to the setter. 8256 // This field access may turn out to be a call to the setter.
8229 // Create a getter call, which may later be turned into 8257 // Create a getter call, which may later be turned into
8230 // a setter call, or else the backend will generate 8258 // a setter call, or else the backend will generate
8231 // a throw NoSuchMethodError(). 8259 // a throw NoSuchMethodError().
8232 access = new StaticGetterNode(call_pos, 8260 access = new StaticGetterNode(ident_pos,
8233 NULL, 8261 NULL,
8234 false, 8262 false,
8235 Class::ZoneHandle(cls.raw()), 8263 Class::ZoneHandle(cls.raw()),
8236 field_name); 8264 field_name);
8237 } 8265 }
8238 } else { 8266 } else {
8239 ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter); 8267 ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
8240 access = new StaticGetterNode(call_pos, 8268 access = new StaticGetterNode(ident_pos,
8241 NULL, 8269 NULL,
8242 false, 8270 false,
8243 Class::ZoneHandle(cls.raw()), 8271 Class::ZoneHandle(cls.raw()),
8244 field_name); 8272 field_name);
8245 } 8273 }
8246 } else { 8274 } else {
8247 access = GenerateStaticFieldLookup(field, TokenPos()); 8275 access = GenerateStaticFieldLookup(field, ident_pos);
8248 } 8276 }
8249 return access; 8277 return access;
8250 } 8278 }
8251 8279
8252 8280
8253 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) { 8281 AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) {
8254 if (!node->IsPrimaryNode()) { 8282 if (!node->IsPrimaryNode()) {
8255 return node; 8283 return node;
8256 } 8284 }
8257 PrimaryNode* primary = node->AsPrimaryNode(); 8285 PrimaryNode* primary = node->AsPrimaryNode();
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
8540 8568
8541 AstNode* Parser::ParsePostfixExpr() { 8569 AstNode* Parser::ParsePostfixExpr() {
8542 TRACE_PARSER("ParsePostfixExpr"); 8570 TRACE_PARSER("ParsePostfixExpr");
8543 String* expr_ident = 8571 String* expr_ident =
8544 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL; 8572 Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
8545 const intptr_t expr_pos = TokenPos(); 8573 const intptr_t expr_pos = TokenPos();
8546 AstNode* expr = ParsePrimary(); 8574 AstNode* expr = ParsePrimary();
8547 expr = ParseSelectors(expr, false); 8575 expr = ParseSelectors(expr, false);
8548 if (IsIncrementOperator(CurrentToken())) { 8576 if (IsIncrementOperator(CurrentToken())) {
8549 TRACE_PARSER("IncrementOperator"); 8577 TRACE_PARSER("IncrementOperator");
8578 if (!IsLegalAssignableSyntax(expr, TokenPos())) {
8579 ErrorMsg(expr_pos, "expression is not assignable");
8580 }
8550 Token::Kind incr_op = CurrentToken(); 8581 Token::Kind incr_op = CurrentToken();
8551 ConsumeToken(); 8582 ConsumeToken();
8552 // Not prefix. 8583 // Not prefix.
8553 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr); 8584 LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
8554 LocalVariable* temp = let_expr->AddInitializer(expr); 8585 LocalVariable* temp = let_expr->AddInitializer(expr);
8555 Token::Kind binary_op = 8586 Token::Kind binary_op =
8556 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; 8587 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
8557 BinaryOpNode* add = new BinaryOpNode( 8588 BinaryOpNode* add = new BinaryOpNode(
8558 expr_pos, 8589 expr_pos,
8559 binary_op, 8590 binary_op,
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
8746 if (result.IsNull()) { 8777 if (result.IsNull()) {
8747 ErrorMsg(token_pos, "Invalid const object %s", error_str); 8778 ErrorMsg(token_pos, "Invalid const object %s", error_str);
8748 } 8779 }
8749 return result.raw(); 8780 return result.raw();
8750 } 8781 }
8751 8782
8752 8783
8753 // If the field is already initialized, return no ast (NULL). 8784 // If the field is already initialized, return no ast (NULL).
8754 // Otherwise, if the field is constant, initialize the field and return no ast. 8785 // Otherwise, if the field is constant, initialize the field and return no ast.
8755 // If the field is not initialized and not const, return the ast for the getter. 8786 // If the field is not initialized and not const, return the ast for the getter.
8756 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { 8787 AstNode* Parser::RunStaticFieldInitializer(const Field& field,
8788 intptr_t field_ref_pos) {
8757 ASSERT(field.is_static()); 8789 ASSERT(field.is_static());
8758 const Class& field_owner = Class::ZoneHandle(field.owner()); 8790 const Class& field_owner = Class::ZoneHandle(field.owner());
8759 const String& field_name = String::ZoneHandle(field.name()); 8791 const String& field_name = String::ZoneHandle(field.name());
8760 const String& getter_name = String::Handle(Field::GetterName(field_name)); 8792 const String& getter_name = String::Handle(Field::GetterName(field_name));
8761 const Function& getter = 8793 const Function& getter =
8762 Function::Handle(field_owner.LookupStaticFunction(getter_name)); 8794 Function::Handle(field_owner.LookupStaticFunction(getter_name));
8763 const Instance& value = Instance::Handle(field.value()); 8795 const Instance& value = Instance::Handle(field.value());
8764 if (value.raw() == Object::transition_sentinel().raw()) { 8796 if (value.raw() == Object::transition_sentinel().raw()) {
8765 if (field.is_const()) { 8797 if (field.is_const()) {
8766 ErrorMsg("circular dependency while initializing static field '%s'", 8798 ErrorMsg("circular dependency while initializing static field '%s'",
8767 field_name.ToCString()); 8799 field_name.ToCString());
8768 } else { 8800 } else {
8769 // The implicit static getter will throw the exception if necessary. 8801 // The implicit static getter will throw the exception if necessary.
8770 return new StaticGetterNode(TokenPos(), 8802 return new StaticGetterNode(field_ref_pos,
8771 NULL, 8803 NULL,
8772 false, 8804 false,
8773 field_owner, 8805 field_owner,
8774 field_name); 8806 field_name);
8775 } 8807 }
8776 } else if (value.raw() == Object::sentinel().raw()) { 8808 } else if (value.raw() == Object::sentinel().raw()) {
8777 // This field has not been referenced yet and thus the value has 8809 // This field has not been referenced yet and thus the value has
8778 // not been evaluated. If the field is const, call the static getter method 8810 // not been evaluated. If the field is const, call the static getter method
8779 // to evaluate the expression and canonicalize the value. 8811 // to evaluate the expression and canonicalize the value.
8780 if (field.is_const()) { 8812 if (field.is_const()) {
(...skipping 11 matching lines...) Expand all
8792 if (const_value.IsError()) { 8824 if (const_value.IsError()) {
8793 const Error& error = Error::Cast(const_value); 8825 const Error& error = Error::Cast(const_value);
8794 if (error.IsUnhandledException()) { 8826 if (error.IsUnhandledException()) {
8795 // An exception may not occur in every parse attempt, i.e., the 8827 // An exception may not occur in every parse attempt, i.e., the
8796 // generated AST is not deterministic. Therefore mark the function as 8828 // generated AST is not deterministic. Therefore mark the function as
8797 // not optimizable. 8829 // not optimizable.
8798 current_function().set_is_optimizable(false); 8830 current_function().set_is_optimizable(false);
8799 field.set_value(Object::null_instance()); 8831 field.set_value(Object::null_instance());
8800 // It is a compile-time error if evaluation of a compile-time constant 8832 // It is a compile-time error if evaluation of a compile-time constant
8801 // would raise an exception. 8833 // would raise an exception.
8802 AppendErrorMsg(error, TokenPos(), 8834 AppendErrorMsg(error, field_ref_pos,
8803 "error initializing const field '%s'", 8835 "error initializing const field '%s'",
8804 String::Handle(field.name()).ToCString()); 8836 String::Handle(field.name()).ToCString());
8805 } else { 8837 } else {
8806 isolate()->long_jump_base()->Jump(1, error); 8838 isolate()->long_jump_base()->Jump(1, error);
8807 } 8839 }
8808 } 8840 }
8809 ASSERT(const_value.IsNull() || const_value.IsInstance()); 8841 ASSERT(const_value.IsNull() || const_value.IsInstance());
8810 Instance& instance = Instance::Handle(); 8842 Instance& instance = Instance::Handle();
8811 instance ^= const_value.raw(); 8843 instance ^= const_value.raw();
8812 instance = TryCanonicalize(instance, TokenPos()); 8844 instance = TryCanonicalize(instance, field_ref_pos);
8813 field.set_value(instance); 8845 field.set_value(instance);
8814 return NULL; // Constant 8846 return NULL; // Constant
8815 } else { 8847 } else {
8816 return new StaticGetterNode(TokenPos(), 8848 return new StaticGetterNode(field_ref_pos,
8817 NULL, 8849 NULL,
8818 false, 8850 false,
8819 field_owner, 8851 field_owner,
8820 field_name); 8852 field_name);
8821 } 8853 }
8822 } 8854 }
8823 if (getter.IsNull() || 8855 if (getter.IsNull() ||
8824 (getter.kind() == RawFunction::kImplicitStaticFinalGetter)) { 8856 (getter.kind() == RawFunction::kImplicitStaticFinalGetter)) {
8825 return NULL; 8857 return NULL;
8826 } 8858 }
8827 ASSERT(getter.kind() == RawFunction::kImplicitGetter); 8859 ASSERT(getter.kind() == RawFunction::kImplicitGetter);
8828 return new StaticGetterNode(TokenPos(), NULL, false, field_owner, field_name); 8860 return new StaticGetterNode(field_ref_pos,
8861 NULL,
8862 false,
8863 field_owner,
8864 field_name);
8829 } 8865 }
8830 8866
8831 8867
8832 RawObject* Parser::EvaluateConstConstructorCall( 8868 RawObject* Parser::EvaluateConstConstructorCall(
8833 const Class& type_class, 8869 const Class& type_class,
8834 const AbstractTypeArguments& type_arguments, 8870 const AbstractTypeArguments& type_arguments,
8835 const Function& constructor, 8871 const Function& constructor,
8836 ArgumentListNode* arguments) { 8872 ArgumentListNode* arguments) {
8837 // Factories have one extra argument: the type arguments. 8873 // Factories have one extra argument: the type arguments.
8838 // Constructors have 2 extra arguments: rcvr and construction phase. 8874 // Constructors have 2 extra arguments: rcvr and construction phase.
(...skipping 1495 matching lines...) Expand 10 before | Expand all | Expand 10 after
10334 const Type& mixin_type = Type::Handle(current_class().mixin()); 10370 const Type& mixin_type = Type::Handle(current_class().mixin());
10335 if (mixin_type.type_class() == current_function().origin()) { 10371 if (mixin_type.type_class() == current_function().origin()) {
10336 ErrorMsg("method of mixin class '%s' may not refer to 'super'", 10372 ErrorMsg("method of mixin class '%s' may not refer to 'super'",
10337 String::Handle(Class::Handle( 10373 String::Handle(Class::Handle(
10338 current_function().origin()).Name()).ToCString()); 10374 current_function().origin()).Name()).ToCString());
10339 } 10375 }
10340 } 10376 }
10341 ConsumeToken(); 10377 ConsumeToken();
10342 if (CurrentToken() == Token::kPERIOD) { 10378 if (CurrentToken() == Token::kPERIOD) {
10343 ConsumeToken(); 10379 ConsumeToken();
10380 const intptr_t ident_pos = TokenPos();
10344 const String& ident = *ExpectIdentifier("identifier expected"); 10381 const String& ident = *ExpectIdentifier("identifier expected");
10345 if (CurrentToken() == Token::kLPAREN) { 10382 if (CurrentToken() == Token::kLPAREN) {
10346 primary = ParseSuperCall(ident); 10383 primary = ParseSuperCall(ident);
10347 } else { 10384 } else {
10348 primary = ParseSuperFieldAccess(ident); 10385 primary = ParseSuperFieldAccess(ident, ident_pos);
10349 } 10386 }
10350 } else if ((CurrentToken() == Token::kLBRACK) || 10387 } else if ((CurrentToken() == Token::kLBRACK) ||
10351 Token::CanBeOverloaded(CurrentToken()) || 10388 Token::CanBeOverloaded(CurrentToken()) ||
10352 (CurrentToken() == Token::kNE)) { 10389 (CurrentToken() == Token::kNE)) {
10353 primary = ParseSuperOperator(); 10390 primary = ParseSuperOperator();
10354 } else { 10391 } else {
10355 primary = new PrimaryNode(TokenPos(), Symbols::Super()); 10392 primary = new PrimaryNode(TokenPos(), Symbols::Super());
10356 } 10393 }
10357 } else { 10394 } else {
10358 UnexpectedToken(); 10395 UnexpectedToken();
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
10716 void Parser::SkipQualIdent() { 10753 void Parser::SkipQualIdent() {
10717 ASSERT(IsIdentifier()); 10754 ASSERT(IsIdentifier());
10718 ConsumeToken(); 10755 ConsumeToken();
10719 if (CurrentToken() == Token::kPERIOD) { 10756 if (CurrentToken() == Token::kPERIOD) {
10720 ConsumeToken(); // Consume the kPERIOD token. 10757 ConsumeToken(); // Consume the kPERIOD token.
10721 ExpectIdentifier("identifier expected after '.'"); 10758 ExpectIdentifier("identifier expected after '.'");
10722 } 10759 }
10723 } 10760 }
10724 10761
10725 } // namespace dart 10762 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/language/assignable_expression_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698