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 Returnundefined, 22 Sttoglobalrecord, 23 Strictnoteq, 24 Tryldglobalbyname, 25 Imm, 26 Jeqz, 27 Jmp, 28 Jnez, 29 Label, 30 Lda, 31 Ldai, 32 Sta, 33 VReg, 34 IRNode 35} from "../../src/irnodes"; 36import { checkInstructions, compileMainSnippet, SnippetCompiler } from "../utils/base"; 37import { creatAstFromSnippet } from "../utils/asthelper" 38import { PandaGen } from '../../src/pandagen'; 39 40describe("switchTest", function () { 41 it("single case", function () { 42 let insns = compileMainSnippet("let a = 0; switch (a) {case 0 : ;}"); 43 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 44 let rhs = new VReg(); 45 let caseLabel = new Label(); 46 let switchEndLabel = new Label(); 47 let expected = [ 48 new Ldai(new Imm(0)), 49 new Sttoglobalrecord(new Imm(0), 'a'), 50 // switch bodynew Imm(0), 51 new Tryldglobalbyname(new Imm(1), 'a'), 52 new Sta(rhs), 53 new Ldai(new Imm(0)), 54 new Strictnoteq(new Imm(2), rhs), 55 new Jeqz(caseLabel), 56 new Jmp(switchEndLabel), 57 // switch cases 58 caseLabel, 59 switchEndLabel, 60 new Returnundefined() 61 ]; 62 expect(checkInstructions(insns, expected)).to.be.true; 63 expect((<Jnez>insns[6]).getTarget() === insns[8]).to.be.true; 64 expect((<Jmp>insns[7]).getTarget() === insns[9]).to.be.true; 65 }); 66 67 it("multiple cases without break", function () { 68 let insns = compileMainSnippet(`let a = 0; switch (a) 69 { 70 case 0 : ; 71 case 1 : ; 72 default : ; 73 }`); 74 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 75 let rhs = new VReg(); 76 let caseLabel_0 = new Label(); 77 let caseLabel_1 = new Label(); 78 let defaultLabel = new Label(); 79 let switchEndLabel = new Label(); 80 let expected = [ 81 new Ldai(new Imm(0)), 82 new Sttoglobalrecord(new Imm(0), 'a'), 83 // switch body 84 new Tryldglobalbyname(new Imm(1), 'a'), 85 new Sta(rhs), 86 new Ldai(new Imm(0)), 87 new Strictnoteq(new Imm(2), rhs), 88 new Jeqz(caseLabel_0), 89 new Ldai(new Imm(1)), 90 new Strictnoteq(new Imm(3), rhs), 91 new Jeqz(caseLabel_1), 92 new Jmp(defaultLabel), 93 // cases 94 caseLabel_0, 95 caseLabel_1, 96 // default case 97 defaultLabel, 98 switchEndLabel, 99 new Returnundefined() 100 ]; 101 expect(checkInstructions(insns, expected)).to.be.true; 102 }); 103 104 it("multiple cases with default", function () { 105 let insns = compileMainSnippet(`let a = 0; switch (a) 106 { 107 case 0 : break; 108 case 1 : break; 109 default : ; 110 }`); 111 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 112 let rhs = new VReg(); 113 let caseLabel_0 = new Label(); 114 let caseLabel_1 = new Label(); 115 let defaultLabel = new Label(); 116 let switchEndLabel = new Label(); 117 let expected = [ 118 new Ldai(new Imm(0)), 119 new Sttoglobalrecord(new Imm(0), 'a'), 120 // switch body 121 new Tryldglobalbyname(new Imm(1), 'a'), 122 new Sta(rhs), 123 new Ldai(new Imm(0)), 124 new Strictnoteq(new Imm(2), rhs), 125 new Jeqz(caseLabel_0), 126 new Ldai(new Imm(1)), 127 new Strictnoteq(new Imm(3), rhs), 128 new Jeqz(caseLabel_1), 129 new Jmp(defaultLabel), 130 // switch cases 131 caseLabel_0, 132 new Jmp(switchEndLabel), 133 caseLabel_1, 134 new Jmp(switchEndLabel), 135 defaultLabel, 136 switchEndLabel, 137 new Returnundefined() 138 ]; 139 expect(checkInstructions(insns, expected)).to.be.true; 140 }); 141 142 it("multiple cases without default", function () { 143 let insns = compileMainSnippet(`let a = 0; switch (a) 144 { 145 case 0 : break; 146 case 1 : break; 147 }`); 148 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 149 let rhs = new VReg(); 150 let caseLabel_0 = new Label(); 151 let caseLabel_1 = new Label(); 152 let switchEndLabel = new Label(); 153 let expected = [ 154 new Ldai(new Imm(0)), 155 new Sttoglobalrecord(new Imm(0), 'a'), 156 // switch body 157 new Tryldglobalbyname(new Imm(1), 'a'), 158 new Sta(rhs), 159 new Ldai(new Imm(0)), 160 new Strictnoteq(new Imm(2), rhs), 161 new Jeqz(caseLabel_0), 162 new Ldai(new Imm(1)), 163 new Strictnoteq(new Imm(3), rhs), 164 new Jeqz(caseLabel_1), 165 new Jmp(switchEndLabel), 166 // switch cases 167 caseLabel_0, 168 new Jmp(switchEndLabel), 169 caseLabel_1, 170 new Jmp(switchEndLabel), 171 switchEndLabel, 172 new Returnundefined() 173 ]; 174 expect(checkInstructions(insns, expected)).to.be.true; 175 }); 176 177 it("multiple cases with default surrounded by cases", function () { 178 let insns = compileMainSnippet(`let a = 0; switch (a) 179 { 180 case 0 : break; 181 default : ; 182 case 1 : ; 183 }`); 184 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 185 let rhs = new VReg(); 186 let caseLabel_0 = new Label(); 187 let caseLabel_1 = new Label(); 188 let defaultLabel = new Label(); 189 let switchEndLabel = new Label(); 190 let expected = [ 191 new Ldai(new Imm(0)), 192 new Sttoglobalrecord(new Imm(0), 'a'), 193 // switch body 194 new Tryldglobalbyname(new Imm(1), 'a'), 195 new Sta(rhs), 196 new Ldai(new Imm(0)), 197 new Strictnoteq(new Imm(2), rhs), 198 new Jeqz(caseLabel_0), 199 new Ldai(new Imm(1)), 200 new Strictnoteq(new Imm(3), rhs), 201 new Jeqz(caseLabel_1), 202 new Jmp(defaultLabel), 203 // switch cases 204 caseLabel_0, 205 new Jmp(switchEndLabel), 206 // default case 207 defaultLabel, 208 caseLabel_1, 209 switchEndLabel, 210 new Returnundefined() 211 ]; 212 expect(checkInstructions(insns, expected)).to.be.true; 213 }); 214 215 it("discriminant's scope", function () { 216 let snippetCompiler = new SnippetCompiler(); 217 snippetCompiler.compile( 218 `function test() { 219 let a = 0; 220 switch (a) { 221 case 0: 222 const a = 0; 223 break; 224 } 225 }`); 226 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 227 228 let a = new VReg(); 229 let discriminant_a = new VReg(); 230 let body_a = new VReg(); 231 let caseLabel_0 = new Label(); 232 let switchEndLabel = new Label(); 233 let expected = [ 234 new Ldai(new Imm(0)), 235 new Sta(a), 236 // switch discriminant 237 new Lda(a), 238 new Sta(discriminant_a), 239 // switch body 240 new Ldai(new Imm(0)), 241 new Strictnoteq(new Imm(1), discriminant_a), 242 new Jeqz(caseLabel_0), 243 new Jmp(switchEndLabel), 244 // switch cases 245 caseLabel_0, 246 new Ldai(new Imm(0)), 247 new Sta(body_a), 248 new Jmp(switchEndLabel), 249 switchEndLabel, 250 new Returnundefined() 251 ]; 252 let functionPg = snippetCompiler.getPandaGenByName("UnitTest.test"); 253 let insns = functionPg!.getInsns(); 254 255 expect(checkInstructions(insns, expected)).to.be.true; 256 }); 257}); 258