• Home
Name Date Size #Lines LOC

..--

headers_parser/22-Oct-2025-2,2091,408

.gitignoreD22-Oct-2025106 1110

CMakeLists.txtD22-Oct-202532.8 KiB654631

README.mdD22-Oct-202517.1 KiB558436

cppToCTypes.yamlD22-Oct-2025133.6 KiB4,0703,905

enums.rbD22-Oct-20253.9 KiB13398

es2panda_lib.cppD22-Oct-202547.5 KiB1,2311,045

es2panda_lib.hD22-Oct-202512.7 KiB276215

es2panda_lib.idl.erbD22-Oct-202512.7 KiB320266

es2panda_lib.rbD22-Oct-202553.6 KiB1,5401,315

es2panda_lib_decl.inc.erbD22-Oct-20253.1 KiB8368

es2panda_lib_enums.inc.erbD22-Oct-20251.6 KiB5145

es2panda_lib_impl.inc.erbD22-Oct-202511.9 KiB310275

es2panda_lib_include.inc.erbD22-Oct-2025722 2118

es2panda_lib_list.inc.erbD22-Oct-20251.8 KiB6454

ignoredAllowed.yamlD22-Oct-20255.6 KiB255218

public.hD22-Oct-20256.7 KiB228171

README.md

1# es2panda_lib generation
2
3> What is it?
4
5Automatic export of ArkTS public classes and methods into C API.
6
7> I fixed CODECHECK and got a new failure "UNSUPPORTED TYPE".
8
91) Check if your new method should be private and automatically excluded from C API, error will disappear.
10
112) Otherwise support method arguments types in `cppToCTypes.yaml`.
12
13> What is `cppToCTypes.yaml`
14
15It describes how C++ types should be transformed into C types in plugin API.
16Tranformation "one to many" is supported to express map of e.g. `std::vector<int>` to `int*, size_t pair` pair.
17
18## How to add new type:
19
201) Copy the template below to the end of [cppToCTypes.yaml](./cppToCTypes.yaml).
21
22    <details><summary>Template</summary>
23
24    ```yaml
25      # Describes C++ original argument.
26      - es2panda_arg:
27          name: '|arg_name|'
28          type:
29            name: 'FunctionSignature'
30            namespace: 'ir' # optional
31          min_ptr_depth: 1  # optional
32          max_ptr_depth: 1  # optional
33
34      # Describes C arguments, into which the original argument will be expanded.
35        new_args:
36        - type:
37            name: "es2panda_FunctionSignature"
38            ptr_depth: '|es2panda_arg.type.ptr_depth_int|'
39          name: '|arg_name|'
40          namespace: "ir::"
41
42      # Describes additional C return arguments IF original argument is return type and expands to multiple arguments.
43        return_args:
44        - type:
45            name: size_t
46            ptr_depth: 1
47          name: '|arg_name|Len'
48
49        cast:
50          # Create C++ variable from C argument.
51            expression: >-
52              auto |es2panda_arg.type.ptr_depth||arg_name|E2p =
53              reinterpret_cast<ir::FunctionSignature |es2panda_arg.type.ptr_depth|>(|arg_name|);
54
55          # Create C variable from C++ return value.
56            reverse_cast:
57              start: >-
58                reinterpret_cast<?const? es2panda_FunctionSignature |es2panda_arg.type.ptr_depth|>
59
60          # Cast C argument to C++ class, to call method from it.
61            call_cast:
62              call_var:
63                name: classInstance
64                type:
65                  name: es2panda_FunctionSignature
66                  ptr_depth: 1
67              start: >-
68                (reinterpret_cast<?const? ir::FunctionSignature *>(classInstance))->
69
70          # Create new class and return C++ pointer to it.
71            constructor_cast:
72              start: >-
73                ctxAllocator->New<ir::FunctionSignature>(
74              end: )
75
76          # Name of veriable, created by expression.
77            var_name: '|arg_name|E2p'
78    ```
79
80    </details>
81
822) Remove comments.
833) Remove unnecessary fields:
84    - `return_args` is needed only if you return new type from function and this type expands to multiple arguments.
85    - `reverse_cast` is needed only if you return new type from function.
86    - `call_cast` is needed only if you add new class to generation.
87    - `constructor_cast` is needed only if you add new class to generation.
884) Modify it for new type. Below you can see [Template description](#template-description).
89
90## Template description:
91All non-basic types are described in [cppToCTypes.yaml](./cppToCTypes.yaml).
92
93There are 4 keys in first layer:
941) `es2panda_arg`: describes original C++ argument. It is used to match which **template** from `cppToCTypes.yaml` should be used for current argument.
95
96    <details><summary>More info</summary>
97
98    FunctionSignature in `cppToCTypes.yaml`:
99    ```yaml
100    es2panda_arg:
101        name: '|arg_name|'
102        type:
103            name: 'FunctionSignature'
104            namespace: 'ir'
105        min_ptr_depth: 1
106    ```
107
108    ### Generator finds match if:
109    ```
110    original_argument['type']['name']      == es2panda_arg['type']['name'] &&
111    original_argument['type']['namespace'] == es2panda_arg['type']['namespace'] &&
112    original_argument['type']['ptr_depth'] >= es2panda_arg['min_ptr_depth'] &&
113    original_argument['type']['ptr_depth'] <= es2panda_arg['max_ptr_depth']
114    ```
115    If any of the fields are missing, the generator will skip the corresponding check (except for the type::name field).
116
117    ### What is `|arg_name|`:
118    It is placeholder. After matching **template**, generator stores placeholder values:
119    ```ruby
120    # Generator finds placeholder |arg_name| in es2panda_arg['name']
121    # It stores the same value from original_argument:
122    |arg_name| = original_argument['type']
123    ```
124
125    You can utilize this placeholder in various contexts, and it will be substituted with the saved value.
126
127    ### Addressing other fields not outlined in the **template**:
128    Following the alignment of the **template** and retention of placeholder values, es2panda_arg is supplanted by original_argument. Hence, other attributes are preserved.
129
130    ### Clarification on ptr_depth and ref_depth:
131
132    `ptr_depth` is number of `*` in argument.
133    `ref_depth` is number of `&` in argument.
134
135    #### Why is it needed:
136    `min_ptr_depth` and `max_ptr_depth` are needed to separate 0 and 1+ ptr-cases, because the es2panda API stores pointers to empty structures and is not able to provide an instance of the class, only a pointer to it (except for primitive C types).
137    For example:
138        `AstNode` -> `es2panda_AstNode *`
139        `AstNode *` -> `es2panda_AstNode *`
140        `AstNode **` -> `es2panda_AstNode **`
141    Where es2panda_AstNode is pointer to empty structure in es2panda API.
142
143    ---
144    </details>
145
1462) `new_args`: describes C arguments, into which the original argument will be expanded.
147
148    <details><summary>More info</summary>
149
150    FunctionSignature in `cppToCTypes.yaml`:
151    ```yaml
152    new_args:
153        - type:
154            name: "es2panda_FunctionSignature"
155            ptr_depth: 1
156        name: '|arg_name|'
157        namespace: "ir::"
158    ```
159
160    Describes argument for C-API:
161    ```c++
162    // original C++ argument:
163    ir::FunctionSignature *MyVarName
164
165    // new C argument:
166    es2panda_FunctionSignature *MyVarName
167    ```
168
169    **Note:** please manually write namespace in the format like `ir::` (with `::`).
170
171    ---
172    </details>
173
1743) `return_args`: describes additional C return arguments IF original argument is return type and expands to multiple arguments.
175
176    <details><summary>More info</summary>
177
178    FunctionSignature in `cppToCTypes.yaml`:
179    ```yaml
180    - name: '|arg_name|Len'
181      type:
182        name: size_t
183        ptr_depth: 1
184    ```
185
186    ### When it is needed:
187    If `original_argument` expands to **several argument** and if it is **return type** additional arguments should appear, through which the necessary values will be returned.
188    For example:
189    ```c++
190    // Example: ArenaVector<int> -> int *, size_t *
191
192    // C++ function
193    ArenaVector<int> Foo();
194
195    // C-API function
196    int *FooInAPI(size_t *arenaVectorLen /* return argument appeared */)
197    ```
198
199    ---
200    </details>
201
2024) `cast`:
203    - `expression`: create C++ variable from C argument.
204
205        <details><summary>More info</summary>
206
207        FunctionSignature in `cppToCTypes.yaml`:
208        ```yaml
209        expression: >-
210            auto |es2panda_arg.type.ptr_depth||arg_name|E2p =
211            reinterpret_cast<ir::FunctionSignature |es2panda_arg.type.ptr_depth|>(|arg_name|);
212        ```
213
214        Result:
215        ```c++
216        // C++ function
217        void Foo(FunctionSignature *myArgument);
218
219        // C-API function
220        void FooInAPI(es2panda_FunctionSignature *myArgument) {
221            auto *myArgumentE2p = reinterpret_cast<ir::FunctionSignature *>(myArgument);
222            // ... other code
223        }
224        ```
225
226        ### Note:
227        You can see clever placeholder `|es2panda_arg.type.ptr_depth|`. It allows to get value from `es2panda_arg['type']['ptr_depth']`.
228        If `es2panda_arg['type']['ptr_depth'] = 2`, then `|es2panda_arg.type.ptr_depth|` will be raplaced with `**` and `|es2panda_arg.type.ptr_depth_int|` will be replaced with `2`.
229
230        ---
231        </details>
232
233    - `reverse_cast`: create C variable from C++ return value.
234
235        <details><summary>More info</summary>
236
237        FunctionSignature in `cppToCTypes.yaml`:
238        ```yaml
239        reverse_cast:
240            start: >-
241                reinterpret_cast<?const? es2panda_FunctionSignature |es2panda_arg.type.ptr_depth|>
242        ```
243
244        Result:
245        ```c++
246        // C++ function
247        FunctionSignature *Foo();
248
249        // C-API function
250        es2panda_FunctionSignature *FooInAPI() {
251            // auto res = reverse_cast['start']( Foo() )reverse_cast['end']
252            auto res = reinterpret_cast<es2panda_FunctionSignature *>(Foo());
253            return res;
254        }
255        ```
256
257        ### Note:
258        You can see `?const?`, it will be replaced with `const` if the type is const, and will be deleted otherwise.
259
260        ---
261        </details>
262
263    - `call_cast`: cast C argument to C++ class, to call method from it.
264
265        <details><summary>More info</summary>
266
267        FunctionSignature in `cppToCTypes.yaml`:
268        ```yaml
269        call_cast:
270            call_var:
271                name: classInstance
272                type:
273                    name: es2panda_FunctionSignature
274                    ptr_depth: 1
275            start: >-
276                (reinterpret_cast<?const? ir::FunctionSignature *>(classInstance))->
277        ```
278
279        Result:
280        ```c++
281        // C++ method
282        class FunctionSignature {
283            void Foo();
284        }
285
286        // C-API function
287        void FooInAPI(es2panda_FunctionSignature *classInstance /* call_var appeared */) {
288            // call_cast['start']Foo();
289            (reinterpret_cast<ir::FunctionSignature *>(classInstance))->Foo();
290        }
291
292        ```
293
294        `call_var`: additional C argument - class pointer, to call method from.
295
296        ### Note:
297        You can see `?const?`, it will be replaced with `const` if the type is const, and will be deleted otherwise.
298
299        ---
300        </details>
301
302
303    - `constructor_cast`: create new class and return C++ pointer to it.
304
305        <details><summary>More info</summary>
306
307        FunctionSignature in `cppToCTypes.yaml`:
308        ```yaml
309        constructor_cast:
310            start: >-
311                ctxAllocator->New<ir::FunctionSignature>(
312            end: )
313        ```
314
315        Result:
316        ```c++
317        // C++ constructor
318        class FunctionSignature {
319            FunctionSignature(int arg1, int arg2);
320        }
321
322        // C-API function
323        es2panda_FunctionSignature FunctionSignatureInAPI(int arg1, int arg2) {
324            // return reverse_cast['start']( constructor_cast['start'] <ARGUMENTS> constructor_cast['end'] )reverse_cast['end']
325            return reinterpret_cast<es2panda_FunctionSignature *>(/* constructor cast -> */ ctxAllocator->New<ir::FunctionSignature>(arg1, arg2));
326        }
327        ```
328
329        ### Note:
330        Using only in constructors. Constructor cast is wrapped by reverse cast.
331
332        ---
333        </details>
334
335    - `var_name`: name of veriable, created by expression.
336
337        <details><summary>More info</summary>
338
339        FunctionSignature in `cppToCTypes.yaml`:
340        ```yaml
341        var_name: '|arg_name|E2p'
342        ```
343
344        Result:
345        ```c++
346        // C++ function
347        void Foo(FunctionSignature *myArgument);
348
349        // C-API function
350        void FooInAPI(es2panda_FunctionSignature *myArgument) {
351            // expression:
352            auto *myArgumentE2p = reinterpret_cast<ir::FunctionSignature *>(myArgument);
353
354            // ... other code
355
356            // calling C++ function, using new variable with name 'var_name'
357            Foo(myArgumentE2p /* var_name */);
358        }
359        ```
360
361        ---
362        </details>
363
364
365es2panda_lib_decl.inc, es2panda_lib_enums.inc, es2panda_lib_impl.inc, es2panda_lib_include.inc, es2panda_lib_list.inc
366
367## How to run:
368```bash
369ninja gen_api   # only generates *.inc files.
370
371ninja es2panda-public   # compiles es2panda_lib
372```
373You can find generated files in `<build>/tools/es2panda/generated/es2panda_lib`.
374
375## IDL
376
377### About our IDL specification (idlize package):
378- IDL is basically Webidl2 with some adjustments.
379- Webidl uses DomString, idlize uses string.
380
381Usefull links:
382- `idlize` package - [link](https://gitee.com/nikolay-igotti/idlize).
383- `sdk-idl` examples - [link](https://gitee.com/nikolay-igotti/interface_sdk-idl).
384
385
386### How to check IDL for correctness:
387```bash
388# Cmake
389mkdir build && cd build && cmake -GNinja -DCMAKE_BUILD_TYPE=Debug <runtime_core>/static_core
390
391# Run generation
392ninja gen_api
393
394# Cd to generated dir
395cd <build>/tools/es2panda/generated/es2panda_lib
396mkdir test
397
398# Check idl for correctness
399cp ./es2panda_lib.idl ./test/
400npx @azanat/idlize --idl2h --input-dir=<build>/tools/es2panda/generated/es2panda_lib/test
401
402# See results
403cat <build>/tools/es2panda/generated/es2panda_lib/generated/headers/arkoala_api_generated.h
404```
405
406
407### IDL generation rules:
408Manually written functions from the `es2panda_lib.h` were also manually transferred to `es2panda_lib.idl.rb`.
409Other methods are generated automatically.
410
411#### 1. Classes, structures, types from C++ represented in IDL as interfaces:
412```c++
413// C++
414typedef struct es2panda_Config es2panda_Config;
415
416// IDL
417[Entity=Class] interface es2panda_Config {};
418```
419
420#### 2. Enums are represented as `dictionary` in IDL with pre-calculated values.
421
422#### 3. Pointers to a function are represented as an interface with a single `Do` method whose signature matches that of the target function.
423```c++
424// C++
425typedef es2panda_AstNode *(*NodeTransformer)(es2panda_AstNode *);
426
427// IDL
428interface NodeTransformer {
429    AstNode Do(AstNode e2p_node);
430};
431```
432
433#### 4. C-pointers representation:
434All arguments except primitive types in IDL are the first pointer to an object.
435E.g. `AstNode *` in C equals to `AstNode` in IDL.
436
437For deeper ones:
438- `AstNode **` => `sequence<AstNode>`
439- `AstNode ***` => `sequence<sequence<AstNode>>`
440- etc.
441
442For primitive types:
443- `int` => `i32`
444- `int *` => `sequence<i32>`
445- `int **` => `sequence<sequence<i32>>`
446- etc.
447
448Exception:
449- `void *` => `VoidPtr`
450
451#### 5. Return argument `size_t *returnTypeLen` is omitted and not represented in IDL. Other return arguments are represented.
452
453#### 6. es2panda classes conversion:
454All the types/classes listed below are represented in the IDL without any changes:
455- ast_nodes:
456    - Classes from macro `AST_NODE_MAPPING`
457    - Classes from macro `AST_NODE_REINTERPRET_MAPPING`
458    - `AstNode`
459    - `Expression`
460    - `Statement`
461    - `TypeNode`
462- ast_node_additional_children:
463    - `TypedStatement`
464    - `ClassElement`
465    - `AnnotatedExpression`
466    - `Literal`
467    - `LoopStatement`
468    - `MaybeOptionalExpression`
469    - `Property`
470- ast_types:
471    - Classes from macro`TYPE_MAPPING`
472    - `Type`
473- ast_type_additional_children:
474    - `ETSStringType`
475    - `ETSDynamicType`
476    - `ETSAsyncFuncReturnType`
477    - `ETSDynamicFunctionType`
478    - `ETSEnumType`
479    - `ETSBigIntType`
480- ast_variables:
481    - `Variable`
482    - `LocalVariable`
483    - `GlobalVariable`
484    - `ModuleVariable`
485    - `EnumVariable`
486- scopes:
487    - Classes from macro `SCOPE_TYPES`
488    - `Scope`
489    - `VariableScope`
490- declarations:
491    - Classes from macro `DECLARATION_KINDS`
492    - `Decl`
493
494Other types/classes are represented in the same way as in C-API.
495
496
497#### 7. Primitive types conversion:
498- `bool` => `boolean`
499- `int` => `i32`
500- `size_t` => `u32`
501- `char` => `i8`
502- `int8_t` => `i8`
503- `uint8_t` => `u8`
504- `int16_t` => `i16`
505- `char16_t` => `i16`
506- `int32_t` => `i32`
507- `uint32_t` => `u32`
508- `int64_t` => `i64`
509- `uint64_t` => `u64`
510- `float` => `f32`
511- `double` => `f64`
512- `sequence<i8>` => `String`
513
514#### 8. Classes representation:
515Example:
516```c++
517// C++
518class UnaryExpression : public Expression {
519    explicit UnaryExpression(Expression *const argument);
520    Expression *Argument();
521    const Expression *Argument() const
522}
523
524// C-API
525es2panda_AstNode *(*CreateUnaryExpression)(es2panda_Context *context, es2panda_AstNode *argument);
526es2panda_AstNode *(*UnaryExpressionArgument)(es2panda_Context *context, es2panda_AstNode *classInstance);
527const es2panda_AstNode *(*UnaryExpressionArgumentConst)(es2panda_Context *context, es2panda_AstNode *classInstance);
528
529// IDL
530[Entity=Class, Es2pandaAstNodeType=147, cpp_namespace=ir] interface UnaryExpression: Expression {
531    static UnaryExpression Create(es2panda_Context context, Expression argument);
532    [get] Expression Argument(es2panda_Context context);
533    [get] Expression ArgumentConst(es2panda_Context context);
534}
535```
536
537More detailed:
538- `Entity=Class` indicates that it's a class in es2panda.
539- `Es2pandaAstNodeType` precalculated AstNodeType. This property is not present if the class does not have `AstNodeType` value.
540- `cpp_namespace` namespace in C++ es2panda.
541- `: Expression` Inherits the `Expression` class.
542- `Create` - class constructor.
543- `static` - all constructors marked as static methods.
544- `[get]` - marker for probably getter-methods. We do not guarantee 100% accuracy!
545
546#### 9. Class inheritance in IDL:
547- Some classes inherit `T`. It was decided to leave them for the sake of completeness.
548- If class inherits Template class e.g. `: public Annotated<Expression>` in IDL it is represented as `: Expression`.
549- If class has multi-inheritance, then inheritance is omitted and not represented in IDL.
550
551## Tests:
552Tests are located in `ets_frontend/ets2panda/test/unit/public`, their names start with "e2p_test_plugin".
553
554Run tests:
555```bash
556ninja es2panda-plugin-test
557```
558