OLD | NEW |
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 "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
(...skipping 3083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3094 if ((CurrentToken() == Token::kLBRACE) || | 3094 if ((CurrentToken() == Token::kLBRACE) || |
3095 (CurrentToken() == Token::kARROW)) { | 3095 (CurrentToken() == Token::kARROW)) { |
3096 if (method->has_abstract) { | 3096 if (method->has_abstract) { |
3097 ErrorMsg(method->name_pos, | 3097 ErrorMsg(method->name_pos, |
3098 "abstract method '%s' may not have a function body", | 3098 "abstract method '%s' may not have a function body", |
3099 method->name->ToCString()); | 3099 method->name->ToCString()); |
3100 } else if (method->has_external) { | 3100 } else if (method->has_external) { |
3101 ErrorMsg(method->name_pos, | 3101 ErrorMsg(method->name_pos, |
3102 "external method '%s' may not have a function body", | 3102 "external method '%s' may not have a function body", |
3103 method->name->ToCString()); | 3103 method->name->ToCString()); |
3104 } else if (method->IsFactoryOrConstructor() && method->has_const) { | 3104 } else if (method->IsConstructor() && method->has_const) { |
3105 ErrorMsg(method->name_pos, | 3105 ErrorMsg(method->name_pos, |
3106 "const constructor or factory '%s' may not have a function body", | 3106 "const constructor '%s' may not have a function body", |
| 3107 method->name->ToCString()); |
| 3108 } else if (method->IsFactory() && method->has_const) { |
| 3109 ErrorMsg(method->name_pos, |
| 3110 "const factory '%s' may not have a function body", |
3107 method->name->ToCString()); | 3111 method->name->ToCString()); |
3108 } | 3112 } |
3109 if (method->redirect_name != NULL) { | 3113 if (method->redirect_name != NULL) { |
3110 ErrorMsg(method->name_pos, | 3114 ErrorMsg(method->name_pos, |
3111 "Constructor with redirection may not have a function body"); | 3115 "Constructor with redirection may not have a function body"); |
3112 } | 3116 } |
3113 if (CurrentToken() == Token::kLBRACE) { | 3117 if (CurrentToken() == Token::kLBRACE) { |
3114 SkipBlock(); | 3118 SkipBlock(); |
3115 method_end_pos = TokenPos(); | 3119 method_end_pos = TokenPos(); |
3116 ExpectToken(Token::kRBRACE); | 3120 ExpectToken(Token::kRBRACE); |
3117 } else { | 3121 } else { |
3118 ConsumeToken(); | 3122 ConsumeToken(); |
3119 SkipExpr(); | 3123 SkipExpr(); |
3120 method_end_pos = TokenPos(); | 3124 method_end_pos = TokenPos(); |
3121 ExpectSemicolon(); | 3125 ExpectSemicolon(); |
3122 } | 3126 } |
3123 } else if (IsLiteral("native")) { | 3127 } else if (IsLiteral("native")) { |
3124 if (method->has_abstract) { | 3128 if (method->has_abstract) { |
3125 ErrorMsg(method->name_pos, | 3129 ErrorMsg(method->name_pos, |
3126 "abstract method '%s' may not have a function body", | 3130 "abstract method '%s' may not have a function body", |
3127 method->name->ToCString()); | 3131 method->name->ToCString()); |
3128 } else if (method->IsFactoryOrConstructor() && method->has_const) { | 3132 } else if (method->IsConstructor() && method->has_const) { |
3129 ErrorMsg(method->name_pos, | 3133 ErrorMsg(method->name_pos, |
3130 "const constructor or factory '%s' may not be native", | 3134 "const constructor '%s' may not be native", |
3131 method->name->ToCString()); | 3135 method->name->ToCString()); |
3132 } | 3136 } |
3133 if (method->redirect_name != NULL) { | 3137 if (method->redirect_name != NULL) { |
3134 ErrorMsg(method->name_pos, | 3138 ErrorMsg(method->name_pos, |
3135 "Constructor with redirection may not have a function body"); | 3139 "Constructor with redirection may not have a function body"); |
3136 } | 3140 } |
3137 ParseNativeDeclaration(); | 3141 ParseNativeDeclaration(); |
3138 method_end_pos = TokenPos(); | 3142 method_end_pos = TokenPos(); |
3139 ExpectSemicolon(); | 3143 ExpectSemicolon(); |
3140 } else { | 3144 } else { |
(...skipping 5560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8701 ASSERT(getter.kind() == RawFunction::kImplicitGetter); | 8705 ASSERT(getter.kind() == RawFunction::kImplicitGetter); |
8702 return new StaticGetterNode(TokenPos(), NULL, false, field_owner, field_name); | 8706 return new StaticGetterNode(TokenPos(), NULL, false, field_owner, field_name); |
8703 } | 8707 } |
8704 | 8708 |
8705 | 8709 |
8706 RawObject* Parser::EvaluateConstConstructorCall( | 8710 RawObject* Parser::EvaluateConstConstructorCall( |
8707 const Class& type_class, | 8711 const Class& type_class, |
8708 const AbstractTypeArguments& type_arguments, | 8712 const AbstractTypeArguments& type_arguments, |
8709 const Function& constructor, | 8713 const Function& constructor, |
8710 ArgumentListNode* arguments) { | 8714 ArgumentListNode* arguments) { |
8711 const int kNumExtraArgs = 2; // implicit rcvr and construction phase args. | 8715 // Factories have one extra argument: the type arguments. |
| 8716 // Constructors have 2 extra arguments: rcvr and construction phase. |
| 8717 const int kNumExtraArgs = constructor.IsFactory() ? 1 : 2; |
8712 const int num_arguments = arguments->length() + kNumExtraArgs; | 8718 const int num_arguments = arguments->length() + kNumExtraArgs; |
8713 const Array& arg_values = Array::Handle(Array::New(num_arguments)); | 8719 const Array& arg_values = Array::Handle(Array::New(num_arguments)); |
8714 Instance& instance = Instance::Handle(); | 8720 Instance& instance = Instance::Handle(); |
8715 ASSERT(!constructor.IsFactory()); | 8721 if (!constructor.IsFactory()) { |
8716 instance = Instance::New(type_class, Heap::kOld); | 8722 instance = Instance::New(type_class, Heap::kOld); |
8717 if (!type_arguments.IsNull()) { | 8723 if (!type_arguments.IsNull()) { |
8718 if (!type_arguments.IsInstantiated()) { | 8724 if (!type_arguments.IsInstantiated()) { |
8719 ErrorMsg("type must be constant in const constructor"); | 8725 ErrorMsg("type must be constant in const constructor"); |
| 8726 } |
| 8727 instance.SetTypeArguments( |
| 8728 AbstractTypeArguments::Handle(type_arguments.Canonicalize())); |
8720 } | 8729 } |
8721 instance.SetTypeArguments( | 8730 arg_values.SetAt(0, instance); |
8722 AbstractTypeArguments::Handle(type_arguments.Canonicalize())); | 8731 arg_values.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll))); |
| 8732 } else { |
| 8733 // Prepend type_arguments to list of arguments to factory. |
| 8734 ASSERT(type_arguments.IsZoneHandle()); |
| 8735 arg_values.SetAt(0, type_arguments); |
8723 } | 8736 } |
8724 arg_values.SetAt(0, instance); | |
8725 arg_values.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll))); | |
8726 for (int i = 0; i < arguments->length(); i++) { | 8737 for (int i = 0; i < arguments->length(); i++) { |
8727 AstNode* arg = arguments->NodeAt(i); | 8738 AstNode* arg = arguments->NodeAt(i); |
8728 // Arguments have been evaluated to a literal value already. | 8739 // Arguments have been evaluated to a literal value already. |
8729 ASSERT(arg->IsLiteralNode()); | 8740 ASSERT(arg->IsLiteralNode()); |
8730 arg_values.SetAt((i + kNumExtraArgs), arg->AsLiteralNode()->literal()); | 8741 arg_values.SetAt((i + kNumExtraArgs), arg->AsLiteralNode()->literal()); |
8731 } | 8742 } |
8732 const Array& args_descriptor = | 8743 const Array& args_descriptor = |
8733 Array::Handle(ArgumentsDescriptor::New(num_arguments, | 8744 Array::Handle(ArgumentsDescriptor::New(num_arguments, |
8734 arguments->names())); | 8745 arguments->names())); |
8735 const Object& result = | 8746 const Object& result = |
8736 Object::Handle(DartEntry::InvokeFunction(constructor, | 8747 Object::Handle(DartEntry::InvokeFunction(constructor, |
8737 arg_values, | 8748 arg_values, |
8738 args_descriptor)); | 8749 args_descriptor)); |
8739 if (result.IsError()) { | 8750 if (result.IsError()) { |
8740 // An exception may not occur in every parse attempt, i.e., the | 8751 // An exception may not occur in every parse attempt, i.e., the |
8741 // generated AST is not deterministic. Therefore mark the function as | 8752 // generated AST is not deterministic. Therefore mark the function as |
8742 // not optimizable. | 8753 // not optimizable. |
8743 current_function().set_is_optimizable(false); | 8754 current_function().set_is_optimizable(false); |
8744 if (result.IsUnhandledException()) { | 8755 if (result.IsUnhandledException()) { |
8745 return result.raw(); | 8756 return result.raw(); |
8746 } else { | 8757 } else { |
8747 isolate()->long_jump_base()->Jump(1, Error::Cast(result)); | 8758 isolate()->long_jump_base()->Jump(1, Error::Cast(result)); |
8748 UNREACHABLE(); | 8759 UNREACHABLE(); |
8749 return Object::null(); | 8760 return Object::null(); |
8750 } | 8761 } |
8751 } else { | 8762 } else { |
| 8763 if (constructor.IsFactory()) { |
| 8764 // The factory method returns the allocated object. |
| 8765 instance ^= result.raw(); |
| 8766 } |
8752 return TryCanonicalize(instance, TokenPos()); | 8767 return TryCanonicalize(instance, TokenPos()); |
8753 } | 8768 } |
8754 } | 8769 } |
8755 | 8770 |
8756 | 8771 |
8757 // Do a lookup for the identifier in the block scope and the class scope | 8772 // Do a lookup for the identifier in the block scope and the class scope |
8758 // return true if the identifier is found, false otherwise. | 8773 // return true if the identifier is found, false otherwise. |
8759 // If node is non NULL return an AST node corresponding to the identifier. | 8774 // If node is non NULL return an AST node corresponding to the identifier. |
8760 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, | 8775 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, |
8761 const String &ident, | 8776 const String &ident, |
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9878 external_constructor_name.ToCString()); | 9893 external_constructor_name.ToCString()); |
9879 } | 9894 } |
9880 const Object& constructor_result = Object::Handle( | 9895 const Object& constructor_result = Object::Handle( |
9881 EvaluateConstConstructorCall(type_class, | 9896 EvaluateConstConstructorCall(type_class, |
9882 type_arguments, | 9897 type_arguments, |
9883 constructor, | 9898 constructor, |
9884 arguments)); | 9899 arguments)); |
9885 if (constructor_result.IsUnhandledException()) { | 9900 if (constructor_result.IsUnhandledException()) { |
9886 new_object = GenerateRethrow(new_pos, constructor_result); | 9901 new_object = GenerateRethrow(new_pos, constructor_result); |
9887 } else { | 9902 } else { |
9888 const Instance& const_instance = Instance::Cast(constructor_result); | 9903 // Const constructors can return null in the case where a const native |
| 9904 // factory returns a null value. Thus we cannot use a Instance::Cast here. |
| 9905 Instance& const_instance = Instance::Handle(); |
| 9906 const_instance ^= constructor_result.raw(); |
9889 new_object = new LiteralNode(new_pos, | 9907 new_object = new LiteralNode(new_pos, |
9890 Instance::ZoneHandle(const_instance.raw())); | 9908 Instance::ZoneHandle(const_instance.raw())); |
9891 if (!type_bound.IsNull()) { | 9909 if (!type_bound.IsNull()) { |
9892 ASSERT(!type_bound.IsMalformed()); | 9910 ASSERT(!type_bound.IsMalformed()); |
9893 Error& malformed_error = Error::Handle(); | 9911 Error& malformed_error = Error::Handle(); |
9894 ASSERT(!is_top_level_); // We cannot check unresolved types. | 9912 ASSERT(!is_top_level_); // We cannot check unresolved types. |
9895 if (!const_instance.IsInstanceOf(type_bound, | 9913 if (!const_instance.IsInstanceOf(type_bound, |
9896 TypeArguments::Handle(), | 9914 TypeArguments::Handle(), |
9897 &malformed_error)) { | 9915 &malformed_error)) { |
9898 type_bound = ClassFinalizer::NewFinalizedMalformedType( | 9916 type_bound = ClassFinalizer::NewFinalizedMalformedType( |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10554 void Parser::SkipQualIdent() { | 10572 void Parser::SkipQualIdent() { |
10555 ASSERT(IsIdentifier()); | 10573 ASSERT(IsIdentifier()); |
10556 ConsumeToken(); | 10574 ConsumeToken(); |
10557 if (CurrentToken() == Token::kPERIOD) { | 10575 if (CurrentToken() == Token::kPERIOD) { |
10558 ConsumeToken(); // Consume the kPERIOD token. | 10576 ConsumeToken(); // Consume the kPERIOD token. |
10559 ExpectIdentifier("identifier expected after '.'"); | 10577 ExpectIdentifier("identifier expected after '.'"); |
10560 } | 10578 } |
10561 } | 10579 } |
10562 | 10580 |
10563 } // namespace dart | 10581 } // namespace dart |
OLD | NEW |