OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1916 const Function& super_operator = Function::ZoneHandle( | 1916 const Function& super_operator = Function::ZoneHandle( |
1917 GetSuperFunction(operator_pos, | 1917 GetSuperFunction(operator_pos, |
1918 operator_function_name, | 1918 operator_function_name, |
1919 op_arguments, | 1919 op_arguments, |
1920 kResolveGetter, | 1920 kResolveGetter, |
1921 &is_no_such_method)); | 1921 &is_no_such_method)); |
1922 if (is_no_such_method) { | 1922 if (is_no_such_method) { |
1923 op_arguments = BuildNoSuchMethodArguments( | 1923 op_arguments = BuildNoSuchMethodArguments( |
1924 operator_pos, operator_function_name, *op_arguments); | 1924 operator_pos, operator_function_name, *op_arguments); |
1925 } | 1925 } |
1926 if (super_operator.name() == Symbols::EqualOperator().raw()) { | 1926 super_op = new StaticCallNode(operator_pos, super_operator, op_arguments); |
1927 // Expand super.== call to match correct == semantics into: | |
1928 // Let t1 = left, t2 = right { | |
1929 // (t1 === null || t2 === null) ? t1 === t2 | |
1930 // : static_call(super.==, t1, t2) | |
1931 // } | |
1932 // Normal == calls are not expanded at the AST level to produce | |
1933 // more compact code and enable more optimization opportunities. | |
1934 ASSERT(!is_no_such_method); // == is always found. | |
1935 EnsureExpressionTemp(); // Needed for ConditionalExprNode. | |
1936 LetNode* result = new LetNode(operator_pos); | |
1937 AstNode* left = | |
1938 new LoadLocalNode(operator_pos, | |
1939 result->AddInitializer(op_arguments->NodeAt(0))); | |
1940 AstNode* right = | |
1941 new LoadLocalNode(operator_pos, | |
1942 result->AddInitializer(op_arguments->NodeAt(1))); | |
1943 LiteralNode* null_operand = | |
1944 new LiteralNode(operator_pos, Instance::ZoneHandle()); | |
1945 ComparisonNode* is_left_null = new ComparisonNode(operator_pos, | |
1946 Token::kEQ_STRICT, | |
1947 left, | |
1948 null_operand); | |
1949 ComparisonNode* is_right_null = new ComparisonNode(operator_pos, | |
1950 Token::kEQ_STRICT, | |
1951 right, | |
1952 null_operand); | |
1953 BinaryOpNode* null_check = new BinaryOpNode(operator_pos, | |
1954 Token::kOR, | |
1955 is_left_null, | |
1956 is_right_null); | |
1957 ArgumentListNode* new_arguments = new ArgumentListNode(operator_pos); | |
1958 new_arguments->Add(left); | |
1959 new_arguments->Add(right); | |
1960 StaticCallNode* call = new StaticCallNode(operator_pos, | |
1961 super_operator, | |
1962 new_arguments); | |
1963 ComparisonNode* strict_eq = new ComparisonNode(operator_pos, | |
1964 Token::kEQ_STRICT, | |
1965 left, | |
1966 right); | |
1967 result->AddNode(new ConditionalExprNode(operator_pos, | |
1968 null_check, | |
1969 strict_eq, | |
1970 call)); | |
1971 super_op = result; | |
1972 } else { | |
1973 super_op = new StaticCallNode(operator_pos, super_operator, op_arguments); | |
1974 } | |
1975 if (negate_result) { | 1927 if (negate_result) { |
1976 super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op); | 1928 super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op); |
1977 } | 1929 } |
1978 } | 1930 } |
1979 return super_op; | 1931 return super_op; |
1980 } | 1932 } |
1981 | 1933 |
1982 | 1934 |
1983 AstNode* Parser::CreateImplicitClosureNode(const Function& func, | 1935 AstNode* Parser::CreateImplicitClosureNode(const Function& func, |
1984 intptr_t token_pos, | 1936 intptr_t token_pos, |
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2872 // instantiate types. | 2824 // instantiate types. |
2873 CaptureInstantiator(); | 2825 CaptureInstantiator(); |
2874 } | 2826 } |
2875 } | 2827 } |
2876 } | 2828 } |
2877 | 2829 |
2878 OpenBlock(); // Open a nested scope for the outermost function block. | 2830 OpenBlock(); // Open a nested scope for the outermost function block. |
2879 intptr_t end_token_pos = 0; | 2831 intptr_t end_token_pos = 0; |
2880 if (CurrentToken() == Token::kLBRACE) { | 2832 if (CurrentToken() == Token::kLBRACE) { |
2881 ConsumeToken(); | 2833 ConsumeToken(); |
| 2834 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { |
| 2835 const Class& owner = Class::Handle(func.Owner()); |
| 2836 if (!owner.IsObjectClass()) { |
| 2837 AddEqualityNullCheck(); |
| 2838 } |
| 2839 } |
2882 ParseStatementSequence(); | 2840 ParseStatementSequence(); |
2883 end_token_pos = TokenPos(); | 2841 end_token_pos = TokenPos(); |
2884 ExpectToken(Token::kRBRACE); | 2842 ExpectToken(Token::kRBRACE); |
2885 } else if (CurrentToken() == Token::kARROW) { | 2843 } else if (CurrentToken() == Token::kARROW) { |
2886 ConsumeToken(); | 2844 ConsumeToken(); |
| 2845 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { |
| 2846 const Class& owner = Class::Handle(func.Owner()); |
| 2847 if (!owner.IsObjectClass()) { |
| 2848 AddEqualityNullCheck(); |
| 2849 } |
| 2850 } |
2887 const intptr_t expr_pos = TokenPos(); | 2851 const intptr_t expr_pos = TokenPos(); |
2888 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 2852 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
2889 ASSERT(expr != NULL); | 2853 ASSERT(expr != NULL); |
2890 current_block_->statements->Add(new ReturnNode(expr_pos, expr)); | 2854 current_block_->statements->Add(new ReturnNode(expr_pos, expr)); |
2891 end_token_pos = TokenPos(); | 2855 end_token_pos = TokenPos(); |
2892 } else if (IsLiteral("native")) { | 2856 } else if (IsLiteral("native")) { |
| 2857 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { |
| 2858 const Class& owner = Class::Handle(func.Owner()); |
| 2859 if (!owner.IsObjectClass()) { |
| 2860 AddEqualityNullCheck(); |
| 2861 } |
| 2862 } |
2893 ParseNativeFunctionBlock(¶ms, func); | 2863 ParseNativeFunctionBlock(¶ms, func); |
2894 end_token_pos = TokenPos(); | 2864 end_token_pos = TokenPos(); |
2895 ExpectSemicolon(); | 2865 ExpectSemicolon(); |
2896 } else if (func.is_external()) { | 2866 } else if (func.is_external()) { |
2897 // Body of an external method contains a single throw. | 2867 // Body of an external method contains a single throw. |
2898 const String& function_name = String::ZoneHandle(func.name()); | 2868 const String& function_name = String::ZoneHandle(func.name()); |
2899 // TODO(regis): For an instance function, pass the receiver to | 2869 // TODO(regis): For an instance function, pass the receiver to |
2900 // NoSuchMethodError. | 2870 // NoSuchMethodError. |
2901 current_block_->statements->Add( | 2871 current_block_->statements->Add( |
2902 ThrowNoSuchMethodError(TokenPos(), | 2872 ThrowNoSuchMethodError(TokenPos(), |
(...skipping 14 matching lines...) Expand all Loading... |
2917 func.end_token_pos() == end_token_pos); | 2887 func.end_token_pos() == end_token_pos); |
2918 func.set_end_token_pos(end_token_pos); | 2888 func.set_end_token_pos(end_token_pos); |
2919 SequenceNode* body = CloseBlock(); | 2889 SequenceNode* body = CloseBlock(); |
2920 current_block_->statements->Add(body); | 2890 current_block_->statements->Add(body); |
2921 innermost_function_ = saved_innermost_function.raw(); | 2891 innermost_function_ = saved_innermost_function.raw(); |
2922 last_used_try_index_ = saved_try_index; | 2892 last_used_try_index_ = saved_try_index; |
2923 return CloseBlock(); | 2893 return CloseBlock(); |
2924 } | 2894 } |
2925 | 2895 |
2926 | 2896 |
| 2897 void Parser::AddEqualityNullCheck() { |
| 2898 const intptr_t token_pos = Scanner::kDummyTokenIndex; |
| 2899 AstNode* argument = |
| 2900 new LoadLocalNode(token_pos, |
| 2901 current_block_->scope->parent()->VariableAt(1)); |
| 2902 LiteralNode* null_operand = |
| 2903 new LiteralNode(token_pos, Instance::ZoneHandle()); |
| 2904 ComparisonNode* check_arg = new ComparisonNode(token_pos, |
| 2905 Token::kEQ_STRICT, |
| 2906 argument, |
| 2907 null_operand); |
| 2908 ComparisonNode* result = new ComparisonNode(token_pos, |
| 2909 Token::kEQ_STRICT, |
| 2910 LoadReceiver(token_pos), |
| 2911 null_operand); |
| 2912 SequenceNode* arg_is_null = new SequenceNode(token_pos, NULL); |
| 2913 arg_is_null->Add(new ReturnNode(token_pos, result)); |
| 2914 IfNode* if_arg_null = new IfNode(token_pos, |
| 2915 check_arg, |
| 2916 arg_is_null, |
| 2917 NULL); |
| 2918 current_block_->statements->Add(if_arg_null); |
| 2919 } |
| 2920 |
| 2921 |
2927 void Parser::SkipIf(Token::Kind token) { | 2922 void Parser::SkipIf(Token::Kind token) { |
2928 if (CurrentToken() == token) { | 2923 if (CurrentToken() == token) { |
2929 ConsumeToken(); | 2924 ConsumeToken(); |
2930 } | 2925 } |
2931 } | 2926 } |
2932 | 2927 |
2933 | 2928 |
2934 // Skips tokens up to matching closing parenthesis. | 2929 // Skips tokens up to matching closing parenthesis. |
2935 void Parser::SkipToMatchingParenthesis() { | 2930 void Parser::SkipToMatchingParenthesis() { |
2936 ASSERT(CurrentToken() == Token::kLPAREN); | 2931 ASSERT(CurrentToken() == Token::kLPAREN); |
(...skipping 7672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10609 void Parser::SkipQualIdent() { | 10604 void Parser::SkipQualIdent() { |
10610 ASSERT(IsIdentifier()); | 10605 ASSERT(IsIdentifier()); |
10611 ConsumeToken(); | 10606 ConsumeToken(); |
10612 if (CurrentToken() == Token::kPERIOD) { | 10607 if (CurrentToken() == Token::kPERIOD) { |
10613 ConsumeToken(); // Consume the kPERIOD token. | 10608 ConsumeToken(); // Consume the kPERIOD token. |
10614 ExpectIdentifier("identifier expected after '.'"); | 10609 ExpectIdentifier("identifier expected after '.'"); |
10615 } | 10610 } |
10616 } | 10611 } |
10617 | 10612 |
10618 } // namespace dart | 10613 } // namespace dart |
OLD | NEW |