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 And2, 22 Eq, 23 Isfalse, 24 Istrue, 25 Returnundefined, 26 Sttoglobalrecord, 27 Tryldglobalbyname, 28 Imm, 29 Jeqz, 30 Jmp, 31 Label, 32 Lda, 33 Ldai, 34 Sta, 35 VReg, 36 IRNode 37} from "../../src/irnodes"; 38import { checkInstructions, compileMainSnippet } from "../utils/base"; 39import { creatAstFromSnippet } from "../utils/asthelper"; 40import { PandaGen } from '../../src/pandagen'; 41 42describe("IfConditionTest", function () { 43 it('ifConditionEmpty', function () { 44 let insns = compileMainSnippet("let s = 1;\n" + 45 "if (s > 2) {}"); 46 let jumps = insns.filter(item => item instanceof Jeqz); 47 48 expect(jumps.length).to.equal(1); 49 50 let targetLabel = (<Jeqz>jumps[0]).getTarget(); 51 // The last instruction is return. 52 expect(targetLabel).to.equal(insns[insns.length - 2]); 53 }); 54 55 it('ifConditionWithThenStatement', function () { 56 let insns = compileMainSnippet("let a = 2;\n" + 57 "if (a > 4) {\n" + 58 " a = 3;\n" + 59 "}"); 60 let jumps = insns.filter(item => item instanceof Jeqz); 61 62 expect(jumps.length).to.equal(1); 63 64 let targetLabel = (<Jeqz>jumps[0]).getTarget(); 65 // The last instruction is return. 66 expect(targetLabel).to.equal(insns[insns.length - 2]); 67 }); 68 69 it('ifConditionWithThenStatementAndElseStatement', function () { 70 let insns = compileMainSnippet("let a = 5;\n" + 71 "if (a > 3) {\n" + 72 " a = 2;\n" + 73 "} else {\n" + 74 " a = 4;\n" + 75 "}"); 76 let jumps = insns.filter(item => (item instanceof Jeqz || item instanceof Jmp)); 77 let labels = insns.filter(item => (item instanceof Label)); 78 79 expect(jumps.length).to.equal(2); 80 expect(labels.length).to.equal(2); 81 82 let elseLabel = (<Jeqz>jumps[0]).getTarget(); 83 let endIfLabel = (<Jmp>jumps[1]).getTarget(); 84 85 expect(elseLabel).to.equal(labels[0]); 86 expect(endIfLabel).to.equal(labels[1]); 87 88 expect(elseLabel).to.equal(insns[insns.length - 5]); 89 expect(endIfLabel).to.equal(insns[insns.length - 2]); 90 }); 91 92 it("if (a & b)", function () { 93 let insns = compileMainSnippet(` 94 let a = 1; 95 let b = 2; 96 if (a & b) { 97 } 98 `); 99 IRNode.pg = new PandaGen("foo", creatAstFromSnippet(` 100 let a = 1; 101 let b = 2; 102 if (a & b) { 103 } 104 `), 0, undefined); 105 IRNode.pg.updateIcSize(2); 106 let lhs = new VReg(); 107 let endIfLabel = new Label(); 108 let expected = [ 109 new Tryldglobalbyname(new Imm(2), 'a'), 110 new Sta(lhs), 111 new Tryldglobalbyname(new Imm(3), 'b'), 112 new And2(new Imm(4), lhs), 113 new Istrue(), 114 new Jeqz(endIfLabel), 115 endIfLabel, 116 ]; 117 insns = insns.slice(4, insns.length - 1); // skip let a = 1; let b = 2; and return. 118 expect(checkInstructions(insns, expected)).to.be.true; 119 }); 120 121 it("if (a == b)", function () { 122 let insns = compileMainSnippet(` 123 let a = 1; 124 let b = 2; 125 if (a == b) { 126 } 127 `); 128 IRNode.pg = new PandaGen("foo", creatAstFromSnippet(` 129 let a = 1; 130 let b = 2; 131 if (a == b) { 132 } 133 `), 0, undefined); 134 IRNode.pg.updateIcSize(2); 135 136 let a = new VReg(); 137 let trueReg = new VReg(); 138 let endIfLabel = new Label(); 139 let expected = [ 140 new Tryldglobalbyname(new Imm(2), 'a'), 141 new Sta(a), 142 new Tryldglobalbyname(new Imm(3), 'b'), 143 new Eq(new Imm(4), trueReg), 144 new Jeqz(endIfLabel), 145 endIfLabel, 146 ]; 147 insns = insns.slice(4, insns.length - 1); // skip let a = 1; let b = 2; and return. 148 expect(checkInstructions(insns, expected)).to.be.true; 149 }); 150 151 it("let a = true ? 5 : 0;", function () { 152 let insns = compileMainSnippet(`let a = true ? 5 : 0;`); 153 IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`let a = true ? 5 : 0;`), 0, undefined); 154 insns = insns.slice(0, insns.length - 1); 155 let expectedElseLabel = new Label(); 156 let expectedEndLabel = new Label(); 157 let expected = [ 158 new Lda(new VReg()), 159 new Istrue(), 160 new Jeqz(expectedElseLabel), 161 new Ldai(new Imm(5)), 162 new Jmp(expectedEndLabel), 163 expectedElseLabel, 164 new Ldai(new Imm(0)), 165 expectedEndLabel, 166 new Sttoglobalrecord(new Imm(0), 'a'), 167 ]; 168 expect(checkInstructions(insns, expected)).to.be.true; 169 170 let jumps = insns.filter(item => (item instanceof Jeqz || item instanceof Jmp)); 171 let labels = insns.filter(item => (item instanceof Label)); 172 173 expect(jumps.length).to.equal(2); 174 expect(labels.length).to.equal(2); 175 }); 176 177 it("if (true && 5) {}", function () { 178 let insns = compileMainSnippet("if (true && 5) {}"); 179 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("if (true && 5) {}"), 0, undefined); 180 let ifFalseLabel = new Label(); 181 let expected = [ 182 new Lda(new VReg()), 183 new Istrue(), 184 new Jeqz(ifFalseLabel), 185 new Ldai(new Imm(5)), 186 new Istrue(), 187 new Jeqz(ifFalseLabel), 188 ifFalseLabel, 189 new Returnundefined() 190 ] 191 expect(checkInstructions(insns, expected)).to.be.true; 192 }); 193 194 it("if (false || 5) {}", function () { 195 let insns = compileMainSnippet("if (false || 5) {}"); 196 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("if (false || 5) {}"), 0, undefined); 197 let ifFalseLabel = new Label(); 198 let endLabel = new Label(); 199 let expected = [ 200 new Lda(new VReg()), 201 new Isfalse(), 202 new Jeqz(endLabel), 203 new Ldai(new Imm(5)), 204 new Istrue(), 205 new Jeqz(ifFalseLabel), 206 endLabel, 207 ifFalseLabel, 208 new Returnundefined() 209 ] 210 expect(checkInstructions(insns, expected)).to.be.true; 211 }); 212}); 213