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