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 Add2, 22 And2, 23 Ashr2, 24 Createemptyobject, 25 Div2, 26 Exp, 27 Mod2, 28 Mul2, 29 Or2, 30 Returnundefined, 31 Shl2, 32 Shr2, 33 Stglobalvar, 34 Sttoglobalrecord, 35 Stobjbyname, 36 Strictnoteq, 37 Sub2, 38 Tryldglobalbyname, 39 Trystglobalbyname, 40 Xor2, 41 Imm, 42 Jeqz, 43 Jmp, 44 Label, 45 Lda, 46 Ldai, 47 LdaStr, 48 Mov, 49 Sta, 50 VReg, 51 IRNode 52} from "../../src/irnodes"; 53import { checkInstructions, compileMainSnippet } from "../utils/base"; 54import { creatAstFromSnippet } from "../utils/asthelper"; 55import { PandaGen } from '../../src/pandagen'; 56 57describe("BinaryOperationsTest", function () { 58 it("2 + 3", function () { 59 let insns = compileMainSnippet("2 + 3"); 60 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("2 + 3"), 0, undefined); 61 let lhs = new VReg(); 62 let expected = [ 63 new Ldai(new Imm(2)), 64 new Sta(lhs), 65 new Ldai(new Imm(3)), 66 new Add2(new Imm(0), lhs), 67 new Returnundefined() 68 ]; 69 expect(checkInstructions(insns, expected)).to.be.true; 70 }); 71 72 it("5 - 1", function () { 73 let insns = compileMainSnippet("5 - 1"); 74 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("5 - 1"), 0, undefined); 75 let lhs = new VReg(); 76 let expected = [ 77 new Ldai(new Imm(5)), 78 new Sta(lhs), 79 new Ldai(new Imm(1)), 80 new Sub2(new Imm(0), lhs), 81 new Returnundefined() 82 ]; 83 expect(checkInstructions(insns, expected)).to.be.true; 84 }); 85 86 it("null ?? 1", function () { 87 let insns = compileMainSnippet("null ?? 1"); 88 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("null ?? 1"), 0, undefined); 89 90 let leftNullishLabel = new Label(); 91 let endLabel = new Label(); 92 let expected = [ 93 new Lda(new VReg()), 94 new Sta(new VReg()), 95 new Strictnoteq(new Imm(0), new VReg()), 96 new Jeqz(leftNullishLabel), 97 new Lda(new VReg()), 98 new Strictnoteq(new Imm(1), new VReg()), 99 new Jeqz(leftNullishLabel), 100 new Lda(new VReg()), 101 new Jmp(endLabel), 102 leftNullishLabel, 103 new Ldai(new Imm(1)), 104 endLabel, 105 new Returnundefined() 106 ]; 107 108 expect(checkInstructions(insns, expected)).to.be.true; 109 110 let jumps = insns.filter(item => item instanceof Jeqz || item instanceof Jmp) 111 112 expect(jumps.length).to.equal(3); 113 }); 114 115 it("undefined ?? 1", function () { 116 let insns = compileMainSnippet("undefined ?? 1"); 117 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("undefined ?? 1"), 0, undefined); 118 119 let leftNullishLabel = new Label(); 120 let endLabel = new Label(); 121 let expected = [ 122 new Lda(new VReg()), 123 new Sta(new VReg()), 124 new Strictnoteq(new Imm(0), new VReg()), 125 new Jeqz(leftNullishLabel), 126 new Lda(new VReg()), 127 new Strictnoteq(new Imm(1), new VReg()), 128 new Jeqz(leftNullishLabel), 129 130 new Lda(new VReg()), 131 new Jmp(endLabel), 132 133 leftNullishLabel, 134 new Ldai(new Imm(1)), 135 endLabel, 136 new Returnundefined() 137 ]; 138 expect(checkInstructions(insns, expected)).to.be.true; 139 140 let jumps = insns.filter(item => item instanceof Jeqz || item instanceof Jmp) 141 142 expect(jumps.length).to.equal(3); 143 }); 144 145 it("2 ?? 1", function () { 146 let insns = compileMainSnippet("2 ?? 1"); 147 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("2 ?? 1"), 0, undefined); 148 let lhs = new VReg(); 149 150 let leftNullishLabel = new Label(); 151 let endLabel = new Label(); 152 let expected = [ 153 new Ldai(new Imm(2)), 154 new Sta(new VReg()), 155 new Strictnoteq(new Imm(0), new VReg()), 156 new Jeqz(leftNullishLabel), 157 new Lda(new VReg()), 158 new Strictnoteq(new Imm(1), new VReg()), 159 new Jeqz(leftNullishLabel), 160 161 new Lda(lhs), 162 new Jmp(endLabel), 163 164 leftNullishLabel, 165 new Ldai(new Imm(1)), 166 endLabel, 167 new Returnundefined() 168 ]; 169 expect(checkInstructions(insns, expected)).to.be.true; 170 171 let jumps = insns.filter(item => item instanceof Jeqz || item instanceof Jmp) 172 173 expect(jumps.length).to.equal(3); 174 }); 175 176 it("3 * 4", function () { 177 let insns = compileMainSnippet("3 * 4"); 178 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("3 * 4"), 0, undefined); 179 let lhs = new VReg(); 180 let expected = [ 181 new Ldai(new Imm(3)), 182 new Sta(lhs), 183 new Ldai(new Imm(4)), 184 new Mul2(new Imm(0), lhs), 185 new Returnundefined() 186 ]; 187 expect(checkInstructions(insns, expected)).to.be.true; 188 }); 189 190 it("2 ** 3", function () { 191 let insns = compileMainSnippet("2 ** 3"); 192 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("2 ** 3"), 0, undefined); 193 let lhs = new VReg(); 194 let expected = [ 195 new Ldai(new Imm(2)), 196 new Sta(lhs), 197 new Ldai(new Imm(3)), 198 new Exp(new Imm(0), lhs), 199 new Returnundefined(), 200 ]; 201 expect(checkInstructions(insns, expected)).to.be.true; 202 }); 203 204 it("7 / 1", function () { 205 let insns = compileMainSnippet("7 / 1"); 206 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("7 / 1"), 0, undefined); 207 let lhs = new VReg(); 208 let expected = [ 209 new Ldai(new Imm(7)), 210 new Sta(lhs), 211 new Ldai(new Imm(1)), 212 new Div2(new Imm(0), lhs), 213 new Returnundefined() 214 ]; 215 expect(checkInstructions(insns, expected)).to.be.true; 216 }); 217 218 it("8 % 2", function () { 219 let insns = compileMainSnippet("8 % 2"); 220 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("8 % 2"), 0, undefined); 221 let lhs = new VReg(); 222 let expected = [ 223 new Ldai(new Imm(8)), 224 new Sta(lhs), 225 new Ldai(new Imm(2)), 226 new Mod2(new Imm(0), lhs), 227 new Returnundefined() 228 ]; 229 expect(checkInstructions(insns, expected)).to.be.true; 230 }); 231 232 it("2 << 3", function () { 233 let insns = compileMainSnippet("2 << 3"); 234 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("2 << 3"), 0, undefined); 235 let lhs = new VReg(); 236 let expected = [ 237 new Ldai(new Imm(2)), 238 new Sta(lhs), 239 new Ldai(new Imm(3)), 240 new Shl2(new Imm(0), lhs), 241 new Returnundefined() 242 ]; 243 expect(checkInstructions(insns, expected)).to.be.true; 244 }); 245 246 it("4 >> 1", function () { 247 let insns = compileMainSnippet("4 >> 1"); 248 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("4 >> 1"), 0, undefined); 249 let lhs = new VReg(); 250 let expected = [ 251 new Ldai(new Imm(4)), 252 new Sta(lhs), 253 new Ldai(new Imm(1)), 254 new Ashr2(new Imm(0), lhs), 255 new Returnundefined() 256 ]; 257 expect(checkInstructions(insns, expected)).to.be.true; 258 }); 259 260 it("12 >>> 2", function () { 261 let insns = compileMainSnippet("12 >>> 2"); 262 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("12 >>> 2"), 0, undefined); 263 let lhs = new VReg(); 264 let expected = [ 265 new Ldai(new Imm(12)), 266 new Sta(lhs), 267 new Ldai(new Imm(2)), 268 new Shr2(new Imm(0), lhs), 269 new Returnundefined() 270 ]; 271 expect(checkInstructions(insns, expected)).to.be.true; 272 }); 273 274 it("3 & 4", function () { 275 let insns = compileMainSnippet("3 & 4"); 276 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("3 & 4"), 0, undefined); 277 let lhs = new VReg(); 278 let expected = [ 279 new Ldai(new Imm(3)), 280 new Sta(lhs), 281 new Ldai(new Imm(4)), 282 new And2(new Imm(0), lhs), 283 new Returnundefined() 284 ]; 285 expect(checkInstructions(insns, expected)).to.be.true; 286 }); 287 288 it("2 | 5", function () { 289 let insns = compileMainSnippet("2 | 5"); 290 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("2 | 5"), 0, undefined); 291 let lhs = new VReg(); 292 let expected = [ 293 new Ldai(new Imm(2)), 294 new Sta(lhs), 295 new Ldai(new Imm(5)), 296 new Or2(new Imm(0), lhs), 297 new Returnundefined() 298 ]; 299 expect(checkInstructions(insns, expected)).to.be.true; 300 }); 301 302 it("7 ^ 3", function () { 303 let insns = compileMainSnippet("7 ^ 3"); 304 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("7 ^ 3"), 0, undefined); 305 let lhs = new VReg(); 306 let expected = [ 307 new Ldai(new Imm(7)), 308 new Sta(lhs), 309 new Ldai(new Imm(3)), 310 new Xor2(new Imm(0), lhs), 311 new Returnundefined() 312 ]; 313 expect(checkInstructions(insns, expected)).to.be.true; 314 }); 315 316 it("let i; i = 2", function () { 317 let insns = compileMainSnippet("let i; i = 2;"); 318 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("let i; i = 2;"), 0, undefined); 319 let expected = [ 320 new Lda(new VReg()), 321 new Sttoglobalrecord(new Imm(0), 'i'), 322 new Ldai(new Imm(2)), 323 new Trystglobalbyname(new Imm(1), 'i'), 324 new Returnundefined() 325 ]; 326 expect(checkInstructions(insns, expected)).to.be.true; 327 }); 328 329 it("a = 1 under strict mode", function () { 330 let insns = compileMainSnippet(` 331 "use strict"; 332 a = 1; 333 `); 334 IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`"use strict";a = 1;`), 0, undefined); 335 let expected = [ 336 new LdaStr("use strict"), 337 new Ldai(new Imm(1)), 338 new Trystglobalbyname(new Imm(0), "a"), 339 new Returnundefined() 340 ]; 341 342 expect(checkInstructions(insns, expected)).to.be.true; 343 }) 344 345 it("Assignment to ParenthesizedExpression case1", function () { 346 let insns = compileMainSnippet("((x)) = 1;"); 347 IRNode.pg = new PandaGen("foo", creatAstFromSnippet("((x)) = 1;"), 0, undefined); 348 349 let expected = [ 350 new Ldai(new Imm(1)), 351 new Stglobalvar(new Imm(0), "x"), 352 new Returnundefined() 353 ]; 354 355 expect(checkInstructions(insns, expected)).to.be.true; 356 }); 357 358 it("Assignment to ParenthesizedExpression case2", function () { 359 let insns = compileMainSnippet(`let a = {}; 360 ((a.b)) = 1;`); 361 IRNode.pg = new PandaGen("foo", creatAstFromSnippet(`let a = {};((a.b)) = 1;`), 0, undefined); 362 let objReg = new VReg(); 363 let tempObj = new VReg(); 364 365 let expected = [ 366 new Createemptyobject(), 367 new Sta(new VReg()), 368 // insns for `((a.b)) = 1` 369 new Sttoglobalrecord(new Imm(0), 'a'), 370 new Tryldglobalbyname(new Imm(1), 'a'), 371 new Sta(tempObj), 372 new Mov(objReg, tempObj), 373 new Ldai(new Imm(1)), 374 375 new Stobjbyname(new Imm(2), "b", objReg), 376 new Returnundefined() 377 ] 378 expect(checkInstructions(insns, expected)).to.be.true; 379 }); 380}); 381