• 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    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