• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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