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

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

Issue 10832283: Allow non-const field initializers (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months 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/co19/co19-runtime.status » ('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 "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 1599 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 } 1610 }
1611 } 1611 }
1612 if (!found) { 1612 if (!found) {
1613 ErrorMsg("final field '%s' not initialized", 1613 ErrorMsg("final field '%s' not initialized",
1614 String::Handle(field.name()).ToCString()); 1614 String::Handle(field.name()).ToCString());
1615 } 1615 }
1616 } 1616 }
1617 } 1617 }
1618 1618
1619 1619
1620 struct FieldInitExpression {
1621 Field* inst_field;
1622 AstNode* expr;
1623 };
1624
1625
1626 void Parser::ParseInitializedInstanceFields(const Class& cls, 1620 void Parser::ParseInitializedInstanceFields(const Class& cls,
1627 GrowableArray<FieldInitExpression>* initializers, 1621 LocalVariable* receiver,
1628 GrowableArray<Field*>* initialized_fields) { 1622 GrowableArray<Field*>* initialized_fields) {
1629 TRACE_PARSER("ParseInitializedInstanceFields"); 1623 TRACE_PARSER("ParseInitializedInstanceFields");
1630 const Array& fields = Array::Handle(cls.fields()); 1624 const Array& fields = Array::Handle(cls.fields());
1631 Field& f = Field::Handle(); 1625 Field& f = Field::Handle();
1632 const intptr_t saved_pos = TokenPos(); 1626 const intptr_t saved_pos = TokenPos();
1633 for (int i = 0; i < fields.Length(); i++) { 1627 for (int i = 0; i < fields.Length(); i++) {
1634 f ^= fields.At(i); 1628 f ^= fields.At(i);
1635 if (!f.is_static() && f.has_initializer()) { 1629 if (!f.is_static() && f.has_initializer()) {
1636 Field& field = Field::ZoneHandle(); 1630 Field& field = Field::ZoneHandle();
1637 field ^= fields.At(i); 1631 field ^= fields.At(i);
1638 if (field.is_final()) { 1632 if (field.is_final()) {
1639 // Final fields with initializer expression may not be initialized 1633 // Final fields with initializer expression may not be initialized
1640 // again by constructors. Remember that this field is already 1634 // again by constructors. Remember that this field is already
1641 // initialized. 1635 // initialized.
1642 initialized_fields->Add(&field); 1636 initialized_fields->Add(&field);
1643 } 1637 }
1644 intptr_t field_pos = field.token_pos(); 1638 intptr_t field_pos = field.token_pos();
1645 SetPosition(field_pos); 1639 SetPosition(field_pos);
1646 ASSERT(IsIdentifier()); 1640 ASSERT(IsIdentifier());
1647 ConsumeToken(); 1641 ConsumeToken();
1648 ExpectToken(Token::kASSIGN); 1642 ExpectToken(Token::kASSIGN);
1649 // TODO(hausner): Allow non-const expressions here for final fields. 1643
1650 AstNode* init_expr = ParseConstExpr(); 1644 AstNode* init_expr = NULL;
1645 if (field.is_const()) {
1646 init_expr = ParseConstExpr();
1647 } else {
1648 init_expr = ParseExpr(kAllowConst, kConsumeCascades);
1649 if (init_expr->EvalConstExpr() != NULL) {
1650 init_expr = new LiteralNode(field_pos, EvaluateConstExpr(init_expr));
1651 }
1652 }
1651 ASSERT(init_expr != NULL); 1653 ASSERT(init_expr != NULL);
1652 FieldInitExpression initializer; 1654 AstNode* instance = new LoadLocalNode(field.token_pos(), receiver);
1653 initializer.inst_field = &field; 1655 AstNode* field_init =
1654 initializer.expr = init_expr; 1656 new StoreInstanceFieldNode(field.token_pos(),
1655 initializers->Add(initializer); 1657 instance,
1658 field,
1659 init_expr);
1660 current_block_->statements->Add(field_init);
1656 } 1661 }
1657 } 1662 }
1658 SetPosition(saved_pos); 1663 SetPosition(saved_pos);
1659 } 1664 }
1660 1665
1661 1666
1662 void Parser::CheckDuplicateFieldInit(intptr_t init_pos, 1667 void Parser::CheckDuplicateFieldInit(intptr_t init_pos,
1663 GrowableArray<Field*>* initialized_fields, 1668 GrowableArray<Field*>* initialized_fields,
1664 Field* field) { 1669 Field* field) {
1665 ASSERT(!field->is_static()); 1670 ASSERT(!field->is_static());
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
1764 } 1769 }
1765 CheckFunctionIsCallable(call_pos, redirect_ctor); 1770 CheckFunctionIsCallable(call_pos, redirect_ctor);
1766 current_block_->statements->Add( 1771 current_block_->statements->Add(
1767 new StaticCallNode(call_pos, redirect_ctor, arguments)); 1772 new StaticCallNode(call_pos, redirect_ctor, arguments));
1768 } 1773 }
1769 1774
1770 1775
1771 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { 1776 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
1772 ASSERT(func.IsConstructor()); 1777 ASSERT(func.IsConstructor());
1773 const intptr_t ctor_pos = TokenPos(); 1778 const intptr_t ctor_pos = TokenPos();
1774
1775 // Implicit 'this' is the only parameter/local variable.
1776 OpenFunctionBlock(func); 1779 OpenFunctionBlock(func);
1777 1780 const Class& cls = Class::Handle(func.owner());
1778 // Parse expressions of instance fields that have an explicit
1779 // initializers.
1780 GrowableArray<FieldInitExpression> initializers;
1781 GrowableArray<Field*> initialized_fields;
1782 Class& cls = Class::Handle(func.owner());
1783 ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
1784
1785 LocalVariable* receiver = new LocalVariable( 1781 LocalVariable* receiver = new LocalVariable(
1786 ctor_pos, 1782 ctor_pos,
1787 String::ZoneHandle(Symbols::This()), 1783 String::ZoneHandle(Symbols::This()),
1788 Type::ZoneHandle(Type::DynamicType())); 1784 Type::ZoneHandle(Type::DynamicType()));
1789 current_block_->scope->AddVariable(receiver); 1785 current_block_->scope->AddVariable(receiver);
1790 1786
1791 LocalVariable* phase_parameter = new LocalVariable( 1787 LocalVariable* phase_parameter = new LocalVariable(
1792 ctor_pos, 1788 ctor_pos,
1793 String::ZoneHandle(Symbols::PhaseParameter()), 1789 String::ZoneHandle(Symbols::PhaseParameter()),
1794 Type::ZoneHandle(Type::IntInterface())); 1790 Type::ZoneHandle(Type::IntInterface()));
1795 current_block_->scope->AddVariable(phase_parameter); 1791 current_block_->scope->AddVariable(phase_parameter);
1796 1792
1797 // Now that the "this" parameter is in scope, we can generate the code 1793 // Parse expressions of instance fields that have an explicit
1798 // to strore the initializer expressions in the respective instance fields. 1794 // initializer expression.
1799 for (int i = 0; i < initializers.length(); i++) { 1795 // The receiver must not be visible to field initializer expressions.
1800 const Field* field = initializers[i].inst_field; 1796 receiver->set_invisible(true);
1801 AstNode* instance = new LoadLocalNode(field->token_pos(), receiver); 1797 GrowableArray<Field*> initialized_fields;
1802 AstNode* field_init = 1798 ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
1803 new StoreInstanceFieldNode(field->token_pos(), 1799 receiver->set_invisible(false);
1804 instance,
1805 *field,
1806 initializers[i].expr);
1807 current_block_->statements->Add(field_init);
1808 }
1809 1800
1810 GenerateSuperConstructorCall(cls, receiver); 1801 GenerateSuperConstructorCall(cls, receiver);
1811 CheckConstFieldsInitialized(cls); 1802 CheckConstFieldsInitialized(cls);
1812 1803
1813 // Empty constructor body. 1804 // Empty constructor body.
1814 SequenceNode* statements = CloseBlock(); 1805 SequenceNode* statements = CloseBlock();
1815 return statements; 1806 return statements;
1816 } 1807 }
1817 1808
1818 1809
1810 // Helper function to make the first num_variables variables in the
1811 // given scope visible/invisible.
1812 static void SetInvisible(LocalScope* scope, int num_variables, bool invisible) {
1813 ASSERT(num_variables <= scope->num_variables());
1814 for (int i = 0; i < num_variables; i++) {
1815 scope->VariableAt(i)->set_invisible(invisible);
1816 }
1817 }
1818
1819
1819 // Parser is at the opening parenthesis of the formal parameter declaration 1820 // Parser is at the opening parenthesis of the formal parameter declaration
1820 // of function. Parse the formal parameters, initializers and code. 1821 // of function. Parse the formal parameters, initializers and code.
1821 SequenceNode* Parser::ParseConstructor(const Function& func, 1822 SequenceNode* Parser::ParseConstructor(const Function& func,
1822 Array& default_parameter_values) { 1823 Array& default_parameter_values) {
1823 TRACE_PARSER("ParseConstructor"); 1824 TRACE_PARSER("ParseConstructor");
1824 ASSERT(func.IsConstructor()); 1825 ASSERT(func.IsConstructor());
1825 ASSERT(!func.IsFactory()); 1826 ASSERT(!func.IsFactory());
1826 ASSERT(!func.is_static()); 1827 ASSERT(!func.is_static());
1827 ASSERT(!func.IsLocalFunction()); 1828 ASSERT(!func.IsLocalFunction());
1828 const Class& cls = Class::Handle(func.owner()); 1829 const Class& cls = Class::Handle(func.owner());
(...skipping 29 matching lines...) Expand all
1858 1859
1859 if (func.is_const()) { 1860 if (func.is_const()) {
1860 params.SetImplicitlyFinal(); 1861 params.SetImplicitlyFinal();
1861 } 1862 }
1862 ParseFormalParameterList(allow_explicit_default_values, &params); 1863 ParseFormalParameterList(allow_explicit_default_values, &params);
1863 1864
1864 SetupDefaultsForOptionalParams(&params, default_parameter_values); 1865 SetupDefaultsForOptionalParams(&params, default_parameter_values);
1865 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 1866 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
1866 ASSERT(func.NumberOfParameters() == params.parameters->length()); 1867 ASSERT(func.NumberOfParameters() == params.parameters->length());
1867 1868
1868 // Initialize instance fields that have an explicit initializer expression.
1869 // This has to be done before code for field initializer parameters
1870 // is generated.
1871 // NB: the instance field initializers have to be compiled before
1872 // the parameters are added to the scope, so that a parameter
1873 // name cannot shadow a name used in the field initializer expression.
1874 GrowableArray<FieldInitExpression> initializers;
1875 GrowableArray<Field*> initialized_fields;
1876 ParseInitializedInstanceFields(cls, &initializers, &initialized_fields);
1877
1878 // Now populate function scope with the formal parameters. 1869 // Now populate function scope with the formal parameters.
1879 AddFormalParamsToScope(&params, current_block_->scope); 1870 AddFormalParamsToScope(&params, current_block_->scope);
1871
1872 // Initialize instance fields that have an explicit initializer expression.
1873 // The formal parameter names must not be visible to the instance
1874 // field initializer expressions, yet the parameters must be added to
1875 // the scope so the expressions use the correct offsets for 'this' when
1876 // storing values. We make the formal parameters temporarily invisible
1877 // while parsing the instance field initializer expressions.
1878 SetInvisible(current_block_->scope, params.parameters->length(), true);
1879 GrowableArray<Field*> initialized_fields;
1880 LocalVariable* receiver = current_block_->scope->VariableAt(0); 1880 LocalVariable* receiver = current_block_->scope->VariableAt(0);
1881
1882 // Now that the "this" parameter is in scope, we can generate the code
1883 // to store the initializer expressions in the respective instance fields.
1884 // We do this before the field parameters and the initializers from the
1885 // constructor's initializer list get compiled.
1886 OpenBlock(); 1881 OpenBlock();
1887 for (int i = 0; i < initializers.length(); i++) { 1882 ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
1888 const Field* field = initializers[i].inst_field; 1883 // Make the parameters (which are in the outer scope) visible again.
1889 AstNode* instance = new LoadLocalNode(field->token_pos(), receiver); 1884 SetInvisible(current_block_->scope->parent(),
1890 AstNode* field_init = 1885 params.parameters->length(), false);
1891 new StoreInstanceFieldNode(field->token_pos(),
1892 instance,
1893 *field,
1894 initializers[i].expr);
1895 current_block_->statements->Add(field_init);
1896 }
1897 1886
1898 // Turn formal field parameters into field initializers or report error 1887 // Turn formal field parameters into field initializers or report error
1899 // if the function is not a constructor. 1888 // if the function is not a constructor.
1900 if (params.has_field_initializer) { 1889 if (params.has_field_initializer) {
1901 for (int i = 0; i < params.parameters->length(); i++) { 1890 for (int i = 0; i < params.parameters->length(); i++) {
1902 ParamDesc& param = (*params.parameters)[i]; 1891 ParamDesc& param = (*params.parameters)[i];
1903 if (param.is_field_initializer) { 1892 if (param.is_field_initializer) {
1904 const String& field_name = *param.name; 1893 const String& field_name = *param.name;
1905 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); 1894 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
1906 if (field.IsNull()) { 1895 if (field.IsNull()) {
(...skipping 7147 matching lines...) Expand 10 before | Expand all | Expand 10 after
9054 void Parser::SkipQualIdent() { 9043 void Parser::SkipQualIdent() {
9055 ASSERT(IsIdentifier()); 9044 ASSERT(IsIdentifier());
9056 ConsumeToken(); 9045 ConsumeToken();
9057 if (CurrentToken() == Token::kPERIOD) { 9046 if (CurrentToken() == Token::kPERIOD) {
9058 ConsumeToken(); // Consume the kPERIOD token. 9047 ConsumeToken(); // Consume the kPERIOD token.
9059 ExpectIdentifier("identifier expected after '.'"); 9048 ExpectIdentifier("identifier expected after '.'");
9060 } 9049 }
9061 } 9050 }
9062 9051
9063 } // namespace dart 9052 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698