| 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 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 const bool kTestOnly = true; | 716 const bool kTestOnly = true; |
| 717 if (parser.current_function().IsInFactoryScope()) { | 717 if (parser.current_function().IsInFactoryScope()) { |
| 718 instantiator = parser.LookupTypeArgumentsParameter(node_sequence->scope(), | 718 instantiator = parser.LookupTypeArgumentsParameter(node_sequence->scope(), |
| 719 kTestOnly); | 719 kTestOnly); |
| 720 } else { | 720 } else { |
| 721 instantiator = parser.LookupReceiver(node_sequence->scope(), kTestOnly); | 721 instantiator = parser.LookupReceiver(node_sequence->scope(), kTestOnly); |
| 722 } | 722 } |
| 723 if (!parser.current_function().IsLocalFunction() || | 723 if (!parser.current_function().IsLocalFunction() || |
| 724 ((instantiator != NULL) && instantiator->is_captured())) { | 724 ((instantiator != NULL) && instantiator->is_captured())) { |
| 725 parsed_function->set_instantiator( | 725 parsed_function->set_instantiator( |
| 726 new LoadLocalNode(node_sequence->token_pos(), *instantiator)); | 726 new LoadLocalNode(node_sequence->token_pos(), instantiator)); |
| 727 } | 727 } |
| 728 } | 728 } |
| 729 | 729 |
| 730 parsed_function->set_default_parameter_values(default_parameter_values); | 730 parsed_function->set_default_parameter_values(default_parameter_values); |
| 731 isolate->set_ast_node_id(prev_ast_node_id); | 731 isolate->set_ast_node_id(prev_ast_node_id); |
| 732 } | 732 } |
| 733 | 733 |
| 734 | 734 |
| 735 // TODO(regis): Implement support for non-const final static fields (currently | 735 // TODO(regis): Implement support for non-const final static fields (currently |
| 736 // supported "final" fields are actually const fields). | 736 // supported "final" fields are actually const fields). |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 ASSERT(func.num_fixed_parameters() == 1); // receiver. | 859 ASSERT(func.num_fixed_parameters() == 1); // receiver. |
| 860 ASSERT(func.num_optional_parameters() == 0); | 860 ASSERT(func.num_optional_parameters() == 0); |
| 861 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 861 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 862 | 862 |
| 863 // Build local scope for function and populate with the formal parameters. | 863 // Build local scope for function and populate with the formal parameters. |
| 864 OpenFunctionBlock(func); | 864 OpenFunctionBlock(func); |
| 865 AddFormalParamsToScope(¶ms, current_block_->scope); | 865 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 866 | 866 |
| 867 // Receiver is local 0. | 867 // Receiver is local 0. |
| 868 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 868 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
| 869 LoadLocalNode* load_receiver = new LoadLocalNode(TokenPos(), *receiver); | 869 LoadLocalNode* load_receiver = new LoadLocalNode(TokenPos(), receiver); |
| 870 // TokenPos() returns the function's token position which points to the | 870 // TokenPos() returns the function's token position which points to the |
| 871 // name of the field; | 871 // name of the field; |
| 872 ASSERT(IsIdentifier()); | 872 ASSERT(IsIdentifier()); |
| 873 const String& field_name = *CurrentLiteral(); | 873 const String& field_name = *CurrentLiteral(); |
| 874 const Class& field_class = Class::Handle(func.owner()); | 874 const Class& field_class = Class::Handle(func.owner()); |
| 875 const Field& field = | 875 const Field& field = |
| 876 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); | 876 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); |
| 877 | 877 |
| 878 LoadInstanceFieldNode* load_field = | 878 LoadInstanceFieldNode* load_field = |
| 879 new LoadInstanceFieldNode(TokenPos(), load_receiver, field); | 879 new LoadInstanceFieldNode(TokenPos(), load_receiver, field); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 907 &field_type); | 907 &field_type); |
| 908 ASSERT(func.num_fixed_parameters() == 2); // receiver, value. | 908 ASSERT(func.num_fixed_parameters() == 2); // receiver, value. |
| 909 ASSERT(func.num_optional_parameters() == 0); | 909 ASSERT(func.num_optional_parameters() == 0); |
| 910 ASSERT(AbstractType::Handle(func.result_type()).IsVoidType()); | 910 ASSERT(AbstractType::Handle(func.result_type()).IsVoidType()); |
| 911 | 911 |
| 912 // Build local scope for function and populate with the formal parameters. | 912 // Build local scope for function and populate with the formal parameters. |
| 913 OpenFunctionBlock(func); | 913 OpenFunctionBlock(func); |
| 914 AddFormalParamsToScope(¶ms, current_block_->scope); | 914 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 915 | 915 |
| 916 LoadLocalNode* receiver = | 916 LoadLocalNode* receiver = |
| 917 new LoadLocalNode(TokenPos(), *current_block_->scope->VariableAt(0)); | 917 new LoadLocalNode(TokenPos(), current_block_->scope->VariableAt(0)); |
| 918 LoadLocalNode* value = | 918 LoadLocalNode* value = |
| 919 new LoadLocalNode(TokenPos(), *current_block_->scope->VariableAt(1)); | 919 new LoadLocalNode(TokenPos(), current_block_->scope->VariableAt(1)); |
| 920 | 920 |
| 921 StoreInstanceFieldNode* store_field = | 921 StoreInstanceFieldNode* store_field = |
| 922 new StoreInstanceFieldNode(TokenPos(), receiver, field, value); | 922 new StoreInstanceFieldNode(TokenPos(), receiver, field, value); |
| 923 | 923 |
| 924 current_block_->statements->Add(store_field); | 924 current_block_->statements->Add(store_field); |
| 925 current_block_->statements->Add(new ReturnNode(TokenPos())); | 925 current_block_->statements->Add(new ReturnNode(TokenPos())); |
| 926 return CloseBlock(); | 926 return CloseBlock(); |
| 927 } | 927 } |
| 928 | 928 |
| 929 | 929 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1334 ExpectToken(Token::kRBRACK); | 1334 ExpectToken(Token::kRBRACK); |
| 1335 | 1335 |
| 1336 if (Token::IsAssignmentOperator(CurrentToken()) && | 1336 if (Token::IsAssignmentOperator(CurrentToken()) && |
| 1337 (CurrentToken() != Token::kASSIGN)) { | 1337 (CurrentToken() != Token::kASSIGN)) { |
| 1338 // Compound assignment. Ensure side effects in index expression | 1338 // Compound assignment. Ensure side effects in index expression |
| 1339 // only execute once. If the index is not a local variable or an | 1339 // only execute once. If the index is not a local variable or an |
| 1340 // literal, evaluate and save in a temporary local. | 1340 // literal, evaluate and save in a temporary local. |
| 1341 if (!IsSimpleLocalOrLiteralNode(index_expr)) { | 1341 if (!IsSimpleLocalOrLiteralNode(index_expr)) { |
| 1342 LocalVariable* temp = | 1342 LocalVariable* temp = |
| 1343 CreateTempConstVariable(operator_pos, index_expr->id(), "lix"); | 1343 CreateTempConstVariable(operator_pos, index_expr->id(), "lix"); |
| 1344 AstNode* save = | 1344 AstNode* save = new StoreLocalNode(operator_pos, temp, index_expr); |
| 1345 new StoreLocalNode(operator_pos, *temp, index_expr); | |
| 1346 current_block_->statements->Add(save); | 1345 current_block_->statements->Add(save); |
| 1347 index_expr = new LoadLocalNode(operator_pos, *temp); | 1346 index_expr = new LoadLocalNode(operator_pos, temp); |
| 1348 } | 1347 } |
| 1349 } | 1348 } |
| 1350 | 1349 |
| 1351 // Resolve the [] operator function in the superclass. | 1350 // Resolve the [] operator function in the superclass. |
| 1352 const String& index_operator_name = | 1351 const String& index_operator_name = |
| 1353 String::ZoneHandle(Symbols::IndexToken()); | 1352 String::ZoneHandle(Symbols::IndexToken()); |
| 1354 bool is_no_such_method = false; | 1353 bool is_no_such_method = false; |
| 1355 const Function& index_operator = Function::ZoneHandle( | 1354 const Function& index_operator = Function::ZoneHandle( |
| 1356 GetSuperFunction(operator_pos, | 1355 GetSuperFunction(operator_pos, |
| 1357 index_operator_name, | 1356 index_operator_name, |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1520 // we're not compiling class Object), or if the super class is an | 1519 // we're not compiling class Object), or if the super class is an |
| 1521 // artificially generated "wrapper class" that has no constructor. | 1520 // artificially generated "wrapper class" that has no constructor. |
| 1522 if (super_class.IsNull() || (super_class.num_native_fields() > 0)) { | 1521 if (super_class.IsNull() || (super_class.num_native_fields() > 0)) { |
| 1523 return; | 1522 return; |
| 1524 } | 1523 } |
| 1525 String& ctor_name = String::Handle(super_class.Name()); | 1524 String& ctor_name = String::Handle(super_class.Name()); |
| 1526 String& ctor_suffix = String::Handle(Symbols::Dot()); | 1525 String& ctor_suffix = String::Handle(Symbols::Dot()); |
| 1527 ctor_name = String::Concat(ctor_name, ctor_suffix); | 1526 ctor_name = String::Concat(ctor_name, ctor_suffix); |
| 1528 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); | 1527 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| 1529 // Implicit 'this' parameter is the first argument. | 1528 // Implicit 'this' parameter is the first argument. |
| 1530 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver); | 1529 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); |
| 1531 arguments->Add(implicit_argument); | 1530 arguments->Add(implicit_argument); |
| 1532 // Implicit construction phase parameter is second argument. | 1531 // Implicit construction phase parameter is second argument. |
| 1533 AstNode* phase_parameter = | 1532 AstNode* phase_parameter = |
| 1534 new LiteralNode(supercall_pos, | 1533 new LiteralNode(supercall_pos, |
| 1535 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 1534 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 1536 arguments->Add(phase_parameter); | 1535 arguments->Add(phase_parameter); |
| 1537 const Function& super_ctor = Function::ZoneHandle( | 1536 const Function& super_ctor = Function::ZoneHandle( |
| 1538 super_class.LookupConstructor(ctor_name)); | 1537 super_class.LookupConstructor(ctor_name)); |
| 1539 if (super_ctor.IsNull()) { | 1538 if (super_ctor.IsNull()) { |
| 1540 ErrorMsg(supercall_pos, | 1539 ErrorMsg(supercall_pos, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1571 ctor_suffix = String::Concat( | 1570 ctor_suffix = String::Concat( |
| 1572 ctor_suffix, *ExpectIdentifier("constructor name expected")); | 1571 ctor_suffix, *ExpectIdentifier("constructor name expected")); |
| 1573 } | 1572 } |
| 1574 ctor_name = String::Concat(ctor_name, ctor_suffix); | 1573 ctor_name = String::Concat(ctor_name, ctor_suffix); |
| 1575 if (CurrentToken() != Token::kLPAREN) { | 1574 if (CurrentToken() != Token::kLPAREN) { |
| 1576 ErrorMsg("parameter list expected"); | 1575 ErrorMsg("parameter list expected"); |
| 1577 } | 1576 } |
| 1578 | 1577 |
| 1579 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); | 1578 ArgumentListNode* arguments = new ArgumentListNode(supercall_pos); |
| 1580 // 'this' parameter is the first argument to super class constructor. | 1579 // 'this' parameter is the first argument to super class constructor. |
| 1581 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, *receiver); | 1580 AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver); |
| 1582 arguments->Add(implicit_argument); | 1581 arguments->Add(implicit_argument); |
| 1583 // Second implicit parameter is the construction phase. We optimistically | 1582 // Second implicit parameter is the construction phase. We optimistically |
| 1584 // assume that we can execute both the super initializer and the super | 1583 // assume that we can execute both the super initializer and the super |
| 1585 // constructor body. We may later change this to only execute the | 1584 // constructor body. We may later change this to only execute the |
| 1586 // super initializer. | 1585 // super initializer. |
| 1587 AstNode* phase_parameter = | 1586 AstNode* phase_parameter = |
| 1588 new LiteralNode(supercall_pos, | 1587 new LiteralNode(supercall_pos, |
| 1589 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 1588 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); |
| 1590 arguments->Add(phase_parameter); | 1589 arguments->Add(phase_parameter); |
| 1591 // 'this' parameter must not be accessible to the other super call arguments. | 1590 // '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... |
| 1632 receiver->set_invisible(true); | 1631 receiver->set_invisible(true); |
| 1633 AstNode* init_expr = ParseConditionalExpr(); | 1632 AstNode* init_expr = ParseConditionalExpr(); |
| 1634 receiver->set_invisible(false); | 1633 receiver->set_invisible(false); |
| 1635 SetAllowFunctionLiterals(saved_mode); | 1634 SetAllowFunctionLiterals(saved_mode); |
| 1636 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 1635 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 1637 if (field.IsNull()) { | 1636 if (field.IsNull()) { |
| 1638 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", | 1637 ErrorMsg(field_pos, "unresolved reference to instance field '%s'", |
| 1639 field_name.ToCString()); | 1638 field_name.ToCString()); |
| 1640 } | 1639 } |
| 1641 CheckDuplicateFieldInit(field_pos, initialized_fields, &field); | 1640 CheckDuplicateFieldInit(field_pos, initialized_fields, &field); |
| 1642 AstNode* instance = new LoadLocalNode(field_pos, *receiver); | 1641 AstNode* instance = new LoadLocalNode(field_pos, receiver); |
| 1643 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); | 1642 return new StoreInstanceFieldNode(field_pos, instance, field, init_expr); |
| 1644 } | 1643 } |
| 1645 | 1644 |
| 1646 | 1645 |
| 1647 void Parser::CheckConstFieldsInitialized(const Class& cls) { | 1646 void Parser::CheckConstFieldsInitialized(const Class& cls) { |
| 1648 const Array& fields = Array::Handle(cls.fields()); | 1647 const Array& fields = Array::Handle(cls.fields()); |
| 1649 Field& field = Field::Handle(); | 1648 Field& field = Field::Handle(); |
| 1650 SequenceNode* initializers = current_block_->statements; | 1649 SequenceNode* initializers = current_block_->statements; |
| 1651 for (int field_num = 0; field_num < fields.Length(); field_num++) { | 1650 for (int field_num = 0; field_num < fields.Length(); field_num++) { |
| 1652 field ^= fields.At(field_num); | 1651 field ^= fields.At(field_num); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1787 ctor_suffix = String::Concat( | 1786 ctor_suffix = String::Concat( |
| 1788 ctor_suffix, *ExpectIdentifier("constructor name expected")); | 1787 ctor_suffix, *ExpectIdentifier("constructor name expected")); |
| 1789 } | 1788 } |
| 1790 ctor_name = String::Concat(ctor_name, ctor_suffix); | 1789 ctor_name = String::Concat(ctor_name, ctor_suffix); |
| 1791 if (CurrentToken() != Token::kLPAREN) { | 1790 if (CurrentToken() != Token::kLPAREN) { |
| 1792 ErrorMsg("parameter list expected"); | 1791 ErrorMsg("parameter list expected"); |
| 1793 } | 1792 } |
| 1794 | 1793 |
| 1795 ArgumentListNode* arguments = new ArgumentListNode(call_pos); | 1794 ArgumentListNode* arguments = new ArgumentListNode(call_pos); |
| 1796 // 'this' parameter is the first argument to constructor. | 1795 // 'this' parameter is the first argument to constructor. |
| 1797 AstNode* implicit_argument = new LoadLocalNode(call_pos, *receiver); | 1796 AstNode* implicit_argument = new LoadLocalNode(call_pos, receiver); |
| 1798 arguments->Add(implicit_argument); | 1797 arguments->Add(implicit_argument); |
| 1799 // Construction phase parameter is second argument. | 1798 // Construction phase parameter is second argument. |
| 1800 LocalVariable* phase_param = LookupPhaseParameter(); | 1799 LocalVariable* phase_param = LookupPhaseParameter(); |
| 1801 ASSERT(phase_param != NULL); | 1800 ASSERT(phase_param != NULL); |
| 1802 AstNode* phase_argument = new LoadLocalNode(call_pos, *phase_param); | 1801 AstNode* phase_argument = new LoadLocalNode(call_pos, phase_param); |
| 1803 arguments->Add(phase_argument); | 1802 arguments->Add(phase_argument); |
| 1804 ParseActualParameters(arguments, kAllowConst); | 1803 ParseActualParameters(arguments, kAllowConst); |
| 1805 | 1804 |
| 1806 // Resolve the constructor. | 1805 // Resolve the constructor. |
| 1807 const Function& redirect_ctor = Function::ZoneHandle( | 1806 const Function& redirect_ctor = Function::ZoneHandle( |
| 1808 cls.LookupConstructor(ctor_name)); | 1807 cls.LookupConstructor(ctor_name)); |
| 1809 if (redirect_ctor.IsNull()) { | 1808 if (redirect_ctor.IsNull()) { |
| 1810 ErrorMsg(call_pos, "constructor '%s' not found", ctor_name.ToCString()); | 1809 ErrorMsg(call_pos, "constructor '%s' not found", ctor_name.ToCString()); |
| 1811 } | 1810 } |
| 1812 String& error_message = String::Handle(); | 1811 String& error_message = String::Handle(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 LocalVariable* phase_parameter = new LocalVariable( | 1846 LocalVariable* phase_parameter = new LocalVariable( |
| 1848 ctor_pos, | 1847 ctor_pos, |
| 1849 String::ZoneHandle(Symbols::PhaseParameter()), | 1848 String::ZoneHandle(Symbols::PhaseParameter()), |
| 1850 Type::ZoneHandle(Type::IntInterface())); | 1849 Type::ZoneHandle(Type::IntInterface())); |
| 1851 current_block_->scope->AddVariable(phase_parameter); | 1850 current_block_->scope->AddVariable(phase_parameter); |
| 1852 | 1851 |
| 1853 // Now that the "this" parameter is in scope, we can generate the code | 1852 // Now that the "this" parameter is in scope, we can generate the code |
| 1854 // to strore the initializer expressions in the respective instance fields. | 1853 // to strore the initializer expressions in the respective instance fields. |
| 1855 for (int i = 0; i < initializers.length(); i++) { | 1854 for (int i = 0; i < initializers.length(); i++) { |
| 1856 const Field* field = initializers[i].inst_field; | 1855 const Field* field = initializers[i].inst_field; |
| 1857 AstNode* instance = new LoadLocalNode(field->token_pos(), *receiver); | 1856 AstNode* instance = new LoadLocalNode(field->token_pos(), receiver); |
| 1858 AstNode* field_init = | 1857 AstNode* field_init = |
| 1859 new StoreInstanceFieldNode(field->token_pos(), | 1858 new StoreInstanceFieldNode(field->token_pos(), |
| 1860 instance, | 1859 instance, |
| 1861 *field, | 1860 *field, |
| 1862 initializers[i].expr); | 1861 initializers[i].expr); |
| 1863 current_block_->statements->Add(field_init); | 1862 current_block_->statements->Add(field_init); |
| 1864 } | 1863 } |
| 1865 | 1864 |
| 1866 GenerateSuperConstructorCall(cls, receiver); | 1865 GenerateSuperConstructorCall(cls, receiver); |
| 1867 CheckConstFieldsInitialized(cls); | 1866 CheckConstFieldsInitialized(cls); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 AddFormalParamsToScope(¶ms, current_block_->scope); | 1934 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 1936 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 1935 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
| 1937 | 1936 |
| 1938 // Now that the "this" parameter is in scope, we can generate the code | 1937 // Now that the "this" parameter is in scope, we can generate the code |
| 1939 // to store the initializer expressions in the respective instance fields. | 1938 // to store the initializer expressions in the respective instance fields. |
| 1940 // We do this before the field parameters and the initializers from the | 1939 // We do this before the field parameters and the initializers from the |
| 1941 // constructor's initializer list get compiled. | 1940 // constructor's initializer list get compiled. |
| 1942 OpenBlock(); | 1941 OpenBlock(); |
| 1943 for (int i = 0; i < initializers.length(); i++) { | 1942 for (int i = 0; i < initializers.length(); i++) { |
| 1944 const Field* field = initializers[i].inst_field; | 1943 const Field* field = initializers[i].inst_field; |
| 1945 AstNode* instance = new LoadLocalNode(field->token_pos(), *receiver); | 1944 AstNode* instance = new LoadLocalNode(field->token_pos(), receiver); |
| 1946 AstNode* field_init = | 1945 AstNode* field_init = |
| 1947 new StoreInstanceFieldNode(field->token_pos(), | 1946 new StoreInstanceFieldNode(field->token_pos(), |
| 1948 instance, | 1947 instance, |
| 1949 *field, | 1948 *field, |
| 1950 initializers[i].expr); | 1949 initializers[i].expr); |
| 1951 current_block_->statements->Add(field_init); | 1950 current_block_->statements->Add(field_init); |
| 1952 } | 1951 } |
| 1953 | 1952 |
| 1954 // Turn formal field parameters into field initializers or report error | 1953 // Turn formal field parameters into field initializers or report error |
| 1955 // if the function is not a constructor. | 1954 // if the function is not a constructor. |
| 1956 if (params.has_field_initializer) { | 1955 if (params.has_field_initializer) { |
| 1957 for (int i = 0; i < params.parameters->length(); i++) { | 1956 for (int i = 0; i < params.parameters->length(); i++) { |
| 1958 ParamDesc& param = (*params.parameters)[i]; | 1957 ParamDesc& param = (*params.parameters)[i]; |
| 1959 if (param.is_field_initializer) { | 1958 if (param.is_field_initializer) { |
| 1960 const String& field_name = *param.name; | 1959 const String& field_name = *param.name; |
| 1961 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); | 1960 Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name)); |
| 1962 if (field.IsNull()) { | 1961 if (field.IsNull()) { |
| 1963 ErrorMsg(param.name_pos, | 1962 ErrorMsg(param.name_pos, |
| 1964 "unresolved reference to instance field '%s'", | 1963 "unresolved reference to instance field '%s'", |
| 1965 field_name.ToCString()); | 1964 field_name.ToCString()); |
| 1966 } | 1965 } |
| 1967 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); | 1966 CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field); |
| 1968 AstNode* instance = new LoadLocalNode(param.name_pos, *receiver); | 1967 AstNode* instance = new LoadLocalNode(param.name_pos, receiver); |
| 1969 LocalVariable* p = | 1968 LocalVariable* p = |
| 1970 current_block_->scope->LookupVariable(*param.name, false); | 1969 current_block_->scope->LookupVariable(*param.name, false); |
| 1971 ASSERT(p != NULL); | 1970 ASSERT(p != NULL); |
| 1972 // Initializing formals cannot be used in the explicit initializer | 1971 // Initializing formals cannot be used in the explicit initializer |
| 1973 // list, nor can they be used in the constructor body. | 1972 // list, nor can they be used in the constructor body. |
| 1974 // Thus, make the parameter invisible. | 1973 // Thus, make the parameter invisible. |
| 1975 p->set_invisible(true); | 1974 p->set_invisible(true); |
| 1976 AstNode* value = new LoadLocalNode(param.name_pos, *p); | 1975 AstNode* value = new LoadLocalNode(param.name_pos, p); |
| 1977 AstNode* initializer = new StoreInstanceFieldNode( | 1976 AstNode* initializer = new StoreInstanceFieldNode( |
| 1978 param.name_pos, instance, field, value); | 1977 param.name_pos, instance, field, value); |
| 1979 current_block_->statements->Add(initializer); | 1978 current_block_->statements->Add(initializer); |
| 1980 } | 1979 } |
| 1981 } | 1980 } |
| 1982 } | 1981 } |
| 1983 | 1982 |
| 1984 // Now parse the explicit initializer list or constructor redirection. | 1983 // Now parse the explicit initializer list or constructor redirection. |
| 1985 ParseInitializers(cls, receiver, &initialized_fields); | 1984 ParseInitializers(cls, receiver, &initialized_fields); |
| 1986 | 1985 |
| 1987 SequenceNode* init_statements = CloseBlock(); | 1986 SequenceNode* init_statements = CloseBlock(); |
| 1988 if (init_statements->length() > 0) { | 1987 if (init_statements->length() > 0) { |
| 1989 // Generate guard around the initializer code. | 1988 // Generate guard around the initializer code. |
| 1990 LocalVariable* phase_param = LookupPhaseParameter(); | 1989 LocalVariable* phase_param = LookupPhaseParameter(); |
| 1991 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); | 1990 AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param); |
| 1992 AstNode* phase_check = new BinaryOpNode( | 1991 AstNode* phase_check = new BinaryOpNode( |
| 1993 TokenPos(), Token::kBIT_AND, phase_value, | 1992 TokenPos(), Token::kBIT_AND, phase_value, |
| 1994 new LiteralNode(TokenPos(), | 1993 new LiteralNode(TokenPos(), |
| 1995 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); | 1994 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| 1996 AstNode* comparison = | 1995 AstNode* comparison = |
| 1997 new ComparisonNode(TokenPos(), Token::kNE_STRICT, | 1996 new ComparisonNode(TokenPos(), Token::kNE_STRICT, |
| 1998 phase_check, | 1997 phase_check, |
| 1999 new LiteralNode(TokenPos(), | 1998 new LiteralNode(TokenPos(), |
| 2000 Smi::ZoneHandle(Smi::New(0)))); | 1999 Smi::ZoneHandle(Smi::New(0)))); |
| 2001 AstNode* guarded_init_statements = | 2000 AstNode* guarded_init_statements = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2031 // expressions are not evaluated twice. | 2030 // expressions are not evaluated twice. |
| 2032 ArgumentListNode* ctor_args = super_call->arguments(); | 2031 ArgumentListNode* ctor_args = super_call->arguments(); |
| 2033 // The super initializer call has at least 2 arguments: the | 2032 // The super initializer call has at least 2 arguments: the |
| 2034 // implicit receiver, and the hidden construction phase. | 2033 // implicit receiver, and the hidden construction phase. |
| 2035 ASSERT(ctor_args->length() >= 2); | 2034 ASSERT(ctor_args->length() >= 2); |
| 2036 for (int i = 2; i < ctor_args->length(); i++) { | 2035 for (int i = 2; i < ctor_args->length(); i++) { |
| 2037 AstNode* arg = ctor_args->NodeAt(i); | 2036 AstNode* arg = ctor_args->NodeAt(i); |
| 2038 if (!IsSimpleLocalOrLiteralNode(arg)) { | 2037 if (!IsSimpleLocalOrLiteralNode(arg)) { |
| 2039 LocalVariable* temp = | 2038 LocalVariable* temp = |
| 2040 CreateTempConstVariable(arg->token_pos(), arg->id(), "sca"); | 2039 CreateTempConstVariable(arg->token_pos(), arg->id(), "sca"); |
| 2041 AstNode* save_temp = | 2040 AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg); |
| 2042 new StoreLocalNode(arg->token_pos(), *temp, arg); | |
| 2043 ctor_args->SetNodeAt(i, save_temp); | 2041 ctor_args->SetNodeAt(i, save_temp); |
| 2044 } | 2042 } |
| 2045 } | 2043 } |
| 2046 } | 2044 } |
| 2047 OpenBlock(); // Block to collect constructor body nodes. | 2045 OpenBlock(); // Block to collect constructor body nodes. |
| 2048 | 2046 |
| 2049 // Insert the implicit super call to the super constructor body. | 2047 // Insert the implicit super call to the super constructor body. |
| 2050 if (super_call != NULL) { | 2048 if (super_call != NULL) { |
| 2051 ArgumentListNode* initializer_args = super_call->arguments(); | 2049 ArgumentListNode* initializer_args = super_call->arguments(); |
| 2052 const Function& super_ctor = super_call->function(); | 2050 const Function& super_ctor = super_call->function(); |
| 2053 // Patch the initializer call so it only executes the super initializer. | 2051 // Patch the initializer call so it only executes the super initializer. |
| 2054 initializer_args->SetNodeAt(1, | 2052 initializer_args->SetNodeAt(1, |
| 2055 new LiteralNode(TokenPos(), | 2053 new LiteralNode(TokenPos(), |
| 2056 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); | 2054 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit)))); |
| 2057 | 2055 |
| 2058 ArgumentListNode* super_call_args = new ArgumentListNode(TokenPos()); | 2056 ArgumentListNode* super_call_args = new ArgumentListNode(TokenPos()); |
| 2059 // First argument is the receiver. | 2057 // First argument is the receiver. |
| 2060 super_call_args->Add(new LoadLocalNode(TokenPos(), *receiver)); | 2058 super_call_args->Add(new LoadLocalNode(TokenPos(), receiver)); |
| 2061 // Second argument is the construction phase argument. | 2059 // Second argument is the construction phase argument. |
| 2062 AstNode* phase_parameter = | 2060 AstNode* phase_parameter = |
| 2063 new LiteralNode(TokenPos(), | 2061 new LiteralNode(TokenPos(), |
| 2064 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))); | 2062 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))); |
| 2065 super_call_args->Add(phase_parameter); | 2063 super_call_args->Add(phase_parameter); |
| 2066 super_call_args->set_names(initializer_args->names()); | 2064 super_call_args->set_names(initializer_args->names()); |
| 2067 for (int i = 2; i < initializer_args->length(); i++) { | 2065 for (int i = 2; i < initializer_args->length(); i++) { |
| 2068 AstNode* arg = initializer_args->NodeAt(i); | 2066 AstNode* arg = initializer_args->NodeAt(i); |
| 2069 if (arg->IsLiteralNode()) { | 2067 if (arg->IsLiteralNode()) { |
| 2070 LiteralNode* lit = arg->AsLiteralNode(); | 2068 LiteralNode* lit = arg->AsLiteralNode(); |
| 2071 super_call_args->Add(new LiteralNode(TokenPos(), lit->literal())); | 2069 super_call_args->Add(new LiteralNode(TokenPos(), lit->literal())); |
| 2072 } else { | 2070 } else { |
| 2073 ASSERT(arg->IsLoadLocalNode() || arg->IsStoreLocalNode()); | 2071 ASSERT(arg->IsLoadLocalNode() || arg->IsStoreLocalNode()); |
| 2074 if (arg->IsLoadLocalNode()) { | 2072 if (arg->IsLoadLocalNode()) { |
| 2075 const LocalVariable& temp = arg->AsLoadLocalNode()->local(); | 2073 const LocalVariable* temp = arg->AsLoadLocalNode()->local(); |
| 2076 super_call_args->Add(new LoadLocalNode(TokenPos(), temp)); | 2074 super_call_args->Add(new LoadLocalNode(TokenPos(), temp)); |
| 2077 } else if (arg->IsStoreLocalNode()) { | 2075 } else if (arg->IsStoreLocalNode()) { |
| 2078 const LocalVariable& temp = arg->AsStoreLocalNode()->local(); | 2076 const LocalVariable* temp = arg->AsStoreLocalNode()->local(); |
| 2079 super_call_args->Add(new LoadLocalNode(TokenPos(), temp)); | 2077 super_call_args->Add(new LoadLocalNode(TokenPos(), temp)); |
| 2080 } | 2078 } |
| 2081 } | 2079 } |
| 2082 } | 2080 } |
| 2083 ASSERT(super_ctor.AreValidArguments(super_call_args->length(), | 2081 ASSERT(super_ctor.AreValidArguments(super_call_args->length(), |
| 2084 super_call_args->names(), | 2082 super_call_args->names(), |
| 2085 NULL)); | 2083 NULL)); |
| 2086 current_block_->statements->Add( | 2084 current_block_->statements->Add( |
| 2087 new StaticCallNode(TokenPos(), super_ctor, super_call_args)); | 2085 new StaticCallNode(TokenPos(), super_ctor, super_call_args)); |
| 2088 } | 2086 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2099 // Some constructors have no function body. | 2097 // Some constructors have no function body. |
| 2100 ConsumeToken(); | 2098 ConsumeToken(); |
| 2101 } else { | 2099 } else { |
| 2102 UnexpectedToken(); | 2100 UnexpectedToken(); |
| 2103 } | 2101 } |
| 2104 | 2102 |
| 2105 SequenceNode* ctor_block = CloseBlock(); | 2103 SequenceNode* ctor_block = CloseBlock(); |
| 2106 if (ctor_block->length() > 0) { | 2104 if (ctor_block->length() > 0) { |
| 2107 // Generate guard around the constructor body code. | 2105 // Generate guard around the constructor body code. |
| 2108 LocalVariable* phase_param = LookupPhaseParameter(); | 2106 LocalVariable* phase_param = LookupPhaseParameter(); |
| 2109 AstNode* phase_value = new LoadLocalNode(TokenPos(), *phase_param); | 2107 AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param); |
| 2110 AstNode* phase_check = | 2108 AstNode* phase_check = |
| 2111 new BinaryOpNode(TokenPos(), Token::kBIT_AND, | 2109 new BinaryOpNode(TokenPos(), Token::kBIT_AND, |
| 2112 phase_value, | 2110 phase_value, |
| 2113 new LiteralNode(TokenPos(), | 2111 new LiteralNode(TokenPos(), |
| 2114 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody)))); | 2112 Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody)))); |
| 2115 AstNode* comparison = | 2113 AstNode* comparison = |
| 2116 new ComparisonNode(TokenPos(), Token::kNE_STRICT, | 2114 new ComparisonNode(TokenPos(), Token::kNE_STRICT, |
| 2117 phase_check, | 2115 phase_check, |
| 2118 new LiteralNode(TokenPos(), | 2116 new LiteralNode(TokenPos(), |
| 2119 Smi::ZoneHandle(Smi::New(0)))); | 2117 Smi::ZoneHandle(Smi::New(0)))); |
| (...skipping 2099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4219 | 4217 |
| 4220 | 4218 |
| 4221 AstNode* Parser::LoadReceiver(intptr_t token_pos) { | 4219 AstNode* Parser::LoadReceiver(intptr_t token_pos) { |
| 4222 // A nested function may access 'this', referring to the receiver of the | 4220 // A nested function may access 'this', referring to the receiver of the |
| 4223 // outermost enclosing function. | 4221 // outermost enclosing function. |
| 4224 const bool kTestOnly = false; | 4222 const bool kTestOnly = false; |
| 4225 LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly); | 4223 LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly); |
| 4226 if (receiver == NULL) { | 4224 if (receiver == NULL) { |
| 4227 ErrorMsg(token_pos, "illegal implicit access to receiver 'this'"); | 4225 ErrorMsg(token_pos, "illegal implicit access to receiver 'this'"); |
| 4228 } | 4226 } |
| 4229 return new LoadLocalNode(TokenPos(), *receiver); | 4227 return new LoadLocalNode(TokenPos(), receiver); |
| 4230 } | 4228 } |
| 4231 | 4229 |
| 4232 | 4230 |
| 4233 AstNode* Parser::LoadTypeArgumentsParameter(intptr_t token_pos) { | 4231 AstNode* Parser::LoadTypeArgumentsParameter(intptr_t token_pos) { |
| 4234 // A nested function may access ':type_arguments' to use as instantiator, | 4232 // A nested function may access ':type_arguments' to use as instantiator, |
| 4235 // referring to the implicit first parameter of the outermost enclosing | 4233 // referring to the implicit first parameter of the outermost enclosing |
| 4236 // factory function. | 4234 // factory function. |
| 4237 const bool kTestOnly = false; | 4235 const bool kTestOnly = false; |
| 4238 LocalVariable* param = LookupTypeArgumentsParameter(current_block_->scope, | 4236 LocalVariable* param = LookupTypeArgumentsParameter(current_block_->scope, |
| 4239 kTestOnly); | 4237 kTestOnly); |
| 4240 ASSERT(param != NULL); | 4238 ASSERT(param != NULL); |
| 4241 return new LoadLocalNode(TokenPos(), *param); | 4239 return new LoadLocalNode(TokenPos(), param); |
| 4242 } | 4240 } |
| 4243 | 4241 |
| 4244 | 4242 |
| 4245 AstNode* Parser::CallGetter(intptr_t token_pos, | 4243 AstNode* Parser::CallGetter(intptr_t token_pos, |
| 4246 AstNode* object, | 4244 AstNode* object, |
| 4247 const String& name) { | 4245 const String& name) { |
| 4248 return new InstanceGetterNode(TokenPos(), object, name); | 4246 return new InstanceGetterNode(TokenPos(), object, name); |
| 4249 } | 4247 } |
| 4250 | 4248 |
| 4251 | 4249 |
| 4252 // Returns ast nodes of the variable initialization. | 4250 // Returns ast nodes of the variable initialization. |
| 4253 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, | 4251 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, |
| 4254 bool is_final, | 4252 bool is_final, |
| 4255 bool is_const) { | 4253 bool is_const) { |
| 4256 TRACE_PARSER("ParseVariableDeclaration"); | 4254 TRACE_PARSER("ParseVariableDeclaration"); |
| 4257 ASSERT(IsIdentifier()); | 4255 ASSERT(IsIdentifier()); |
| 4258 const intptr_t ident_pos = TokenPos(); | 4256 const intptr_t ident_pos = TokenPos(); |
| 4259 LocalVariable* variable = | 4257 LocalVariable* variable = |
| 4260 new LocalVariable(ident_pos, *CurrentLiteral(), type); | 4258 new LocalVariable(ident_pos, *CurrentLiteral(), type); |
| 4261 ASSERT(current_block_ != NULL); | 4259 ASSERT(current_block_ != NULL); |
| 4262 ASSERT(current_block_->scope != NULL); | 4260 ASSERT(current_block_->scope != NULL); |
| 4263 ConsumeToken(); // Variable identifier. | 4261 ConsumeToken(); // Variable identifier. |
| 4264 AstNode* initialization = NULL; | 4262 AstNode* initialization = NULL; |
| 4265 if (CurrentToken() == Token::kASSIGN) { | 4263 if (CurrentToken() == Token::kASSIGN) { |
| 4266 // Variable initialization. | 4264 // Variable initialization. |
| 4267 const intptr_t assign_pos = TokenPos(); | 4265 const intptr_t assign_pos = TokenPos(); |
| 4268 ConsumeToken(); | 4266 ConsumeToken(); |
| 4269 AstNode* expr = ParseExpr(is_const, kConsumeCascades); | 4267 AstNode* expr = ParseExpr(is_const, kConsumeCascades); |
| 4270 initialization = new StoreLocalNode(assign_pos, *variable, expr); | 4268 initialization = new StoreLocalNode(assign_pos, variable, expr); |
| 4271 } else if (is_final || is_const) { | 4269 } else if (is_final || is_const) { |
| 4272 ErrorMsg(ident_pos, | 4270 ErrorMsg(ident_pos, |
| 4273 "missing initialization of 'final' or 'const' variable"); | 4271 "missing initialization of 'final' or 'const' variable"); |
| 4274 } else { | 4272 } else { |
| 4275 // Initialize variable with null. | 4273 // Initialize variable with null. |
| 4276 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); | 4274 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); |
| 4277 initialization = new StoreLocalNode(ident_pos, *variable, null_expr); | 4275 initialization = new StoreLocalNode(ident_pos, variable, null_expr); |
| 4278 } | 4276 } |
| 4279 // Add variable to scope after parsing the initalizer expression. | 4277 // Add variable to scope after parsing the initalizer expression. |
| 4280 // The expression must not be able to refer to the variable. | 4278 // The expression must not be able to refer to the variable. |
| 4281 if (!current_block_->scope->AddVariable(variable)) { | 4279 if (!current_block_->scope->AddVariable(variable)) { |
| 4282 ErrorMsg(ident_pos, "identifier '%s' already defined", | 4280 ErrorMsg(ident_pos, "identifier '%s' already defined", |
| 4283 variable->name().ToCString()); | 4281 variable->name().ToCString()); |
| 4284 } | 4282 } |
| 4285 if (is_final || is_const) { | 4283 if (is_final || is_const) { |
| 4286 variable->set_is_final(); | 4284 variable->set_is_final(); |
| 4287 } | 4285 } |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4543 // This pruning is done by omitting to hook the local scope in its parent | 4541 // This pruning is done by omitting to hook the local scope in its parent |
| 4544 // scope in the constructor of LocalScope. | 4542 // scope in the constructor of LocalScope. |
| 4545 AstNode* closure = | 4543 AstNode* closure = |
| 4546 new ClosureNode(ident_pos, function, NULL, statements->scope()); | 4544 new ClosureNode(ident_pos, function, NULL, statements->scope()); |
| 4547 | 4545 |
| 4548 if (function_variable == NULL) { | 4546 if (function_variable == NULL) { |
| 4549 ASSERT(is_literal); | 4547 ASSERT(is_literal); |
| 4550 return closure; | 4548 return closure; |
| 4551 } else { | 4549 } else { |
| 4552 AstNode* initialization = | 4550 AstNode* initialization = |
| 4553 new StoreLocalNode(ident_pos, *function_variable, closure); | 4551 new StoreLocalNode(ident_pos, function_variable, closure); |
| 4554 return initialization; | 4552 return initialization; |
| 4555 } | 4553 } |
| 4556 } | 4554 } |
| 4557 | 4555 |
| 4558 | 4556 |
| 4559 // Returns true if the current and next tokens can be parsed as type | 4557 // Returns true if the current and next tokens can be parsed as type |
| 4560 // parameters. Current token position is not saved and restored. | 4558 // parameters. Current token position is not saved and restored. |
| 4561 bool Parser::TryParseTypeParameter() { | 4559 bool Parser::TryParseTypeParameter() { |
| 4562 if (CurrentToken() == Token::kLT) { | 4560 if (CurrentToken() == Token::kLT) { |
| 4563 // We are possibly looking at type parameters. Find closing ">". | 4561 // We are possibly looking at type parameters. Find closing ">". |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4926 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); | 4924 SequenceNode* case_expressions = new SequenceNode(case_pos, NULL); |
| 4927 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { | 4925 while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) { |
| 4928 if (CurrentToken() == Token::kCASE) { | 4926 if (CurrentToken() == Token::kCASE) { |
| 4929 if (default_seen) { | 4927 if (default_seen) { |
| 4930 ErrorMsg("default clause must be last case"); | 4928 ErrorMsg("default clause must be last case"); |
| 4931 } | 4929 } |
| 4932 ConsumeToken(); // Keyword case. | 4930 ConsumeToken(); // Keyword case. |
| 4933 const intptr_t expr_pos = TokenPos(); | 4931 const intptr_t expr_pos = TokenPos(); |
| 4934 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 4932 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 4935 AstNode* switch_expr_load = new LoadLocalNode(case_pos, | 4933 AstNode* switch_expr_load = new LoadLocalNode(case_pos, |
| 4936 *switch_expr_value); | 4934 switch_expr_value); |
| 4937 AstNode* case_comparison = new ComparisonNode(expr_pos, | 4935 AstNode* case_comparison = new ComparisonNode(expr_pos, |
| 4938 Token::kEQ, | 4936 Token::kEQ, |
| 4939 expr, | 4937 expr, |
| 4940 switch_expr_load); | 4938 switch_expr_load); |
| 4941 case_expressions->Add(case_comparison); | 4939 case_expressions->Add(case_comparison); |
| 4942 } else { | 4940 } else { |
| 4943 if (default_seen) { | 4941 if (default_seen) { |
| 4944 ErrorMsg("only one default clause is allowed"); | 4942 ErrorMsg("only one default clause is allowed"); |
| 4945 } | 4943 } |
| 4946 ConsumeToken(); // Keyword default. | 4944 ConsumeToken(); // Keyword default. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5017 OpenBlock(); | 5015 OpenBlock(); |
| 5018 current_block_->scope->AddLabel(label); | 5016 current_block_->scope->AddLabel(label); |
| 5019 | 5017 |
| 5020 // Store switch expression in temporary local variable. | 5018 // Store switch expression in temporary local variable. |
| 5021 LocalVariable* temp_variable = | 5019 LocalVariable* temp_variable = |
| 5022 new LocalVariable(expr_pos, | 5020 new LocalVariable(expr_pos, |
| 5023 String::ZoneHandle(Symbols::New(":switch_expr")), | 5021 String::ZoneHandle(Symbols::New(":switch_expr")), |
| 5024 Type::ZoneHandle(Type::DynamicType())); | 5022 Type::ZoneHandle(Type::DynamicType())); |
| 5025 current_block_->scope->AddVariable(temp_variable); | 5023 current_block_->scope->AddVariable(temp_variable); |
| 5026 AstNode* save_switch_expr = | 5024 AstNode* save_switch_expr = |
| 5027 new StoreLocalNode(expr_pos, *temp_variable, switch_expr); | 5025 new StoreLocalNode(expr_pos, temp_variable, switch_expr); |
| 5028 current_block_->statements->Add(save_switch_expr); | 5026 current_block_->statements->Add(save_switch_expr); |
| 5029 | 5027 |
| 5030 // Parse case clauses | 5028 // Parse case clauses |
| 5031 bool default_seen = false; | 5029 bool default_seen = false; |
| 5032 while (true) { | 5030 while (true) { |
| 5033 // Check for statement label | 5031 // Check for statement label |
| 5034 SourceLabel* case_label = NULL; | 5032 SourceLabel* case_label = NULL; |
| 5035 if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) { | 5033 if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) { |
| 5036 // Case statements start with a label. | 5034 // Case statements start with a label. |
| 5037 String* label_name = CurrentLiteral(); | 5035 String* label_name = CurrentLiteral(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5162 new LocalVariable(collection_pos, iterator_name, iterator_type); | 5160 new LocalVariable(collection_pos, iterator_name, iterator_type); |
| 5163 current_block_->scope->AddVariable(iterator_var); | 5161 current_block_->scope->AddVariable(iterator_var); |
| 5164 | 5162 |
| 5165 // Generate initialization of iterator variable. | 5163 // Generate initialization of iterator variable. |
| 5166 const String& iterator_method_name = | 5164 const String& iterator_method_name = |
| 5167 String::ZoneHandle(Symbols::GetIterator()); | 5165 String::ZoneHandle(Symbols::GetIterator()); |
| 5168 ArgumentListNode* no_args = new ArgumentListNode(collection_pos); | 5166 ArgumentListNode* no_args = new ArgumentListNode(collection_pos); |
| 5169 AstNode* get_iterator = new InstanceCallNode( | 5167 AstNode* get_iterator = new InstanceCallNode( |
| 5170 collection_pos, collection_expr, iterator_method_name, no_args); | 5168 collection_pos, collection_expr, iterator_method_name, no_args); |
| 5171 AstNode* iterator_init = | 5169 AstNode* iterator_init = |
| 5172 new StoreLocalNode(collection_pos, *iterator_var, get_iterator); | 5170 new StoreLocalNode(collection_pos, iterator_var, get_iterator); |
| 5173 current_block_->statements->Add(iterator_init); | 5171 current_block_->statements->Add(iterator_init); |
| 5174 | 5172 |
| 5175 // Generate while loop condition. | 5173 // Generate while loop condition. |
| 5176 AstNode* iterator_has_next = new InstanceCallNode( | 5174 AstNode* iterator_has_next = new InstanceCallNode( |
| 5177 collection_pos, | 5175 collection_pos, |
| 5178 new LoadLocalNode(collection_pos, *iterator_var), | 5176 new LoadLocalNode(collection_pos, iterator_var), |
| 5179 String::ZoneHandle(Symbols::HasNext()), | 5177 String::ZoneHandle(Symbols::HasNext()), |
| 5180 no_args); | 5178 no_args); |
| 5181 | 5179 |
| 5182 // Parse the for loop body. Ideally, we would use ParseNestedStatement() | 5180 // Parse the for loop body. Ideally, we would use ParseNestedStatement() |
| 5183 // here, but that does not work well because we have to insert an implicit | 5181 // here, but that does not work well because we have to insert an implicit |
| 5184 // variable assignment and potentially a variable declaration in the | 5182 // variable assignment and potentially a variable declaration in the |
| 5185 // loop body. | 5183 // loop body. |
| 5186 OpenLoopBlock(); | 5184 OpenLoopBlock(); |
| 5187 current_block_->scope->AddLabel(label); | 5185 current_block_->scope->AddLabel(label); |
| 5188 | 5186 |
| 5189 AstNode* iterator_next = new InstanceCallNode( | 5187 AstNode* iterator_next = new InstanceCallNode( |
| 5190 collection_pos, | 5188 collection_pos, |
| 5191 new LoadLocalNode(collection_pos, *iterator_var), | 5189 new LoadLocalNode(collection_pos, iterator_var), |
| 5192 String::ZoneHandle(Symbols::Next()), | 5190 String::ZoneHandle(Symbols::Next()), |
| 5193 no_args); | 5191 no_args); |
| 5194 | 5192 |
| 5195 // Generate assignment of next iterator value to loop variable. | 5193 // Generate assignment of next iterator value to loop variable. |
| 5196 AstNode* loop_var_assignment = NULL; | 5194 AstNode* loop_var_assignment = NULL; |
| 5197 if (loop_var != NULL) { | 5195 if (loop_var != NULL) { |
| 5198 // The for loop declares a new variable. Add it to the loop body scope. | 5196 // The for loop declares a new variable. Add it to the loop body scope. |
| 5199 current_block_->scope->AddVariable(loop_var); | 5197 current_block_->scope->AddVariable(loop_var); |
| 5200 loop_var_assignment = | 5198 loop_var_assignment = |
| 5201 new StoreLocalNode(loop_var_pos, *loop_var, iterator_next); | 5199 new StoreLocalNode(loop_var_pos, loop_var, iterator_next); |
| 5202 } else { | 5200 } else { |
| 5203 AstNode* loop_var_primary = | 5201 AstNode* loop_var_primary = |
| 5204 ResolveIdent(loop_var_pos, *loop_var_name, false); | 5202 ResolveIdent(loop_var_pos, *loop_var_name, false); |
| 5205 ASSERT(!loop_var_primary->IsPrimaryNode()); | 5203 ASSERT(!loop_var_primary->IsPrimaryNode()); |
| 5206 loop_var_assignment = | 5204 loop_var_assignment = |
| 5207 CreateAssignmentNode(loop_var_primary, iterator_next); | 5205 CreateAssignmentNode(loop_var_primary, iterator_next); |
| 5208 if (loop_var_assignment == NULL) { | 5206 if (loop_var_assignment == NULL) { |
| 5209 ErrorMsg(loop_var_pos, "variable or field '%s' is not assignable", | 5207 ErrorMsg(loop_var_pos, "variable or field '%s' is not assignable", |
| 5210 loop_var_name->ToCString()); | 5208 loop_var_name->ToCString()); |
| 5211 } | 5209 } |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5602 OpenBlock(); | 5600 OpenBlock(); |
| 5603 | 5601 |
| 5604 // Generate code to load the exception object (:exception_var) into | 5602 // Generate code to load the exception object (:exception_var) into |
| 5605 // the exception variable specified in this block. | 5603 // the exception variable specified in this block. |
| 5606 ASSERT(exception_param.var != NULL); | 5604 ASSERT(exception_param.var != NULL); |
| 5607 LocalVariable* var = LookupLocalScope(*exception_param.var); | 5605 LocalVariable* var = LookupLocalScope(*exception_param.var); |
| 5608 ASSERT(var != NULL); | 5606 ASSERT(var != NULL); |
| 5609 ASSERT(catch_excp_var != NULL); | 5607 ASSERT(catch_excp_var != NULL); |
| 5610 current_block_->statements->Add( | 5608 current_block_->statements->Add( |
| 5611 new StoreLocalNode(catch_pos, | 5609 new StoreLocalNode(catch_pos, |
| 5612 *var, | 5610 var, |
| 5613 new LoadLocalNode(catch_pos, *catch_excp_var))); | 5611 new LoadLocalNode(catch_pos, catch_excp_var))); |
| 5614 if (stack_trace_param.var != NULL) { | 5612 if (stack_trace_param.var != NULL) { |
| 5615 // A stack trace variable is specified in this block, so generate code | 5613 // A stack trace variable is specified in this block, so generate code |
| 5616 // to load the stack trace object (:stacktrace_var) into the stack trace | 5614 // to load the stack trace object (:stacktrace_var) into the stack trace |
| 5617 // variable specified in this block. | 5615 // variable specified in this block. |
| 5618 LocalVariable* trace = LookupLocalScope(*stack_trace_param.var); | 5616 LocalVariable* trace = LookupLocalScope(*stack_trace_param.var); |
| 5619 ASSERT(catch_trace_var != NULL); | 5617 ASSERT(catch_trace_var != NULL); |
| 5620 current_block_->statements->Add( | 5618 current_block_->statements->Add( |
| 5621 new StoreLocalNode(catch_pos, | 5619 new StoreLocalNode(catch_pos, |
| 5622 *trace, | 5620 trace, |
| 5623 new LoadLocalNode(catch_pos, *catch_trace_var))); | 5621 new LoadLocalNode(catch_pos, catch_trace_var))); |
| 5624 } | 5622 } |
| 5625 | 5623 |
| 5626 ParseStatementSequence(); // Parse the catch handler code. | 5624 ParseStatementSequence(); // Parse the catch handler code. |
| 5627 current_block_->statements->Add( | 5625 current_block_->statements->Add( |
| 5628 new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); | 5626 new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label)); |
| 5629 SequenceNode* catch_handler = CloseBlock(); | 5627 SequenceNode* catch_handler = CloseBlock(); |
| 5630 ExpectToken(Token::kRBRACE); | 5628 ExpectToken(Token::kRBRACE); |
| 5631 | 5629 |
| 5632 if (!exception_param.type->IsDynamicType()) { // Has a type specification. | 5630 if (!exception_param.type->IsDynamicType()) { // Has a type specification. |
| 5633 // Now form an 'if type check' as an exception type exists in | 5631 // Now form an 'if type check' as an exception type exists in |
| 5634 // the catch specifier. | 5632 // the catch specifier. |
| 5635 if (!exception_param.type->IsInstantiated() && | 5633 if (!exception_param.type->IsInstantiated() && |
| 5636 (current_block_->scope->function_level() > 0)) { | 5634 (current_block_->scope->function_level() > 0)) { |
| 5637 // Make sure that the instantiator is captured. | 5635 // Make sure that the instantiator is captured. |
| 5638 CaptureInstantiator(); | 5636 CaptureInstantiator(); |
| 5639 } | 5637 } |
| 5640 TypeNode* exception_type = new TypeNode(catch_pos, *exception_param.type); | 5638 TypeNode* exception_type = new TypeNode(catch_pos, *exception_param.type); |
| 5641 AstNode* exception_var = new LoadLocalNode(catch_pos, *catch_excp_var); | 5639 AstNode* exception_var = new LoadLocalNode(catch_pos, catch_excp_var); |
| 5642 if (!exception_type->type().IsInstantiated()) { | 5640 if (!exception_type->type().IsInstantiated()) { |
| 5643 EnsureExpressionTemp(); | 5641 EnsureExpressionTemp(); |
| 5644 } | 5642 } |
| 5645 AstNode* type_cond_expr = new ComparisonNode( | 5643 AstNode* type_cond_expr = new ComparisonNode( |
| 5646 catch_pos, Token::kIS, exception_var, exception_type); | 5644 catch_pos, Token::kIS, exception_var, exception_type); |
| 5647 current_block_->statements->Add( | 5645 current_block_->statements->Add( |
| 5648 new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); | 5646 new IfNode(catch_pos, type_cond_expr, catch_handler, NULL)); |
| 5649 } else { | 5647 } else { |
| 5650 // No exception type exists in the catch specifier so execute the | 5648 // No exception type exists in the catch specifier so execute the |
| 5651 // catch handler code unconditionally. | 5649 // catch handler code unconditionally. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5667 ConsumeToken(); // Consume the 'finally'. | 5665 ConsumeToken(); // Consume the 'finally'. |
| 5668 const intptr_t finally_pos = TokenPos(); | 5666 const intptr_t finally_pos = TokenPos(); |
| 5669 // Add the finally block to the exit points recorded so far. | 5667 // Add the finally block to the exit points recorded so far. |
| 5670 intptr_t node_index = 0; | 5668 intptr_t node_index = 0; |
| 5671 AstNode* node_to_inline = | 5669 AstNode* node_to_inline = |
| 5672 inner_try_block->GetNodeToInlineFinally(node_index); | 5670 inner_try_block->GetNodeToInlineFinally(node_index); |
| 5673 while (node_to_inline != NULL) { | 5671 while (node_to_inline != NULL) { |
| 5674 finally_block = ParseFinallyBlock(); | 5672 finally_block = ParseFinallyBlock(); |
| 5675 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, | 5673 InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos, |
| 5676 finally_block, | 5674 finally_block, |
| 5677 *context_var); | 5675 context_var); |
| 5678 AddFinallyBlockToNode(node_to_inline, node); | 5676 AddFinallyBlockToNode(node_to_inline, node); |
| 5679 node_index += 1; | 5677 node_index += 1; |
| 5680 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); | 5678 node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index); |
| 5681 tokens_iterator_.SetCurrentPosition(finally_pos); | 5679 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 5682 } | 5680 } |
| 5683 if (!generic_catch_seen) { | 5681 if (!generic_catch_seen) { |
| 5684 // No generic catch handler exists so execute this finally block | 5682 // No generic catch handler exists so execute this finally block |
| 5685 // before rethrowing the exception. | 5683 // before rethrowing the exception. |
| 5686 finally_block = ParseFinallyBlock(); | 5684 finally_block = ParseFinallyBlock(); |
| 5687 catch_handler_list->Add(finally_block); | 5685 catch_handler_list->Add(finally_block); |
| 5688 tokens_iterator_.SetCurrentPosition(finally_pos); | 5686 tokens_iterator_.SetCurrentPosition(finally_pos); |
| 5689 } | 5687 } |
| 5690 finally_block = ParseFinallyBlock(); | 5688 finally_block = ParseFinallyBlock(); |
| 5691 } else { | 5689 } else { |
| 5692 if (!catch_seen) { | 5690 if (!catch_seen) { |
| 5693 ErrorMsg("'catch' or 'finally' expected"); | 5691 ErrorMsg("'catch' or 'finally' expected"); |
| 5694 } | 5692 } |
| 5695 } | 5693 } |
| 5696 | 5694 |
| 5697 if (!generic_catch_seen) { | 5695 if (!generic_catch_seen) { |
| 5698 // No generic catch handler exists so rethrow the exception so that | 5696 // No generic catch handler exists so rethrow the exception so that |
| 5699 // the next catch handler can deal with it. | 5697 // the next catch handler can deal with it. |
| 5700 catch_handler_list->Add( | 5698 catch_handler_list->Add( |
| 5701 new ThrowNode(handler_pos, | 5699 new ThrowNode(handler_pos, |
| 5702 new LoadLocalNode(handler_pos, *catch_excp_var), | 5700 new LoadLocalNode(handler_pos, catch_excp_var), |
| 5703 new LoadLocalNode(handler_pos, *catch_trace_var))); | 5701 new LoadLocalNode(handler_pos, catch_trace_var))); |
| 5704 } | 5702 } |
| 5705 CatchClauseNode* catch_block = new CatchClauseNode(handler_pos, | 5703 CatchClauseNode* catch_block = new CatchClauseNode(handler_pos, |
| 5706 catch_handler_list, | 5704 catch_handler_list, |
| 5707 *context_var, | 5705 context_var, |
| 5708 *catch_excp_var, | 5706 catch_excp_var, |
| 5709 *catch_trace_var); | 5707 catch_trace_var); |
| 5710 | 5708 |
| 5711 // Now create the try/catch ast node and return it. If there is a label | 5709 // Now create the try/catch ast node and return it. If there is a label |
| 5712 // on the try/catch, close the block that's embedding the try statement | 5710 // on the try/catch, close the block that's embedding the try statement |
| 5713 // and attach the label to it. | 5711 // and attach the label to it. |
| 5714 AstNode* try_catch_node = | 5712 AstNode* try_catch_node = |
| 5715 new TryCatchNode(try_pos, try_block, end_catch_label, | 5713 new TryCatchNode(try_pos, try_block, end_catch_label, |
| 5716 *context_var, catch_block, finally_block); | 5714 context_var, catch_block, finally_block); |
| 5717 | 5715 |
| 5718 if (try_label != NULL) { | 5716 if (try_label != NULL) { |
| 5719 current_block_->statements->Add(try_catch_node); | 5717 current_block_->statements->Add(try_catch_node); |
| 5720 SequenceNode* sequence = CloseBlock(); | 5718 SequenceNode* sequence = CloseBlock(); |
| 5721 sequence->set_label(try_label); | 5719 sequence->set_label(try_label); |
| 5722 try_catch_node = sequence; | 5720 try_catch_node = sequence; |
| 5723 } | 5721 } |
| 5724 return try_catch_node; | 5722 return try_catch_node; |
| 5725 } | 5723 } |
| 5726 | 5724 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5893 ASSERT(label->owner() != NULL); | 5891 ASSERT(label->owner() != NULL); |
| 5894 LocalScope* scope = label->owner()->parent(); | 5892 LocalScope* scope = label->owner()->parent(); |
| 5895 ASSERT(scope != NULL); | 5893 ASSERT(scope != NULL); |
| 5896 LocalVariable* excp_var = scope->LocalLookupVariable( | 5894 LocalVariable* excp_var = scope->LocalLookupVariable( |
| 5897 String::ZoneHandle(Symbols::ExceptionVar())); | 5895 String::ZoneHandle(Symbols::ExceptionVar())); |
| 5898 ASSERT(excp_var != NULL); | 5896 ASSERT(excp_var != NULL); |
| 5899 LocalVariable* trace_var = scope->LocalLookupVariable( | 5897 LocalVariable* trace_var = scope->LocalLookupVariable( |
| 5900 String::ZoneHandle(Symbols::StacktraceVar())); | 5898 String::ZoneHandle(Symbols::StacktraceVar())); |
| 5901 ASSERT(trace_var != NULL); | 5899 ASSERT(trace_var != NULL); |
| 5902 statement = new ThrowNode(statement_pos, | 5900 statement = new ThrowNode(statement_pos, |
| 5903 new LoadLocalNode(statement_pos, *excp_var), | 5901 new LoadLocalNode(statement_pos, excp_var), |
| 5904 new LoadLocalNode(statement_pos, *trace_var)); | 5902 new LoadLocalNode(statement_pos, trace_var)); |
| 5905 } | 5903 } |
| 5906 } else { | 5904 } else { |
| 5907 statement = ParseExpr(kAllowConst, kConsumeCascades); | 5905 statement = ParseExpr(kAllowConst, kConsumeCascades); |
| 5908 ExpectSemicolon(); | 5906 ExpectSemicolon(); |
| 5909 } | 5907 } |
| 5910 return statement; | 5908 return statement; |
| 5911 } | 5909 } |
| 5912 | 5910 |
| 5913 | 5911 |
| 5914 RawError* Parser::FormatErrorWithAppend(const Error& prev_error, | 5912 RawError* Parser::FormatErrorWithAppend(const Error& prev_error, |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6286 ConsumeToken(); | 6284 ConsumeToken(); |
| 6287 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 6285 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 6288 list->Add(expr); | 6286 list->Add(expr); |
| 6289 } | 6287 } |
| 6290 expressions = list; | 6288 expressions = list; |
| 6291 } | 6289 } |
| 6292 return expressions; | 6290 return expressions; |
| 6293 } | 6291 } |
| 6294 | 6292 |
| 6295 | 6293 |
| 6296 const LocalVariable& Parser::GetIncrementTempLocal() { | 6294 const LocalVariable* Parser::GetIncrementTempLocal() { |
| 6297 if (expression_temp_ == NULL) { | 6295 if (expression_temp_ == NULL) { |
| 6298 expression_temp_ = ParsedFunction::CreateExpressionTempVar( | 6296 expression_temp_ = ParsedFunction::CreateExpressionTempVar( |
| 6299 current_function().token_pos()); | 6297 current_function().token_pos()); |
| 6300 } | 6298 } |
| 6301 return *expression_temp_; | 6299 return expression_temp_; |
| 6302 } | 6300 } |
| 6303 | 6301 |
| 6304 | 6302 |
| 6305 void Parser::EnsureExpressionTemp() { | 6303 void Parser::EnsureExpressionTemp() { |
| 6306 // Temporary used later by the flow_graph_builder. | 6304 // Temporary used later by the flow_graph_builder. |
| 6307 GetIncrementTempLocal(); | 6305 GetIncrementTempLocal(); |
| 6308 } | 6306 } |
| 6309 | 6307 |
| 6310 | 6308 |
| 6311 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos, | 6309 LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos, |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6412 if (node->IsLoadIndexedNode()) { | 6410 if (node->IsLoadIndexedNode()) { |
| 6413 LoadIndexedNode* left_node = node->AsLoadIndexedNode(); | 6411 LoadIndexedNode* left_node = node->AsLoadIndexedNode(); |
| 6414 LoadIndexedNode* right_node = left_node; | 6412 LoadIndexedNode* right_node = left_node; |
| 6415 intptr_t node_id = node->id(); | 6413 intptr_t node_id = node->id(); |
| 6416 intptr_t token_pos = node->token_pos(); | 6414 intptr_t token_pos = node->token_pos(); |
| 6417 node = NULL; // Do not use it. | 6415 node = NULL; // Do not use it. |
| 6418 if (!IsSimpleLocalOrLiteralNode(left_node->array())) { | 6416 if (!IsSimpleLocalOrLiteralNode(left_node->array())) { |
| 6419 LocalVariable* temp = | 6417 LocalVariable* temp = |
| 6420 CreateTempConstVariable(token_pos, node_id, "lia"); | 6418 CreateTempConstVariable(token_pos, node_id, "lia"); |
| 6421 StoreLocalNode* save = | 6419 StoreLocalNode* save = |
| 6422 new StoreLocalNode(token_pos, *temp, left_node->array()); | 6420 new StoreLocalNode(token_pos, temp, left_node->array()); |
| 6423 left_node = | 6421 left_node = |
| 6424 new LoadIndexedNode(token_pos, save, left_node->index_expr()); | 6422 new LoadIndexedNode(token_pos, save, left_node->index_expr()); |
| 6425 right_node = new LoadIndexedNode(token_pos, | 6423 right_node = new LoadIndexedNode(token_pos, |
| 6426 new LoadLocalNode(token_pos, *temp), | 6424 new LoadLocalNode(token_pos, temp), |
| 6427 right_node->index_expr()); | 6425 right_node->index_expr()); |
| 6428 } | 6426 } |
| 6429 if (!IsSimpleLocalOrLiteralNode(left_node->index_expr())) { | 6427 if (!IsSimpleLocalOrLiteralNode(left_node->index_expr())) { |
| 6430 LocalVariable* temp = | 6428 LocalVariable* temp = |
| 6431 CreateTempConstVariable(token_pos, node_id, "lix"); | 6429 CreateTempConstVariable(token_pos, node_id, "lix"); |
| 6432 StoreLocalNode* save = | 6430 StoreLocalNode* save = |
| 6433 new StoreLocalNode(token_pos, *temp, left_node->index_expr()); | 6431 new StoreLocalNode(token_pos, temp, left_node->index_expr()); |
| 6434 left_node = new LoadIndexedNode(token_pos, | 6432 left_node = new LoadIndexedNode(token_pos, |
| 6435 left_node->array(), | 6433 left_node->array(), |
| 6436 save); | 6434 save); |
| 6437 right_node = new LoadIndexedNode(token_pos, | 6435 right_node = new LoadIndexedNode(token_pos, |
| 6438 right_node->array(), | 6436 right_node->array(), |
| 6439 new LoadLocalNode(token_pos, *temp)); | 6437 new LoadLocalNode(token_pos, temp)); |
| 6440 } | 6438 } |
| 6441 *expr = right_node; | 6439 *expr = right_node; |
| 6442 return left_node; | 6440 return left_node; |
| 6443 } | 6441 } |
| 6444 if (node->IsInstanceGetterNode()) { | 6442 if (node->IsInstanceGetterNode()) { |
| 6445 InstanceGetterNode* left_node = node->AsInstanceGetterNode(); | 6443 InstanceGetterNode* left_node = node->AsInstanceGetterNode(); |
| 6446 InstanceGetterNode* right_node = left_node; | 6444 InstanceGetterNode* right_node = left_node; |
| 6447 intptr_t node_id = node->id(); | 6445 intptr_t node_id = node->id(); |
| 6448 intptr_t token_pos = node->token_pos(); | 6446 intptr_t token_pos = node->token_pos(); |
| 6449 node = NULL; // Do not use it. | 6447 node = NULL; // Do not use it. |
| 6450 if (!IsSimpleLocalOrLiteralNode(left_node->receiver())) { | 6448 if (!IsSimpleLocalOrLiteralNode(left_node->receiver())) { |
| 6451 LocalVariable* temp = | 6449 LocalVariable* temp = |
| 6452 CreateTempConstVariable(token_pos, node_id, "igr"); | 6450 CreateTempConstVariable(token_pos, node_id, "igr"); |
| 6453 StoreLocalNode* save = | 6451 StoreLocalNode* save = |
| 6454 new StoreLocalNode(token_pos, *temp, left_node->receiver()); | 6452 new StoreLocalNode(token_pos, temp, left_node->receiver()); |
| 6455 left_node = new InstanceGetterNode(token_pos, | 6453 left_node = new InstanceGetterNode(token_pos, |
| 6456 save, | 6454 save, |
| 6457 left_node->field_name()); | 6455 left_node->field_name()); |
| 6458 right_node = new InstanceGetterNode(token_pos, | 6456 right_node = new InstanceGetterNode(token_pos, |
| 6459 new LoadLocalNode(token_pos, *temp), | 6457 new LoadLocalNode(token_pos, temp), |
| 6460 right_node->field_name()); | 6458 right_node->field_name()); |
| 6461 } | 6459 } |
| 6462 *expr = right_node; | 6460 *expr = right_node; |
| 6463 return left_node; | 6461 return left_node; |
| 6464 } | 6462 } |
| 6465 return *expr; | 6463 return *expr; |
| 6466 } | 6464 } |
| 6467 | 6465 |
| 6468 | 6466 |
| 6469 // Ensure that the expression temp is allocated for nodes that may need it. | 6467 // Ensure that the expression temp is allocated for nodes that may need it. |
| 6470 AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) { | 6468 AstNode* Parser::CreateAssignmentNode(AstNode* original, AstNode* rhs) { |
| 6471 AstNode* result = original->MakeAssignmentNode(rhs); | 6469 AstNode* result = original->MakeAssignmentNode(rhs); |
| 6472 if ((result != NULL) && | 6470 if ((result != NULL) && |
| 6473 (result->IsStoreIndexedNode() || result->IsInstanceSetterNode())) { | 6471 (result->IsStoreIndexedNode() || result->IsInstanceSetterNode())) { |
| 6474 EnsureExpressionTemp(); | 6472 EnsureExpressionTemp(); |
| 6475 } | 6473 } |
| 6476 return result; | 6474 return result; |
| 6477 } | 6475 } |
| 6478 | 6476 |
| 6479 | 6477 |
| 6480 AstNode* Parser::ParseCascades(AstNode* expr) { | 6478 AstNode* Parser::ParseCascades(AstNode* expr) { |
| 6481 intptr_t cascade_pos = TokenPos(); | 6479 intptr_t cascade_pos = TokenPos(); |
| 6482 LocalVariable* cascade_receiver_var = | 6480 LocalVariable* cascade_receiver_var = |
| 6483 CreateTempConstVariable(cascade_pos, expr->id(), "casc"); | 6481 CreateTempConstVariable(cascade_pos, expr->id(), "casc"); |
| 6484 StoreLocalNode* save_cascade = | 6482 StoreLocalNode* save_cascade = |
| 6485 new StoreLocalNode(cascade_pos, *cascade_receiver_var, expr); | 6483 new StoreLocalNode(cascade_pos, cascade_receiver_var, expr); |
| 6486 current_block_->statements->Add(save_cascade); | 6484 current_block_->statements->Add(save_cascade); |
| 6487 while (CurrentToken() == Token::kCASCADE) { | 6485 while (CurrentToken() == Token::kCASCADE) { |
| 6488 cascade_pos = TokenPos(); | 6486 cascade_pos = TokenPos(); |
| 6489 LoadLocalNode* load_cascade_receiver = | 6487 LoadLocalNode* load_cascade_receiver = |
| 6490 new LoadLocalNode(cascade_pos, *cascade_receiver_var); | 6488 new LoadLocalNode(cascade_pos, cascade_receiver_var); |
| 6491 if (Token::IsIdentifier(LookaheadToken(1))) { | 6489 if (Token::IsIdentifier(LookaheadToken(1))) { |
| 6492 // Replace .. with . for ParseSelectors(). | 6490 // Replace .. with . for ParseSelectors(). |
| 6493 token_kind_ = Token::kPERIOD; | 6491 token_kind_ = Token::kPERIOD; |
| 6494 } else if (LookaheadToken(1) == Token::kLBRACK) { | 6492 } else if (LookaheadToken(1) == Token::kLBRACK) { |
| 6495 ConsumeToken(); | 6493 ConsumeToken(); |
| 6496 } else { | 6494 } else { |
| 6497 ErrorMsg("identifier or [ expected after .."); | 6495 ErrorMsg("identifier or [ expected after .."); |
| 6498 } | 6496 } |
| 6499 expr = ParseSelectors(load_cascade_receiver, true); | 6497 expr = ParseSelectors(load_cascade_receiver, true); |
| 6500 | 6498 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 6517 if (assign_expr == NULL) { | 6515 if (assign_expr == NULL) { |
| 6518 ErrorMsg(assignment_pos, | 6516 ErrorMsg(assignment_pos, |
| 6519 "left hand side of '%s' is not assignable", | 6517 "left hand side of '%s' is not assignable", |
| 6520 Token::Str(assignment_op)); | 6518 Token::Str(assignment_op)); |
| 6521 } | 6519 } |
| 6522 expr = assign_expr; | 6520 expr = assign_expr; |
| 6523 } | 6521 } |
| 6524 current_block_->statements->Add(expr); | 6522 current_block_->statements->Add(expr); |
| 6525 } | 6523 } |
| 6526 // Result of the cascade is the receiver. | 6524 // Result of the cascade is the receiver. |
| 6527 return new LoadLocalNode(cascade_pos, *cascade_receiver_var); | 6525 return new LoadLocalNode(cascade_pos, cascade_receiver_var); |
| 6528 } | 6526 } |
| 6529 | 6527 |
| 6530 | 6528 |
| 6531 AstNode* Parser::ParseExpr(bool require_compiletime_const, | 6529 AstNode* Parser::ParseExpr(bool require_compiletime_const, |
| 6532 bool consume_cascades) { | 6530 bool consume_cascades) { |
| 6533 TRACE_PARSER("ParseExpr"); | 6531 TRACE_PARSER("ParseExpr"); |
| 6534 const intptr_t expr_pos = TokenPos(); | 6532 const intptr_t expr_pos = TokenPos(); |
| 6535 AstNode* expr = ParseConditionalExpr(); | 6533 AstNode* expr = ParseConditionalExpr(); |
| 6536 if (!Token::IsAssignmentOperator(CurrentToken())) { | 6534 if (!Token::IsAssignmentOperator(CurrentToken())) { |
| 6537 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { | 6535 if ((CurrentToken() == Token::kCASCADE) && consume_cascades) { |
| (...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7075 postfix_expr = ParseSelectors(postfix_expr, false); | 7073 postfix_expr = ParseSelectors(postfix_expr, false); |
| 7076 if (IsIncrementOperator(CurrentToken())) { | 7074 if (IsIncrementOperator(CurrentToken())) { |
| 7077 TRACE_PARSER("IncrementOperator"); | 7075 TRACE_PARSER("IncrementOperator"); |
| 7078 Token::Kind incr_op = CurrentToken(); | 7076 Token::Kind incr_op = CurrentToken(); |
| 7079 if (!IsAssignableExpr(postfix_expr)) { | 7077 if (!IsAssignableExpr(postfix_expr)) { |
| 7080 ErrorMsg("expression is not assignable"); | 7078 ErrorMsg("expression is not assignable"); |
| 7081 } | 7079 } |
| 7082 ConsumeToken(); | 7080 ConsumeToken(); |
| 7083 // Not prefix. | 7081 // Not prefix. |
| 7084 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr); | 7082 AstNode* left_expr = PrepareCompoundAssignmentNodes(&postfix_expr); |
| 7085 const LocalVariable& temp = GetIncrementTempLocal(); | 7083 const LocalVariable* temp = GetIncrementTempLocal(); |
| 7086 AstNode* save = | 7084 AstNode* save = |
| 7087 new StoreLocalNode(postfix_expr_pos, temp, postfix_expr); | 7085 new StoreLocalNode(postfix_expr_pos, temp, postfix_expr); |
| 7088 Token::Kind binary_op = | 7086 Token::Kind binary_op = |
| 7089 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; | 7087 (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB; |
| 7090 BinaryOpNode* add = new BinaryOpNode( | 7088 BinaryOpNode* add = new BinaryOpNode( |
| 7091 postfix_expr_pos, | 7089 postfix_expr_pos, |
| 7092 binary_op, | 7090 binary_op, |
| 7093 save, | 7091 save, |
| 7094 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1)))); | 7092 new LiteralNode(postfix_expr_pos, Smi::ZoneHandle(Smi::New(1)))); |
| 7095 AstNode* store = CreateAssignmentNode(left_expr, add); | 7093 AstNode* store = CreateAssignmentNode(left_expr, add); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7389 // If node is non NULL return an AST node corresponding to the identifier. | 7387 // If node is non NULL return an AST node corresponding to the identifier. |
| 7390 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, | 7388 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, |
| 7391 const String &ident, | 7389 const String &ident, |
| 7392 AstNode** node) { | 7390 AstNode** node) { |
| 7393 TRACE_PARSER("ResolveIdentInLocalScope"); | 7391 TRACE_PARSER("ResolveIdentInLocalScope"); |
| 7394 Isolate* isolate = Isolate::Current(); | 7392 Isolate* isolate = Isolate::Current(); |
| 7395 // First try to find the identifier in the nested local scopes. | 7393 // First try to find the identifier in the nested local scopes. |
| 7396 LocalVariable* local = LookupLocalScope(ident); | 7394 LocalVariable* local = LookupLocalScope(ident); |
| 7397 if (local != NULL) { | 7395 if (local != NULL) { |
| 7398 if (node != NULL) { | 7396 if (node != NULL) { |
| 7399 *node = new LoadLocalNode(ident_pos, *local); | 7397 *node = new LoadLocalNode(ident_pos, local); |
| 7400 } | 7398 } |
| 7401 return true; | 7399 return true; |
| 7402 } | 7400 } |
| 7403 | 7401 |
| 7404 // Try to find the identifier in the class scope of the current class. | 7402 // Try to find the identifier in the class scope of the current class. |
| 7405 Class& cls = Class::Handle(isolate, current_class().raw()); | 7403 Class& cls = Class::Handle(isolate, current_class().raw()); |
| 7406 Function& func = Function::Handle(isolate, Function::null()); | 7404 Function& func = Function::Handle(isolate, Function::null()); |
| 7407 Field& field = Field::Handle(isolate, Field::null()); | 7405 Field& field = Field::Handle(isolate, Field::null()); |
| 7408 | 7406 |
| 7409 // First check if a field exists. | 7407 // First check if a field exists. |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7893 ArgumentListNode* arguments) { | 7891 ArgumentListNode* arguments) { |
| 7894 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { | 7892 if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) { |
| 7895 EnsureExpressionTemp(); | 7893 EnsureExpressionTemp(); |
| 7896 } | 7894 } |
| 7897 LocalVariable* allocated = | 7895 LocalVariable* allocated = |
| 7898 CreateTempConstVariable(token_pos, token_pos, "alloc"); | 7896 CreateTempConstVariable(token_pos, token_pos, "alloc"); |
| 7899 return new ConstructorCallNode(token_pos, | 7897 return new ConstructorCallNode(token_pos, |
| 7900 type_arguments, | 7898 type_arguments, |
| 7901 constructor, | 7899 constructor, |
| 7902 arguments, | 7900 arguments, |
| 7903 *allocated); | 7901 allocated); |
| 7904 } | 7902 } |
| 7905 | 7903 |
| 7906 | 7904 |
| 7907 static void AddKeyValuePair(ArrayNode* pairs, | 7905 static void AddKeyValuePair(ArrayNode* pairs, |
| 7908 bool is_const, | 7906 bool is_const, |
| 7909 AstNode* key, | 7907 AstNode* key, |
| 7910 AstNode* value) { | 7908 AstNode* value) { |
| 7911 if (is_const) { | 7909 if (is_const) { |
| 7912 ASSERT(key->IsLiteralNode()); | 7910 ASSERT(key->IsLiteralNode()); |
| 7913 ASSERT(key->AsLiteralNode()->literal().IsString()); | 7911 ASSERT(key->AsLiteralNode()->literal().IsString()); |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8593 primary = ResolveIdentInLibraryPrefixScope(*(qual_ident.lib_prefix), | 8591 primary = ResolveIdentInLibraryPrefixScope(*(qual_ident.lib_prefix), |
| 8594 qual_ident); | 8592 qual_ident); |
| 8595 } | 8593 } |
| 8596 ASSERT(primary != NULL); | 8594 ASSERT(primary != NULL); |
| 8597 } else if (CurrentToken() == Token::kTHIS) { | 8595 } else if (CurrentToken() == Token::kTHIS) { |
| 8598 const String& this_name = String::Handle(Symbols::This()); | 8596 const String& this_name = String::Handle(Symbols::This()); |
| 8599 LocalVariable* local = LookupLocalScope(this_name); | 8597 LocalVariable* local = LookupLocalScope(this_name); |
| 8600 if (local == NULL) { | 8598 if (local == NULL) { |
| 8601 ErrorMsg("receiver 'this' is not in scope"); | 8599 ErrorMsg("receiver 'this' is not in scope"); |
| 8602 } | 8600 } |
| 8603 primary = new LoadLocalNode(TokenPos(), *local); | 8601 primary = new LoadLocalNode(TokenPos(), local); |
| 8604 ConsumeToken(); | 8602 ConsumeToken(); |
| 8605 } else if (CurrentToken() == Token::kINTEGER) { | 8603 } else if (CurrentToken() == Token::kINTEGER) { |
| 8606 const Integer& literal = Integer::ZoneHandle(CurrentIntegerLiteral()); | 8604 const Integer& literal = Integer::ZoneHandle(CurrentIntegerLiteral()); |
| 8607 primary = new LiteralNode(TokenPos(), literal); | 8605 primary = new LiteralNode(TokenPos(), literal); |
| 8608 ConsumeToken(); | 8606 ConsumeToken(); |
| 8609 } else if (CurrentToken() == Token::kTRUE) { | 8607 } else if (CurrentToken() == Token::kTRUE) { |
| 8610 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::True())); | 8608 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::True())); |
| 8611 ConsumeToken(); | 8609 ConsumeToken(); |
| 8612 } else if (CurrentToken() == Token::kFALSE) { | 8610 } else if (CurrentToken() == Token::kFALSE) { |
| 8613 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::False())); | 8611 primary = new LiteralNode(TokenPos(), Bool::ZoneHandle(Bool::False())); |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8960 void Parser::SkipQualIdent() { | 8958 void Parser::SkipQualIdent() { |
| 8961 ASSERT(IsIdentifier()); | 8959 ASSERT(IsIdentifier()); |
| 8962 ConsumeToken(); | 8960 ConsumeToken(); |
| 8963 if (CurrentToken() == Token::kPERIOD) { | 8961 if (CurrentToken() == Token::kPERIOD) { |
| 8964 ConsumeToken(); // Consume the kPERIOD token. | 8962 ConsumeToken(); // Consume the kPERIOD token. |
| 8965 ExpectIdentifier("identifier expected after '.'"); | 8963 ExpectIdentifier("identifier expected after '.'"); |
| 8966 } | 8964 } |
| 8967 } | 8965 } |
| 8968 | 8966 |
| 8969 } // namespace dart | 8967 } // namespace dart |
| OLD | NEW |