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 EcmaLessdyn, 22 EcmaReturnundefined, 23 EcmaStlettoglobalrecord, 24 EcmaTryldglobalbyname, 25 EcmaTrystglobalbyname, 26 Imm, 27 Jeqz, 28 Jmp, 29 Label, LdaiDyn, 30 ResultType, 31 StaDyn, 32 VReg 33} from "../../src/irnodes"; 34import { checkInstructions, compileMainSnippet } from "../utils/base"; 35 36 37describe("DoWhileLoopTest", function () { 38 it('doWhileLoopEmpty', function () { 39 let insns = compileMainSnippet("do {} while (true)"); 40 41 let jumps = insns.filter(item => item instanceof Jmp); 42 43 expect(jumps.length).to.equal(1); 44 45 let jmpLabel = (<Jmp>jumps[0]).getTarget(); 46 47 expect(jmpLabel).to.equal(insns[0]); 48 }); 49 50 it('doWhileLoopWithBody', function () { 51 let insns = compileMainSnippet("let a = 5;" + 52 "do { a++ } while (a < 11);"); 53 54 let jumps = insns.filter(item => (item instanceof Jmp || item instanceof Jeqz)); 55 56 expect(jumps.length).to.equal(2); 57 58 let jgezLabel = (<Jmp>jumps[0]).getTarget(); 59 let jmpLabel = (<Jmp>jumps[1]).getTarget(); 60 61 expect(jmpLabel).to.equal(insns[2]); 62 expect(jgezLabel).to.equal(insns[15]); 63 64 expect(insns[13]).to.equal(jumps[0]); 65 expect(insns[14]).to.equal(jumps[1]); 66 }); 67 68 it('doWhileLoopWithContinue', function () { 69 let insns = compileMainSnippet("let a = 5;" + 70 "do { a = 1; continue; } while (a < 1);"); 71 let a = new VReg(); 72 let lhs = new VReg(); 73 let labelPre = new Label(); 74 let labelCond = new Label(); 75 let labelPost = new Label(); 76 let expected = [ 77 new LdaiDyn(new Imm(5)), 78 new EcmaStlettoglobalrecord('a'), 79 // body 80 labelPre, 81 new LdaiDyn(new Imm(1)), 82 new EcmaTrystglobalbyname('a'), 83 new Jmp(labelCond), // continue 84 // condition 85 labelCond, 86 new EcmaTryldglobalbyname('a'), 87 new StaDyn(lhs), 88 new LdaiDyn(new Imm(1)), 89 new EcmaLessdyn(lhs), 90 new Jeqz(labelPost), 91 new Jmp(labelPre), 92 labelPost, 93 new EcmaReturnundefined() 94 ] 95 96 // check the instruction kinds are the same as we expect 97 expect(checkInstructions(insns, expected)).to.be.true; 98 // check continue jumps to the expected instruction 99 let jmp = <Jmp>insns[5]; 100 let targetLabel = (jmp).getTarget(); 101 expect(targetLabel).to.equal(insns[6]); 102 }); 103 104 it('doWhileLoopWithBreak', function () { 105 let insns = compileMainSnippet("let a = 5;" + 106 "do { a = 1; break; } while (a < 1);"); 107 let a = new VReg(); 108 let lhs = new VReg(); 109 let labelPre = new Label(); 110 let labelPost = new Label(); 111 let labelCond = new Label(); 112 let expected = [ 113 new LdaiDyn(new Imm(5)), 114 new EcmaStlettoglobalrecord('a'), 115 //body 116 labelPre, 117 new LdaiDyn(new Imm(1)), 118 new EcmaTrystglobalbyname('a'), 119 new Jmp(labelPost), // break 120 // condition 121 labelCond, 122 new EcmaTryldglobalbyname('a'), 123 new StaDyn(lhs), 124 new LdaiDyn(new Imm(1)), 125 new EcmaLessdyn(lhs), 126 new Jeqz(labelPost), 127 new Jmp(labelPre), 128 labelPost, 129 new EcmaReturnundefined() 130 ] 131 132 // check the instruction kinds are the same as we expect 133 expect(checkInstructions(insns, expected)).to.be.true; 134 // check continue jumps to the expected instruction 135 let jmp = <Jmp>insns[5]; 136 let targetLabel = (jmp).getTarget(); 137 expect(targetLabel).to.equal(insns[13]); 138 }); 139});