Chromium Code Reviews| 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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 return &result; | 262 return &result; |
| 263 } | 263 } |
| 264 | 264 |
| 265 | 265 |
| 266 // A QualIdent is an optionally qualified identifier. | 266 // A QualIdent is an optionally qualified identifier. |
| 267 struct QualIdent { | 267 struct QualIdent { |
| 268 QualIdent() { | 268 QualIdent() { |
| 269 Clear(); | 269 Clear(); |
| 270 } | 270 } |
| 271 void Clear() { | 271 void Clear() { |
| 272 is_local_scope_ident = false; | |
| 273 lib_prefix = NULL; | 272 lib_prefix = NULL; |
| 274 qualifier = NULL; | 273 qualifier = NULL; |
| 275 ident_pos = 0; | 274 ident_pos = 0; |
| 276 ident = NULL; | 275 ident = NULL; |
| 277 } | 276 } |
| 278 bool is_local_scope_ident; | |
| 279 LibraryPrefix* lib_prefix; | 277 LibraryPrefix* lib_prefix; |
| 280 String* qualifier; | 278 String* qualifier; |
| 281 intptr_t ident_pos; | 279 intptr_t ident_pos; |
| 282 String* ident; | 280 String* ident; |
| 283 }; | 281 }; |
| 284 | 282 |
| 285 | 283 |
| 286 struct ParamDesc { | 284 struct ParamDesc { |
| 287 ParamDesc() | 285 ParamDesc() |
| 288 : type(NULL), | 286 : type(NULL), |
| (...skipping 1613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1902 SkipExpr(); | 1900 SkipExpr(); |
| 1903 SetAllowFunctionLiterals(true); | 1901 SetAllowFunctionLiterals(true); |
| 1904 } | 1902 } |
| 1905 } while (CurrentToken() == Token::kCOMMA); | 1903 } while (CurrentToken() == Token::kCOMMA); |
| 1906 } | 1904 } |
| 1907 | 1905 |
| 1908 | 1906 |
| 1909 void Parser::ParseQualIdent(QualIdent* qual_ident) { | 1907 void Parser::ParseQualIdent(QualIdent* qual_ident) { |
| 1910 ASSERT(IsIdentifier()); | 1908 ASSERT(IsIdentifier()); |
| 1911 if (!is_top_level_) { | 1909 if (!is_top_level_) { |
| 1912 AstNode* var_or_field = NULL; | |
| 1913 bool is_local_ident = ResolveIdentInLocalScope(token_index_, | |
| 1914 *CurrentLiteral(), | |
| 1915 &var_or_field); | |
| 1916 qual_ident->ident_pos = token_index_; | 1910 qual_ident->ident_pos = token_index_; |
| 1917 qual_ident->ident = CurrentLiteral(); | 1911 qual_ident->ident = CurrentLiteral(); |
| 1918 qual_ident->lib_prefix = NULL; | 1912 qual_ident->lib_prefix = NULL; |
| 1919 qual_ident->qualifier = NULL; | 1913 qual_ident->qualifier = NULL; |
| 1920 qual_ident->is_local_scope_ident = is_local_ident; | |
| 1921 ConsumeToken(); | 1914 ConsumeToken(); |
| 1922 if (!is_local_ident && (CurrentToken() == Token::kPERIOD)) { | 1915 if (CurrentToken() == Token::kPERIOD) { |
| 1923 LibraryPrefix& lib_prefix = LibraryPrefix::ZoneHandle(); | 1916 if (!ResolveIdentInLocalScope(qual_ident->ident_pos, |
| 1924 lib_prefix = current_class().LookupLibraryPrefix(*(qual_ident->ident)); | 1917 *(qual_ident->ident), |
| 1925 if (!lib_prefix.IsNull()) { | 1918 NULL)) { |
| 1926 // We have a library prefix qualified identifier. | 1919 LibraryPrefix& lib_prefix = LibraryPrefix::ZoneHandle(); |
| 1927 ConsumeToken(); // Consume the kPERIOD token. | 1920 lib_prefix = current_class().LookupLibraryPrefix(*(qual_ident->ident)); |
| 1928 qual_ident->lib_prefix = &lib_prefix; | 1921 if (!lib_prefix.IsNull()) { |
| 1929 qual_ident->qualifier = qual_ident->ident; | 1922 // We have a library prefix qualified identifier. |
| 1930 qual_ident->ident_pos = token_index_; | 1923 ConsumeToken(); // Consume the kPERIOD token. |
| 1931 qual_ident->ident = ExpectIdentifier("identifier expected after '.'"); | 1924 qual_ident->lib_prefix = &lib_prefix; |
| 1925 qual_ident->qualifier = qual_ident->ident; | |
| 1926 qual_ident->ident_pos = token_index_; | |
| 1927 qual_ident->ident = ExpectIdentifier("identifier expected after '.'"); | |
| 1928 } | |
| 1932 } | 1929 } |
| 1933 } | 1930 } |
| 1934 } else { | 1931 } else { |
| 1935 qual_ident->ident_pos = token_index_; | 1932 qual_ident->ident_pos = token_index_; |
| 1936 qual_ident->ident = CurrentLiteral(); | 1933 qual_ident->ident = CurrentLiteral(); |
| 1937 qual_ident->lib_prefix = NULL; | 1934 qual_ident->lib_prefix = NULL; |
| 1938 qual_ident->qualifier = NULL; | 1935 qual_ident->qualifier = NULL; |
| 1939 qual_ident->is_local_scope_ident = false; | |
| 1940 ConsumeToken(); | 1936 ConsumeToken(); |
| 1941 if (CurrentToken() == Token::kPERIOD) { | 1937 if (CurrentToken() == Token::kPERIOD) { |
| 1942 ConsumeToken(); // Consume the kPERIOD token. | 1938 ConsumeToken(); // Consume the kPERIOD token. |
| 1943 qual_ident->qualifier = qual_ident->ident; | 1939 qual_ident->qualifier = qual_ident->ident; |
| 1944 qual_ident->ident_pos = token_index_; | 1940 qual_ident->ident_pos = token_index_; |
| 1945 qual_ident->ident = ExpectIdentifier("identifier expected after '.'"); | 1941 qual_ident->ident = ExpectIdentifier("identifier expected after '.'"); |
| 1946 } | 1942 } |
| 1947 } | 1943 } |
| 1948 } | 1944 } |
| 1949 | 1945 |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2636 // and the alias name of a function type alias. | 2632 // and the alias name of a function type alias. |
| 2637 // Token position remains unchanged. | 2633 // Token position remains unchanged. |
| 2638 bool Parser::IsFunctionTypeAliasName() { | 2634 bool Parser::IsFunctionTypeAliasName() { |
| 2639 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { | 2635 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { |
| 2640 return true; | 2636 return true; |
| 2641 } | 2637 } |
| 2642 const intptr_t saved_pos = token_index_; | 2638 const intptr_t saved_pos = token_index_; |
| 2643 bool is_alias_name = false; | 2639 bool is_alias_name = false; |
| 2644 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { | 2640 if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) { |
| 2645 ConsumeToken(); | 2641 ConsumeToken(); |
| 2646 if (IsTypeParameter() && (CurrentToken() == Token::kLPAREN)) { | 2642 if (TryParseTypeParameter() && (CurrentToken() == Token::kLPAREN)) { |
| 2647 is_alias_name = true; | 2643 is_alias_name = true; |
| 2648 } | 2644 } |
| 2649 } | 2645 } |
| 2650 SetPosition(saved_pos); | 2646 SetPosition(saved_pos); |
| 2651 return is_alias_name; | 2647 return is_alias_name; |
| 2652 } | 2648 } |
| 2653 | 2649 |
| 2654 | 2650 |
| 2655 void Parser::ParseFunctionTypeAlias(GrowableArray<const Class*>* classes) { | 2651 void Parser::ParseFunctionTypeAlias(GrowableArray<const Class*>* classes) { |
| 2656 TRACE_PARSER("ParseFunctionTypeAlias"); | 2652 TRACE_PARSER("ParseFunctionTypeAlias"); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2789 if (CurrentToken() == Token::kFACTORY) { | 2785 if (CurrentToken() == Token::kFACTORY) { |
| 2790 Warning("'factory' is obsolete, use 'default' instead."); | 2786 Warning("'factory' is obsolete, use 'default' instead."); |
| 2791 } | 2787 } |
| 2792 ConsumeToken(); | 2788 ConsumeToken(); |
| 2793 if (CurrentToken() != Token::kIDENT) { | 2789 if (CurrentToken() != Token::kIDENT) { |
| 2794 ErrorMsg("class name expected"); | 2790 ErrorMsg("class name expected"); |
| 2795 } | 2791 } |
| 2796 const intptr_t factory_pos = token_index_; | 2792 const intptr_t factory_pos = token_index_; |
| 2797 QualIdent factory_name; | 2793 QualIdent factory_name; |
| 2798 ParseQualIdent(&factory_name); | 2794 ParseQualIdent(&factory_name); |
| 2799 if (factory_name.is_local_scope_ident) { | |
| 2800 ErrorMsg(factory_pos, | |
| 2801 "using '%s' in this context is invalid", | |
| 2802 factory_name.ident->ToCString()); | |
| 2803 } | |
| 2804 String& qualifier = String::Handle(); | 2795 String& qualifier = String::Handle(); |
| 2805 if (factory_name.qualifier != NULL) { | 2796 if (factory_name.qualifier != NULL) { |
| 2806 qualifier ^= factory_name.qualifier->raw(); | 2797 qualifier ^= factory_name.qualifier->raw(); |
| 2807 } | 2798 } |
| 2808 const UnresolvedClass& unresolved_factory_class = UnresolvedClass::Handle( | 2799 const UnresolvedClass& unresolved_factory_class = UnresolvedClass::Handle( |
| 2809 UnresolvedClass::New(factory_pos, qualifier, *(factory_name.ident))); | 2800 UnresolvedClass::New(factory_pos, qualifier, *(factory_name.ident))); |
| 2810 const Class& factory_class = Class::Handle( | 2801 const Class& factory_class = Class::Handle( |
| 2811 Class::New(String::Handle(String::NewSymbol(":factory_signature")), | 2802 Class::New(String::Handle(String::NewSymbol(":factory_signature")), |
| 2812 script_)); | 2803 script_)); |
| 2813 factory_class.set_library(library_); | 2804 factory_class.set_library(library_); |
| (...skipping 1095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3909 } else { | 3900 } else { |
| 3910 AstNode* initialization = | 3901 AstNode* initialization = |
| 3911 new StoreLocalNode(ident_pos, *function_variable, closure); | 3902 new StoreLocalNode(ident_pos, *function_variable, closure); |
| 3912 return initialization; | 3903 return initialization; |
| 3913 } | 3904 } |
| 3914 } | 3905 } |
| 3915 | 3906 |
| 3916 | 3907 |
| 3917 // Returns true if the current and next tokens can be parsed as type | 3908 // Returns true if the current and next tokens can be parsed as type |
| 3918 // parameters. Current token position is not saved and restored. | 3909 // parameters. Current token position is not saved and restored. |
| 3919 bool Parser::IsTypeParameter() { | 3910 bool Parser::TryParseTypeParameter() { |
| 3920 if (CurrentToken() == Token::kLT) { | 3911 if (CurrentToken() == Token::kLT) { |
| 3921 // We are possibly looking at type parameters. Find closing ">". | 3912 // We are possibly looking at type parameters. Find closing ">". |
| 3922 int nesting_level = 0; | 3913 int nesting_level = 0; |
| 3923 do { | 3914 do { |
| 3924 if (CurrentToken() == Token::kLT) { | 3915 if (CurrentToken() == Token::kLT) { |
| 3925 nesting_level++; | 3916 nesting_level++; |
| 3926 } else if (CurrentToken() == Token::kGT) { | 3917 } else if (CurrentToken() == Token::kGT) { |
| 3927 nesting_level--; | 3918 nesting_level--; |
| 3928 } else if (CurrentToken() == Token::kSHR) { | 3919 } else if (CurrentToken() == Token::kSHR) { |
| 3929 nesting_level -= 2; | 3920 nesting_level -= 2; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 3949 | 3940 |
| 3950 | 3941 |
| 3951 // Returns true if the current token is kIDENT or a pseudo-keyword. | 3942 // Returns true if the current token is kIDENT or a pseudo-keyword. |
| 3952 bool Parser::IsIdentifier() { | 3943 bool Parser::IsIdentifier() { |
| 3953 return Token::IsIdentifier(CurrentToken()); | 3944 return Token::IsIdentifier(CurrentToken()); |
| 3954 } | 3945 } |
| 3955 | 3946 |
| 3956 | 3947 |
| 3957 // Returns true if the next tokens can be parsed as a type with optional | 3948 // Returns true if the next tokens can be parsed as a type with optional |
| 3958 // type parameters. Current token position is not restored. | 3949 // type parameters. Current token position is not restored. |
| 3959 bool Parser::IsOptionalType() { | 3950 bool Parser::TryParseOptionalType() { |
| 3960 if (CurrentToken() == Token::kIDENT) { | 3951 if (CurrentToken() == Token::kIDENT) { |
| 3961 QualIdent type_name; | 3952 QualIdent type_name; |
| 3962 ParseQualIdent(&type_name); | 3953 ParseQualIdent(&type_name); |
| 3963 // Check if the type_name has been defined as a variable in a local scope, | 3954 if (CurrentToken() == Token::kLT && !TryParseTypeParameter()) { |
|
hausner
2012/01/23 18:31:24
I've been conditioned to expect extra parens here.
regis
2012/01/23 19:56:23
Done.
| |
| 3964 // hiding the type. | |
| 3965 if (type_name.is_local_scope_ident) { | |
| 3966 return false; | |
| 3967 } | |
| 3968 if (CurrentToken() == Token::kLT && !IsTypeParameter()) { | |
| 3969 return false; | 3955 return false; |
| 3970 } | 3956 } |
| 3971 } | 3957 } |
| 3972 return true; | 3958 return true; |
| 3973 } | 3959 } |
| 3974 | 3960 |
| 3975 | 3961 |
| 3976 // Returns true if the next tokens can be parsed as a type with optional | 3962 // Returns true if the next tokens can be parsed as a type with optional |
| 3977 // type parameters, or keyword "void". | 3963 // type parameters, or keyword "void". |
| 3978 // Current token position is not restored. | 3964 // Current token position is not restored. |
| 3979 bool Parser::IsReturnType() { | 3965 bool Parser::TryParseReturnType() { |
| 3980 if (CurrentToken() == Token::kVOID) { | 3966 if (CurrentToken() == Token::kVOID) { |
| 3981 ConsumeToken(); | 3967 ConsumeToken(); |
| 3982 return true; | 3968 return true; |
| 3983 } else if (CurrentToken() == Token::kIDENT) { | 3969 } else if (CurrentToken() == Token::kIDENT) { |
| 3984 return IsOptionalType(); | 3970 return TryParseOptionalType(); |
| 3985 } | 3971 } |
| 3986 return false; | 3972 return false; |
| 3987 } | 3973 } |
| 3988 | 3974 |
| 3989 | 3975 |
| 3990 // Look ahead to detect whether the next tokens should be parsed as | 3976 // Look ahead to detect whether the next tokens should be parsed as |
| 3991 // a variable declaration. Returns true if we detect the token pattern: | 3977 // a variable declaration. Returns true if we detect the token pattern: |
| 3992 // ('var' | 'final' | type ident (';' | '=' | ',')) | 3978 // ('var' | 'final' | type ident (';' | '=' | ',')) |
| 3993 // Token position remains unchanged. | 3979 // Token position remains unchanged. |
| 3994 bool Parser::IsVariableDeclaration() { | 3980 bool Parser::IsVariableDeclaration() { |
| 3995 if ((CurrentToken() == Token::kVAR) || | 3981 if ((CurrentToken() == Token::kVAR) || |
| 3996 (CurrentToken() == Token::kFINAL)) { | 3982 (CurrentToken() == Token::kFINAL)) { |
| 3997 return true; | 3983 return true; |
| 3998 } | 3984 } |
| 3999 if (CurrentToken() != Token::kIDENT) { | 3985 if (CurrentToken() != Token::kIDENT) { |
| 4000 // Not a legal type identifier. | 3986 // Not a legal type identifier. |
| 4001 return false; | 3987 return false; |
| 4002 } | 3988 } |
| 4003 const intptr_t saved_pos = token_index_; | 3989 const intptr_t saved_pos = token_index_; |
| 4004 bool is_var_decl = false; | 3990 bool is_var_decl = false; |
| 4005 if (IsOptionalType()) { | 3991 if (TryParseOptionalType()) { |
| 4006 if (IsIdentifier()) { | 3992 if (IsIdentifier()) { |
| 4007 ConsumeToken(); | 3993 ConsumeToken(); |
| 4008 if ((CurrentToken() == Token::kSEMICOLON) || | 3994 if ((CurrentToken() == Token::kSEMICOLON) || |
| 4009 (CurrentToken() == Token::kCOMMA) || | 3995 (CurrentToken() == Token::kCOMMA) || |
| 4010 (CurrentToken() == Token::kASSIGN)) { | 3996 (CurrentToken() == Token::kASSIGN)) { |
| 4011 is_var_decl = true; | 3997 is_var_decl = true; |
| 4012 } | 3998 } |
| 4013 } | 3999 } |
| 4014 } | 4000 } |
| 4015 SetPosition(saved_pos); | 4001 SetPosition(saved_pos); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 4030 return (IsIdentifier() && | 4016 return (IsIdentifier() && |
| 4031 (LookaheadToken(1) == Token::kLPAREN)) || IsFunctionDeclaration(); | 4017 (LookaheadToken(1) == Token::kLPAREN)) || IsFunctionDeclaration(); |
| 4032 } | 4018 } |
| 4033 | 4019 |
| 4034 | 4020 |
| 4035 bool Parser::IsTopLevelAccessor() { | 4021 bool Parser::IsTopLevelAccessor() { |
| 4036 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { | 4022 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { |
| 4037 return true; | 4023 return true; |
| 4038 } | 4024 } |
| 4039 const intptr_t saved_pos = token_index_; | 4025 const intptr_t saved_pos = token_index_; |
| 4040 if (IsReturnType()) { | 4026 if (TryParseReturnType()) { |
| 4041 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { | 4027 if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) { |
| 4042 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. | 4028 if (Token::IsIdentifier(LookaheadToken(1))) { // Accessor name. |
| 4043 SetPosition(saved_pos); | 4029 SetPosition(saved_pos); |
| 4044 return true; | 4030 return true; |
| 4045 } | 4031 } |
| 4046 } | 4032 } |
| 4047 } | 4033 } |
| 4048 SetPosition(saved_pos); | 4034 SetPosition(saved_pos); |
| 4049 return false; | 4035 return false; |
| 4050 } | 4036 } |
| 4051 | 4037 |
| 4052 | 4038 |
| 4053 bool Parser::IsFunctionLiteral() { | 4039 bool Parser::IsFunctionLiteral() { |
| 4054 if (!allow_function_literals_) { | 4040 if (!allow_function_literals_) { |
| 4055 return false; | 4041 return false; |
| 4056 } | 4042 } |
| 4057 const intptr_t saved_pos = token_index_; | 4043 const intptr_t saved_pos = token_index_; |
| 4058 bool is_function_literal = false; | 4044 bool is_function_literal = false; |
| 4059 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { | 4045 if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) { |
| 4060 ConsumeToken(); // Consume function identifier. | 4046 ConsumeToken(); // Consume function identifier. |
| 4061 } else if (IsReturnType()) { | 4047 } else if (TryParseReturnType()) { |
| 4062 if (!IsIdentifier()) { | 4048 if (!IsIdentifier()) { |
| 4063 SetPosition(saved_pos); | 4049 SetPosition(saved_pos); |
| 4064 return false; | 4050 return false; |
| 4065 } | 4051 } |
| 4066 ConsumeToken(); // Comsume function identifier. | 4052 ConsumeToken(); // Comsume function identifier. |
| 4067 } | 4053 } |
| 4068 if (CurrentToken() == Token::kLPAREN) { | 4054 if (CurrentToken() == Token::kLPAREN) { |
| 4069 SkipToMatchingParenthesis(); | 4055 SkipToMatchingParenthesis(); |
| 4070 if ((CurrentToken() == Token::kLBRACE) || | 4056 if ((CurrentToken() == Token::kLBRACE) || |
| 4071 (CurrentToken() == Token::kARROW)) { | 4057 (CurrentToken() == Token::kARROW)) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 4082 // statement. | 4068 // statement. |
| 4083 bool Parser::IsForInStatement() { | 4069 bool Parser::IsForInStatement() { |
| 4084 const intptr_t saved_pos = token_index_; | 4070 const intptr_t saved_pos = token_index_; |
| 4085 bool result = false; | 4071 bool result = false; |
| 4086 if (CurrentToken() == Token::kVAR || CurrentToken() == Token::kFINAL) { | 4072 if (CurrentToken() == Token::kVAR || CurrentToken() == Token::kFINAL) { |
| 4087 ConsumeToken(); | 4073 ConsumeToken(); |
| 4088 } | 4074 } |
| 4089 if (IsIdentifier()) { | 4075 if (IsIdentifier()) { |
| 4090 if (LookaheadToken(1) == Token::kIN) { | 4076 if (LookaheadToken(1) == Token::kIN) { |
| 4091 result = true; | 4077 result = true; |
| 4092 } else if (IsOptionalType()) { | 4078 } else if (TryParseOptionalType()) { |
| 4093 if (IsIdentifier()) { | 4079 if (IsIdentifier()) { |
| 4094 ConsumeToken(); | 4080 ConsumeToken(); |
| 4095 } | 4081 } |
| 4096 result = (CurrentToken() == Token::kIN); | 4082 result = (CurrentToken() == Token::kIN); |
| 4097 } | 4083 } |
| 4098 } | 4084 } |
| 4099 SetPosition(saved_pos); | 4085 SetPosition(saved_pos); |
| 4100 return result; | 4086 return result; |
| 4101 } | 4087 } |
| 4102 | 4088 |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5062 if (target->FunctionLevel() != current_block_->scope->function_level()) { | 5048 if (target->FunctionLevel() != current_block_->scope->function_level()) { |
| 5063 ErrorMsg(jump_pos, "'%s' target must be in same function context", | 5049 ErrorMsg(jump_pos, "'%s' target must be in same function context", |
| 5064 Token::Str(jump_kind)); | 5050 Token::Str(jump_kind)); |
| 5065 } | 5051 } |
| 5066 return new JumpNode(jump_pos, jump_kind, target); | 5052 return new JumpNode(jump_pos, jump_kind, target); |
| 5067 } | 5053 } |
| 5068 | 5054 |
| 5069 | 5055 |
| 5070 bool Parser::IsDefinedInLexicalScope(const String& ident) { | 5056 bool Parser::IsDefinedInLexicalScope(const String& ident) { |
| 5071 AstNode* var_or_field = NULL; | 5057 AstNode* var_or_field = NULL; |
| 5072 if (ResolveIdentInLocalScope(token_index_, ident, &var_or_field)) { | 5058 if (ResolveIdentInLocalScope(token_index_, ident, &var_or_field)) { |
|
siva
2012/01/23 18:11:38
Since we now take NULL as a param maybe this can b
regis
2012/01/23 19:56:23
Done.
| |
| 5073 return true; | 5059 return true; |
| 5074 } | 5060 } |
| 5075 Object& obj = Object::Handle(); | 5061 Object& obj = Object::Handle(); |
| 5076 obj = library_.LookupObject(ident); | 5062 obj = library_.LookupObject(ident); |
| 5077 return !obj.IsNull(); | 5063 return !obj.IsNull(); |
| 5078 } | 5064 } |
| 5079 | 5065 |
| 5080 | 5066 |
| 5081 AstNode* Parser::ParseStatement() { | 5067 AstNode* Parser::ParseStatement() { |
| 5082 TRACE_PARSER("ParseStatement"); | 5068 TRACE_PARSER("ParseStatement"); |
| (...skipping 1347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6430 return instance.raw(); | 6416 return instance.raw(); |
| 6431 } | 6417 } |
| 6432 | 6418 |
| 6433 | 6419 |
| 6434 // Do a lookup for the identifier in the block scope and the class scope | 6420 // Do a lookup for the identifier in the block scope and the class scope |
| 6435 // return true if the identifier is found, false otherwise. | 6421 // return true if the identifier is found, false otherwise. |
| 6436 // If node is non NULL return an AST node corresponding to the identifier. | 6422 // If node is non NULL return an AST node corresponding to the identifier. |
| 6437 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, | 6423 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, |
| 6438 const String &ident, | 6424 const String &ident, |
| 6439 AstNode** node) { | 6425 AstNode** node) { |
| 6440 ASSERT(node != NULL); | |
| 6441 TRACE_PARSER("ResolveIdentInLocalScope"); | 6426 TRACE_PARSER("ResolveIdentInLocalScope"); |
| 6442 Isolate* isolate = Isolate::Current(); | 6427 Isolate* isolate = Isolate::Current(); |
| 6443 // First try to find the identifier in the nested local scopes. | 6428 // First try to find the identifier in the nested local scopes. |
| 6444 LocalVariable* local = LookupLocalScope(ident); | 6429 LocalVariable* local = LookupLocalScope(ident); |
| 6445 if (local != NULL) { | 6430 if (local != NULL) { |
| 6446 *node = new LoadLocalNode(ident_pos, *local); | 6431 if (node != NULL) { |
| 6432 *node = new LoadLocalNode(ident_pos, *local); | |
| 6433 } | |
| 6447 return true; | 6434 return true; |
| 6448 } | 6435 } |
| 6449 | 6436 |
| 6450 // Try to find the identifier in the class scope. | 6437 // Try to find the identifier in the class scope. |
| 6451 Class& cls = Class::Handle(isolate, current_class().raw()); | 6438 Class& cls = Class::Handle(isolate, current_class().raw()); |
| 6452 Function& func = Function::Handle(isolate, Function::null()); | 6439 Function& func = Function::Handle(isolate, Function::null()); |
| 6453 Field& field = Field::Handle(isolate, Field::null()); | 6440 Field& field = Field::Handle(isolate, Field::null()); |
| 6454 while (!cls.IsNull()) { | 6441 while (!cls.IsNull()) { |
| 6455 // First check if a field exists. | 6442 // First check if a field exists. |
| 6456 field = cls.LookupField(ident); | 6443 field = cls.LookupField(ident); |
| 6457 if (!field.IsNull()) { | 6444 if (!field.IsNull()) { |
| 6458 if (!field.is_static()) { | 6445 if (node != NULL) { |
| 6459 CheckInstanceFieldAccess(ident_pos, ident); | 6446 if (!field.is_static()) { |
| 6460 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); | 6447 CheckInstanceFieldAccess(ident_pos, ident); |
| 6461 } else { | 6448 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); |
| 6462 *node = GenerateStaticFieldLookup(field, ident_pos); | 6449 } else { |
| 6450 *node = GenerateStaticFieldLookup(field, ident_pos); | |
| 6451 } | |
| 6463 } | 6452 } |
| 6464 return true; | 6453 return true; |
| 6465 } | 6454 } |
| 6466 | 6455 |
| 6467 // Check if an instance/static function exists. | 6456 // Check if an instance/static function exists. |
| 6468 func = cls.LookupFunction(ident); | 6457 func = cls.LookupFunction(ident); |
| 6469 if (!func.IsNull() && | 6458 if (!func.IsNull() && |
| 6470 (func.IsDynamicFunction() || func.IsStaticFunction())) { | 6459 (func.IsDynamicFunction() || func.IsStaticFunction())) { |
| 6471 *node = new PrimaryNode(ident_pos, | 6460 if (node != NULL) { |
| 6472 Function::ZoneHandle(isolate, func.raw())); | 6461 *node = new PrimaryNode(ident_pos, |
| 6462 Function::ZoneHandle(isolate, func.raw())); | |
| 6463 } | |
| 6473 return true; | 6464 return true; |
| 6474 } | 6465 } |
| 6475 | 6466 |
| 6476 // Now check if a getter/setter method exists for it in which case | 6467 // Now check if a getter/setter method exists for it in which case |
| 6477 // it is still a field. | 6468 // it is still a field. |
| 6478 func = cls.LookupGetterFunction(ident); | 6469 func = cls.LookupGetterFunction(ident); |
| 6479 if (!func.IsNull()) { | 6470 if (!func.IsNull()) { |
| 6480 if (func.IsDynamicFunction()) { | 6471 if (func.IsDynamicFunction()) { |
| 6481 CheckInstanceFieldAccess(ident_pos, ident); | 6472 CheckInstanceFieldAccess(ident_pos, ident); |
| 6482 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 6473 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
|
siva
2012/01/23 18:11:38
The CheckInstance and ASSERT could also be inside
regis
2012/01/23 19:56:23
Done.
| |
| 6483 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); | 6474 if (node != NULL) { |
| 6475 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); | |
| 6476 } | |
| 6484 return true; | 6477 return true; |
| 6485 } else if (func.IsStaticFunction()) { | 6478 } else if (func.IsStaticFunction()) { |
| 6486 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 6479 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
|
regis
2012/01/23 19:56:23
Done here too.
| |
| 6487 *node = new StaticGetterNode(ident_pos, | 6480 if (node != NULL) { |
| 6488 Class::ZoneHandle(isolate, cls.raw()), | 6481 *node = new StaticGetterNode(ident_pos, |
| 6489 ident); | 6482 Class::ZoneHandle(isolate, cls.raw()), |
| 6483 ident); | |
| 6484 } | |
| 6490 return true; | 6485 return true; |
| 6491 } | 6486 } |
| 6492 } | 6487 } |
| 6493 func = cls.LookupSetterFunction(ident); | 6488 func = cls.LookupSetterFunction(ident); |
| 6494 if (!func.IsNull()) { | 6489 if (!func.IsNull()) { |
| 6495 if (func.IsDynamicFunction()) { | 6490 if (func.IsDynamicFunction()) { |
| 6496 // We create a getter node even though a getter doesn't exist as | 6491 if (node != NULL) { |
| 6497 // it could be followed by an assignment which will convert it to | 6492 // We create a getter node even though a getter doesn't exist as |
| 6498 // a setter node. If there is no assignment we will get an error | 6493 // it could be followed by an assignment which will convert it to |
| 6499 // when we try to invoke the getter. | 6494 // a setter node. If there is no assignment we will get an error |
| 6500 CheckInstanceFieldAccess(ident_pos, ident); | 6495 // when we try to invoke the getter. |
| 6501 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 6496 CheckInstanceFieldAccess(ident_pos, ident); |
| 6502 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); | 6497 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 6498 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); | |
| 6499 } | |
| 6503 return true; | 6500 return true; |
| 6504 } else if (func.IsStaticFunction()) { | 6501 } else if (func.IsStaticFunction()) { |
| 6505 // We create a getter node even though a getter doesn't exist as | 6502 if (node != NULL) { |
| 6506 // it could be followed by an assignment which will convert it to | 6503 // We create a getter node even though a getter doesn't exist as |
| 6507 // a setter node. If there is no assignment we will get an error | 6504 // it could be followed by an assignment which will convert it to |
| 6508 // when we try to invoke the getter. | 6505 // a setter node. If there is no assignment we will get an error |
| 6509 *node = new StaticGetterNode(ident_pos, | 6506 // when we try to invoke the getter. |
| 6510 Class::ZoneHandle(isolate, cls.raw()), | 6507 *node = new StaticGetterNode(ident_pos, |
| 6511 ident); | 6508 Class::ZoneHandle(isolate, cls.raw()), |
| 6509 ident); | |
| 6510 } | |
| 6512 return true; | 6511 return true; |
| 6513 } | 6512 } |
| 6514 } | 6513 } |
| 6515 | 6514 |
| 6516 cls = cls.SuperClass(); | 6515 cls = cls.SuperClass(); |
| 6517 } | 6516 } |
| 6518 *node = NULL; | 6517 if (node != NULL) { |
| 6518 *node = NULL; | |
| 6519 } | |
| 6519 return false; // Not an unqualified identifier. | 6520 return false; // Not an unqualified identifier. |
| 6520 } | 6521 } |
| 6521 | 6522 |
| 6522 | 6523 |
| 6523 // Do a lookup for the identifier in the library scope of the specified | 6524 // Do a lookup for the identifier in the library scope of the specified |
| 6524 // library. If resolve_locally is true the lookup does not consider | 6525 // library. If resolve_locally is true the lookup does not consider |
| 6525 // the libraries imported by it for the lookup. | 6526 // the libraries imported by it for the lookup. |
| 6526 AstNode* Parser::ResolveIdentInLibraryScope(const Library& lib, | 6527 AstNode* Parser::ResolveIdentInLibraryScope(const Library& lib, |
| 6527 const QualIdent& qual_ident, | 6528 const QualIdent& qual_ident, |
| 6528 bool resolve_locally) { | 6529 bool resolve_locally) { |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6651 RawAbstractType* Parser::ParseType(TypeResolution type_resolution) { | 6652 RawAbstractType* Parser::ParseType(TypeResolution type_resolution) { |
| 6652 if (CurrentToken() != Token::kIDENT) { | 6653 if (CurrentToken() != Token::kIDENT) { |
| 6653 ErrorMsg("type name expected"); | 6654 ErrorMsg("type name expected"); |
| 6654 } | 6655 } |
| 6655 QualIdent type_name; | 6656 QualIdent type_name; |
| 6656 const intptr_t type_pos = token_index_; | 6657 const intptr_t type_pos = token_index_; |
| 6657 if (type_resolution == kIgnore) { | 6658 if (type_resolution == kIgnore) { |
| 6658 SkipQualIdent(); | 6659 SkipQualIdent(); |
| 6659 } else { | 6660 } else { |
| 6660 ParseQualIdent(&type_name); | 6661 ParseQualIdent(&type_name); |
| 6661 if (type_name.is_local_scope_ident) { | 6662 if (!is_top_level_ && (type_name.qualifier == NULL) && |
| 6663 ResolveIdentInLocalScope(type_pos, *(type_name.ident), NULL)) { | |
|
siva
2012/01/23 18:11:38
Should we be reporting this as an error?
hausner
2012/01/23 18:31:24
The parens around type_name.ident seem weird.
regis
2012/01/23 19:56:23
They were sometimes added, sometimes not. I now re
regis
2012/01/23 19:56:23
Yes, we have to. The fact that the qualident is de
| |
| 6662 ErrorMsg(type_pos, "using '%s' in this context is invalid", | 6664 ErrorMsg(type_pos, "using '%s' in this context is invalid", |
| 6663 type_name.ident->ToCString()); | 6665 type_name.ident->ToCString()); |
| 6664 } | 6666 } |
| 6665 } | 6667 } |
| 6666 Class& scope_class = Class::Handle(); | 6668 Class& scope_class = Class::Handle(); |
| 6667 Object& type_class = Object::Handle(); | 6669 Object& type_class = Object::Handle(); |
| 6668 if (type_resolution == kIgnore) { | 6670 if (type_resolution == kIgnore) { |
| 6669 // Leave type_class as null. | 6671 // Leave type_class as null. |
| 6670 } else if (type_resolution == kDoNotResolve) { | 6672 } else if (type_resolution == kDoNotResolve) { |
| 6671 String& qualifier = String::Handle(); | 6673 String& qualifier = String::Handle(); |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7132 | 7134 |
| 7133 // The grammar allows for an optional ('.' identifier)?, which is a named | 7135 // The grammar allows for an optional ('.' identifier)?, which is a named |
| 7134 // constructor. For that reason, we cannot unconditionally call | 7136 // constructor. For that reason, we cannot unconditionally call |
| 7135 // ParseType(kMustResolve) after we see an identifier, because the named | 7137 // ParseType(kMustResolve) after we see an identifier, because the named |
| 7136 // constructor would be misinterpreted as a qualified type name. | 7138 // constructor would be misinterpreted as a qualified type name. |
| 7137 // TODO(regis): Revisit once we correctly support qualified identifiers. | 7139 // TODO(regis): Revisit once we correctly support qualified identifiers. |
| 7138 // For now, we inline a customized version of ParseType(kMustResolve). | 7140 // For now, we inline a customized version of ParseType(kMustResolve). |
| 7139 const intptr_t type_pos = token_index_; | 7141 const intptr_t type_pos = token_index_; |
| 7140 QualIdent type_name; | 7142 QualIdent type_name; |
| 7141 ParseQualIdent(&type_name); | 7143 ParseQualIdent(&type_name); |
| 7142 if (type_name.is_local_scope_ident) { | 7144 ASSERT(!is_top_level_); |
|
hausner
2012/01/23 18:31:24
Not sure whether you can assert this here. What if
regis
2012/01/23 19:56:23
As discussed, we already have top level initialize
| |
| 7145 if ((type_name.qualifier == NULL) && | |
| 7146 ResolveIdentInLocalScope(type_pos, *(type_name.ident), NULL)) { | |
|
siva
2012/01/23 18:11:38
In the cases where current token is "." and the qu
regis
2012/01/23 19:56:23
Consider this example calling a named constructor:
| |
| 7143 ErrorMsg(type_pos, "using '%s' in this context is invalid", | 7147 ErrorMsg(type_pos, "using '%s' in this context is invalid", |
| 7144 type_name.ident->ToCString()); | 7148 type_name.ident->ToCString()); |
| 7145 } | 7149 } |
| 7146 String* named_constructor = NULL; | 7150 String* named_constructor = NULL; |
| 7147 if (CurrentToken() == Token::kPERIOD) { | 7151 if (CurrentToken() == Token::kPERIOD) { |
| 7148 ConsumeToken(); | 7152 ConsumeToken(); |
| 7149 named_constructor = ExpectIdentifier("identifier expected after '.'"); | 7153 named_constructor = ExpectIdentifier("identifier expected after '.'"); |
| 7150 } | 7154 } |
| 7151 const Class& scope_class = Class::Handle(TypeParametersScopeClass()); | 7155 const Class& scope_class = Class::Handle(TypeParametersScopeClass()); |
| 7152 if (!scope_class.IsNull()) { | 7156 if (!scope_class.IsNull()) { |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7383 AstNode* primary = NULL; | 7387 AstNode* primary = NULL; |
| 7384 if (IsFunctionLiteral()) { | 7388 if (IsFunctionLiteral()) { |
| 7385 // The name of a literal function is visible from inside the function, but | 7389 // The name of a literal function is visible from inside the function, but |
| 7386 // must not collide with names in the scope declaring the literal. | 7390 // must not collide with names in the scope declaring the literal. |
| 7387 OpenBlock(); | 7391 OpenBlock(); |
| 7388 primary = ParseFunctionStatement(true); | 7392 primary = ParseFunctionStatement(true); |
| 7389 CloseBlock(); | 7393 CloseBlock(); |
| 7390 } else if (IsIdentifier()) { | 7394 } else if (IsIdentifier()) { |
| 7391 QualIdent qual_ident; | 7395 QualIdent qual_ident; |
| 7392 ParseQualIdent(&qual_ident); | 7396 ParseQualIdent(&qual_ident); |
| 7393 if (qual_ident.is_local_scope_ident) { | 7397 if (qual_ident.qualifier == NULL) { |
| 7394 ResolveIdentInLocalScope(qual_ident.ident_pos, | 7398 if (!ResolveIdentInLocalScope(qual_ident.ident_pos, |
| 7395 *qual_ident.ident, | 7399 *(qual_ident.ident), |
|
hausner
2012/01/23 18:31:24
The parens are unnecessary.
regis
2012/01/23 19:56:23
Done.
| |
| 7396 &primary); | 7400 &primary)) { |
| 7397 } else { | 7401 // This is a non-local unqualified identifier so resolve the identifier |
| 7398 if (qual_ident.qualifier == NULL) { | |
| 7399 // This is an unqualified identifier so resolve the identifier | |
| 7400 // locally in the main app library and all libraries imported by it. | 7402 // locally in the main app library and all libraries imported by it. |
| 7401 primary = ResolveIdentInLibraryScope(library_, | 7403 primary = ResolveIdentInLibraryScope(library_, |
| 7402 qual_ident, | 7404 qual_ident, |
| 7403 kResolveIncludingImports); | 7405 kResolveIncludingImports); |
| 7404 } else { | |
| 7405 // This is a qualified identifier with a library prefix so resolve | |
| 7406 // the identifier locally in that library (we do not include the | |
| 7407 // libraries imported by that library). | |
| 7408 const Library& lib = Library::Handle(qual_ident.lib_prefix->library()); | |
| 7409 primary = ResolveIdentInLibraryScope(lib, | |
| 7410 qual_ident, | |
| 7411 kResolveLocally); | |
| 7412 } | 7406 } |
| 7407 } else { | |
| 7408 // This is a qualified identifier with a library prefix so resolve | |
| 7409 // the identifier locally in that library (we do not include the | |
| 7410 // libraries imported by that library). | |
| 7411 const Library& lib = Library::Handle(qual_ident.lib_prefix->library()); | |
| 7412 primary = ResolveIdentInLibraryScope(lib, | |
| 7413 qual_ident, | |
| 7414 kResolveLocally); | |
| 7413 } | 7415 } |
| 7414 ASSERT(primary != NULL); | 7416 ASSERT(primary != NULL); |
| 7415 } else if (CurrentToken() == Token::kTHIS) { | 7417 } else if (CurrentToken() == Token::kTHIS) { |
| 7416 const String& this_name = String::Handle(String::NewSymbol(kThisName)); | 7418 const String& this_name = String::Handle(String::NewSymbol(kThisName)); |
| 7417 LocalVariable* local = LookupLocalScope(this_name); | 7419 LocalVariable* local = LookupLocalScope(this_name); |
| 7418 if (local == NULL) { | 7420 if (local == NULL) { |
| 7419 ErrorMsg("unexpected use of 'this' in primary expression"); | 7421 ErrorMsg("unexpected use of 'this' in primary expression"); |
| 7420 } | 7422 } |
| 7421 primary = new LoadLocalNode(token_index_, *local); | 7423 primary = new LoadLocalNode(token_index_, *local); |
| 7422 ConsumeToken(); | 7424 ConsumeToken(); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7770 void Parser::SkipQualIdent() { | 7772 void Parser::SkipQualIdent() { |
| 7771 ASSERT(IsIdentifier()); | 7773 ASSERT(IsIdentifier()); |
| 7772 ConsumeToken(); | 7774 ConsumeToken(); |
| 7773 if (CurrentToken() == Token::kPERIOD) { | 7775 if (CurrentToken() == Token::kPERIOD) { |
| 7774 ConsumeToken(); // Consume the kPERIOD token. | 7776 ConsumeToken(); // Consume the kPERIOD token. |
| 7775 ExpectIdentifier("identifier expected after '.'"); | 7777 ExpectIdentifier("identifier expected after '.'"); |
| 7776 } | 7778 } |
| 7777 } | 7779 } |
| 7778 | 7780 |
| 7779 } // namespace dart | 7781 } // namespace dart |
| OLD | NEW |