1/* 2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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*/ 15const { generateFunctionDirect } = require("./function_direct"); 16const { generateFunctionSync } = require("./function_sync"); 17const { generateFunctionAsync } = require("./function_async"); 18const { generateInterface } = require("./interface"); 19const { generateClass } = require("./class"); 20const { FuncType, InterfaceList, EnumList } = require("../tools/common"); 21const { generateEnum } = require("./enum"); 22const { generateFunctionOnOff } = require("./function_onoff"); 23const { NapiLog } = require("../tools/NapiLog"); 24const { addUniqFunc2List, addUniqObj2List } = require("../tools/tool"); 25 26function findParentByName(parentName, data) { 27 for (let i in data.interface) { 28 if (parentName == data.interface[i].name) { 29 return data.interface[i] 30 } 31 } 32 33 for (let i in data.class) { 34 if (parentName == data.class[i].name) { 35 return data.class[i] 36 } 37 } 38 return null 39} 40 41/** 42 * 生成父类的成员变量和方法 43 * @param currentObj 当前类 44 * @param data 全局数据上下文 45 * @param parentBody 输出参数,保存父类的成员变量和方法 46 * @returns void 47 */ 48function genParentPropties(currentObj, data, parentBody) { 49 for (let i in currentObj.body.parentNameList) { 50 let parentName = currentObj.body.parentNameList[i] 51 let parentObj = findParentByName(parentName, data) 52 if (!parentObj) { 53 NapiLog.logError("Failed to find %s's parent by name [%s]".format(currentObj.body.name, parentName)) 54 return 55 } 56 57 // 为父类添加子类的对象信息 58 addUniqObj2List(currentObj, parentObj.body.childList) 59 60 // 为当前类添加父类对象信息 61 addUniqObj2List(parentObj, currentObj.body.parentList) 62 63 for (let i in parentObj.body.value) { 64 // 添加父类的所有成员属性到parentBody 65 addUniqObj2List(parentObj.body.value[i], parentBody.value) 66 } 67 for (let i in parentObj.body.function) { 68 // 添加父类的所有成员方法到parentBody 69 addUniqFunc2List(parentObj.body.function[i], parentBody.function) 70 } 71 if (parentObj.body.parentNameList.length > 0) { 72 // 递归查找父类的父类 73 genParentPropties(parentObj, data, parentBody) 74 } 75 } 76} 77 78// 为有继承关系的interface和class类型建立父子类关系信息 79function genExtendsRelation(data) { 80 for (let i in data.interface) { 81 let ifObj = data.interface[i] 82 if (ifObj && ifObj.body.parentNameList && ifObj.body.parentNameList.length > 0) { 83 ifObj.body.parentBody = {value:[], function:[]} 84 genParentPropties(ifObj, data, ifObj.body.parentBody) 85 } 86 } 87 88 for (let i in data.class) { 89 let classObj = data.class[i] 90 if (classObj.body.parentName) { 91 classObj.body.parentBody = {value:[], function:[]} 92 genParentPropties(classObj, data, classObj.body.parentBody) 93 } 94 } 95} 96 97//生成module_middle.cpp、module.h、module.cpp 98function generateNamespace(name, data, inNamespace = "") { 99 let namespaceResult = { 100 implH: "", 101 implCpp: "", 102 middleFunc: "", 103 middleInit: "" 104 } 105 106 namespaceResult.middleInit += formatMiddleInit(inNamespace, name) 107 genExtendsRelation(data) 108 InterfaceList.push(data.interface) 109 EnumList.push(data.enum) 110 let result = generateEnumResult(data); 111 namespaceResult.implH += result.implH 112 namespaceResult.implCpp += result.implCpp 113 namespaceResult.middleInit += result.middleInit 114 for (let i in data.interface) { 115 let ii = data.interface[i] 116 let result = generateInterface(ii.name, ii.body, inNamespace + name + "::") 117 namespaceResult = getNamespaceResult(result, namespaceResult) 118 } 119 120 for (let i in data.class) { 121 let ii = data.class[i] 122 let result = generateClass(ii.name, ii.body, inNamespace + name + "::", ii.functiontType) 123 namespaceResult = getNamespaceResult(result, namespaceResult) 124 } 125 for (let i in data.function) { 126 let func = data.function[i] 127 let tmp = generateFunction(func, data) 128 namespaceResult.middleFunc += tmp[0] 129 namespaceResult.implH += tmp[1] 130 namespaceResult.implCpp += tmp[2] 131 namespaceResult.middleInit += ' pxt->DefineFunction("%s", %s%s::%s_middle%s);\n' 132 .format(func.name, inNamespace, name, func.name, inNamespace.length > 0 ? ", " + name : "") 133 } 134 for (let i in data.namespace) { 135 let ns = data.namespace[i] 136 let result = generateNamespace(ns.name, ns.body, inNamespace + name + "::") 137 namespaceResult = getNamespaceResult(result, namespaceResult) 138 } 139 InterfaceList.pop(); 140 EnumList.pop(); 141 if (inNamespace.length > 0) { 142 namespaceResult.middleInit += "}" 143 } 144 return generateResult(name, namespaceResult.implH, namespaceResult.implCpp, namespaceResult.middleFunc, 145 namespaceResult.middleInit) 146} 147 148function getNamespaceResult(subResult, returnResult) { 149 returnResult.middleFunc += subResult.middleBody 150 returnResult.implH += subResult.implH 151 returnResult.implCpp += subResult.implCpp 152 returnResult.middleInit += subResult.middleInit 153 return returnResult 154} 155 156function generateEnumResult(data) { 157 let resultEnum = { 158 implH: "", 159 implCpp: "", 160 middleInit: "" 161 } 162 163 for (let i in data.enum) { 164 let enumm = data.enum[i] 165 let result = generateEnum(enumm.name, enumm.body) 166 resultEnum.implH += result.implH 167 resultEnum.implCpp += result.implCpp 168 resultEnum.middleInit += result.midInitEnum 169 } 170 return resultEnum 171} 172 173function generateResult(name, implH, implCpp, middleFunc, middleInit) { 174 let result = { 175 implH: `namespace %s {%s\n}`.format(name, implH), 176 implCpp: `namespace %s {%s}`.format(name, implCpp), 177 middleBody: `namespace %s {%s}`.format(name, middleFunc), 178 middleInit: middleInit 179 } 180 return result; 181} 182 183function generateFunction(func, data) { 184 let tmp; 185 if (func.name == 'on' || func.name == 'off' ) { 186 return generateFunctionOnOff(func, data) 187 } 188 switch (func.type) { 189 case FuncType.DIRECT: 190 tmp = generateFunctionDirect(func, data) 191 break; 192 case FuncType.SYNC: 193 tmp = generateFunctionSync(func, data) 194 break 195 case FuncType.ASYNC: 196 case FuncType.PROMISE: 197 tmp = generateFunctionAsync(func, data) 198 break 199 default: 200 return 201 } 202 return tmp 203} 204 205function formatMiddleInit(inNamespace, name) { 206 let middleInit = "" 207 if (inNamespace.length > 0) { 208 let nsl = inNamespace.split("::") 209 nsl.pop() 210 let parentNs = nsl[nsl.length - 1] 211 middleInit = `{\nnapi_value %s=pxt->CreateSubObject(%s,"%s");\n` 212 .format(name, nsl.length == 1 ? "exports" : parentNs, name) 213 } 214 return middleInit 215} 216 217module.exports = { 218 generateNamespace, 219 getNamespaceResult, 220 generateEnumResult, 221 generateResult, 222 generateFunction, 223 formatMiddleInit 224}