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 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2869 // instantiate types. | 2821 // instantiate types. |
2870 CaptureInstantiator(); | 2822 CaptureInstantiator(); |
2871 } | 2823 } |
2872 } | 2824 } |
2873 } | 2825 } |
2874 | 2826 |
2875 OpenBlock(); // Open a nested scope for the outermost function block. | 2827 OpenBlock(); // Open a nested scope for the outermost function block. |
2876 intptr_t end_token_pos = 0; | 2828 intptr_t end_token_pos = 0; |
2877 if (CurrentToken() == Token::kLBRACE) { | 2829 if (CurrentToken() == Token::kLBRACE) { |
2878 ConsumeToken(); | 2830 ConsumeToken(); |
2831 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { | |
2832 const Class& owner = Class::Handle(func.Owner()); | |
2833 if (!owner.IsObjectClass()) { | |
2834 AddEqualityNullCheck(); | |
2835 } | |
2836 } | |
2879 ParseStatementSequence(); | 2837 ParseStatementSequence(); |
2880 end_token_pos = TokenPos(); | 2838 end_token_pos = TokenPos(); |
2881 ExpectToken(Token::kRBRACE); | 2839 ExpectToken(Token::kRBRACE); |
2882 } else if (CurrentToken() == Token::kARROW) { | 2840 } else if (CurrentToken() == Token::kARROW) { |
2883 ConsumeToken(); | 2841 ConsumeToken(); |
2842 if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { | |
2843 const Class& owner = Class::Handle(func.Owner()); | |
2844 if (!owner.IsObjectClass()) { | |
2845 AddEqualityNullCheck(); | |
2846 } | |
2847 } | |
2884 const intptr_t expr_pos = TokenPos(); | 2848 const intptr_t expr_pos = TokenPos(); |
2885 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 2849 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
2886 ASSERT(expr != NULL); | 2850 ASSERT(expr != NULL); |
2887 current_block_->statements->Add(new ReturnNode(expr_pos, expr)); | 2851 current_block_->statements->Add(new ReturnNode(expr_pos, expr)); |
2888 end_token_pos = TokenPos(); | 2852 end_token_pos = TokenPos(); |
2889 } else if (IsLiteral("native")) { | 2853 } else if (IsLiteral("native")) { |
2890 ParseNativeFunctionBlock(¶ms, func); | 2854 ParseNativeFunctionBlock(¶ms, func); |
hausner
2013/09/25 16:36:11
This is a nit, but your scheme does not work for n
Florian Schneider
2013/09/26 11:34:21
Good point. Right now, native methods contain just
| |
2891 end_token_pos = TokenPos(); | 2855 end_token_pos = TokenPos(); |
2892 ExpectSemicolon(); | 2856 ExpectSemicolon(); |
2893 } else if (func.is_external()) { | 2857 } else if (func.is_external()) { |
2894 // Body of an external method contains a single throw. | 2858 // Body of an external method contains a single throw. |
2895 const String& function_name = String::ZoneHandle(func.name()); | 2859 const String& function_name = String::ZoneHandle(func.name()); |
2896 // TODO(regis): For an instance function, pass the receiver to | 2860 // TODO(regis): For an instance function, pass the receiver to |
2897 // NoSuchMethodError. | 2861 // NoSuchMethodError. |
2898 current_block_->statements->Add( | 2862 current_block_->statements->Add( |
2899 ThrowNoSuchMethodError(TokenPos(), | 2863 ThrowNoSuchMethodError(TokenPos(), |
2900 current_class(), | 2864 current_class(), |
(...skipping 12 matching lines...) Expand all Loading... | |
2913 func.end_token_pos() == end_token_pos); | 2877 func.end_token_pos() == end_token_pos); |
2914 func.set_end_token_pos(end_token_pos); | 2878 func.set_end_token_pos(end_token_pos); |
2915 SequenceNode* body = CloseBlock(); | 2879 SequenceNode* body = CloseBlock(); |
2916 current_block_->statements->Add(body); | 2880 current_block_->statements->Add(body); |
2917 innermost_function_ = saved_innermost_function.raw(); | 2881 innermost_function_ = saved_innermost_function.raw(); |
2918 last_used_try_index_ = saved_try_index; | 2882 last_used_try_index_ = saved_try_index; |
2919 return CloseBlock(); | 2883 return CloseBlock(); |
2920 } | 2884 } |
2921 | 2885 |
2922 | 2886 |
2887 void Parser::AddEqualityNullCheck() { | |
2888 const intptr_t token_pos = Scanner::kDummyTokenIndex; | |
2889 AstNode* argument = | |
2890 new LoadLocalNode(token_pos, | |
2891 current_block_->scope->parent()->VariableAt(1)); | |
2892 LiteralNode* null_operand = | |
2893 new LiteralNode(token_pos, Instance::ZoneHandle()); | |
2894 ComparisonNode* check_arg = new ComparisonNode(token_pos, | |
2895 Token::kEQ_STRICT, | |
2896 argument, | |
2897 null_operand); | |
2898 ComparisonNode* result = new ComparisonNode(token_pos, | |
2899 Token::kEQ_STRICT, | |
2900 LoadReceiver(token_pos), | |
2901 null_operand); | |
2902 SequenceNode* arg_is_null = new SequenceNode(token_pos, NULL); | |
2903 arg_is_null->Add(new ReturnNode(token_pos, result)); | |
2904 IfNode* if_arg_null = new IfNode(token_pos, | |
2905 check_arg, | |
2906 arg_is_null, | |
2907 NULL); | |
2908 current_block_->statements->Add(if_arg_null); | |
2909 } | |
2910 | |
2911 | |
2923 void Parser::SkipIf(Token::Kind token) { | 2912 void Parser::SkipIf(Token::Kind token) { |
2924 if (CurrentToken() == token) { | 2913 if (CurrentToken() == token) { |
2925 ConsumeToken(); | 2914 ConsumeToken(); |
2926 } | 2915 } |
2927 } | 2916 } |
2928 | 2917 |
2929 | 2918 |
2930 // Skips tokens up to matching closing parenthesis. | 2919 // Skips tokens up to matching closing parenthesis. |
2931 void Parser::SkipToMatchingParenthesis() { | 2920 void Parser::SkipToMatchingParenthesis() { |
2932 ASSERT(CurrentToken() == Token::kLPAREN); | 2921 ASSERT(CurrentToken() == Token::kLPAREN); |
(...skipping 7584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10517 void Parser::SkipQualIdent() { | 10506 void Parser::SkipQualIdent() { |
10518 ASSERT(IsIdentifier()); | 10507 ASSERT(IsIdentifier()); |
10519 ConsumeToken(); | 10508 ConsumeToken(); |
10520 if (CurrentToken() == Token::kPERIOD) { | 10509 if (CurrentToken() == Token::kPERIOD) { |
10521 ConsumeToken(); // Consume the kPERIOD token. | 10510 ConsumeToken(); // Consume the kPERIOD token. |
10522 ExpectIdentifier("identifier expected after '.'"); | 10511 ExpectIdentifier("identifier expected after '.'"); |
10523 } | 10512 } |
10524 } | 10513 } |
10525 | 10514 |
10526 } // namespace dart | 10515 } // namespace dart |
OLD | NEW |