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 Copyrestargs, 22 Definefunc, 23 Returnundefined, 24 Stglobalvar, 25 Sttoglobalrecord, 26 Stricteq, 27 Imm, 28 Jeqz, 29 Label, 30 Lda, 31 Ldai, 32 Sta, 33 VReg, 34 IRNode 35} from "../../src/irnodes"; 36import { 37 GlobalVariable, 38 LocalVariable 39} from "../../src/variable"; 40import { checkInstructions, compileAllSnippet, SnippetCompiler } from "../utils/base"; 41import { creatAstFromSnippet } from "../utils/asthelper" 42import { PandaGen } from '../../src/pandagen'; 43 44describe("FunctionDeclarationTest", function () { 45 it('function definition in the global scope', function () { 46 let snippetCompiler = new SnippetCompiler(); 47 snippetCompiler.compile("function foo() {}"); 48 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 49 let funcInternalName = "UnitTest.foo"; 50 let funcName = "foo"; 51 let expected = [ 52 new Definefunc(new Imm(0), funcInternalName, new Imm(0)), 53 new Stglobalvar(new Imm(1), funcName), 54 new Returnundefined() 55 ]; 56 let insns = snippetCompiler.getGlobalInsns(); 57 let globalScope = snippetCompiler.getGlobalScope(); 58 expect(checkInstructions(insns, expected)).to.be.true; 59 let foo = globalScope!.findLocal(funcName); 60 expect(foo != undefined).to.be.true; 61 expect(foo instanceof GlobalVariable).to.be.true; 62 }); 63 64 it('function redefinition in the global scope', function () { 65 let snippetCompiler = new SnippetCompiler(); 66 snippetCompiler.compile(` 67 function foo() {} 68 function foo() {} 69 `); 70 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 71 let expected = [ 72 new Definefunc(new Imm(0), "UnitTest.#2#foo", new Imm(0)), 73 new Stglobalvar(new Imm(1), "foo"), 74 new Returnundefined() 75 ]; 76 let insns = snippetCompiler.getGlobalInsns(); 77 let globalScope = snippetCompiler.getGlobalScope(); 78 expect(checkInstructions(insns, expected)).to.be.true; 79 let foo = globalScope!.findLocal("foo"); 80 expect(foo != undefined).to.be.true; 81 expect(foo instanceof GlobalVariable).to.be.true; 82 }); 83 84 it('function definition inside a function', function () { 85 let snippetCompiler = new SnippetCompiler(); 86 snippetCompiler.compile(`function out() {function foo() {}}`); 87 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 88 let funcReg = new VReg(); 89 let expected = [ 90 new Definefunc(new Imm(0), "UnitTest.foo", new Imm(0)), 91 new Sta(funcReg), 92 93 new Returnundefined() 94 ]; 95 let functionPg = snippetCompiler.getPandaGenByName("UnitTest.out"); 96 let insns = functionPg!.getInsns(); 97 let functionScope = functionPg!.getScope(); 98 99 expect(checkInstructions(insns!, expected)).to.be.true; 100 let foo = functionScope!.findLocal("foo"); 101 expect(foo != undefined).to.be.true; 102 expect(foo instanceof LocalVariable).to.be.true; 103 let parameterLength = functionPg!.getParameterLength(); 104 expect(parameterLength === 0).to.be.true; 105 }); 106 107 it("function expression", function () { 108 let snippetCompiler = new SnippetCompiler(); 109 snippetCompiler.compile("let foo = function() {}"); 110 let insns = snippetCompiler.getGlobalInsns(); 111 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 112 let expected = [ 113 new Definefunc(new Imm(0), "UnitTest.foo", new Imm(0)), 114 new Sttoglobalrecord(new Imm(1), "foo"), 115 new Returnundefined() 116 ]; 117 expect(checkInstructions(insns, expected)).to.be.true; 118 }); 119 120 it("Parameters with initializer", function () { 121 let compilerunit = compileAllSnippet("function test(a, b = 1) {}"); 122 let undefinedVReg = new VReg(); 123 let value = new VReg(); 124 let endLabel = new Label(); 125 126 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 127 let expectedMain = [ 128 new Definefunc(new Imm(0), "UnitTest.test", new Imm(1)), 129 new Stglobalvar(new Imm(1), "test"), 130 new Returnundefined() 131 ]; 132 133 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 134 let expectedFunc = [ 135 // func_test_0 136 new Lda(new VReg()), 137 new Stricteq(new Imm(0), undefinedVReg), 138 new Jeqz(endLabel), 139 new Ldai(new Imm(1)), 140 new Sta(value), 141 endLabel, 142 new Returnundefined(), 143 ]; 144 145 compilerunit.forEach(element => { 146 if (element.internalName === "UnitTest.func_main_0") { 147 let insns = element.getInsns(); 148 expect(checkInstructions(insns, expectedMain)).to.be.true; 149 } else if (element.internalName === "UnitTest.test") { 150 let insns = element.getInsns(); 151 expect(checkInstructions(insns, expectedFunc)).to.be.true; 152 let parameterLength = element.getParameterLength(); 153 expect(parameterLength === 1).to.be.true; 154 } 155 }); 156 }); 157 158 it("Rest Parameters", function () { 159 let snippetCompiler = new SnippetCompiler(); 160 snippetCompiler.compile(`function test(a, ...b) {}`); 161 162 IRNode.pg = new PandaGen("", creatAstFromSnippet(``), 0, undefined); 163 let idx = new Imm(1); 164 let lastParam = new VReg(); 165 let expectedFunc = [ 166 // func_test_0 167 new Copyrestargs(idx), 168 new Sta(lastParam), 169 new Returnundefined(), 170 ]; 171 172 let functionPg = snippetCompiler.getPandaGenByName("UnitTest.test"); 173 let insns = functionPg!.getInsns(); 174 175 expect(checkInstructions(insns, expectedFunc)).to.be.true; 176 }); 177}); 178