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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/scopes.h"
6#include "platform/assert.h"
7#include "vm/unit_test.h"
8
9namespace dart {
10
11ISOLATE_UNIT_TEST_CASE(LocalScope) {
12 // Allocate a couple of local variables first.
13 const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
14 const String& a = String::ZoneHandle(Symbols::New(thread, "a"));
15 LocalVariable* var_a = new LocalVariable(
16 TokenPosition::kNoSource, TokenPosition::kNoSource, a, dynamic_type);
17 LocalVariable* inner_var_a = new LocalVariable(
18 TokenPosition::kNoSource, TokenPosition::kNoSource, a, dynamic_type);
19 const String& b = String::ZoneHandle(Symbols::New(thread, "b"));
20 LocalVariable* var_b = new LocalVariable(
21 TokenPosition::kNoSource, TokenPosition::kNoSource, b, dynamic_type);
22 const String& c = String::ZoneHandle(Symbols::New(thread, "c"));
23 LocalVariable* var_c = new LocalVariable(
24 TokenPosition::kNoSource, TokenPosition::kNoSource, c, dynamic_type);
25 const String& L = String::ZoneHandle(Symbols::New(thread, "L"));
26 SourceLabel* label_L =
27 new SourceLabel(TokenPosition::kNoSource, L, SourceLabel::kFor);
28
29 LocalScope* outer_scope = new LocalScope(NULL, 0, 0);
30 LocalScope* inner_scope1 = new LocalScope(outer_scope, 0, 0);
31 LocalScope* inner_scope2 = new LocalScope(outer_scope, 0, 0);
32
33 EXPECT(outer_scope->parent() == NULL);
34 EXPECT_EQ(outer_scope, inner_scope1->parent());
35 EXPECT_EQ(outer_scope, inner_scope2->parent());
36 EXPECT_EQ(inner_scope2, outer_scope->child());
37 EXPECT_EQ(inner_scope1, inner_scope2->sibling());
38 EXPECT(inner_scope1->child() == NULL);
39 EXPECT(inner_scope2->child() == NULL);
40
41 // Populate the local scopes as follows:
42 // { // outer_scope
43 // var a;
44 // { // inner_scope1
45 // var b;
46 // }
47 // L: { // inner_scope2
48 // var c;
49 // }
50 // }
51 EXPECT(outer_scope->AddVariable(var_a));
52 EXPECT(inner_scope1->AddVariable(var_b));
53 EXPECT(inner_scope2->AddVariable(var_c));
54 EXPECT(inner_scope2->AddLabel(label_L));
55 EXPECT(!outer_scope->AddVariable(var_a));
56
57 // Check the simple layout above.
58 EXPECT_EQ(var_a, outer_scope->LocalLookupVariable(a));
59 EXPECT_EQ(var_a, inner_scope1->LookupVariable(a, true));
60 EXPECT_EQ(label_L, inner_scope2->LookupLabel(L));
61 EXPECT(outer_scope->LocalLookupVariable(b) == NULL);
62 EXPECT(inner_scope1->LocalLookupVariable(c) == NULL);
63
64 // Modify the local scopes to contain shadowing:
65 // { // outer_scope
66 // var a;
67 // { // inner_scope1
68 // var b;
69 // var a; // inner_var_a
70 // }
71 // { // inner_scope2
72 // var c;
73 // L: ...
74 // }
75 // }
76 EXPECT(inner_scope1->AddVariable(inner_var_a));
77 EXPECT_EQ(inner_var_a, inner_scope1->LookupVariable(a, true));
78 EXPECT(inner_scope1->LookupVariable(a, true) != var_a);
79
80 // Modify the local scopes with access of an outer scope variable:
81 // { // outer_scope
82 // var a;
83 // { // inner_scope1
84 // var b;
85 // var a; // inner_var_a
86 // }
87 // { // inner_scope2
88 // var c = a;
89 // L: ...
90 // }
91 // }
92 EXPECT(inner_scope2->LocalLookupVariable(a) == NULL);
93 EXPECT(inner_scope2->AddVariable(var_a));
94 EXPECT_EQ(var_a, inner_scope2->LocalLookupVariable(a));
95
96 EXPECT_EQ(1, outer_scope->num_variables());
97 EXPECT_EQ(2, inner_scope1->num_variables());
98 EXPECT_EQ(2, inner_scope2->num_variables());
99
100 // Cannot depend on the order, but we should find the variables.
101 EXPECT(outer_scope->VariableAt(0) == var_a);
102 EXPECT((inner_scope1->VariableAt(0) == inner_var_a) ||
103 (inner_scope1->VariableAt(1) == inner_var_a));
104 EXPECT((inner_scope1->VariableAt(0) == var_b) ||
105 (inner_scope1->VariableAt(1) == var_b));
106 EXPECT((inner_scope2->VariableAt(0) == var_a) ||
107 (inner_scope2->VariableAt(1) == var_a) ||
108 (inner_scope2->VariableAt(2) == var_a));
109 EXPECT((inner_scope2->VariableAt(0) == var_c) ||
110 (inner_scope2->VariableAt(1) == var_c) ||
111 (inner_scope2->VariableAt(2) == var_c));
112}
113
114} // namespace dart
115