| // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | #include "vm/scopes.h" | 
 | #include "platform/assert.h" | 
 | #include "vm/unit_test.h" | 
 |  | 
 | namespace dart { | 
 |  | 
 | ISOLATE_UNIT_TEST_CASE(LocalScope) { | 
 |   // Allocate a couple of local variables first. | 
 |   const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType()); | 
 |   const String& a = String::ZoneHandle(Symbols::New(thread, "a")); | 
 |   LocalVariable* var_a = new LocalVariable( | 
 |       TokenPosition::kNoSource, TokenPosition::kNoSource, a, dynamic_type); | 
 |   LocalVariable* inner_var_a = new LocalVariable( | 
 |       TokenPosition::kNoSource, TokenPosition::kNoSource, a, dynamic_type); | 
 |   const String& b = String::ZoneHandle(Symbols::New(thread, "b")); | 
 |   LocalVariable* var_b = new LocalVariable( | 
 |       TokenPosition::kNoSource, TokenPosition::kNoSource, b, dynamic_type); | 
 |   const String& c = String::ZoneHandle(Symbols::New(thread, "c")); | 
 |   LocalVariable* var_c = new LocalVariable( | 
 |       TokenPosition::kNoSource, TokenPosition::kNoSource, c, dynamic_type); | 
 |  | 
 |   LocalScope* outer_scope = new LocalScope(NULL, 0, 0); | 
 |   LocalScope* inner_scope1 = new LocalScope(outer_scope, 0, 0); | 
 |   LocalScope* inner_scope2 = new LocalScope(outer_scope, 0, 0); | 
 |  | 
 |   EXPECT(outer_scope->parent() == NULL); | 
 |   EXPECT_EQ(outer_scope, inner_scope1->parent()); | 
 |   EXPECT_EQ(outer_scope, inner_scope2->parent()); | 
 |   EXPECT_EQ(inner_scope2, outer_scope->child()); | 
 |   EXPECT_EQ(inner_scope1, inner_scope2->sibling()); | 
 |   EXPECT(inner_scope1->child() == NULL); | 
 |   EXPECT(inner_scope2->child() == NULL); | 
 |  | 
 |   // Populate the local scopes as follows: | 
 |   // {  // outer_scope | 
 |   //   var a; | 
 |   //   {  // inner_scope1 | 
 |   //     var b; | 
 |   //   } | 
 |   //   L: {  // inner_scope2 | 
 |   //     var c; | 
 |   //   } | 
 |   // } | 
 |   EXPECT(outer_scope->AddVariable(var_a)); | 
 |   EXPECT(inner_scope1->AddVariable(var_b)); | 
 |   EXPECT(inner_scope2->AddVariable(var_c)); | 
 |   EXPECT(!outer_scope->AddVariable(var_a)); | 
 |  | 
 |   // Check the simple layout above. | 
 |   EXPECT_EQ(var_a, outer_scope->LocalLookupVariable(a)); | 
 |   EXPECT_EQ(var_a, inner_scope1->LookupVariable(a, true)); | 
 |   EXPECT(outer_scope->LocalLookupVariable(b) == NULL); | 
 |   EXPECT(inner_scope1->LocalLookupVariable(c) == NULL); | 
 |  | 
 |   // Modify the local scopes to contain shadowing: | 
 |   // {  // outer_scope | 
 |   //   var a; | 
 |   //   {  // inner_scope1 | 
 |   //     var b; | 
 |   //     var a;  // inner_var_a | 
 |   //   } | 
 |   //   {  // inner_scope2 | 
 |   //     var c; | 
 |   //     L: ... | 
 |   //   } | 
 |   // } | 
 |   EXPECT(inner_scope1->AddVariable(inner_var_a)); | 
 |   EXPECT_EQ(inner_var_a, inner_scope1->LookupVariable(a, true)); | 
 |   EXPECT(inner_scope1->LookupVariable(a, true) != var_a); | 
 |  | 
 |   // Modify the local scopes with access of an outer scope variable: | 
 |   // {  // outer_scope | 
 |   //   var a; | 
 |   //   {  // inner_scope1 | 
 |   //     var b; | 
 |   //     var a;  // inner_var_a | 
 |   //   } | 
 |   //   {  // inner_scope2 | 
 |   //     var c = a; | 
 |   //     L: ... | 
 |   //   } | 
 |   // } | 
 |   EXPECT(inner_scope2->LocalLookupVariable(a) == NULL); | 
 |   EXPECT(inner_scope2->AddVariable(var_a)); | 
 |   EXPECT_EQ(var_a, inner_scope2->LocalLookupVariable(a)); | 
 |  | 
 |   EXPECT_EQ(1, outer_scope->num_variables()); | 
 |   EXPECT_EQ(2, inner_scope1->num_variables()); | 
 |   EXPECT_EQ(2, inner_scope2->num_variables()); | 
 |  | 
 |   // Cannot depend on the order, but we should find the variables. | 
 |   EXPECT(outer_scope->VariableAt(0) == var_a); | 
 |   EXPECT((inner_scope1->VariableAt(0) == inner_var_a) || | 
 |          (inner_scope1->VariableAt(1) == inner_var_a)); | 
 |   EXPECT((inner_scope1->VariableAt(0) == var_b) || | 
 |          (inner_scope1->VariableAt(1) == var_b)); | 
 |   EXPECT((inner_scope2->VariableAt(0) == var_a) || | 
 |          (inner_scope2->VariableAt(1) == var_a) || | 
 |          (inner_scope2->VariableAt(2) == var_a)); | 
 |   EXPECT((inner_scope2->VariableAt(0) == var_c) || | 
 |          (inner_scope2->VariableAt(1) == var_c) || | 
 |          (inner_scope2->VariableAt(2) == var_c)); | 
 | } | 
 |  | 
 | }  // namespace dart |