• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import {
17    expect
18} from 'chai';
19import 'mocha';
20import {
21    FunctionScope,
22    GlobalScope,
23    LocalScope
24} from "../src/scope";
25import {
26    GlobalVariable,
27    LocalVariable,
28    VarDeclarationKind
29} from "../src/variable";
30
31describe("ScopeTest", function () {
32    it("test add 'none' variable to GlobalScope", function () {
33        let scope = new GlobalScope();
34        let variable = scope.add("x", VarDeclarationKind.NONE);
35        expect(variable instanceof GlobalVariable).to.be.true;
36        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
37        expect(outVariable === variable).to.be.true;
38        expect(lv).to.be.equal(0);
39        expect(sp).to.be.equal(scope);
40    });
41
42    it("test add 'var' variable to GlobalScope", function () {
43        let scope = new GlobalScope();
44        let variable = scope.add("x", VarDeclarationKind.VAR);
45        expect(variable instanceof GlobalVariable).to.be.true;
46        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
47        expect(outVariable === variable).to.be.true;
48        expect(lv).to.be.equal(0);
49        expect(sp).to.be.equal(scope);
50    });
51
52    it("test add 'let' variable to GlobalScope", function () {
53        let scope = new GlobalScope();
54        let variable = scope.add("x", VarDeclarationKind.LET);
55        expect(variable instanceof LocalVariable).to.be.true;
56        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
57        expect(outVariable === variable).to.be.true;
58        expect(lv).to.be.equal(0);
59        expect(sp).to.be.equal(scope);
60    });
61
62    it("test add 'const' variable to GlobalScope", function () {
63        let scope = new GlobalScope();
64        let variable = scope.add("x", VarDeclarationKind.CONST);
65        expect(variable instanceof LocalVariable).to.be.true;
66        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
67        expect(outVariable === variable).to.be.true;
68        expect(lv).to.be.equal(0);
69        expect(sp).to.be.equal(scope);
70    });
71
72    it("test add several variables to GlobalScope", function () {
73        let scope = new GlobalScope();
74        let x = scope.add("x", VarDeclarationKind.LET);
75        let y = scope.add("y", VarDeclarationKind.NONE);
76        let z = scope.add("z", VarDeclarationKind.LET);
77    });
78
79    it("test add 'none' variable to FunctionScope", function () {
80        let globalScope = new GlobalScope();
81        let scope = new FunctionScope(globalScope);
82        let variable = scope.add("x", VarDeclarationKind.NONE);
83        expect(variable instanceof GlobalVariable).to.be.true;
84        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
85        expect(outVariable === variable).to.be.true;
86        expect(lv).to.be.equal(0);
87        expect(sp).to.be.equal(globalScope);
88    });
89
90    it("test add 'var' variable to FunctionScope", function () {
91        let scope = new FunctionScope();
92        let variable = scope.add("x", VarDeclarationKind.VAR);
93        expect(variable instanceof LocalVariable).to.be.true;
94        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
95        expect(outVariable === variable).to.be.true;
96        expect(lv).to.be.equal(0);
97        expect(sp).to.be.equal(scope);
98    });
99
100    it("test add 'let' variable to FunctionScope", function () {
101        let scope = new FunctionScope();
102        let variable = scope.add("x", VarDeclarationKind.LET);
103        expect(variable instanceof LocalVariable).to.be.true;
104        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
105        expect(outVariable === variable).to.be.true;
106        expect(lv).to.be.equal(0);
107        expect(sp).to.be.equal(scope);
108    });
109
110    it("test add 'const' variable to FunctionScope", function () {
111        let scope = new FunctionScope();
112        let variable = scope.add("x", VarDeclarationKind.LET);
113        expect(variable instanceof LocalVariable).to.be.true;
114        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
115        expect(outVariable === variable).to.be.true;
116        expect(lv).to.be.equal(0);
117        expect(sp).to.be.equal(scope);
118    });
119
120    it("test add several variables to FunctionScope", function () {
121        let globalScope = new GlobalScope();
122        let scope = new FunctionScope(globalScope);
123        let x = scope.add("x", VarDeclarationKind.LET);
124        let y = scope.add("y", VarDeclarationKind.NONE);
125        let z = scope.add("z", VarDeclarationKind.LET);
126    });
127
128    it("test add 'none' variable to LocalScope", function () {
129        let parent = new GlobalScope();
130        let scope = new LocalScope(parent);
131        let variable = scope.add("x", VarDeclarationKind.NONE);
132        expect(variable instanceof GlobalVariable).to.be.true;
133        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
134        expect(outVariable === variable).to.be.true;
135        let { scope: spParent, level: lvParent, v: outVariableParent } = parent.find("x");
136        expect(outVariableParent === variable).to.be.true;
137        expect(spParent instanceof GlobalScope).to.be.true;
138    });
139
140    it("test add 'var' variable to LocalScope", function () {
141        let parent = new FunctionScope();
142        let scope = new LocalScope(parent);
143        let variable = scope.add("x", VarDeclarationKind.VAR);
144        expect(variable instanceof LocalVariable).to.be.true;
145        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
146        expect(outVariable === variable).to.be.true;
147        expect(lv).to.be.equal(0);
148        expect(sp).to.be.equal(parent);
149        let { scope: spParent, level: lvParent, v: outVariableParent } = parent.find("x");
150        expect(outVariableParent === variable).to.be.true;
151        expect(lvParent).to.be.equal(0);
152        expect(spParent).to.be.equal(parent);
153    });
154
155    it("test add 'let' variable to LocalScope", function () {
156        let parent = new FunctionScope();
157        let scope = new LocalScope(parent);
158        let variable = scope.add("x", VarDeclarationKind.LET);
159        expect(variable instanceof LocalVariable).to.be.true;
160        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
161        expect(outVariable === variable).to.be.true;
162        expect(lv).to.be.equal(0);
163        expect(sp).to.be.equal(scope);
164        let { scope: spParent, level: lvParent, v: outVariableParent } = parent.find("x");
165        expect(outVariableParent === undefined).to.be.true;
166    });
167
168    it("test add 'const' variable to LocalScope", function () {
169        let parent = new FunctionScope();
170        let scope = new LocalScope(parent);
171        let variable = scope.add("x", VarDeclarationKind.LET);
172        expect(variable instanceof LocalVariable).to.be.true;
173        let { scope: sp, level: lv, v: outVariable } = scope.find("x");
174        expect(outVariable === variable).to.be.true;
175        expect(lv).to.be.equal(0);
176        expect(sp).to.be.equal(scope);
177        let { scope: spParent, level: lvParent, v: outVariableParent } = parent.find("x");
178        expect(outVariableParent === undefined).to.be.true;
179    });
180
181    it("test add several variables to LocalScope", function () {
182        let global = new GlobalScope();
183        let parent = new FunctionScope(global);
184        let scope = new LocalScope(parent);
185        let x = scope.add("x", VarDeclarationKind.LET);
186        let y = scope.add("y", VarDeclarationKind.NONE);
187        let z = scope.add("z", VarDeclarationKind.LET);
188        expect(y instanceof GlobalVariable).to.be.true;
189    });
190    /**
191     *
192     *                      +-----------+
193     *                      |  global   |
194     *                      +-----/-----+
195     *                            |
196     *                      +-----\-----+
197     *                      |    func1  |
198     *                      +----_.-,---+
199     *                        _-`    `.
200     *                     _-`         `.
201     *                  _-`              `.
202     *           +-----`---+           +---'----+
203     *           |  func21 |           | func22 |
204     *           +---,.-,--+           +--------+
205     *           _.-`    `.
206     *        ,-`          `.
207     * +----'`---+       +---'-----+
208     * | func31  |       | func32  |
209     * +----/----+       +---------+
210     *      |
211     *      |
212     * +----\----+
213     * |  func4  |
214     * +---------+
215     */
216    it("test multi-scope nesting function", function () {
217        let globalScope = new GlobalScope();
218        let func1Scope = new FunctionScope(globalScope);
219        let aV = func1Scope.add("a", VarDeclarationKind.LET);
220        let bV = func1Scope.add("b", VarDeclarationKind.VAR);
221        let p0 = func1Scope.addParameter("p0", VarDeclarationKind.VAR, 0);
222        let p1 = func1Scope.addParameter("p1", VarDeclarationKind.VAR, 1);
223        let p2 = func1Scope.addParameter("p2", VarDeclarationKind.VAR, 2);
224        let localScope = new LocalScope(func1Scope);
225        let func21Scope = new FunctionScope(localScope);
226        let func22Scope = new FunctionScope(func1Scope);
227        let func31Scope = new FunctionScope(func21Scope);
228        let func32Scope = new FunctionScope(func21Scope);
229        let func4Scope = new FunctionScope(func31Scope);
230
231        aV.setLexVar(func1Scope);
232        p2.setLexVar(func1Scope);
233        let aFindEntry = func32Scope.find("a");
234        expect(aFindEntry.v, "check a variable").to.be.equal(aV);
235        expect(aFindEntry.level, "check level").to.be.equal(0);
236        expect(aFindEntry.scope).to.be.equal(func1Scope);
237
238        let p2FindEntry = func22Scope.find("p2");
239        expect(p2FindEntry.v, "check p0 parameter").to.be.equal(p2);
240        expect(p2FindEntry.level, "check level").to.be.equal(0);
241        expect(p2FindEntry.scope).to.be.equal(func1Scope);
242
243        expect(func1Scope.getNumLexEnv(), "func1 status").to.be.equal(2);
244        expect(func21Scope.getNumLexEnv(), "func21 status").to.be.equal(0);
245        expect(func22Scope.getNumLexEnv(), "func22 status").to.be.equal(0);
246        expect(func31Scope.getNumLexEnv(), "func31 status").to.be.equal(0);
247        expect(func32Scope.getNumLexEnv(), "func32 status").to.be.equal(0);
248        expect(func4Scope.getNumLexEnv(), "func4 status").to.be.equal(0);
249    });
250})
251