18c339a94Sopenharmony_ci/*
28c339a94Sopenharmony_ci* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
38c339a94Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License");
48c339a94Sopenharmony_ci* you may not use this file except in compliance with the License.
58c339a94Sopenharmony_ci* You may obtain a copy of the License at
68c339a94Sopenharmony_ci*
78c339a94Sopenharmony_ci* http://www.apache.org/licenses/LICENSE-2.0
88c339a94Sopenharmony_ci*
98c339a94Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software
108c339a94Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS,
118c339a94Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128c339a94Sopenharmony_ci* See the License for the specific language governing permissions and
138c339a94Sopenharmony_ci* limitations under the License.
148c339a94Sopenharmony_ci*/
158c339a94Sopenharmony_ciconst { generateFunctionDirect } = require('./function_direct');
168c339a94Sopenharmony_ciconst { generateFunctionSync } = require('./function_sync');
178c339a94Sopenharmony_ciconst { generateFunctionAsync } = require('./function_async');
188c339a94Sopenharmony_ciconst { generateInterface } = require('./interface');
198c339a94Sopenharmony_ciconst { generateClass } = require('./class');
208c339a94Sopenharmony_ciconst { generateType } = require('./type');
218c339a94Sopenharmony_ciconst { FuncType, InterfaceList, EnumList, TypeList, CallFunctionList, isOnOffRegisterFunc, isCreateThreadsafeFunc } =
228c339a94Sopenharmony_cirequire('../tools/common');
238c339a94Sopenharmony_ciconst { generateEnum } = require('./enum');
248c339a94Sopenharmony_ciconst { generateFunctionOnOff } = require('./function_onoff');
258c339a94Sopenharmony_ciconst { generateThreadsafeFunc } = require('./function_threadsafe');
268c339a94Sopenharmony_ci
278c339a94Sopenharmony_ciconst { NapiLog } = require('../tools/NapiLog');
288c339a94Sopenharmony_ciconst { addUniqFunc2List, addUniqObj2List } = require('../tools/tool');
298c339a94Sopenharmony_ci
308c339a94Sopenharmony_cifunction findParentByName(parentName, data) {
318c339a94Sopenharmony_ci    for (let i in data.interface) {
328c339a94Sopenharmony_ci        if (parentName === data.interface[i].name) {
338c339a94Sopenharmony_ci            return data.interface[i];
348c339a94Sopenharmony_ci        }
358c339a94Sopenharmony_ci    }
368c339a94Sopenharmony_ci
378c339a94Sopenharmony_ci    for (let i in data.class) {
388c339a94Sopenharmony_ci        if (parentName === data.class[i].name) {
398c339a94Sopenharmony_ci            return data.class[i];
408c339a94Sopenharmony_ci        }
418c339a94Sopenharmony_ci    }
428c339a94Sopenharmony_ci    return null;
438c339a94Sopenharmony_ci}
448c339a94Sopenharmony_ci
458c339a94Sopenharmony_ci/**
468c339a94Sopenharmony_ci * 生成父类的成员变量和方法
478c339a94Sopenharmony_ci * @param currentObj 当前类
488c339a94Sopenharmony_ci * @param data 全局数据上下文
498c339a94Sopenharmony_ci * @param parentBody 输出参数,保存父类的成员变量和方法
508c339a94Sopenharmony_ci * @returns void
518c339a94Sopenharmony_ci */
528c339a94Sopenharmony_cifunction genParentPropties(currentObj, data, parentBody) {
538c339a94Sopenharmony_ci    for (let i in currentObj.body.parentNameList) {
548c339a94Sopenharmony_ci        let parentName = currentObj.body.parentNameList[i];
558c339a94Sopenharmony_ci        let parentObj = findParentByName(parentName, data);
568c339a94Sopenharmony_ci        if (!parentObj) {
578c339a94Sopenharmony_ci            NapiLog.logError("Failed to find %s's parent by name [%s]".format(currentObj.body.name, parentName));
588c339a94Sopenharmony_ci            return;
598c339a94Sopenharmony_ci        }
608c339a94Sopenharmony_ci
618c339a94Sopenharmony_ci        // 为父类添加子类的对象信息
628c339a94Sopenharmony_ci        addUniqObj2List(currentObj, parentObj.body.childList);
638c339a94Sopenharmony_ci
648c339a94Sopenharmony_ci        // 为当前类添加父类对象信息
658c339a94Sopenharmony_ci        addUniqObj2List(parentObj, currentObj.body.parentList);
668c339a94Sopenharmony_ci
678c339a94Sopenharmony_ci        for (let i in parentObj.body.value) {
688c339a94Sopenharmony_ci            // 添加父类的所有成员属性到parentBody
698c339a94Sopenharmony_ci            addUniqObj2List(parentObj.body.value[i], parentBody.value);
708c339a94Sopenharmony_ci        }
718c339a94Sopenharmony_ci        for (let i in parentObj.body.function) {
728c339a94Sopenharmony_ci            // 添加父类的所有成员方法到parentBody
738c339a94Sopenharmony_ci            addUniqFunc2List(parentObj.body.function[i], parentBody.function);
748c339a94Sopenharmony_ci        }
758c339a94Sopenharmony_ci        if (parentObj.body.parentNameList.length > 0) {
768c339a94Sopenharmony_ci            // 递归查找父类的父类
778c339a94Sopenharmony_ci            genParentPropties(parentObj, data, parentBody);
788c339a94Sopenharmony_ci        }
798c339a94Sopenharmony_ci    }
808c339a94Sopenharmony_ci}
818c339a94Sopenharmony_ci
828c339a94Sopenharmony_ci// 为有继承关系的interface和class类型建立父子类关系信息
838c339a94Sopenharmony_cifunction genExtendsRelation(data) {
848c339a94Sopenharmony_ci    for (let i in data.interface) {
858c339a94Sopenharmony_ci        let ifObj = data.interface[i];
868c339a94Sopenharmony_ci        if (ifObj && ifObj.body.parentNameList && ifObj.body.parentNameList.length > 0) {
878c339a94Sopenharmony_ci            ifObj.body.parentBody = {value:[], function:[]};
888c339a94Sopenharmony_ci            genParentPropties(ifObj, data, ifObj.body.parentBody);
898c339a94Sopenharmony_ci        }
908c339a94Sopenharmony_ci    }
918c339a94Sopenharmony_ci
928c339a94Sopenharmony_ci    for (let i in data.class) {
938c339a94Sopenharmony_ci        let classObj = data.class[i];
948c339a94Sopenharmony_ci        if (classObj.body.parentName) {
958c339a94Sopenharmony_ci            classObj.body.parentBody = {value:[], function:[]};
968c339a94Sopenharmony_ci            genParentPropties(classObj, data, classObj.body.parentBody);
978c339a94Sopenharmony_ci        }
988c339a94Sopenharmony_ci    }
998c339a94Sopenharmony_ci}
1008c339a94Sopenharmony_ci
1018c339a94Sopenharmony_ci//生成module_middle.cpp、module.h、module.cpp
1028c339a94Sopenharmony_cifunction generateNamespace(name, data, inNamespace = '') {
1038c339a94Sopenharmony_ci    let namespaceResult = { implH: '', implCpp: '', middleFunc: '', middleInit: '', declarationH: '', middleH: '', middleInitEnumDef: '' };
1048c339a94Sopenharmony_ci    namespaceResult.middleInit += formatMiddleInit(inNamespace, name);
1058c339a94Sopenharmony_ci    genExtendsRelation(data);
1068c339a94Sopenharmony_ci    InterfaceList.push(data.interface);
1078c339a94Sopenharmony_ci    TypeList.push(data.type);
1088c339a94Sopenharmony_ci    EnumList.push(data.enum);
1098c339a94Sopenharmony_ci    CallFunctionList.push(data.callFunction);
1108c339a94Sopenharmony_ci    let toolNamespace = getToolNamespaceFunc(inNamespace, name);
1118c339a94Sopenharmony_ci    enumNamespaceFunction(data, namespaceResult, inNamespace, name, toolNamespace);
1128c339a94Sopenharmony_ci    for (let i in data.type) {
1138c339a94Sopenharmony_ci      let ii = data.type[i];
1148c339a94Sopenharmony_ci      let result = generateType(ii.name, ii.body, inNamespace + name + '::', inNamespace, name, toolNamespace);
1158c339a94Sopenharmony_ci      namespaceResult = getNamespaceResult(result, namespaceResult);
1168c339a94Sopenharmony_ci    }
1178c339a94Sopenharmony_ci    for (let i in data.interface) {
1188c339a94Sopenharmony_ci        let ii = data.interface[i];
1198c339a94Sopenharmony_ci        let result = generateInterface(ii.name, ii.body, inNamespace + name + '::');
1208c339a94Sopenharmony_ci        namespaceResult = getNamespaceResult(result, namespaceResult);
1218c339a94Sopenharmony_ci    }
1228c339a94Sopenharmony_ci    for (let i in data.class) {
1238c339a94Sopenharmony_ci        let ii = data.class[i];
1248c339a94Sopenharmony_ci        let result = generateClass(ii.name, ii.body, inNamespace + name + '::', ii.functiontType);
1258c339a94Sopenharmony_ci        namespaceResult = getNamespaceResult(result, namespaceResult);
1268c339a94Sopenharmony_ci    }
1278c339a94Sopenharmony_ci    namespaceResult.implH = namespaceResult.declarationH + namespaceResult.implH;
1288c339a94Sopenharmony_ci    for (let i in data.function) {
1298c339a94Sopenharmony_ci        genNamespaceFunc(data, i, namespaceResult, inNamespace, name);
1308c339a94Sopenharmony_ci    }
1318c339a94Sopenharmony_ci    let flag = true;
1328c339a94Sopenharmony_ci    if (data.namespace.length !== 0) {
1338c339a94Sopenharmony_ci      flag = false;
1348c339a94Sopenharmony_ci    }
1358c339a94Sopenharmony_ci    for (let i in data.namespace) {
1368c339a94Sopenharmony_ci        let ns = data.namespace[i];
1378c339a94Sopenharmony_ci        let result = generateNamespace(ns.name, ns.body, inNamespace + name + '::');
1388c339a94Sopenharmony_ci        namespaceResult = getNamespaceResult(result, namespaceResult);
1398c339a94Sopenharmony_ci    }
1408c339a94Sopenharmony_ci    InterfaceList.pop();
1418c339a94Sopenharmony_ci    TypeList.pop();
1428c339a94Sopenharmony_ci    EnumList.pop();
1438c339a94Sopenharmony_ci    CallFunctionList.pop();
1448c339a94Sopenharmony_ci    if (inNamespace.length > 0) {
1458c339a94Sopenharmony_ci        namespaceResult.middleInit += '}';
1468c339a94Sopenharmony_ci        flag = true;
1478c339a94Sopenharmony_ci    }
1488c339a94Sopenharmony_ci    return generateResult(name, namespaceResult.implH, namespaceResult.implCpp, namespaceResult.middleFunc,
1498c339a94Sopenharmony_ci        namespaceResult.middleInit, namespaceResult.middleH, namespaceResult.middleInitEnumDef, flag);
1508c339a94Sopenharmony_ci}
1518c339a94Sopenharmony_ci
1528c339a94Sopenharmony_cifunction genNamespaceFunc(data, i, namespaceResult, inNamespace, name) {
1538c339a94Sopenharmony_ci    let func = data.function[i];
1548c339a94Sopenharmony_ci    let tmp = generateFunction(func, data, namespaceResult.implH);
1558c339a94Sopenharmony_ci    namespaceResult.middleFunc += tmp[0];
1568c339a94Sopenharmony_ci    namespaceResult.implH += tmp[1];
1578c339a94Sopenharmony_ci    namespaceResult.implCpp += tmp[2];
1588c339a94Sopenharmony_ci    namespaceResult.middleH += tmp[3];
1598c339a94Sopenharmony_ci    let toolNamespace = getToolNamespaceFunc(inNamespace, name);
1608c339a94Sopenharmony_ci    let middleTmp = '    pxt->DefineFunction("%s", %s%s::%s%s_middle%s);\n'
1618c339a94Sopenharmony_ci      .format(func.name, inNamespace, name, toolNamespace, func.name, inNamespace.length > 0 ? ', ' + name : '');
1628c339a94Sopenharmony_ci    if (namespaceResult.middleInit.indexOf(middleTmp) < 0) { // on方法不需要重复定义
1638c339a94Sopenharmony_ci      namespaceResult.middleInit += middleTmp;
1648c339a94Sopenharmony_ci    }
1658c339a94Sopenharmony_ci}
1668c339a94Sopenharmony_ci
1678c339a94Sopenharmony_cifunction getToolNamespaceFunc(inNamespace, name) {
1688c339a94Sopenharmony_ci    let toolNamespace;
1698c339a94Sopenharmony_ci    if (inNamespace !== '') {
1708c339a94Sopenharmony_ci        let index = inNamespace.lastIndexOf('::');
1718c339a94Sopenharmony_ci        let bodyTmp = inNamespace.substring(0, index);
1728c339a94Sopenharmony_ci        let index2 = bodyTmp.lastIndexOf('::');
1738c339a94Sopenharmony_ci        if (index2 > 0 && index2 < index) {
1748c339a94Sopenharmony_ci            toolNamespace = inNamespace.substring(index2 + 2, index) + '_interface::';
1758c339a94Sopenharmony_ci        } else {
1768c339a94Sopenharmony_ci            toolNamespace = name + '_interface::';
1778c339a94Sopenharmony_ci        }
1788c339a94Sopenharmony_ci    } else {
1798c339a94Sopenharmony_ci        toolNamespace = name + '_interface::';
1808c339a94Sopenharmony_ci    }
1818c339a94Sopenharmony_ci    return toolNamespace;
1828c339a94Sopenharmony_ci}
1838c339a94Sopenharmony_ci
1848c339a94Sopenharmony_cifunction enumNamespaceFunction(data, namespaceResult, inNamespace, nameSpaceName, toolNamespace) {
1858c339a94Sopenharmony_ci  let result = generateEnumResult(data, inNamespace, nameSpaceName, toolNamespace);
1868c339a94Sopenharmony_ci  namespaceResult.implH += result.implH;
1878c339a94Sopenharmony_ci  namespaceResult.implCpp += result.implCpp;
1888c339a94Sopenharmony_ci  namespaceResult.middleInit += result.middleInit;
1898c339a94Sopenharmony_ci  namespaceResult.middleInitEnumDef += result.midInitEnumDefine;
1908c339a94Sopenharmony_ci}
1918c339a94Sopenharmony_ci
1928c339a94Sopenharmony_cifunction getNamespaceResult(subResult, returnResult) {
1938c339a94Sopenharmony_ci    returnResult.middleFunc += subResult.middleBody;
1948c339a94Sopenharmony_ci    returnResult.implH += subResult.implH;
1958c339a94Sopenharmony_ci    returnResult.implCpp += subResult.implCpp;
1968c339a94Sopenharmony_ci    returnResult.middleInit += subResult.middleInit;
1978c339a94Sopenharmony_ci    returnResult.declarationH += subResult.declarationH;
1988c339a94Sopenharmony_ci    returnResult.middleH += subResult.middleH;
1998c339a94Sopenharmony_ci
2008c339a94Sopenharmony_ci    if (subResult.midInitEnumDefine !== undefined) {
2018c339a94Sopenharmony_ci      returnResult.middleInitEnumDef += subResult.midInitEnumDefine;
2028c339a94Sopenharmony_ci    }
2038c339a94Sopenharmony_ci
2048c339a94Sopenharmony_ci    return returnResult;
2058c339a94Sopenharmony_ci}
2068c339a94Sopenharmony_ci
2078c339a94Sopenharmony_ci  function generateEnumResult(data, inNamespace, nameSpaceName, toolNamespace) {
2088c339a94Sopenharmony_ci    let resultEnum = {
2098c339a94Sopenharmony_ci        implH: '',
2108c339a94Sopenharmony_ci        implCpp: '',
2118c339a94Sopenharmony_ci        middleInit: '',
2128c339a94Sopenharmony_ci        midInitEnumDefine: ''
2138c339a94Sopenharmony_ci    };
2148c339a94Sopenharmony_ci
2158c339a94Sopenharmony_ci    for (let i in data.enum) {
2168c339a94Sopenharmony_ci        let enumm = data.enum[i];
2178c339a94Sopenharmony_ci        let result = generateEnum(enumm.name, enumm.body, inNamespace, nameSpaceName, toolNamespace);
2188c339a94Sopenharmony_ci        resultEnum.implH += result.implH;
2198c339a94Sopenharmony_ci        resultEnum.implCpp += result.implCpp;
2208c339a94Sopenharmony_ci        resultEnum.middleInit += result.midInitEnum;
2218c339a94Sopenharmony_ci        resultEnum.midInitEnumDefine += result.midInitEnumDefine;
2228c339a94Sopenharmony_ci    }
2238c339a94Sopenharmony_ci    return resultEnum;
2248c339a94Sopenharmony_ci}
2258c339a94Sopenharmony_ci
2268c339a94Sopenharmony_cifunction generateResult(name, implH, implCpp, middleFunc, middleInit, middleH, middleInitEnumDef, flag) {
2278c339a94Sopenharmony_ci  let result;
2288c339a94Sopenharmony_ci  let middleEnumDefine = middleInitEnumDef.indexOf('undefined') >= 0 ? '' : middleInitEnumDef;
2298c339a94Sopenharmony_ci  if (flag) {
2308c339a94Sopenharmony_ci    result = {
2318c339a94Sopenharmony_ci      implH: `\nnamespace %s {\nnamespace %s_interface {%s\n}\n}`.format(name, name, implH),
2328c339a94Sopenharmony_ci      implCpp: `\nnamespace %s {\nnamespace %s_interface {%s\n}\n}`.format(name, name, implCpp),
2338c339a94Sopenharmony_ci      middleBody: `\nnamespace %s {\nnamespace %s_interface {\n%s%s\n}\n}`.format(name, name, middleEnumDefine, middleFunc),
2348c339a94Sopenharmony_ci      middleInit: middleInit,
2358c339a94Sopenharmony_ci      middleH: `\nnamespace %s {\nnamespace %s_interface {%s\n}\n}`.format(name, name, middleH)
2368c339a94Sopenharmony_ci    };
2378c339a94Sopenharmony_ci  } else {
2388c339a94Sopenharmony_ci        result = {
2398c339a94Sopenharmony_ci        implH: `\nnamespace %s {%s\n}`.format(name, implH),
2408c339a94Sopenharmony_ci        implCpp: `\nnamespace %s {%s}`.format(name, implCpp),
2418c339a94Sopenharmony_ci        middleBody: `\nnamespace %s {\n%s%s}`.format(name, middleEnumDefine, middleFunc),
2428c339a94Sopenharmony_ci        middleInit: middleInit,
2438c339a94Sopenharmony_ci        middleH: `\nnamespace %s {%s\n}`.format(name, middleH)
2448c339a94Sopenharmony_ci    };
2458c339a94Sopenharmony_ci  }
2468c339a94Sopenharmony_ci  return result;
2478c339a94Sopenharmony_ci}
2488c339a94Sopenharmony_ci
2498c339a94Sopenharmony_cifunction generateFunction(func, data, implH = null) {
2508c339a94Sopenharmony_ci    let tmp;
2518c339a94Sopenharmony_ci    let className;
2528c339a94Sopenharmony_ci    if (isOnOffRegisterFunc(func.name)) {
2538c339a94Sopenharmony_ci        return generateFunctionOnOff(func, data);
2548c339a94Sopenharmony_ci    } else if (isCreateThreadsafeFunc(func.name)) {
2558c339a94Sopenharmony_ci        return generateThreadsafeFunc(func, data);
2568c339a94Sopenharmony_ci    }
2578c339a94Sopenharmony_ci    switch (func.type) {
2588c339a94Sopenharmony_ci        case FuncType.DIRECT:
2598c339a94Sopenharmony_ci            tmp = generateFunctionDirect(func, data);
2608c339a94Sopenharmony_ci            break;
2618c339a94Sopenharmony_ci        case FuncType.SYNC:
2628c339a94Sopenharmony_ci            tmp = generateFunctionSync(func, data);
2638c339a94Sopenharmony_ci            break;
2648c339a94Sopenharmony_ci        case FuncType.ASYNC:
2658c339a94Sopenharmony_ci        case FuncType.PROMISE:
2668c339a94Sopenharmony_ci            tmp = generateFunctionAsync(func, data, className, implH);
2678c339a94Sopenharmony_ci            break;
2688c339a94Sopenharmony_ci        default:
2698c339a94Sopenharmony_ci            break;
2708c339a94Sopenharmony_ci    }
2718c339a94Sopenharmony_ci    return tmp;
2728c339a94Sopenharmony_ci}
2738c339a94Sopenharmony_ci
2748c339a94Sopenharmony_cifunction formatMiddleInit(inNamespace, name) {
2758c339a94Sopenharmony_ci    let middleInit = '';
2768c339a94Sopenharmony_ci    if (inNamespace.length > 0) {
2778c339a94Sopenharmony_ci        let nsl = inNamespace.split('::');
2788c339a94Sopenharmony_ci        nsl.pop();
2798c339a94Sopenharmony_ci        let parentNs = nsl[nsl.length - 1];
2808c339a94Sopenharmony_ci        middleInit = `{\nnapi_value %s = pxt->CreateSubObject(%s, "%s");\n`
2818c339a94Sopenharmony_ci            .format(name, nsl.length === 1 ? 'exports' : parentNs, name);
2828c339a94Sopenharmony_ci    }
2838c339a94Sopenharmony_ci    return middleInit;
2848c339a94Sopenharmony_ci}
2858c339a94Sopenharmony_ci
2868c339a94Sopenharmony_cimodule.exports = {
2878c339a94Sopenharmony_ci    generateNamespace,
2888c339a94Sopenharmony_ci    getNamespaceResult,
2898c339a94Sopenharmony_ci    generateEnumResult,
2908c339a94Sopenharmony_ci    generateResult,
2918c339a94Sopenharmony_ci    generateFunction,
2928c339a94Sopenharmony_ci    formatMiddleInit
2938c339a94Sopenharmony_ci};
294