idlize

Форк
0
/
idl2h.ts 
232 строки · 8.8 Кб
1
/*
2
 * Copyright (c) 2024 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

16
import {
17
    IDLCallback,
18
    IDLConstructor,
19
    IDLContainerType, IDLEntry, IDLEnum, IDLFunction, IDLInterface, IDLKind, IDLProperty, IDLType, IDLTypedef,
20
    IDLUnionType,
21
    IDLVariable, hasExtAttribute, isTypeParameterType, printType
22
} from "./idl"
23
import { TypeChecker, TypeKind } from "./typecheck";
24
import { capitalize, stringOrNone, toSet } from "./util";
25

26
/**
27
 * TODOs
28
 *   * differentiate int vs float
29
 *   * generate scoped types
30
 */
31

32
const typeMapper = new Map<string, string>(
33
    [
34
        ["undefined", "void"],
35
        ["any", "void*"],
36
        ["number", "ArkUI_Float32"],
37
        ["string", "ArkUI_CharPtr"],
38
        ["boolean", "ArkUI_Bool"],
39
        ["LabelStyle", "ArkUILabelStyle"],
40
        ["ButtonType", "ArkUIButtonType"],
41
        ["ButtonStyleMode", "ArkUIButtonStyleMode"]
42
    ]
43
)
44

45
function mapInterfaceName(type: string, isReference: boolean = false): string {
46
    switch (type) {
47
        case "any": return "void*";
48
        case "undefined": return "void";
49
    }
50
    return `ArkUI${type}${isReference ? "*" : ""}`
51
}
52

53
let currentInterface: IDLInterface|undefined = undefined
54

55
function mapType(typechecker: TypeChecker, type: IDLType|undefined): string {
56
    if (!type) return "/* undefined type */ void"
57
    const rawType = type.name
58
    if (typeMapper.get(rawType)) {
59
        return typeMapper.get(rawType)!
60
    }
61
    if (isTypeParameterType(type) && currentInterface) {
62
        return mapInterfaceName(currentInterface.name!, true)
63
    }
64
    let declarations = typechecker.find(type.name)
65
    if (declarations.length > 0) {
66
        console.log(`Type for ${type.name} is ${TypeKind[declarations[0].kind]}`)
67
    } else {
68
        // console.log(`No type for ${type.name}`)
69
    }
70
    switch (type.kind) {
71
        case IDLKind.UnionType: return `ArkUI_${(type as IDLUnionType).types.map(it => capitalize(it.name)).join("Or")}`
72
        case IDLKind.ContainerType: return mapType(typechecker, (type as IDLContainerType).elementType[0]) + "*"
73
        case IDLKind.ReferenceType: return mapInterfaceName(rawType, true)
74
        case IDLKind.PrimitiveType: return rawType
75
    }
76
    throw new Error(`Unhandled ${type}: ${declarations}`)
77
}
78
function printProperty(typechecker: TypeChecker, iface: IDLInterface, idl: IDLProperty): stringOrNone[] {
79
    let isCommon = hasExtAttribute(idl, "CommonMethod")
80
    let arg = isCommon ? "ArkUINodeHandle node" : `${mapInterfaceName(iface.name, true)} instance`
81
    return [
82
        `\t${mapType(typechecker, idl.type)} (*get${capitalize(idl.name!)})(${arg});`,
83
        idl.isReadonly ? undefined : `\tvoid (*set${capitalize(idl.name!)})(${arg}, ${mapType(typechecker, idl.type)} value);`,
84
    ]
85
}
86

87
function printParameters(typechecker: TypeChecker, parameters: IDLVariable[] | undefined): string {
88
    if (!parameters) return ""
89
    return parameters?.map(param => `${mapType(typechecker, param.type)} ${param.name}`)?.join(", ")
90
}
91

92
function printConstructor(typechecker: TypeChecker, iface: IDLInterface, idl: IDLConstructor, index: number): string {
93
    return `\t${mapInterfaceName(iface.name)}* (*construct${index == 0 ? "" : index.toString()})(${printParameters(typechecker, idl.parameters)});`
94
}
95

96
function printDestructor(idl: IDLInterface): string {
97
    let isCommon = hasExtAttribute(idl, "CommonMethod")
98
    let arg = isCommon ? "ArkUINodeHandle node" : `${mapInterfaceName(idl.name, true)} instance`
99
    return `\tvoid (*destruct)(${arg});`
100
}
101

102
function printFunction(typechecker: TypeChecker, iface: IDLInterface, idl: IDLFunction): string {
103
    let isCommon = hasExtAttribute(idl, "CommonMethod")
104
    let maybeComma = idl.parameters.length > 0 ? ", " : ""
105
    let arg = isCommon ? "ArkUINodeHandle node" : `${mapInterfaceName(iface.name, true)} instance`
106
    return `\t${mapType(typechecker, idl.returnType)} (*${idl.name})(${arg}${maybeComma}${printParameters(typechecker, idl.parameters)});`
107
}
108

109
function printCallable(typechecker: TypeChecker, idl: IDLFunction, index: number): string {
110
    return `\t${mapType(typechecker, idl.returnType)} (*invoke${index == 0 ? "" : index.toString()})(${printParameters(typechecker, idl.parameters)});`
111
}
112

113
function printCallback(idl: IDLCallback): stringOrNone {
114
    return undefined
115
}
116

117
function printInterface(typechecker: TypeChecker, idl: IDLInterface, bodyOnly: boolean): stringOrNone[] {
118
    currentInterface = idl
119
    let result = [
120
        bodyOnly ? undefined : structName(idl),
121
        bodyOnly ? undefined : "{",
122
        ... idl.constructors?.map((it, index) => printConstructor(typechecker, idl, it, index)) ?? [],
123
        idl.constructors.length > 0  ? printDestructor(idl) : undefined,
124
        ... idl.properties?.flatMap(it => printProperty(typechecker, idl, it)) ?? [],
125
        ... idl.methods?.map(it => printFunction(typechecker, idl, it)) ?? [],
126
        ... idl.callables?.map((it, index) => printCallable(typechecker, it, index)) ?? [],
127
        bodyOnly ? undefined : "};"
128
    ]
129
    currentInterface = undefined
130
    return result
131
}
132

133
function structName(idl: IDLInterface): stringOrNone {
134
    let name = `struct ${mapInterfaceName(idl.name!)}`
135
    if (idl.inheritance.length > 0) {
136
        name += " : " + idl.inheritance.map(it => mapInterfaceName(it.name)).join(", ")
137
    }
138
    return name
139
}
140

141
function printEnum(typechecker: TypeChecker, idl: IDLEnum): stringOrNone[] {
142
    return [
143
        `enum ${mapInterfaceName(idl.name)} {`,
144
        ... idl.elements.map(it => `\t${it.name}${it.initializer ? " = " + it.initializer : "" },`),
145
        "};"
146
    ]
147
}
148

149
function printTypedef(typechecker: TypeChecker, idl: IDLTypedef): stringOrNone[] {
150
    return [
151
        `typedef  ${mapType(typechecker, idl.type)} ${idl.name};`
152
    ]
153
}
154

155
export function printHeader(typechecker: TypeChecker, idls: IDLEntry[], interfacesToGenerate: Set<string>): stringOrNone[] {
156
    let result: stringOrNone[] = []
157
    idls.forEach((idl) => {
158
        if (idl.kind == IDLKind.Class || idl.kind == IDLKind.Interface || idl.kind == IDLKind.AnonymousInterface) {
159
            let iface = idl as IDLInterface
160
            if (interfacesToGenerate.size == 0 || interfacesToGenerate.has(iface.name))
161
                result.push(... printInterface(typechecker, idl as IDLInterface, false))
162
        } else if (idl.kind == IDLKind.Enum) {
163
            if (interfacesToGenerate.size == 0)
164
                result.push(... printEnum(typechecker, idl as IDLEnum))
165
        } else if (idl.kind == IDLKind.Typedef) {
166
            if (interfacesToGenerate.size == 0)
167
                result.push(... printTypedef(typechecker, idl as IDLTypedef))
168
        } else if (idl.kind == IDLKind.Callback) {
169
            result.push(printCallback(idl as IDLCallback))
170
        } else
171
            result.push("unexpected kind: " + idl.kind)
172
    })
173
    return result
174
}
175

176
const prologue = `
177
/*
178
 * Copyright (c) 2024 Huawei Device Co., Ltd.
179
 * Licensed under the Apache License, Version 2.0 (the "License");
180
 * you may not use this file except in compliance with the License.
181
 * You may obtain a copy of the License at
182
 *
183
 * http://www.apache.org/licenses/LICENSE-2.0
184
 *
185
 * Unless required by applicable law or agreed to in writing, software
186
 * distributed under the License is distributed on an "AS IS" BASIS,
187
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
188
 * See the License for the specific language governing permissions and
189
 * limitations under the License.
190
 */
191
#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_INTERFACES_ARKOALA_API_H
192
#define FOUNDATION_ACE_FRAMEWORKS_CORE_INTERFACES_ARKOALA_API_H
193

194
#ifdef __cplusplus
195
extern "C" {
196
#endif
197

198
#define ARKUI_FULL_API_VERSION 67
199

200
typedef int ArkUI_Bool;
201
typedef int ArkUI_Int32;
202
typedef unsigned int ArkUI_Uint32;
203
typedef long long ArkUI_Int64;
204
typedef float ArkUI_Float32;
205
typedef double ArkUI_Float64;
206
typedef const char* ArkUI_CharPtr;
207

208
`
209

210
const epilogue = `
211
#ifdef __cplusplus
212
};
213
#endif
214

215
#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_INTERFACES_ARKOALA_API_H
216
`
217

218

219
export function wrapWithPrologueAndEpilogue(body: string): string {
220
    return prologue + body + epilogue
221
}
222

223
export function toHeaderString(typechecker: TypeChecker, allEntries: Array<IDLEntry[]>, interfacesToGenerate: string|undefined): string {
224
    const generatedHeader =
225
      prologue +
226
      allEntries
227
        .flatMap(it => printHeader(typechecker, it, toSet(interfacesToGenerate)))
228
        .filter(element => (element?.length ?? 0) > 0)
229
        .join("\n") +
230
      epilogue
231
    return generatedHeader
232
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.