| 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 "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 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1602 ErrorMsg(supercall_pos, | 1602 ErrorMsg(supercall_pos, |
| 1603 "invalid arguments passed to super class constructor '%s': %s", | 1603 "invalid arguments passed to super class constructor '%s': %s", |
| 1604 ctor_name.ToCString(), | 1604 ctor_name.ToCString(), |
| 1605 error_message.ToCString()); | 1605 error_message.ToCString()); |
| 1606 } | 1606 } |
| 1607 CheckFunctionIsCallable(supercall_pos, super_ctor); | 1607 CheckFunctionIsCallable(supercall_pos, super_ctor); |
| 1608 return new StaticCallNode(supercall_pos, super_ctor, arguments); | 1608 return new StaticCallNode(supercall_pos, super_ctor, arguments); |
| 1609 } | 1609 } |
| 1610 | 1610 |
| 1611 | 1611 |
| 1612 AstNode* Parser::ParseInitializer(const Class& cls, LocalVariable* receiver) { | 1612 AstNode* Parser::ParseInitializer(const Class& cls, |
| 1613 LocalVariable* receiver, |
| 1614 GrowableArray<Field*>* initialized_fields) { |
| 1613 TRACE_PARSER("ParseInitializer"); | 1615 TRACE_PARSER("ParseInitializer"); |
| 1614 const intptr_t field_pos = TokenPos(); | 1616 const intptr_t field_pos = TokenPos(); |
| 1615 if (CurrentToken() == Token::kTHIS) { | 1617 if (CurrentToken() == Token::kTHIS) { |
| 1616 ConsumeToken(); | 1618 ConsumeToken(); |
| 1617 ExpectToken(Token::kPERIOD); | 1619 ExpectToken(Token::kPERIOD); |
| 1618 } | 1620 } |
| 1619 const String& field_name = *ExpectIdentifier("field name expected"); | 1621 const String& field_name = *ExpectIdentifier("field name expected"); |
| 1620 ExpectToken(Token::kASSIGN); | 1622 ExpectToken(Token::kASSIGN); |
| 1621 | 1623 |
| 1622 const bool saved_mode = SetAllowFunctionLiterals(false); | 1624 const bool saved_mode = SetAllowFunctionLiterals(false); |
| 1623 // "this" must not be accessible in initializer expressions. | 1625 // "this" must not be accessible in initializer expressions. |
| 1624 receiver->set_invisible(true); | 1626 receiver->set_invisible(true); |
| 1625 AstNode* init_expr = ParseConditionalExpr(); | 1627 AstNode* init_expr = ParseConditionalExpr(); |
| 1626 receiver->set_invisible(false); | 1628 receiver->set_invisible(false); |
| 1627 SetAllowFunctionLiterals(saved_mode); | 1629 SetAllowFunctionLiterals(saved_mode); |
| 1628 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 1630 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 1629 if (field.IsNull()) { | 1631 if (field.IsNull()) { |
| 1630 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", | 1632 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", |
| 1631 field_name.ToCString()); | 1633 field_name.ToCString()); |
| 1632 } | 1634 } |
| 1635 CheckDuplicateFieldInit(field_pos, initialized_fields, &field); |
| 1633 AstNode* instance = new LoadLocalNode(field_pos, *receiver); | 1636 AstNode* instance = new LoadLocalNode(field_pos, *receiver); |
| 1634 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); | 1637 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); |
| 1635 } | 1638 } |
| 1636 | 1639 |
| 1637 | 1640 |
| 1638 void Parser::CheckConstFieldsInitialized(const Class& cls) { | 1641 void Parser::CheckConstFieldsInitialized(const Class& cls) { |
| 1639 const Array& fields = Array::Handle(cls.fields()); | 1642 const Array& fields = Array::Handle(cls.fields()); |
| 1640 Field& field = Field::Handle(); | 1643 Field& field = Field::Handle(); |
| 1641 SequenceNode* initializers = current_block_->statements; | 1644 SequenceNode* initializers = current_block_->statements; |
| 1642 for (int field_num = 0; field_num < fields.Length(); field_num++) { | 1645 for (int field_num = 0; field_num < fields.Length(); field_num++) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1664 } | 1667 } |
| 1665 | 1668 |
| 1666 | 1669 |
| 1667 struct FieldInitExpression { | 1670 struct FieldInitExpression { |
| 1668 Field* inst_field; | 1671 Field* inst_field; |
| 1669 AstNode* expr; | 1672 AstNode* expr; |
| 1670 }; | 1673 }; |
| 1671 | 1674 |
| 1672 | 1675 |
| 1673 void Parser::ParseInitializedInstanceFields(const Class& cls, | 1676 void Parser::ParseInitializedInstanceFields(const Class& cls, |
| 1674 GrowableArray<FieldInitExpression>* initializers) { | 1677 GrowableArray<FieldInitExpression>* initializers, |
| 1678 GrowableArray<Field*>* initialized_fields) { |
| 1675 TRACE_PARSER("ParseInitializedInstanceFields"); | 1679 TRACE_PARSER("ParseInitializedInstanceFields"); |
| 1676 const Array& fields = Array::Handle(cls.fields()); | 1680 const Array& fields = Array::Handle(cls.fields()); |
| 1677 Field& f = Field::Handle(); | 1681 Field& f = Field::Handle(); |
| 1678 const intptr_t saved_pos = TokenPos(); | 1682 const intptr_t saved_pos = TokenPos(); |
| 1679 for (int i = 0; i < fields.Length(); i++) { | 1683 for (int i = 0; i < fields.Length(); i++) { |
| 1680 f ^= fields.At(i); | 1684 f ^= fields.At(i); |
| 1681 if (!f.is_static() && f.has_initializer()) { | 1685 if (!f.is_static() && f.has_initializer()) { |
| 1682 Field& field = Field::ZoneHandle(); | 1686 Field& field = Field::ZoneHandle(); |
| 1683 field ^= fields.At(i); | 1687 field ^= fields.At(i); |
| 1688 if (field.is_final()) { |
| 1689 // Final fields with initializer expression may not be initialized |
| 1690 // again by constructors. Remember that this field is already |
| 1691 // initialized. |
| 1692 initialized_fields->Add(&field); |
| 1693 } |
| 1684 intptr_t field_pos = field.token_pos(); | 1694 intptr_t field_pos = field.token_pos(); |
| 1685 SetPosition(field_pos); | 1695 SetPosition(field_pos); |
| 1686 ASSERT(IsIdentifier()); | 1696 ASSERT(IsIdentifier()); |
| 1687 ConsumeToken(); | 1697 ConsumeToken(); |
| 1688 ExpectToken(Token::kASSIGN); | 1698 ExpectToken(Token::kASSIGN); |
| 1699 // TODO(hausner): Allow non-const expressions here for final fields. |
| 1689 AstNode* init_expr = ParseConstExpr(); | 1700 AstNode* init_expr = ParseConstExpr(); |
| 1690 ASSERT(init_expr != NULL); | 1701 ASSERT(init_expr != NULL); |
| 1691 FieldInitExpression initializer; | 1702 FieldInitExpression initializer; |
| 1692 initializer.inst_field = &field; | 1703 initializer.inst_field = &field; |
| 1693 initializer.expr = init_expr; | 1704 initializer.expr = init_expr; |
| 1694 initializers->Add(initializer); | 1705 initializers->Add(initializer); |
| 1695 } | 1706 } |
| 1696 } | 1707 } |
| 1697 SetPosition(saved_pos); | 1708 SetPosition(saved_pos); |
| 1698 } | 1709 } |
| 1699 | 1710 |
| 1700 | 1711 |
| 1701 void Parser::ParseInitializers(const Class& cls, LocalVariable* receiver) { | 1712 void Parser::CheckDuplicateFieldInit(intptr_t init_pos, |
| 1713 GrowableArray<Field*>* initialized_fields, |
| 1714 Field* field) { |
| 1715 ASSERT(!field->is_static()); |
| 1716 for (int i = 0; i < initialized_fields->length(); i++) { |
| 1717 Field* initialized_field = (*initialized_fields)[i]; |
| 1718 if (initialized_field->raw() == field->raw()) { |
| 1719 ErrorMsg(init_pos, |
| 1720 "duplicate initialization for field %s", |
| 1721 String::Handle(field->name()).ToCString()); |
| 1722 } |
| 1723 } |
| 1724 initialized_fields->Add(field); |
| 1725 } |
| 1726 |
| 1727 |
| 1728 void Parser::ParseInitializers(const Class& cls, |
| 1729 LocalVariable* receiver, |
| 1730 GrowableArray<Field*>* initialized_fields) { |
| 1702 TRACE_PARSER("ParseInitializers"); | 1731 TRACE_PARSER("ParseInitializers"); |
| 1703 bool super_init_seen = false; | 1732 bool super_init_seen = false; |
| 1704 if (CurrentToken() == Token::kCOLON) { | 1733 if (CurrentToken() == Token::kCOLON) { |
| 1705 if ((LookaheadToken(1) == Token::kTHIS) && | 1734 if ((LookaheadToken(1) == Token::kTHIS) && |
| 1706 ((LookaheadToken(2) == Token::kLPAREN) || | 1735 ((LookaheadToken(2) == Token::kLPAREN) || |
| 1707 ((LookaheadToken(2) == Token::kPERIOD) && | 1736 ((LookaheadToken(2) == Token::kPERIOD) && |
| 1708 (LookaheadToken(4) == Token::kLPAREN)))) { | 1737 (LookaheadToken(4) == Token::kLPAREN)))) { |
| 1709 // Either we see this(...) or this.xxx(...) which is a | 1738 // Either we see this(...) or this.xxx(...) which is a |
| 1710 // redirected constructor. We don't need to check whether | 1739 // redirected constructor. We don't need to check whether |
| 1711 // const fields are initialized. The other constructor will | 1740 // const fields are initialized. The other constructor will |
| 1712 // guarantee that. | 1741 // guarantee that. |
| 1713 ConsumeToken(); // Colon. | 1742 ConsumeToken(); // Colon. |
| 1714 ParseConstructorRedirection(cls, receiver); | 1743 ParseConstructorRedirection(cls, receiver); |
| 1715 return; | 1744 return; |
| 1716 } | 1745 } |
| 1717 do { | 1746 do { |
| 1718 ConsumeToken(); // Colon or comma. | 1747 ConsumeToken(); // Colon or comma. |
| 1719 AstNode* init_statement; | 1748 AstNode* init_statement; |
| 1720 if (CurrentToken() == Token::kSUPER) { | 1749 if (CurrentToken() == Token::kSUPER) { |
| 1721 if (super_init_seen) { | 1750 if (super_init_seen) { |
| 1722 ErrorMsg("duplicate call to super constructor"); | 1751 ErrorMsg("duplicate call to super constructor"); |
| 1723 } | 1752 } |
| 1724 init_statement = ParseSuperInitializer(cls, receiver); | 1753 init_statement = ParseSuperInitializer(cls, receiver); |
| 1725 super_init_seen = true; | 1754 super_init_seen = true; |
| 1726 } else { | 1755 } else { |
| 1727 init_statement = ParseInitializer(cls, receiver); | 1756 init_statement = ParseInitializer(cls, receiver, initialized_fields); |
| 1728 } | 1757 } |
| 1729 current_block_->statements->Add(init_statement); | 1758 current_block_->statements->Add(init_statement); |
| 1730 } while (CurrentToken() == Token::kCOMMA); | 1759 } while (CurrentToken() == Token::kCOMMA); |
| 1731 } | 1760 } |
| 1732 if (!super_init_seen) { | 1761 if (!super_init_seen) { |
| 1733 // Generate implicit super() if we haven't seen an explicit super call | 1762 // Generate implicit super() if we haven't seen an explicit super call |
| 1734 // or constructor redirection. | 1763 // or constructor redirection. |
| 1735 GenerateSuperConstructorCall(cls, receiver); | 1764 GenerateSuperConstructorCall(cls, receiver); |
| 1736 } | 1765 } |
| 1737 CheckConstFieldsInitialized(cls); | 1766 CheckConstFieldsInitialized(cls); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1792 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { | 1821 SequenceNode* Parser::MakeImplicitConstructor(const Function& func) { |
| 1793 ASSERT(func.IsConstructor()); | 1822 ASSERT(func.IsConstructor()); |
| 1794 const intptr_t ctor_pos = TokenPos(); | 1823 const intptr_t ctor_pos = TokenPos(); |
| 1795 | 1824 |
| 1796 // Implicit 'this' is the only parameter/local variable. | 1825 // Implicit 'this' is the only parameter/local variable. |
| 1797 OpenFunctionBlock(func); | 1826 OpenFunctionBlock(func); |
| 1798 | 1827 |
| 1799 // Parse expressions of instance fields that have an explicit | 1828 // Parse expressions of instance fields that have an explicit |
| 1800 // initializers. | 1829 // initializers. |
| 1801 GrowableArray<FieldInitExpression> initializers; | 1830 GrowableArray<FieldInitExpression> initializers; |
| 1831 GrowableArray<Field*> initialized_fields; |
| 1802 Class& cls = Class::Handle(func.owner()); | 1832 Class& cls = Class::Handle(func.owner()); |
| 1803 ParseInitializedInstanceFields(cls, &initializers); | 1833 ParseInitializedInstanceFields(cls, &initializers, &initialized_fields); |
| 1804 | 1834 |
| 1805 LocalVariable* receiver = new LocalVariable( | 1835 LocalVariable* receiver = new LocalVariable( |
| 1806 ctor_pos, | 1836 ctor_pos, |
| 1807 String::ZoneHandle(Symbols::This()), | 1837 String::ZoneHandle(Symbols::This()), |
| 1808 Type::ZoneHandle(Type::DynamicType())); | 1838 Type::ZoneHandle(Type::DynamicType())); |
| 1809 current_block_->scope->AddVariable(receiver); | 1839 current_block_->scope->AddVariable(receiver); |
| 1810 | 1840 |
| 1811 LocalVariable* phase_parameter = new LocalVariable( | 1841 LocalVariable* phase_parameter = new LocalVariable( |
| 1812 ctor_pos, | 1842 ctor_pos, |
| 1813 String::ZoneHandle(Symbols::PhaseParameter()), | 1843 String::ZoneHandle(Symbols::PhaseParameter()), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1884 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 1914 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 1885 ASSERT(func.NumberOfParameters() == params.parameters->length()); | 1915 ASSERT(func.NumberOfParameters() == params.parameters->length()); |
| 1886 | 1916 |
| 1887 // Initialize instance fields that have an explicit initializer expression. | 1917 // Initialize instance fields that have an explicit initializer expression. |
| 1888 // This has to be done before code for field initializer parameters | 1918 // This has to be done before code for field initializer parameters |
| 1889 // is generated. | 1919 // is generated. |
| 1890 // NB: the instance field initializers have to be compiled before | 1920 // NB: the instance field initializers have to be compiled before |
| 1891 // the parameters are added to the scope, so that a parameter | 1921 // the parameters are added to the scope, so that a parameter |
| 1892 // name cannot shadow a name used in the field initializer expression. | 1922 // name cannot shadow a name used in the field initializer expression. |
| 1893 GrowableArray<FieldInitExpression> initializers; | 1923 GrowableArray<FieldInitExpression> initializers; |
| 1894 ParseInitializedInstanceFields(cls, &initializers); | 1924 GrowableArray<Field*> initialized_fields; |
| 1925 ParseInitializedInstanceFields(cls, &initializers, &initialized_fields); |
| 1895 | 1926 |
| 1896 // Now populate function scope with the formal parameters. | 1927 // Now populate function scope with the formal parameters. |
| 1897 AddFormalParamsToScope(¶ms, current_block_->scope); | 1928 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 1898 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 1929 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
| 1899 | 1930 |
| 1900 // Now that the "this" parameter is in scope, we can generate the code | 1931 // Now that the "this" parameter is in scope, we can generate the code |
| 1901 // to store the initializer expressions in the respective instance fields. | 1932 // to store the initializer expressions in the respective instance fields. |
| 1902 // We do this before the field parameters and the initializers from the | 1933 // We do this before the field parameters and the initializers from the |
| 1903 // constructor's initializer list get compiled. | 1934 // constructor's initializer list get compiled. |
| 1904 OpenBlock(); | 1935 OpenBlock(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1919 for (int i = 0; i < params.parameters->length(); i++) { | 1950 for (int i = 0; i < params.parameters->length(); i++) { |
| 1920 ParamDesc& param = (*params.parameters)[i]; | 1951 ParamDesc& param = (*params.parameters)[i]; |
| 1921 if (param.is_field_initializer) { | 1952 if (param.is_field_initializer) { |
| 1922 const String& field_name = *param.name; | 1953 const String& field_name = *param.name; |
| 1923 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 1954 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 1924 if (field.IsNull()) { | 1955 if (field.IsNull()) { |
| 1925 ErrorMsg(param.name_pos, | 1956 ErrorMsg(param.name_pos, |
| 1926 "unresolved reference to instance field '%s'", | 1957 "unresolved reference to instance field '%s'", |
| 1927 field_name.ToCString()); | 1958 field_name.ToCString()); |
| 1928 } | 1959 } |
| 1960 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); |
| 1929 AstNode* instance = new LoadLocalNode(param.name_pos, *receiver); | 1961 AstNode* instance = new LoadLocalNode(param.name_pos, *receiver); |
| 1930 LocalVariable* p = | 1962 LocalVariable* p = |
| 1931 current_block_->scope->LookupVariable(*param.name, false); | 1963 current_block_->scope->LookupVariable(*param.name, false); |
| 1932 ASSERT(p != NULL); | 1964 ASSERT(p != NULL); |
| 1933 // Initializing formals cannot be used in the explicit initializer | 1965 // Initializing formals cannot be used in the explicit initializer |
| 1934 // list, nor can they be used in the constructor body. | 1966 // list, nor can they be used in the constructor body. |
| 1935 // Thus, make the parameter invisible. | 1967 // Thus, make the parameter invisible. |
| 1936 p->set_invisible(true); | 1968 p->set_invisible(true); |
| 1937 AstNode* value = new LoadLocalNode(param.name_pos, *p); | 1969 AstNode* value = new LoadLocalNode(param.name_pos, *p); |
| 1938 AstNode* initializer = new StoreInstanceFieldNode( | 1970 AstNode* initializer = new StoreInstanceFieldNode( |
| 1939 param.name_pos, instance, field, value); | 1971 param.name_pos, instance, field, value); |
| 1940 current_block_->statements->Add(initializer); | 1972 current_block_->statements->Add(initializer); |
| 1941 } | 1973 } |
| 1942 } | 1974 } |
| 1943 } | 1975 } |
| 1944 | 1976 |
| 1945 // Now parse the explicit initializer list or constructor redirection. | 1977 // Now parse the explicit initializer list or constructor redirection. |
| 1946 ParseInitializers(cls, receiver); | 1978 ParseInitializers(cls, receiver, &initialized_fields); |
| 1947 | 1979 |
| 1948 SequenceNode* init_statements = CloseBlock(); | 1980 SequenceNode* init_statements = CloseBlock(); |
| 1949 if (init_statements->length() > 0) { | 1981 if (init_statements->length() > 0) { |
| 1950 // Generate guard around the initializer code. | 1982 // Generate guard around the initializer code. |
| 1951 LocalVariable* phase_param = LookupPhaseParameter(); | 1983 LocalVariable* phase_param = LookupPhaseParameter(); |
| 1952 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); | 1984 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); |
| 1953 AstNode* phase_check = new BinaryOpNode( | 1985 AstNode* phase_check = new BinaryOpNode( |
| 1954 TokenPos(), Token::kBIT_AND, phase_value, | 1986 TokenPos(), Token::kBIT_AND, phase_value, |
| 1955 new LiteralNode(TokenPos(), | 1987 new LiteralNode(TokenPos(), |
| 1956 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); | 1988 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| (...skipping 6884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8841 void Parser::SkipQualIdent() { | 8873 void Parser::SkipQualIdent() { |
| 8842 ASSERT(IsIdentifier()); | 8874 ASSERT(IsIdentifier()); |
| 8843 ConsumeToken(); | 8875 ConsumeToken(); |
| 8844 if (CurrentToken() == Token::kPERIOD) { | 8876 if (CurrentToken() == Token::kPERIOD) { |
| 8845 ConsumeToken(); // Consume the kPERIOD token. | 8877 ConsumeToken(); // Consume the kPERIOD token. |
| 8846 ExpectIdentifier("identifier expected after '.'"); | 8878 ExpectIdentifier("identifier expected after '.'"); |
| 8847 } | 8879 } |
| 8848 } | 8880 } |
| 8849 | 8881 |
| 8850 } // namespace dart | 8882 } // namespace dart |
| OLD | NEW |