| 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 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 const bool kTestOnly = true; | 702 const bool kTestOnly = true; |
| 703 if (parser.current_function().IsInFactoryScope()) { | 703 if (parser.current_function().IsInFactoryScope()) { |
| 704 instantiator = parser.LookupTypeArgumentsParameter(node_sequence->scope(), | 704 instantiator = parser.LookupTypeArgumentsParameter(node_sequence->scope(), |
| 705 kTestOnly); | 705 kTestOnly); |
| 706 } else { | 706 } else { |
| 707 instantiator = parser.LookupReceiver(node_sequence->scope(), kTestOnly); | 707 instantiator = parser.LookupReceiver(node_sequence->scope(), kTestOnly); |
| 708 } | 708 } |
| 709 if (!parser.current_function().IsLocalFunction() || | 709 if (!parser.current_function().IsLocalFunction() || |
| 710 ((instantiator != NULL) && instantiator->is_captured())) { | 710 ((instantiator != NULL) && instantiator->is_captured())) { |
| 711 parsed_function->set_instantiator( | 711 parsed_function->set_instantiator( |
| 712 new LoadLocalNode(node_sequence->token_pos(), *instantiator)); | 712 new LoadLocalNode(node_sequence->token_pos(), instantiator)); |
| 713 } | 713 } |
| 714 } | 714 } |
| 715 | 715 |
| 716 parsed_function->set_default_parameter_values(default_parameter_values); | 716 parsed_function->set_default_parameter_values(default_parameter_values); |
| 717 } | 717 } |
| 718 | 718 |
| 719 | 719 |
| 720 // TODO(regis): Implement support for non-const final static fields (currently | 720 // TODO(regis): Implement support for non-const final static fields (currently |
| 721 // supported "final" fields are actually const fields). | 721 // supported "final" fields are actually const fields). |
| 722 // TODO(regis): Since a const variable is implicitly final, | 722 // TODO(regis): Since a const variable is implicitly final, |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 ASSERT(func.num_fixed_parameters() == 1); // receiver. | 844 ASSERT(func.num_fixed_parameters() == 1); // receiver. |
| 845 ASSERT(func.num_optional_parameters() == 0); | 845 ASSERT(func.num_optional_parameters() == 0); |
| 846 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 846 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 847 | 847 |
| 848 // Build local scope for function and populate with the formal parameters. | 848 // Build local scope for function and populate with the formal parameters. |
| 849 OpenFunctionBlock(func); | 849 OpenFunctionBlock(func); |
| 850 AddFormalParamsToScope(¶ms, current_block_->scope); | 850 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 851 | 851 |
| 852 // Receiver is local 0. | 852 // Receiver is local 0. |
| 853 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 853 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
| 854 LoadLocalNode* load_receiver = new LoadLocalNode(TokenPos(), *receiver); | 854 LoadLocalNode* load_receiver = new LoadLocalNode(TokenPos(), receiver); |
| 855 // TokenPos() returns the function's token position which points to the | 855 // TokenPos() returns the function's token position which points to the |
| 856 // name of the field; | 856 // name of the field; |
| 857 ASSERT(IsIdentifier()); | 857 ASSERT(IsIdentifier()); |
| 858 const String& field_name = *CurrentLiteral(); | 858 const String& field_name = *CurrentLiteral(); |
| 859 const Class& field_class = Class::Handle(func.owner()); | 859 const Class& field_class = Class::Handle(func.owner()); |
| 860 const Field& field = | 860 const Field& field = |
| 861 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); | 861 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); |
| 862 | 862 |
| 863 LoadInstanceFieldNode* load_field = | 863 LoadInstanceFieldNode* load_field = |
| 864 new LoadInstanceFieldNode(TokenPos(), load_receiver, field); | 864 new LoadInstanceFieldNode(TokenPos(), load_receiver, field); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 892 &field_type); | 892 &field_type); |
| 893 ASSERT(func.num_fixed_parameters() == 2); // receiver, value. | 893 ASSERT(func.num_fixed_parameters() == 2); // receiver, value. |
| 894 ASSERT(func.num_optional_parameters() == 0); | 894 ASSERT(func.num_optional_parameters() == 0); |
| 895 ASSERT(AbstractType::Handle(func.result_type()).IsVoidType()); | 895 ASSERT(AbstractType::Handle(func.result_type()).IsVoidType()); |
| 896 | 896 |
| 897 // Build local scope for function and populate with the formal parameters. | 897 // Build local scope for function and populate with the formal parameters. |
| 898 OpenFunctionBlock(func); | 898 OpenFunctionBlock(func); |
| 899 AddFormalParamsToScope(¶ms, current_block_->scope); | 899 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 900 | 900 |
| 901 LoadLocalNode* receiver = | 901 LoadLocalNode* receiver = |
| 902 new LoadLocalNode(TokenPos(), *current_block_->scope->VariableAt(0)); | 902 new LoadLocalNode(TokenPos(), current_block_->scope->VariableAt(0)); |
| 903 LoadLocalNode* value = | 903 LoadLocalNode* value = |
| 904 new LoadLocalNode(TokenPos(), *current_block_->scope->VariableAt(1)); | 904 new LoadLocalNode(TokenPos(), current_block_->scope->VariableAt(1)); |
| 905 | 905 |
| 906 StoreInstanceFieldNode* store_field = | 906 StoreInstanceFieldNode* store_field = |
| 907 new StoreInstanceFieldNode(TokenPos(), receiver, field, value); | 907 new StoreInstanceFieldNode(TokenPos(), receiver, field, value); |
| 908 | 908 |
| 909 current_block_->statements->Add(store_field); | 909 current_block_->statements->Add(store_field); |
| 910 current_block_->statements->Add(new ReturnNode(TokenPos())); | 910 current_block_->statements->Add(new ReturnNode(TokenPos())); |
| 911 return CloseBlock(); | 911 return CloseBlock(); |
| 912 } | 912 } |
| 913 | 913 |
| 914 | 914 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 ExpectToken(Token::kRBRACK); | 1319 ExpectToken(Token::kRBRACK); |
| 1320 | 1320 |
| 1321 if (Token::IsAssignmentOperator(CurrentToken()) && | 1321 if (Token::IsAssignmentOperator(CurrentToken()) && |
| 1322 (CurrentToken() != Token::kASSIGN)) { | 1322 (CurrentToken() != Token::kASSIGN)) { |
| 1323 // Compound assignment. Ensure side effects in index expression | 1323 // Compound assignment. Ensure side effects in index expression |
| 1324 // only execute once. If the index is not a local variable or an | 1324 // only execute once. If the index is not a local variable or an |
| 1325 // literal, evaluate and save in a temporary local. | 1325 // literal, evaluate and save in a temporary local. |
| 1326 if (!IsSimpleLocalOrLiteralNode(index_expr)) { | 1326 if (!IsSimpleLocalOrLiteralNode(index_expr)) { |
| 1327 LocalVariable* temp = | 1327 LocalVariable* temp = |
| 1328 CreateTempConstVariable(operator_pos, "lix"); | 1328 CreateTempConstVariable(operator_pos, "lix"); |
| 1329 AstNode* save = | 1329 AstNode* save = new StoreLocalNode(operator_pos, temp, index_expr); |
| 1330 new StoreLocalNode(operator_pos, *temp, index_expr); | |
| 1331 current_block_->statements->Add(save); | 1330 current_block_->statements->Add(save); |
| 1332 index_expr = new LoadLocalNode(operator_pos, *temp); | 1331 index_expr = new LoadLocalNode(operator_pos, temp); |
| 1333 } | 1332 } |
| 1334 } | 1333 } |
| 1335 | 1334 |
| 1336 // Resolve the [] operator function in the superclass. | 1335 // Resolve the [] operator function in the superclass. |
| 1337 const String& index_operator_name = | 1336 const String& index_operator_name = |
| 1338 String::ZoneHandle(Symbols::IndexToken()); | 1337 String::ZoneHandle(Symbols::IndexToken()); |
| 1339 bool is_no_such_method = false; | 1338 bool is_no_such_method = false; |
| 1340 const Function& index_operator = Function::ZoneHandle( | 1339 const Function& index_operator = Function::ZoneHandle( |
| 1341 GetSuperFunction(operator_pos, | 1340 GetSuperFunction(operator_pos, |
| 1342 index_operator_name, | 1341 index_operator_name, |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1505 // we're not compiling class Object), or if the super class is an | 1504 // we're not compiling class Object), or if the super class is an |
| 1506 // artificially generated "wrapper class" that has no constructor. | 1505 // artificially generated "wrapper class" that has no constructor. |
| 1507 if (super_class.IsNull() || (super_class.num_native_fields() > 0)) { | 1506 if (super_class.IsNull() || (super_class.num_native_fields() > 0)) { |
| 1508 return; | 1507 return; |
| 1509 } | 1508 } |
| 1510 String& ctor_name = String::Handle(super_class.Name()); | 1509 String& ctor_name = String::Handle(super_class.Name()); |
| 1511 String& ctor_suffix = String::Handle(Symbols::Dot()); | 1510 String& ctor_suffix = String::Handle(Symbols::Dot()); |
| 1512 ctor_name = String::Concat(ctor_name, ctor_suffix); | 1511 ctor_name = String::Concat(ctor_name, ctor_suffix); |
| 1513 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); | 1512 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| 1514 // Implicit 'this' parameter is the first argument. | 1513 // Implicit 'this' parameter is the first argument. |
| 1515 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver); | 1514 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); |
| 1516 arguments->Add(implicit_argument); | 1515 arguments->Add(implicit_argument); |
| 1517 // Implicit construction phase parameter is second argument. | 1516 // Implicit construction phase parameter is second argument. |
| 1518 AstNode* phase_parameter = | 1517 AstNode* phase_parameter = |
| 1519 new LiteralNode(supercall_pos, | 1518 new LiteralNode(supercall_pos, |
| 1520 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 1519 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 1521 arguments->Add(phase_parameter); | 1520 arguments->Add(phase_parameter); |
| 1522 const Function& super_ctor = Function::ZoneHandle( | 1521 const Function& super_ctor = Function::ZoneHandle( |
| 1523 super_class.LookupConstructor(ctor_name)); | 1522 super_class.LookupConstructor(ctor_name)); |
| 1524 if (super_ctor.IsNull()) { | 1523 if (super_ctor.IsNull()) { |
| 1525 ErrorMsg(supercall_pos, | 1524 ErrorMsg(supercall_pos, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1556 ctor_suffix = String::Concat( | 1555 ctor_suffix = String::Concat( |
| 1557 ctor_suffix, *ExpectIdentifier("constructor name expected")); | 1556 ctor_suffix, *ExpectIdentifier("constructor name expected")); |
| 1558 } | 1557 } |
| 1559 ctor_name = String::Concat(ctor_name, ctor_suffix); | 1558 ctor_name = String::Concat(ctor_name, ctor_suffix); |
| 1560 if (CurrentToken() != Token::kLPAREN) { | 1559 if (CurrentToken() != Token::kLPAREN) { |
| 1561 ErrorMsg("parameter list expected"); | 1560 ErrorMsg("parameter list expected"); |
| 1562 } | 1561 } |
| 1563 | 1562 |
| 1564 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); | 1563 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| 1565 // 'this' parameter is the first argument to super class constructor. | 1564 // 'this' parameter is the first argument to super class constructor. |
| 1566 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver); | 1565 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); |
| 1567 arguments->Add(implicit_argument); | 1566 arguments->Add(implicit_argument); |
| 1568 // Second implicit parameter is the construction phase. We optimistically | 1567 // Second implicit parameter is the construction phase. We optimistically |
| 1569 // assume that we can execute both the super initializer and the super | 1568 // assume that we can execute both the super initializer and the super |
| 1570 // constructor body. We may later change this to only execute the | 1569 // constructor body. We may later change this to only execute the |
| 1571 // super initializer. | 1570 // super initializer. |
| 1572 AstNode* phase_parameter = | 1571 AstNode* phase_parameter = |
| 1573 new LiteralNode(supercall_pos, | 1572 new LiteralNode(supercall_pos, |
| 1574 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 1573 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 1575 arguments->Add(phase_parameter); | 1574 arguments->Add(phase_parameter); |
| 1576 // 'this' parameter must not be accessible to the other super call arguments. | 1575 // 'this' parameter must not be accessible to the other super call arguments. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1617 receiver->set_invisible(true); | 1616 receiver->set_invisible(true); |
| 1618 AstNode* init_expr = ParseConditionalExpr(); | 1617 AstNode* init_expr = ParseConditionalExpr(); |
| 1619 receiver->set_invisible(false); | 1618 receiver->set_invisible(false); |
| 1620 SetAllowFunctionLiterals(saved_mode); | 1619 SetAllowFunctionLiterals(saved_mode); |
| 1621 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 1620 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 1622 if (field.IsNull()) { | 1621 if (field.IsNull()) { |
| 1623 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", | 1622 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", |
| 1624 field_name.ToCString()); | 1623 field_name.ToCString()); |
| 1625 } | 1624 } |
| 1626 CheckDuplicateFieldInit(field_pos, initialized_fields, &field); | 1625 CheckDuplicateFieldInit(field_pos, initialized_fields, &field); |
| 1627 AstNode* instance = new LoadLocalNode(field_pos, *receiver); | 1626 AstNode* instance = new LoadLocalNode(field_pos, receiver); |
| 1628 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); | 1627 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); |
| 1629 } | 1628 } |
| 1630 | 1629 |
| 1631 | 1630 |
| 1632 void Parser::CheckConstFieldsInitialized(const Class& cls) { | 1631 void Parser::CheckConstFieldsInitialized(const Class& cls) { |
| 1633 const Array& fields = Array::Handle(cls.fields()); | 1632 const Array& fields = Array::Handle(cls.fields()); |
| 1634 Field& field = Field::Handle(); | 1633 Field& field = Field::Handle(); |
| 1635 SequenceNode* initializers = current_block_->statements; | 1634 SequenceNode* initializers = current_block_->statements; |
| 1636 for (int field_num = 0; field_num < fields.Length(); field_num++) { | 1635 for (int field_num = 0; field_num < fields.Length(); field_num++) { |
| 1637 field ^= fields.At(field_num); | 1636 field ^= fields.At(field_num); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 ctor_suffix = String::Concat( | 1771 ctor_suffix = String::Concat( |
| 1773 ctor_suffix, *ExpectIdentifier("constructor name expected")); | 1772 ctor_suffix, *ExpectIdentifier("constructor name expected")); |
| 1774 } | 1773 } |
| 1775 ctor_name = String::Concat(ctor_name, ctor_suffix); | 1774 ctor_name = String::Concat(ctor_name, ctor_suffix); |
| 1776 if (CurrentToken() != Token::kLPAREN) { | 1775 if (CurrentToken() != Token::kLPAREN) { |
| 1777 ErrorMsg("parameter list expected"); | 1776 ErrorMsg("parameter list expected"); |
| 1778 } | 1777 } |
| 1779 | 1778 |
| 1780 ArgumentListNode* arguments = new ArgumentListNode(call_pos); | 1779 ArgumentListNode* arguments = new ArgumentListNode(call_pos); |
| 1781 // 'this' parameter is the first argument to constructor. | 1780 // 'this' parameter is the first argument to constructor. |
| 1782 AstNode* implicit_argument = new LoadLocalNode(call_pos, *receiver); | 1781 AstNode* implicit_argument = new LoadLocalNode(call_pos, receiver); |
| 1783 arguments->Add(implicit_argument); | 1782 arguments->Add(implicit_argument); |
| 1784 // Construction phase parameter is second argument. | 1783 // Construction phase parameter is second argument. |
| 1785 LocalVariable* phase_param = LookupPhaseParameter(); | 1784 LocalVariable* phase_param = LookupPhaseParameter(); |
| 1786 ASSERT(phase_param != NULL); | 1785 ASSERT(phase_param != NULL); |
| 1787 AstNode* phase_argument = new LoadLocalNode(call_pos, *phase_param); | 1786 AstNode* phase_argument = new LoadLocalNode(call_pos, phase_param); |
| 1788 arguments->Add(phase_argument); | 1787 arguments->Add(phase_argument); |
| 1789 ParseActualParameters(arguments, kAllowConst); | 1788 ParseActualParameters(arguments, kAllowConst); |
| 1790 | 1789 |
| 1791 // Resolve the constructor. | 1790 // Resolve the constructor. |
| 1792 const Function& redirect_ctor = Function::ZoneHandle( | 1791 const Function& redirect_ctor = Function::ZoneHandle( |
| 1793 cls.LookupConstructor(ctor_name)); | 1792 cls.LookupConstructor(ctor_name)); |
| 1794 if (redirect_ctor.IsNull()) { | 1793 if (redirect_ctor.IsNull()) { |
| 1795 ErrorMsg(call_pos, "constructor '%s' not found", ctor_name.ToCString()); | 1794 ErrorMsg(call_pos, "constructor '%s' not found", ctor_name.ToCString()); |
| 1796 } | 1795 } |
| 1797 String& error_message = String::Handle(); | 1796 String& error_message = String::Handle(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1832 LocalVariable* phase_parameter = new LocalVariable( | 1831 LocalVariable* phase_parameter = new LocalVariable( |
| 1833 ctor_pos, | 1832 ctor_pos, |
| 1834 String::ZoneHandle(Symbols::PhaseParameter()), | 1833 String::ZoneHandle(Symbols::PhaseParameter()), |
| 1835 Type::ZoneHandle(Type::IntInterface())); | 1834 Type::ZoneHandle(Type::IntInterface())); |
| 1836 current_block_->scope->AddVariable(phase_parameter); | 1835 current_block_->scope->AddVariable(phase_parameter); |
| 1837 | 1836 |
| 1838 // Now that the "this" parameter is in scope, we can generate the code | 1837 // Now that the "this" parameter is in scope, we can generate the code |
| 1839 // to strore the initializer expressions in the respective instance fields. | 1838 // to strore the initializer expressions in the respective instance fields. |
| 1840 for (int i = 0; i < initializers.length(); i++) { | 1839 for (int i = 0; i < initializers.length(); i++) { |
| 1841 const Field* field = initializers[i].inst_field; | 1840 const Field* field = initializers[i].inst_field; |
| 1842 AstNode* instance = new LoadLocalNode(field->token_pos(), *receiver); | 1841 AstNode* instance = new LoadLocalNode(field->token_pos(), receiver); |
| 1843 AstNode* field_init = | 1842 AstNode* field_init = |
| 1844 new StoreInstanceFieldNode(field->token_pos(), | 1843 new StoreInstanceFieldNode(field->token_pos(), |
| 1845 instance, | 1844 instance, |
| 1846 *field, | 1845 *field, |
| 1847 initializers[i].expr); | 1846 initializers[i].expr); |
| 1848 current_block_->statements->Add(field_init); | 1847 current_block_->statements->Add(field_init); |
| 1849 } | 1848 } |
| 1850 | 1849 |
| 1851 GenerateSuperConstructorCall(cls, receiver); | 1850 GenerateSuperConstructorCall(cls, receiver); |
| 1852 CheckConstFieldsInitialized(cls); | 1851 CheckConstFieldsInitialized(cls); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 AddFormalParamsToScope(¶ms, current_block_->scope); | 1919 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 1921 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 1920 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
| 1922 | 1921 |
| 1923 // Now that the "this" parameter is in scope, we can generate the code | 1922 // Now that the "this" parameter is in scope, we can generate the code |
| 1924 // to store the initializer expressions in the respective instance fields. | 1923 // to store the initializer expressions in the respective instance fields. |
| 1925 // We do this before the field parameters and the initializers from the | 1924 // We do this before the field parameters and the initializers from the |
| 1926 // constructor's initializer list get compiled. | 1925 // constructor's initializer list get compiled. |
| 1927 OpenBlock(); | 1926 OpenBlock(); |
| 1928 for (int i = 0; i < initializers.length(); i++) { | 1927 for (int i = 0; i < initializers.length(); i++) { |
| 1929 const Field* field = initializers[i].inst_field; | 1928 const Field* field = initializers[i].inst_field; |
| 1930 AstNode* instance = new LoadLocalNode(field->token_pos(), *receiver); | 1929 AstNode* instance = new LoadLocalNode(field->token_pos(), receiver); |
| 1931 AstNode* field_init = | 1930 AstNode* field_init = |
| 1932 new StoreInstanceFieldNode(field->token_pos(), | 1931 new StoreInstanceFieldNode(field->token_pos(), |
| 1933 instance, | 1932 instance, |
| 1934 *field, | 1933 *field, |
| 1935 initializers[i].expr); | 1934 initializers[i].expr); |
| 1936 current_block_->statements->Add(field_init); | 1935 current_block_->statements->Add(field_init); |
| 1937 } | 1936 } |
| 1938 | 1937 |
| 1939 // Turn formal field parameters into field initializers or report error | 1938 // Turn formal field parameters into field initializers or report error |
| 1940 // if the function is not a constructor. | 1939 // if the function is not a constructor. |
| 1941 if (params.has_field_initializer) { | 1940 if (params.has_field_initializer) { |
| 1942 for (int i = 0; i < params.parameters->length(); i++) { | 1941 for (int i = 0; i < params.parameters->length(); i++) { |
| 1943 ParamDesc& param = (*params.parameters)[i]; | 1942 ParamDesc& param = (*params.parameters)[i]; |
| 1944 if (param.is_field_initializer) { | 1943 if (param.is_field_initializer) { |
| 1945 const String& field_name = *param.name; | 1944 const String& field_name = *param.name; |
| 1946 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 1945 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 1947 if (field.IsNull()) { | 1946 if (field.IsNull()) { |
| 1948 ErrorMsg(param.name_pos, | 1947 ErrorMsg(param.name_pos, |
| 1949 "unresolved reference to instance field '%s'", | 1948 "unresolved reference to instance field '%s'", |
| 1950 field_name.ToCString()); | 1949 field_name.ToCString()); |
| 1951 } | 1950 } |
| 1952 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); | 1951 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); |
| 1953 AstNode* instance = new LoadLocalNode(param.name_pos, *receiver); | 1952 AstNode* instance = new LoadLocalNode(param.name_pos, receiver); |
| 1954 LocalVariable* p = | 1953 LocalVariable* p = |
| 1955 current_block_->scope->LookupVariable(*param.name, false); | 1954 current_block_->scope->LookupVariable(*param.name, false); |
| 1956 ASSERT(p != NULL); | 1955 ASSERT(p != NULL); |
| 1957 // Initializing formals cannot be used in the explicit initializer | 1956 // Initializing formals cannot be used in the explicit initializer |
| 1958 // list, nor can they be used in the constructor body. | 1957 // list, nor can they be used in the constructor body. |
| 1959 // Thus, make the parameter invisible. | 1958 // Thus, make the parameter invisible. |
| 1960 p->set_invisible(true); | 1959 p->set_invisible(true); |
| 1961 AstNode* value = new LoadLocalNode(param.name_pos, *p); | 1960 AstNode* value = new LoadLocalNode(param.name_pos, p); |
| 1962 AstNode* initializer = new StoreInstanceFieldNode( | 1961 AstNode* initializer = new StoreInstanceFieldNode( |
| 1963 param.name_pos, instance, field, value); | 1962 param.name_pos, instance, field, value); |
| 1964 current_block_->statements->Add(initializer); | 1963 current_block_->statements->Add(initializer); |
| 1965 } | 1964 } |
| 1966 } | 1965 } |
| 1967 } | 1966 } |
| 1968 | 1967 |
| 1969 // Now parse the explicit initializer list or constructor redirection. | 1968 // Now parse the explicit initializer list or constructor redirection. |
| 1970 ParseInitializers(cls, receiver, &initialized_fields); | 1969 ParseInitializers(cls, receiver, &initialized_fields); |
| 1971 | 1970 |
| 1972 SequenceNode* init_statements = CloseBlock(); | 1971 SequenceNode* init_statements = CloseBlock(); |
| 1973 if (init_statements->length() > 0) { | 1972 if (init_statements->length() > 0) { |
| 1974 // Generate guard around the initializer code. | 1973 // Generate guard around the initializer code. |
| 1975 LocalVariable* phase_param = LookupPhaseParameter(); | 1974 LocalVariable* phase_param = LookupPhaseParameter(); |
| 1976 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); | 1975 AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param); |
| 1977 AstNode* phase_check = new BinaryOpNode( | 1976 AstNode* phase_check = new BinaryOpNode( |
| 1978 TokenPos(), Token::kBIT_AND, phase_value, | 1977 TokenPos(), Token::kBIT_AND, phase_value, |
| 1979 new LiteralNode(TokenPos(), | 1978 new LiteralNode(TokenPos(), |
| 1980 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); | 1979 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| 1981 AstNode* comparison = | 1980 AstNode* comparison = |
| 1982 new ComparisonNode(TokenPos(), Token::kNE_STRICT, | 1981 new ComparisonNode(TokenPos(), Token::kNE_STRICT, |
| 1983 phase_check, | 1982 phase_check, |
| 1984 new LiteralNode(TokenPos(), | 1983 new LiteralNode(TokenPos(), |
| 1985 Smi::ZoneHandle(Smi::New(0)))); | 1984 Smi::ZoneHandle(Smi::New(0)))); |
| 1986 AstNode* guarded_init_statements = | 1985 AstNode* guarded_init_statements = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2016 // expressions are not evaluated twice. | 2015 // expressions are not evaluated twice. |
| 2017 ArgumentListNode* ctor_args = super_call->arguments(); | 2016 ArgumentListNode* ctor_args = super_call->arguments(); |
| 2018 // The super initializer call has at least 2 arguments: the | 2017 // The super initializer call has at least 2 arguments: the |
| 2019 // implicit receiver, and the hidden construction phase. | 2018 // implicit receiver, and the hidden construction phase. |
| 2020 ASSERT(ctor_args->length() >= 2); | 2019 ASSERT(ctor_args->length() >= 2); |
| 2021 for (int i = 2; i < ctor_args->length(); i++) { | 2020 for (int i = 2; i < ctor_args->length(); i++) { |
| 2022 AstNode* arg = ctor_args->NodeAt(i); | 2021 AstNode* arg = ctor_args->NodeAt(i); |
| 2023 if (!IsSimpleLocalOrLiteralNode(arg)) { | 2022 if (!IsSimpleLocalOrLiteralNode(arg)) { |
| 2024 LocalVariable* temp = | 2023 LocalVariable* temp = |
| 2025 CreateTempConstVariable(arg->token_pos(), "sca"); | 2024 CreateTempConstVariable(arg->token_pos(), "sca"); |
| 2026 AstNode* save_temp = | 2025 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); |
| 2027 new StoreLocalNode(arg->token_pos(), *temp, arg); | |
| 2028 ctor_args->SetNodeAt(i, save_temp); | 2026 ctor_args->SetNodeAt(i, save_temp); |
| 2029 } | 2027 } |
| 2030 } | 2028 } |
| 2031 } | 2029 } |
| 2032 OpenBlock(); // Block to collect constructor body nodes. | 2030 OpenBlock(); // Block to collect constructor body nodes. |
| 2033 | 2031 |
| 2034 // Insert the implicit super call to the super constructor body. | 2032 // Insert the implicit super call to the super constructor body. |
| 2035 if (super_call != NULL) { | 2033 if (super_call != NULL) { |
| 2036 ArgumentListNode* initializer_args = super_call->arguments(); | 2034 ArgumentListNode* initializer_args = super_call->arguments(); |
| 2037 const Function& super_ctor = super_call->function(); | 2035 const Function& super_ctor = super_call->function(); |
| 2038 // Patch the initializer call so it only executes the super initializer. | 2036 // Patch the initializer call so it only executes the super initializer. |
| 2039 initializer_args->SetNodeAt(1, | 2037 initializer_args->SetNodeAt(1, |
| 2040 new LiteralNode(TokenPos(), | 2038 new LiteralNode(TokenPos(), |
| 2041 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); | 2039 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| 2042 | 2040 |
| 2043 ArgumentListNode* super_call_args = new ArgumentListNode(TokenPos()); | 2041 ArgumentListNode* super_call_args = new ArgumentListNode(TokenPos()); |
| 2044 // First argument is the receiver. | 2042 // First argument is the receiver. |
| 2045 super_call_args->Add(new LoadLocalNode(TokenPos(), *receiver)); | 2043 super_call_args->Add(new LoadLocalNode(TokenPos(), receiver)); |
| 2046 // Second argument is the construction phase argument. | 2044 // Second argument is the construction phase argument. |
| 2047 AstNode* phase_parameter = | 2045 AstNode* phase_parameter = |
| 2048 new LiteralNode(TokenPos(), | 2046 new LiteralNode(TokenPos(), |
| 2049 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))); | 2047 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))); |
| 2050 super_call_args->Add(phase_parameter); | 2048 super_call_args->Add(phase_parameter); |
| 2051 super_call_args->set_names(initializer_args->names()); | 2049 super_call_args->set_names(initializer_args->names()); |
| 2052 for (int i = 2; i < initializer_args->length(); i++) { | 2050 for (int i = 2; i < initializer_args->length(); i++) { |
| 2053 AstNode* arg = initializer_args->NodeAt(i); | 2051 AstNode* arg = initializer_args->NodeAt(i); |
| 2054 if (arg->IsLiteralNode()) { | 2052 if (arg->IsLiteralNode()) { |
| 2055 LiteralNode* lit = arg->AsLiteralNode(); | 2053 LiteralNode* lit = arg->AsLiteralNode(); |
| 2056 super_call_args->Add(new LiteralNode(TokenPos(), lit->literal())); | 2054 super_call_args->Add(new LiteralNode(TokenPos(), lit->literal())); |
| 2057 } else { | 2055 } else { |
| 2058 ASSERT(arg->IsLoadLocalNode() || arg->IsStoreLocalNode()); | 2056 ASSERT(arg->IsLoadLocalNode() || arg->IsStoreLocalNode()); |
| 2059 if (arg->IsLoadLocalNode()) { | 2057 if (arg->IsLoadLocalNode()) { |
| 2060 const LocalVariable& temp = arg->AsLoadLocalNode()->local(); | 2058 const LocalVariable& temp = arg->AsLoadLocalNode()->local(); |
| 2061 super_call_args->Add(new LoadLocalNode(TokenPos(), temp)); | 2059 super_call_args->Add(new LoadLocalNode(TokenPos(), &temp)); |
| 2062 } else if (arg->IsStoreLocalNode()) { | 2060 } else if (arg->IsStoreLocalNode()) { |
| 2063 const LocalVariable& temp = arg->AsStoreLocalNode()->local(); | 2061 const LocalVariable& temp = arg->AsStoreLocalNode()->local(); |
| 2064 super_call_args->Add(new LoadLocalNode(TokenPos(), temp)); | 2062 super_call_args->Add(new LoadLocalNode(TokenPos(), &temp)); |
| 2065 } | 2063 } |
| 2066 } | 2064 } |
| 2067 } | 2065 } |
| 2068 ASSERT(super_ctor.AreValidArguments(super_call_args->length(), | 2066 ASSERT(super_ctor.AreValidArguments(super_call_args->length(), |
| 2069 super_call_args->names(), | 2067 super_call_args->names(), |
| 2070 NULL)); | 2068 NULL)); |
| 2071 current_block_->statements->Add( | 2069 current_block_->statements->Add( |
| 2072 new StaticCallNode(TokenPos(), super_ctor, super_call_args)); | 2070 new StaticCallNode(TokenPos(), super_ctor, super_call_args)); |
| 2073 } | 2071 } |
| 2074 | 2072 |
| 2075 if (CurrentToken() == Token::kLBRACE) { | 2073 if (CurrentToken() == Token::kLBRACE) { |
| 2076 ConsumeToken(); | 2074 ConsumeToken(); |
| 2077 ParseStatementSequence(); | 2075 ParseStatementSequence(); |
| 2078 ExpectToken(Token::kRBRACE); | 2076 ExpectToken(Token::kRBRACE); |
| 2079 } else if (CurrentToken() == Token::kARROW) { | 2077 } else if (CurrentToken() == Token::kARROW) { |
| 2080 ErrorMsg("constructors may not return a value"); | 2078 ErrorMsg("constructors may not return a value"); |
| 2081 } else if (IsLiteral("native")) { | 2079 } else if (IsLiteral("native")) { |
| 2082 ErrorMsg("native constructors not supported"); | 2080 ErrorMsg("native constructors not supported"); |
| 2083 } else if (CurrentToken() == Token::kSEMICOLON) { | 2081 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 2084 // Some constructors have no function body. | 2082 // Some constructors have no function body. |
| 2085 ConsumeToken(); | 2083 ConsumeToken(); |
| 2086 } else { | 2084 } else { |
| 2087 UnexpectedToken(); | 2085 UnexpectedToken(); |
| 2088 } | 2086 } |
| 2089 | 2087 |
| 2090 SequenceNode* ctor_block = CloseBlock(); | 2088 SequenceNode* ctor_block = CloseBlock(); |
| 2091 if (ctor_block->length() > 0) { | 2089 if (ctor_block->length() > 0) { |
| 2092 // Generate guard around the constructor body code. | 2090 // Generate guard around the constructor body code. |
| 2093 LocalVariable* phase_param = LookupPhaseParameter(); | 2091 LocalVariable* phase_param = LookupPhaseParameter(); |
| 2094 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); | 2092 AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param); |
| 2095 AstNode* phase_check = | 2093 AstNode* phase_check = |
| 2096 new BinaryOpNode(TokenPos(), Token::kBIT_AND, | 2094 new BinaryOpNode(TokenPos(), Token::kBIT_AND, |
| 2097 phase_value, | 2095 phase_value, |
| 2098 new LiteralNode(TokenPos(), | 2096 new LiteralNode(TokenPos(), |
| 2099 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody)))); | 2097 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody)))); |
| 2100 AstNode* comparison = | 2098 AstNode* comparison = |
| 2101 new ComparisonNode(TokenPos(), Token::kNE_STRICT, | 2099 new ComparisonNode(TokenPos(), Token::kNE_STRICT, |
| 2102 phase_check, | 2100 phase_check, |
| 2103 new LiteralNode(TokenPos(), | 2101 new LiteralNode(TokenPos(), |
| 2104 Smi::ZoneHandle(Smi::New(0)))); | 2102 Smi::ZoneHandle(Smi::New(0)))); |
| (...skipping 2099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4204 | 4202 |
| 4205 | 4203 |
| 4206 AstNode* Parser::LoadReceiver(intptr_t token_pos) { | 4204 AstNode* Parser::LoadReceiver(intptr_t token_pos) { |
| 4207 // A nested function may access 'this', referring to the receiver of the | 4205 // A nested function may access 'this', referring to the receiver of the |
| 4208 // outermost enclosing function. | 4206 // outermost enclosing function. |
| 4209 const bool kTestOnly = false; | 4207 const bool kTestOnly = false; |
| 4210 LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly); | 4208 LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly); |
| 4211 if (receiver == NULL) { | 4209 if (receiver == NULL) { |
| 4212 ErrorMsg(token_pos, "illegal implicit access to receiver 'this'"); | 4210 ErrorMsg(token_pos, "illegal implicit access to receiver 'this'"); |
| 4213 } | 4211 } |
| 4214 return new LoadLocalNode(TokenPos(), *receiver); | 4212 return new LoadLocalNode(TokenPos(), receiver); |
| 4215 } | 4213 } |
| 4216 | 4214 |
| 4217 | 4215 |
| 4218 AstNode* Parser::LoadTypeArgumentsParameter(intptr_t token_pos) { | 4216 AstNode* Parser::LoadTypeArgumentsParameter(intptr_t token_pos) { |
| 4219 // A nested function may access ':type_arguments' to use as instantiator, | 4217 // A nested function may access ':type_arguments' to use as instantiator, |
| 4220 // referring to the implicit first parameter of the outermost enclosing | 4218 // referring to the implicit first parameter of the outermost enclosing |
| 4221 // factory function. | 4219 // factory function. |
| 4222 const bool kTestOnly = false; | 4220 const bool kTestOnly = false; |
| 4223 LocalVariable* param = LookupTypeArgumentsParameter(current_block_->scope, | 4221 LocalVariable* param = LookupTypeArgumentsParameter(current_block_->scope, |
| 4224 kTestOnly); | 4222 kTestOnly); |
| 4225 ASSERT(param != NULL); | 4223 ASSERT(param != NULL); |
| 4226 return new LoadLocalNode(TokenPos(), *param); | 4224 return new LoadLocalNode(TokenPos(), param); |
| 4227 } | 4225 } |
| 4228 | 4226 |
| 4229 | 4227 |
| 4230 AstNode* Parser::CallGetter(intptr_t token_pos, | 4228 AstNode* Parser::CallGetter(intptr_t token_pos, |
| 4231 AstNode* object, | 4229 AstNode* object, |
| 4232 const String& name) { | 4230 const String& name) { |
| 4233 return new InstanceGetterNode(TokenPos(), object, name); | 4231 return new InstanceGetterNode(TokenPos(), object, name); |
| 4234 } | 4232 } |
| 4235 | 4233 |
| 4236 | 4234 |
| 4237 // Returns ast nodes of the variable initialization. | 4235 // Returns ast nodes of the variable initialization. |
| 4238 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, | 4236 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, |
| 4239 bool is_final, | 4237 bool is_final, |
| 4240 bool is_const) { | 4238 bool is_const) { |
| 4241 TRACE_PARSER("ParseVariableDeclaration"); | 4239 TRACE_PARSER("ParseVariableDeclaration"); |
| 4242 ASSERT(IsIdentifier()); | 4240 ASSERT(IsIdentifier()); |
| 4243 const intptr_t ident_pos = TokenPos(); | 4241 const intptr_t ident_pos = TokenPos(); |
| 4244 LocalVariable* variable = | 4242 LocalVariable* variable = |
| 4245 new LocalVariable(ident_pos, *CurrentLiteral(), type); | 4243 new LocalVariable(ident_pos, *CurrentLiteral(), type); |
| 4246 ASSERT(current_block_ != NULL); | 4244 ASSERT(current_block_ != NULL); |
| 4247 ASSERT(current_block_->scope != NULL); | 4245 ASSERT(current_block_->scope != NULL); |
| 4248 ConsumeToken(); // Variable identifier. | 4246 ConsumeToken(); // Variable identifier. |
| 4249 AstNode* initialization = NULL; | 4247 AstNode* initialization = NULL; |
| 4250 if (CurrentToken() == Token::kASSIGN) { | 4248 if (CurrentToken() == Token::kASSIGN) { |
| 4251 // Variable initialization. | 4249 // Variable initialization. |
| 4252 const intptr_t assign_pos = TokenPos(); | 4250 const intptr_t assign_pos = TokenPos(); |
| 4253 ConsumeToken(); | 4251 ConsumeToken(); |
| 4254 AstNode* expr = ParseExpr(is_const, kConsumeCascades); | 4252 AstNode* expr = ParseExpr(is_const, kConsumeCascades); |
| 4255 initialization = new StoreLocalNode(assign_pos, *variable, expr); | 4253 initialization = new StoreLocalNode(assign_pos, variable, expr); |
| 4256 } else if (is_final || is_const) { | 4254 } else if (is_final || is_const) { |
| 4257 ErrorMsg(ident_pos, | 4255 ErrorMsg(ident_pos, |
| 4258 "missing initialization of 'final' or 'const' variable"); | 4256 "missing initialization of 'final' or 'const' variable"); |
| 4259 } else { | 4257 } else { |
| 4260 // Initialize variable with null. | 4258 // Initialize variable with null. |
| 4261 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); | 4259 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); |
| 4262 initialization = new StoreLocalNode(ident_pos, *variable, null_expr); | 4260 initialization = new StoreLocalNode(ident_pos, variable, null_expr); |
| 4263 } | 4261 } |
| 4264 // Add variable to scope after parsing the initalizer expression. | 4262 // Add variable to scope after parsing the initalizer expression. |
| 4265 // The expression must not be able to refer to the variable. | 4263 // The expression must not be able to refer to the variable. |
| 4266 if (!current_block_->scope->AddVariable(variable)) { | 4264 if (!current_block_->scope->AddVariable(variable)) { |
| 4267 ErrorMsg(ident_pos, "identifier '%s' already defined", | 4265 ErrorMsg(ident_pos, "identifier '%s' already defined", |
| 4268 variable->name().ToCString()); | 4266 variable->name().ToCString()); |
| 4269 } | 4267 } |
| 4270 if (is_final || is_const) { | 4268 if (is_final || is_const) { |
| 4271 variable->set_is_final(); | 4269 variable->set_is_final(); |
| 4272 } | 4270 } |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4528 // This pruning is done by omitting to hook the local scope in its parent | 4526 // This pruning is done by omitting to hook the local scope in its parent |
| 4529 // scope in the constructor of LocalScope. | 4527 // scope in the constructor of LocalScope. |
| 4530 AstNode* closure = | 4528 AstNode* closure = |
| 4531 new ClosureNode(ident_pos, function, NULL, statements->scope()); | 4529 new ClosureNode(ident_pos, function, NULL, statements->scope()); |
| 4532 | 4530 |
| 4533 if (function_variable == NULL) { | 4531 if (function_variable == NULL) { |
| 4534 ASSERT(is_literal); | 4532 ASSERT(is_literal); |
| 4535 return closure; | 4533 return closure; |
| 4536 } else { | 4534 } else { |
| 4537 AstNode* initialization = | 4535 AstNode* initialization = |
| 4538 new StoreLocalNode(ident_pos, *function_variable, closure); | 4536 new StoreLocalNode(ident_pos, function_variable, closure); |
| 4539 return initialization; | 4537 return initialization; |
| 4540 } | 4538 } |
| 4541 } | 4539 } |
| 4542 | 4540 |
| 4543 | 4541 |
| 4544 // Returns true if the current and next tokens can be parsed as type | 4542 // Returns true if the current and next tokens can be parsed as type |
| 4545 // parameters. Current token position is not saved and restored. | 4543 // parameters. Current token position is not saved and restored. |
| 4546 bool Parser::TryParseTypeParameter() { | 4544 bool Parser::TryParseTypeParameter() { |
| 4547 if (CurrentToken() == Token::kLT) { | 4545 if (CurrentToken() == Token::kLT) { |
| 4548 // We are possibly looking at type parameters. Find closing ">". | 4546 // We are possibly looking at type parameters. Find closing ">". |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4911 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); | 4909 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); |
| 4912 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { | 4910 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { |
| 4913 if (CurrentToken() == Token::kCASE) { | 4911 if (CurrentToken() == Token::kCASE) { |
| 4914 if (default_seen) { | 4912 if (default_seen) { |
| 4915 ErrorMsg("default clause must be last case"); | 4913 ErrorMsg("default clause must be last case"); |
| 4916 } | 4914 } |
| 4917 ConsumeToken(); // Keyword case. | 4915 ConsumeToken(); // Keyword case. |
| 4918 const intptr_t expr_pos = TokenPos(); | 4916 const intptr_t expr_pos = TokenPos(); |
| 4919 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 4917 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 4920 AstNode* switch_expr_load = new LoadLocalNode(case_pos, | 4918 AstNode* switch_expr_load = new LoadLocalNode(case_pos, |
| 4921 *switch_expr_value); | 4919 switch_expr_value); |
| 4922 AstNode* case_comparison = new ComparisonNode(expr_pos, | 4920 AstNode* case_comparison = new ComparisonNode(expr_pos, |
| 4923 Token::kEQ, | 4921 Token::kEQ, |
| 4924 expr, | 4922 expr, |
| 4925 switch_expr_load); | 4923 switch_expr_load); |
| 4926 case_expressions->Add(case_comparison); | 4924 case_expressions->Add(case_comparison); |
| 4927 } else { | 4925 } else { |
| 4928 if (default_seen) { | 4926 if (default_seen) { |
| 4929 ErrorMsg("only one default clause is allowed"); | 4927 ErrorMsg("only one default clause is allowed"); |
| 4930 } | 4928 } |
| 4931 ConsumeToken(); // Keyword default. | 4929 ConsumeToken(); // Keyword default. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5002 OpenBlock(); | 5000 OpenBlock(); |
| 5003 current_block_->scope->AddLabel(label); | 5001 current_block_->scope->AddLabel(label); |
| 5004 | 5002 |
| 5005 // Store switch expression in temporary local variable. | 5003 // Store switch expression in temporary local variable. |
| 5006 LocalVariable* temp_variable = | 5004 LocalVariable* temp_variable = |
| 5007 new LocalVariable(expr_pos, | 5005 new LocalVariable(expr_pos, |
| 5008 String::ZoneHandle(Symbols::New(":switch_expr")), | 5006 String::ZoneHandle(Symbols::New(":switch_expr")), |
| 5009 Type::ZoneHandle(Type::DynamicType())); | 5007 Type::ZoneHandle(Type::DynamicType())); |
| 5010 current_block_->scope->AddVariable(temp_variable); | 5008 current_block_->scope->AddVariable(temp_variable); |
| 5011 AstNode* save_switch_expr = | 5009 AstNode* save_switch_expr = |
| 5012 new StoreLocalNode(expr_pos, *temp_variable, switch_expr); | 5010 new StoreLocalNode(expr_pos, temp_variable, switch_expr); |
| 5013 current_block_->statements->Add(save_switch_expr); | 5011 current_block_->statements->Add(save_switch_expr); |
| 5014 | 5012 |
| 5015 // Parse case clauses | 5013 // Parse case clauses |
| 5016 bool default_seen = false; | 5014 bool default_seen = false; |
| 5017 while (true) { | 5015 while (true) { |
| 5018 // Check for statement label | 5016 // Check for statement label |
| 5019 SourceLabel* case_label = NULL; | 5017 SourceLabel* case_label = NULL; |
| 5020 if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) { | 5018 if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) { |
| 5021 // Case statements start with a label. | 5019 // Case statements start with a label. |
| 5022 String* label_name = CurrentLiteral(); | 5020 String* label_name = CurrentLiteral(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5147 new LocalVariable(collection_pos, iterator_name, iterator_type); | 5145 new LocalVariable(collection_pos, iterator_name, iterator_type); |
| 5148 current_block_->scope->AddVariable(iterator_var); | 5146 current_block_->scope->AddVariable(iterator_var); |
| 5149 | 5147 |
| 5150 // Generate initialization of iterator variable. | 5148 // Generate initialization of iterator variable. |
| 5151 const String& iterator_method_name = | 5149 const String& iterator_method_name = |
| 5152 String::ZoneHandle(Symbols::GetIterator()); | 5150 String::ZoneHandle(Symbols::GetIterator()); |
| 5153 ArgumentListNode* no_args = new ArgumentListNode(collection_pos); | 5151 ArgumentListNode* no_args = new ArgumentListNode(collection_pos); |
| 5154 AstNode* get_iterator = new InstanceCallNode( | 5152 AstNode* get_iterator = new InstanceCallNode( |
| 5155 collection_pos, collection_expr, iterator_method_name, no_args); | 5153 collection_pos, collection_expr, iterator_method_name, no_args); |
| 5156 AstNode* iterator_init = | 5154 AstNode* iterator_init = |
| 5157 new StoreLocalNode(collection_pos, *iterator_var, get_iterator); | 5155 new StoreLocalNode(collection_pos, iterator_var, get_iterator); |
| 5158 current_block_->statements->Add(iterator_init); | 5156 current_block_->statements->Add(iterator_init); |
| 5159 | 5157 |
| 5160 // Generate while loop condition. | 5158 // Generate while loop condition. |
| 5161 AstNode* iterator_has_next = new InstanceCallNode( | 5159 AstNode* iterator_has_next = new InstanceCallNode( |
| 5162 collection_pos, | 5160 collection_pos, |
| 5163 new LoadLocalNode(collection_pos, *iterator_var), | 5161 new LoadLocalNode(collection_pos, iterator_var), |
| 5164 String::ZoneHandle(Symbols::HasNext()), | 5162 String::ZoneHandle(Symbols::HasNext()), |
| 5165 no_args); | 5163 no_args); |
| 5166 | 5164 |
| 5167 // Parse the for loop body. Ideally, we would use ParseNestedStatement() | 5165 // Parse the for loop body. Ideally, we would use ParseNestedStatement() |
| 5168 // here, but that does not work well because we have to insert an implicit | 5166 // here, but that does not work well because we have to insert an implicit |
| 5169 // variable assignment and potentially a variable declaration in the | 5167 // variable assignment and potentially a variable declaration in the |
| 5170 // loop body. | 5168 // loop body. |
| 5171 OpenLoopBlock(); | 5169 OpenLoopBlock(); |
| 5172 current_block_->scope->AddLabel(label); | 5170 current_block_->scope->AddLabel(label); |
| 5173 | 5171 |
| 5174 AstNode* iterator_next = new InstanceCallNode( | 5172 AstNode* iterator_next = new InstanceCallNode( |
| 5175 collection_pos, | 5173 collection_pos, |
| 5176 new LoadLocalNode(collection_pos, *iterator_var), | 5174 new LoadLocalNode(collection_pos, iterator_var), |
| 5177 String::ZoneHandle(Symbols::Next()), | 5175 String::ZoneHandle(Symbols::Next()), |
| 5178 no_args); | 5176 no_args); |
| 5179 | 5177 |
| 5180 // Generate assignment of next iterator value to loop variable. | 5178 // Generate assignment of next iterator value to loop variable. |
| 5181 AstNode* loop_var_assignment = NULL; | 5179 AstNode* loop_var_assignment = NULL; |
| 5182 if (loop_var != NULL) { | 5180 if (loop_var != NULL) { |
| 5183 // The for loop declares a new variable. Add it to the loop body scope. | 5181 // The for loop declares a new variable. Add it to the loop body scope. |
| 5184 current_block_->scope->AddVariable(loop_var); | 5182 current_block_->scope->AddVariable(loop_var); |
| 5185 loop_var_assignment = | 5183 loop_var_assignment = |
| 5186 new StoreLocalNode(loop_var_pos, *loop_var, iterator_next); | 5184 new StoreLocalNode(loop_var_pos, loop_var, iterator_next); |
| 5187 } else { | 5185 } else { |
| 5188 AstNode* loop_var_primary = | 5186 AstNode* loop_var_primary = |
| 5189 ResolveIdent(loop_var_pos, *loop_var_name, false); | 5187 ResolveIdent(loop_var_pos, *loop_var_name, false); |
| 5190 ASSERT(!loop_var_primary->IsPrimaryNode()); | 5188 ASSERT(!loop_var_primary->IsPrimaryNode()); |
| 5191 loop_var_assignment = | 5189 loop_var_assignment = |
| 5192 CreateAssignmentNode(loop_var_primary, iterator_next); | 5190 CreateAssignmentNode(loop_var_primary, iterator_next); |
| 5193 if (loop_var_assignment == NULL) { | 5191 if (loop_var_assignment == NULL) { |
| 5194 ErrorMsg(loop_var_pos, "variable or field '%s' is not assignable", | 5192 ErrorMsg(loop_var_pos, "variable or field '%s' is not assignable", |
| 5195 loop_var_name->ToCString()); | 5193 loop_var_name->ToCString()); |
| 5196 } | 5194 } |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5587 OpenBlock(); | 5585 OpenBlock(); |
| 5588 | 5586 |
| 5589 // Generate code to load the exception object (:exception_var) into | 5587 // Generate code to load the exception object (:exception_var) into |
| 5590 // the exception variable specified in this block. | 5588 // the exception variable specified in this block. |
| 5591 ASSERT(exception_param.var != NULL); | 5589 ASSERT(exception_param.var != NULL); |
| 5592 LocalVariable* var = LookupLocalScope(*exception_param.var); | 5590 LocalVariable* var = LookupLocalScope(*exception_param.var); |
| 5593 ASSERT(var != NULL); | 5591 ASSERT(var != NULL); |
| 5594 ASSERT(catch_excp_var != NULL); | 5592 ASSERT(catch_excp_var != NULL); |
| 5595 current_block_->statements->Add( | 5593 current_block_->statements->Add( |
| 5596 new StoreLocalNode(catch_pos, | 5594 new StoreLocalNode(catch_pos, |
| 5597 *var, | 5595 var, |
| 5598 new LoadLocalNode(catch_pos, *catch_excp_var))); | 5596 new LoadLocalNode(catch_pos, catch_excp_var))); |
| 5599 if (stack_trace_param.var != NULL) { | 5597 if (stack_trace_param.var != NULL) { |
| 5600 // A stack trace variable is specified in this block, so generate code | 5598 // A stack trace variable is specified in this block, so generate code |
| 5601 // to load the stack trace object (:stacktrace_var) into the stack trace | 5599 // to load the stack trace object (:stacktrace_var) into the stack trace |
| 5602 // variable specified in this block. | 5600 // variable specified in this block. |
| 5603 LocalVariable* trace = LookupLocalScope(*stack_trace_param.var); | 5601 LocalVariable* trace = LookupLocalScope(*stack_trace_param.var); |
| 5604 ASSERT(catch_trace_var != NULL); | 5602 ASSERT(catch_trace_var != NULL); |
| 5605 current_block_->statements->Add( | 5603 current_block_->statements->Add( |
| 5606 new StoreLocalNode(catch_pos, | 5604 new StoreLocalNode(catch_pos, |
| 5607 *trace, | 5605 trace, |
| 5608 new LoadLocalNode(catch_pos, *catch_trace_var))); | 5606 new LoadLocalNode(catch_pos, catch_trace_var))); |
| 5609 } | 5607 } |
| 5610 | 5608 |
| 5611 ParseStatementSequence(); // Parse the catch handler code. | 5609 ParseStatementSequence(); // Parse the catch handler code. |
| 5612 current_block_->statements->Add( | 5610 current_block_->statements->Add( |
| 5613 new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); | 5611 new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); |
| 5614 SequenceNode* catch_handler = CloseBlock(); | 5612 SequenceNode* catch_handler = CloseBlock(); |
| 5615 ExpectToken(Token::kRBRACE); | 5613 ExpectToken(Token::kRBRACE); |
| 5616 | 5614 |
| 5617 if (!exception_param.type->IsDynamicType()) { // Has a type specification. | 5615 if (!exception_param.type->IsDynamicType()) { // Has a type specification. |
| 5618 // Now form an 'if type check' as an exception type exists in | 5616 // Now form an 'if type check' as an exception type exists in |
| 5619 // the catch specifier. | 5617 // the catch specifier. |
| 5620 if (!exception_param.type->IsInstantiated() && | 5618 if (!exception_param.type->IsInstantiated() && |
| 5621 (current_block_->scope->function_level() > 0)) { | 5619 (current_block_->scope->function_level() > 0)) { |
| 5622 // Make sure that the instantiator is captured. | 5620 // Make sure that the instantiator is captured. |
| 5623 CaptureInstantiator(); | 5621 CaptureInstantiator(); |
| 5624 } | 5622 } |
| 5625 TypeNode* exception_type = new TypeNode(catch_pos, *exception_param.type); | 5623 TypeNode* exception_type = new TypeNode(catch_pos, *exception_param.type); |
| 5626 AstNode* exception_var = new LoadLocalNode(catch_pos, *catch_excp_var); | 5624 AstNode* exception_var = new LoadLocalNode(catch_pos, catch_excp_var); |
| 5627 if (!exception_type->type().IsInstantiated()) { | 5625 if (!exception_type->type().IsInstantiated()) { |
| 5628 EnsureExpressionTemp(); | 5626 EnsureExpressionTemp(); |
| 5629 } | 5627 } |
| 5630 AstNode* type_cond_expr = new ComparisonNode( | 5628 AstNode* type_cond_expr = new ComparisonNode( |
| 5631 catch_pos, Token::kIS, exception_var, exception_type); | 5629 catch_pos, Token::kIS, exception_var, exception_type); |
| 5632 current_block_->statements->Add( | 5630 current_block_->statements->Add( |
| 5633 new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); | 5631 new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); |
| 5634 } else { | 5632 } else { |
| 5635 // No exception type exists in the catch specifier so execute the | 5633 // No exception type exists in the catch specifier so execute the |
| 5636 // catch handler code unconditionally. | 5634 // catch handler code unconditionally. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5652 ConsumeToken(); // Consume the 'finally'. | 5650 ConsumeToken(); // Consume the 'finally'. |
| 5653 const intptr_t finally_pos = TokenPos(); | 5651 const intptr_t finally_pos = TokenPos(); |
| 5654 // Add the finally block to the exit points recorded so far. | 5652 // Add the finally block to the exit points recorded so far. |
| 5655 intptr_t node_index = 0; | 5653 intptr_t node_index = 0; |
| 5656 AstNode* node_to_inline = | 5654 AstNode* node_to_inline = |
| 5657 inner_try_block->GetNodeToInlineFinally(node_index); | 5655 inner_try_block->GetNodeToInlineFinally(node_index); |
| 5658 while (node_to_inline != NULL) { | 5656 while (node_to_inline != NULL) { |
| 5659 finally_block = ParseFinallyBlock(); | 5657 finally_block = ParseFinallyBlock(); |
| 5660 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, | 5658 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, |
| 5661 finally_block, | 5659 finally_block, |
| 5662 *context_var); | 5660 context_var); |
| 5663 AddFinallyBlockToNode(node_to_inline, node); | 5661 AddFinallyBlockToNode(node_to_inline, node); |
| 5664 node_index += 1; | 5662 node_index += 1; |
| 5665 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); | 5663 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); |
| 5666 tokens_iterator_.SetCurrentPosition(finally_pos); | 5664 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 5667 } | 5665 } |
| 5668 if (!generic_catch_seen) { | 5666 if (!generic_catch_seen) { |
| 5669 // No generic catch handler exists so execute this finally block | 5667 // No generic catch handler exists so execute this finally block |
| 5670 // before rethrowing the exception. | 5668 // before rethrowing the exception. |
| 5671 finally_block = ParseFinallyBlock(); | 5669 finally_block = ParseFinallyBlock(); |
| 5672 catch_handler_list->Add(finally_block); | 5670 catch_handler_list->Add(finally_block); |
| 5673 tokens_iterator_.SetCurrentPosition(finally_pos); | 5671 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 5674 } | 5672 } |
| 5675 finally_block = ParseFinallyBlock(); | 5673 finally_block = ParseFinallyBlock(); |
| 5676 } else { | 5674 } else { |
| 5677 if (!catch_seen) { | 5675 if (!catch_seen) { |
| 5678 ErrorMsg("'catch' or 'finally' expected"); | 5676 ErrorMsg("'catch' or 'finally' expected"); |
| 5679 } | 5677 } |
| 5680 } | 5678 } |
| 5681 | 5679 |
| 5682 if (!generic_catch_seen) { | 5680 if (!generic_catch_seen) { |
| 5683 // No generic catch handler exists so rethrow the exception so that | 5681 // No generic catch handler exists so rethrow the exception so that |
| 5684 // the next catch handler can deal with it. | 5682 // the next catch handler can deal with it. |
| 5685 catch_handler_list->Add( | 5683 catch_handler_list->Add( |
| 5686 new ThrowNode(handler_pos, | 5684 new ThrowNode(handler_pos, |
| 5687 new LoadLocalNode(handler_pos, *catch_excp_var), | 5685 new LoadLocalNode(handler_pos, catch_excp_var), |
| 5688 new LoadLocalNode(handler_pos, *catch_trace_var))); | 5686 new LoadLocalNode(handler_pos, catch_trace_var))); |
| 5689 } | 5687 } |
| 5690 CatchClauseNode* catch_block = new CatchClauseNode(handler_pos, | 5688 CatchClauseNode* catch_block = new CatchClauseNode(handler_pos, |
| 5691 catch_handler_list, | 5689 catch_handler_list, |
| 5692 *context_var, | 5690 context_var, |
| 5693 *catch_excp_var, | 5691 catch_excp_var, |
| 5694 *catch_trace_var); | 5692 catch_trace_var); |
| 5695 | 5693 |
| 5696 // Now create the try/catch ast node and return it. If there is a label | 5694 // Now create the try/catch ast node and return it. If there is a label |
| 5697 // on the try/catch, close the block that's embedding the try statement | 5695 // on the try/catch, close the block that's embedding the try statement |
| 5698 // and attach the label to it. | 5696 // and attach the label to it. |
| 5699 AstNode* try_catch_node = | 5697 AstNode* try_catch_node = |
| 5700 new TryCatchNode(try_pos, try_block, end_catch_label, | 5698 new TryCatchNode(try_pos, try_block, end_catch_label, |
| 5701 *context_var, catch_block, finally_block); | 5699 context_var, catch_block, finally_block); |
| 5702 | 5700 |
| 5703 if (try_label != NULL) { | 5701 if (try_label != NULL) { |
| 5704 current_block_->statements->Add(try_catch_node); | 5702 current_block_->statements->Add(try_catch_node); |
| 5705 SequenceNode* sequence = CloseBlock(); | 5703 SequenceNode* sequence = CloseBlock(); |
| 5706 sequence->set_label(try_label); | 5704 sequence->set_label(try_label); |
| 5707 try_catch_node = sequence; | 5705 try_catch_node = sequence; |
| 5708 } | 5706 } |
| 5709 return try_catch_node; | 5707 return try_catch_node; |
| 5710 } | 5708 } |
| 5711 | 5709 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5878 ASSERT(label->owner() != NULL); | 5876 ASSERT(label->owner() != NULL); |
| 5879 LocalScope* scope = label->owner()->parent(); | 5877 LocalScope* scope = label->owner()->parent(); |
| 5880 ASSERT(scope != NULL); | 5878 ASSERT(scope != NULL); |
| 5881 LocalVariable* excp_var = scope->LocalLookupVariable( | 5879 LocalVariable* excp_var = scope->LocalLookupVariable( |
| 5882 String::ZoneHandle(Symbols::ExceptionVar())); | 5880 String::ZoneHandle(Symbols::ExceptionVar())); |
| 5883 ASSERT(excp_var != NULL); | 5881 ASSERT(excp_var != NULL); |
| 5884 LocalVariable* trace_var = scope->LocalLookupVariable( | 5882 LocalVariable* trace_var = scope->LocalLookupVariable( |
| 5885 String::ZoneHandle(Symbols::StacktraceVar())); | 5883 String::ZoneHandle(Symbols::StacktraceVar())); |
| 5886 ASSERT(trace_var != NULL); | 5884 ASSERT(trace_var != NULL); |
| 5887 statement = new ThrowNode(statement_pos, | 5885 statement = new ThrowNode(statement_pos, |
| 5888 new LoadLocalNode(statement_pos, *excp_var), | 5886 new LoadLocalNode(statement_pos, excp_var), |
| 5889 new LoadLocalNode(statement_pos, *trace_var)); | 5887 new LoadLocalNode(statement_pos, trace_var)); |
| 5890 } | 5888 } |
| 5891 } else { | 5889 } else { |
| 5892 statement = ParseExpr(kAllowConst, kConsumeCascades); | 5890 statement = ParseExpr(kAllowConst, kConsumeCascades); |
| 5893 ExpectSemicolon(); | 5891 ExpectSemicolon(); |
| 5894 } | 5892 } |
| 5895 return statement; | 5893 return statement; |
| 5896 } | 5894 } |
| 5897 | 5895 |
| 5898 | 5896 |
| 5899 RawError* Parser::FormatErrorWithAppend(const Error& prev_error, | 5897 RawError* Parser::FormatErrorWithAppend(const Error& prev_error, |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6271 ConsumeToken(); | 6269 ConsumeToken(); |
| 6272 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 6270 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 6273 list->Add(expr); | 6271 list->Add(expr); |
| 6274 } | 6272 } |
| 6275 expressions = list; | 6273 expressions = list; |
| 6276 } | 6274 } |
| 6277 return expressions; | 6275 return expressions; |
| 6278 } | 6276 } |
| 6279 | 6277 |
| 6280 | 6278 |
| 6281 const LocalVariable& Parser::GetIncrementTempLocal() { | 6279 const LocalVariable* Parser::GetIncrementTempLocal() { |
| 6282 if (expression_temp_ == NULL) { | 6280 if (expression_temp_ == NULL) { |
| 6283 expression_temp_ = ParsedFunction::CreateExpressionTempVar( | 6281 expression_temp_ = ParsedFunction::CreateExpressionTempVar( |
| 6284 current_function().token_pos()); | 6282 current_function().token_pos()); |
| 6283 ASSERT(expression_temp_ != NULL); |
| 6285 } | 6284 } |
| 6286 return *expression_temp_; | 6285 return expression_temp_; |
| 6287 } | 6286 } |
| 6288 | 6287 |
| 6289 | 6288 |
| 6290 void Parser::EnsureExpressionTemp() { | 6289 void Parser::EnsureExpressionTemp() { |
| 6291 // Temporary used later by the flow_graph_builder. | 6290 // Temporary used later by the flow_graph_builder. |
| 6292 GetIncrementTempLocal(); | 6291 GetIncrementTempLocal(); |
| 6293 } | 6292 } |
| 6294 | 6293 |
| 6295 | 6294 |
| 6296 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos, | 6295 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6395 AstNode* node = *expr; | 6394 AstNode* node = *expr; |
| 6396 if (node->IsLoadIndexedNode()) { | 6395 if (node->IsLoadIndexedNode()) { |
| 6397 LoadIndexedNode* left_node = node->AsLoadIndexedNode(); | 6396 LoadIndexedNode* left_node = node->AsLoadIndexedNode(); |
| 6398 LoadIndexedNode* right_node = left_node; | 6397 LoadIndexedNode* right_node = left_node; |
| 6399 intptr_t token_pos = node->token_pos(); | 6398 intptr_t token_pos = node->token_pos(); |
| 6400 node = NULL; // Do not use it. | 6399 node = NULL; // Do not use it. |
| 6401 if (!IsSimpleLocalOrLiteralNode(left_node->array())) { | 6400 if (!IsSimpleLocalOrLiteralNode(left_node->array())) { |
| 6402 LocalVariable* temp = | 6401 LocalVariable* temp = |
| 6403 CreateTempConstVariable(token_pos, "lia"); | 6402 CreateTempConstVariable(token_pos, "lia"); |
| 6404 StoreLocalNode* save = | 6403 StoreLocalNode* save = |
| 6405 new StoreLocalNode(token_pos, *temp, left_node->array()); | 6404 new StoreLocalNode(token_pos, temp, left_node->array()); |
| 6406 left_node = | 6405 left_node = |
| 6407 new LoadIndexedNode(token_pos, save, left_node->index_expr()); | 6406 new LoadIndexedNode(token_pos, save, left_node->index_expr()); |
| 6408 right_node = new LoadIndexedNode(token_pos, | 6407 right_node = new LoadIndexedNode(token_pos, |
| 6409 new LoadLocalNode(token_pos, *temp), | 6408 new LoadLocalNode(token_pos, temp), |
| 6410 right_node->index_expr()); | 6409 right_node->index_expr()); |
| 6411 } | 6410 } |
| 6412 if (!IsSimpleLocalOrLiteralNode(left_node->index_expr())) { | 6411 if (!IsSimpleLocalOrLiteralNode(left_node->index_expr())) { |
| 6413 LocalVariable* temp = | 6412 LocalVariable* temp = |
| 6414 CreateTempConstVariable(token_pos, "lix"); | 6413 CreateTempConstVariable(token_pos, "lix"); |
| 6415 StoreLocalNode* save = | 6414 StoreLocalNode* save = |
| 6416 new StoreLocalNode(token_pos, *temp, left_node->index_expr()); | 6415 new StoreLocalNode(token_pos, temp, left_node->index_expr()); |
| 6417 left_node = new LoadIndexedNode(token_pos, | 6416 left_node = new LoadIndexedNode(token_pos, |
| 6418 left_node->array(), | 6417 left_node->array(), |
| 6419 save); | 6418 save); |
| 6420 right_node = new LoadIndexedNode(token_pos, | 6419 right_node = new LoadIndexedNode(token_pos, |
| 6421 right_node->array(), | 6420 right_node->array(), |
| 6422 new LoadLocalNode(token_pos, *temp)); | 6421 new LoadLocalNode(token_pos, temp)); |
| 6423 } | 6422 } |
| 6424 *expr = right_node; | 6423 *expr = right_node; |
| 6425 return left_node; | 6424 return left_node; |
| 6426 } | 6425 } |
| 6427 if (node->IsInstanceGetterNode()) { | 6426 if (node->IsInstanceGetterNode()) { |
| 6428 InstanceGetterNode* left_node = node->AsInstanceGetterNode(); | 6427 InstanceGetterNode* left_node = node->AsInstanceGetterNode(); |
| 6429 InstanceGetterNode* right_node = left_node; | 6428 InstanceGetterNode* right_node = left_node; |
| 6430 intptr_t token_pos = node->token_pos(); | 6429 intptr_t token_pos = node->token_pos(); |
| 6431 node = NULL; // Do not use it. | 6430 node = NULL; // Do not use it. |
| 6432 if (!IsSimpleLocalOrLiteralNode(left_node->receiver())) { | 6431 if (!IsSimpleLocalOrLiteralNode(left_node->receiver())) { |
| 6433 LocalVariable* temp = | 6432 LocalVariable* temp = |
| 6434 CreateTempConstVariable(token_pos, "igr"); | 6433 CreateTempConstVariable(token_pos, "igr"); |
| 6435 StoreLocalNode* save = | 6434 StoreLocalNode* save = |
| 6436 new StoreLocalNode(token_pos, *temp, left_node->receiver()); | 6435 new StoreLocalNode(token_pos, temp, left_node->receiver()); |
| 6437 left_node = new InstanceGetterNode(token_pos, | 6436 left_node = new InstanceGetterNode(token_pos, |
| 6438 save, | 6437 save, |
| 6439 left_node->field_name()); | 6438 left_node->field_name()); |
| 6440 right_node = new InstanceGetterNode(token_pos, | 6439 right_node = new InstanceGetterNode(token_pos, |
| 6441 new LoadLocalNode(token_pos, *temp), | 6440 new LoadLocalNode(token_pos, temp), |
| 6442 right_node->field_name()); | 6441 right_node->field_name()); |
| 6443 } | 6442 } |
| 6444 *expr = right_node; | 6443 *expr = right_node; |
| 6445 return left_node; | 6444 return left_node; |
| 6446 } | 6445 } |
| 6447 return *expr; | 6446 return *expr; |
| 6448 } | 6447 } |
| 6449 | 6448 |
| 6450 | 6449 |
| 6451 // Ensure that the expression temp is allocated for nodes that may need it. | 6450 // Ensure that the expression temp is allocated for nodes that may need it. |
| 6452 AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) { | 6451 AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) { |
| 6453 AstNode* result = original->MakeAssignmentNode(rhs); | 6452 AstNode* result = original->MakeAssignmentNode(rhs); |
| 6454 if ((result != NULL) && | 6453 if ((result != NULL) && |
| 6455 (result->IsStoreIndexedNode() || | 6454 (result->IsStoreIndexedNode() || |
| 6456 result->IsInstanceSetterNode() || | 6455 result->IsInstanceSetterNode() || |
| 6457 result->IsStaticSetterNode())) { | 6456 result->IsStaticSetterNode())) { |
| 6458 EnsureExpressionTemp(); | 6457 EnsureExpressionTemp(); |
| 6459 } | 6458 } |
| 6460 return result; | 6459 return result; |
| 6461 } | 6460 } |
| 6462 | 6461 |
| 6463 | 6462 |
| 6464 AstNode* Parser::ParseCascades(AstNode* expr) { | 6463 AstNode* Parser::ParseCascades(AstNode* expr) { |
| 6465 intptr_t cascade_pos = TokenPos(); | 6464 intptr_t cascade_pos = TokenPos(); |
| 6466 LocalVariable* cascade_receiver_var = | 6465 LocalVariable* cascade_receiver_var = |
| 6467 CreateTempConstVariable(cascade_pos, "casc"); | 6466 CreateTempConstVariable(cascade_pos, "casc"); |
| 6468 StoreLocalNode* save_cascade = | 6467 StoreLocalNode* save_cascade = |
| 6469 new StoreLocalNode(cascade_pos, *cascade_receiver_var, expr); | 6468 new StoreLocalNode(cascade_pos, cascade_receiver_var, expr); |
| 6470 current_block_->statements->Add(save_cascade); | 6469 current_block_->statements->Add(save_cascade); |
| 6471 while (CurrentToken() == Token::kCASCADE) { | 6470 while (CurrentToken() == Token::kCASCADE) { |
| 6472 cascade_pos = TokenPos(); | 6471 cascade_pos = TokenPos(); |
| 6473 LoadLocalNode* load_cascade_receiver = | 6472 LoadLocalNode* load_cascade_receiver = |
| 6474 new LoadLocalNode(cascade_pos, *cascade_receiver_var); | 6473 new LoadLocalNode(cascade_pos, cascade_receiver_var); |
| 6475 if (Token::IsIdentifier(LookaheadToken(1))) { | 6474 if (Token::IsIdentifier(LookaheadToken(1))) { |
| 6476 // Replace .. with . for ParseSelectors(). | 6475 // Replace .. with . for ParseSelectors(). |
| 6477 token_kind_ = Token::kPERIOD; | 6476 token_kind_ = Token::kPERIOD; |
| 6478 } else if (LookaheadToken(1) == Token::kLBRACK) { | 6477 } else if (LookaheadToken(1) == Token::kLBRACK) { |
| 6479 ConsumeToken(); | 6478 ConsumeToken(); |
| 6480 } else { | 6479 } else { |
| 6481 ErrorMsg("identifier or [ expected after .."); | 6480 ErrorMsg("identifier or [ expected after .."); |
| 6482 } | 6481 } |
| 6483 expr = ParseSelectors(load_cascade_receiver, true); | 6482 expr = ParseSelectors(load_cascade_receiver, true); |
| 6484 | 6483 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 6501 if (assign_expr == NULL) { | 6500 if (assign_expr == NULL) { |
| 6502 ErrorMsg(assignment_pos, | 6501 ErrorMsg(assignment_pos, |
| 6503 "left hand side of '%s' is not assignable", | 6502 "left hand side of '%s' is not assignable", |
| 6504 Token::Str(assignment_op)); | 6503 Token::Str(assignment_op)); |
| 6505 } | 6504 } |
| 6506 expr = assign_expr; | 6505 expr = assign_expr; |
| 6507 } | 6506 } |
| 6508 current_block_->statements->Add(expr); | 6507 current_block_->statements->Add(expr); |
| 6509 } | 6508 } |
| 6510 // Result of the cascade is the receiver. | 6509 // Result of the cascade is the receiver. |
| 6511 return new LoadLocalNode(cascade_pos, *cascade_receiver_var); | 6510 return new LoadLocalNode(cascade_pos, cascade_receiver_var); |
| 6512 } | 6511 } |
| 6513 | 6512 |
| 6514 | 6513 |
| 6515 AstNode* Parser::ParseExpr(bool require_compiletime_const, | 6514 AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| 6516 bool consume_cascades) { | 6515 bool consume_cascades) { |
| 6517 TRACE_PARSER("ParseExpr"); | 6516 TRACE_PARSER("ParseExpr"); |
| 6518 const intptr_t expr_pos = TokenPos(); | 6517 const intptr_t expr_pos = TokenPos(); |
| 6519 AstNode* expr = ParseConditionalExpr(); | 6518 AstNode* expr = ParseConditionalExpr(); |
| 6520 if (!Token::IsAssignmentOperator(CurrentToken())) { | 6519 if (!Token::IsAssignmentOperator(CurrentToken())) { |
| 6521 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { | 6520 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { |
| (...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7059 postfix_expr = ParseSelectors(postfix_expr, false); | 7058 postfix_expr = ParseSelectors(postfix_expr, false); |
| 7060 if (IsIncrementOperator(CurrentToken())) { | 7059 if (IsIncrementOperator(CurrentToken())) { |
| 7061 TRACE_PARSER("IncrementOperator"); | 7060 TRACE_PARSER("IncrementOperator"); |
| 7062 Token::Kind incr_op = CurrentToken(); | 7061 Token::Kind incr_op = CurrentToken(); |
| 7063 if (!IsAssignableExpr(postfix_expr)) { | 7062 if (!IsAssignableExpr(postfix_expr)) { |
| 7064 ErrorMsg("expression is not assignable"); | 7063 ErrorMsg("expression is not assignable"); |
| 7065 } | 7064 } |
| 7066 ConsumeToken(); | 7065 ConsumeToken(); |
| 7067 // Not prefix. | 7066 // Not prefix. |
| 7068 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr); | 7067 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr); |
| 7069 const LocalVariable& temp = GetIncrementTempLocal(); | 7068 const LocalVariable* temp = GetIncrementTempLocal(); |
| 7070 AstNode* save = | 7069 AstNode* save = |
| 7071 new StoreLocalNode(postfix_expr_pos, temp, postfix_expr); | 7070 new StoreLocalNode(postfix_expr_pos, temp, postfix_expr); |
| 7072 Token::Kind binary_op = | 7071 Token::Kind binary_op = |
| 7073 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; | 7072 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; |
| 7074 BinaryOpNode* add = new BinaryOpNode( | 7073 BinaryOpNode* add = new BinaryOpNode( |
| 7075 postfix_expr_pos, | 7074 postfix_expr_pos, |
| 7076 binary_op, | 7075 binary_op, |
| 7077 save, | 7076 save, |
| 7078 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1)))); | 7077 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1)))); |
| 7079 AstNode* store = CreateAssignmentNode(left_expr, add); | 7078 AstNode* store = CreateAssignmentNode(left_expr, add); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7373 // If node is non NULL return an AST node corresponding to the identifier. | 7372 // If node is non NULL return an AST node corresponding to the identifier. |
| 7374 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, | 7373 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, |
| 7375 const String &ident, | 7374 const String &ident, |
| 7376 AstNode** node) { | 7375 AstNode** node) { |
| 7377 TRACE_PARSER("ResolveIdentInLocalScope"); | 7376 TRACE_PARSER("ResolveIdentInLocalScope"); |
| 7378 Isolate* isolate = Isolate::Current(); | 7377 Isolate* isolate = Isolate::Current(); |
| 7379 // First try to find the identifier in the nested local scopes. | 7378 // First try to find the identifier in the nested local scopes. |
| 7380 LocalVariable* local = LookupLocalScope(ident); | 7379 LocalVariable* local = LookupLocalScope(ident); |
| 7381 if (local != NULL) { | 7380 if (local != NULL) { |
| 7382 if (node != NULL) { | 7381 if (node != NULL) { |
| 7383 *node = new LoadLocalNode(ident_pos, *local); | 7382 *node = new LoadLocalNode(ident_pos, local); |
| 7384 } | 7383 } |
| 7385 return true; | 7384 return true; |
| 7386 } | 7385 } |
| 7387 | 7386 |
| 7388 // Try to find the identifier in the class scope of the current class. | 7387 // Try to find the identifier in the class scope of the current class. |
| 7389 Class& cls = Class::Handle(isolate, current_class().raw()); | 7388 Class& cls = Class::Handle(isolate, current_class().raw()); |
| 7390 Function& func = Function::Handle(isolate, Function::null()); | 7389 Function& func = Function::Handle(isolate, Function::null()); |
| 7391 Field& field = Field::Handle(isolate, Field::null()); | 7390 Field& field = Field::Handle(isolate, Field::null()); |
| 7392 | 7391 |
| 7393 // First check if a field exists. | 7392 // First check if a field exists. |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7877 ArgumentListNode* arguments) { | 7876 ArgumentListNode* arguments) { |
| 7878 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { | 7877 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { |
| 7879 EnsureExpressionTemp(); | 7878 EnsureExpressionTemp(); |
| 7880 } | 7879 } |
| 7881 LocalVariable* allocated = | 7880 LocalVariable* allocated = |
| 7882 CreateTempConstVariable(token_pos, "alloc"); | 7881 CreateTempConstVariable(token_pos, "alloc"); |
| 7883 return new ConstructorCallNode(token_pos, | 7882 return new ConstructorCallNode(token_pos, |
| 7884 type_arguments, | 7883 type_arguments, |
| 7885 constructor, | 7884 constructor, |
| 7886 arguments, | 7885 arguments, |
| 7887 *allocated); | 7886 allocated); |
| 7888 } | 7887 } |
| 7889 | 7888 |
| 7890 | 7889 |
| 7891 static void AddKeyValuePair(ArrayNode* pairs, | 7890 static void AddKeyValuePair(ArrayNode* pairs, |
| 7892 bool is_const, | 7891 bool is_const, |
| 7893 AstNode* key, | 7892 AstNode* key, |
| 7894 AstNode* value) { | 7893 AstNode* value) { |
| 7895 if (is_const) { | 7894 if (is_const) { |
| 7896 ASSERT(key->IsLiteralNode()); | 7895 ASSERT(key->IsLiteralNode()); |
| 7897 ASSERT(key->AsLiteralNode()->literal().IsString()); | 7896 ASSERT(key->AsLiteralNode()->literal().IsString()); |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8577 primary = ResolveIdentInLibraryPrefixScope(*(qual_ident.lib_prefix), | 8576 primary = ResolveIdentInLibraryPrefixScope(*(qual_ident.lib_prefix), |
| 8578 qual_ident); | 8577 qual_ident); |
| 8579 } | 8578 } |
| 8580 ASSERT(primary != NULL); | 8579 ASSERT(primary != NULL); |
| 8581 } else if (CurrentToken() == Token::kTHIS) { | 8580 } else if (CurrentToken() == Token::kTHIS) { |
| 8582 const String& this_name = String::Handle(Symbols::This()); | 8581 const String& this_name = String::Handle(Symbols::This()); |
| 8583 LocalVariable* local = LookupLocalScope(this_name); | 8582 LocalVariable* local = LookupLocalScope(this_name); |
| 8584 if (local == NULL) { | 8583 if (local == NULL) { |
| 8585 ErrorMsg("receiver 'this' is not in scope"); | 8584 ErrorMsg("receiver 'this' is not in scope"); |
| 8586 } | 8585 } |
| 8587 primary = new LoadLocalNode(TokenPos(), *local); | 8586 primary = new LoadLocalNode(TokenPos(), local); |
| 8588 ConsumeToken(); | 8587 ConsumeToken(); |
| 8589 } else if (CurrentToken() == Token::kINTEGER) { | 8588 } else if (CurrentToken() == Token::kINTEGER) { |
| 8590 const Integer& literal = Integer::ZoneHandle(CurrentIntegerLiteral()); | 8589 const Integer& literal = Integer::ZoneHandle(CurrentIntegerLiteral()); |
| 8591 primary = new LiteralNode(TokenPos(), literal); | 8590 primary = new LiteralNode(TokenPos(), literal); |
| 8592 ConsumeToken(); | 8591 ConsumeToken(); |
| 8593 } else if (CurrentToken() == Token::kTRUE) { | 8592 } else if (CurrentToken() == Token::kTRUE) { |
| 8594 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::True())); | 8593 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::True())); |
| 8595 ConsumeToken(); | 8594 ConsumeToken(); |
| 8596 } else if (CurrentToken() == Token::kFALSE) { | 8595 } else if (CurrentToken() == Token::kFALSE) { |
| 8597 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::False())); | 8596 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::False())); |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8944 void Parser::SkipQualIdent() { | 8943 void Parser::SkipQualIdent() { |
| 8945 ASSERT(IsIdentifier()); | 8944 ASSERT(IsIdentifier()); |
| 8946 ConsumeToken(); | 8945 ConsumeToken(); |
| 8947 if (CurrentToken() == Token::kPERIOD) { | 8946 if (CurrentToken() == Token::kPERIOD) { |
| 8948 ConsumeToken(); // Consume the kPERIOD token. | 8947 ConsumeToken(); // Consume the kPERIOD token. |
| 8949 ExpectIdentifier("identifier expected after '.'"); | 8948 ExpectIdentifier("identifier expected after '.'"); |
| 8950 } | 8949 } |
| 8951 } | 8950 } |
| 8952 | 8951 |
| 8953 } // namespace dart | 8952 } // namespace dart |
| OLD | NEW |