1 /*
2 * Copyright (c) 2022-2025 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 #include <common.h>
17
18 using std::string, std::cout, std::endl, std::vector;
19
20 static es2panda_Impl *impl = nullptr;
21
22 #ifdef KOALA_WINDOWS
23 #include <windows.h>
24 #define PLUGIN_DIR "windows_host_tools"
25 #define LIB_PREFIX "lib"
26 #define LIB_SUFFIX ".dll"
27 #endif
28
29 #if defined(KOALA_LINUX) || defined(KOALA_MACOS)
30 #include <dlfcn.h>
31
32 #ifdef __x86_64__
33 #define PLUGIN_DIR "linux_host_tools"
34 #else
35 #define PLUGIN_DIR "linux_arm64_host_tools"
36 #endif
37
38 #define LIB_PREFIX "lib"
39 #define LIB_SUFFIX ".so"
40 #endif
41
42 const char* LIB_ES2PANDA_PUBLIC = LIB_PREFIX "es2panda_public" LIB_SUFFIX;
43
44 #ifdef KOALA_WINDOWS
45 const char *SEPARATOR = "\\";
46 #else
47 const char *SEPARATOR = "/";
48 #endif
49 const char *LIB_DIR = "lib";
50
51 static std::string ES2PANDA_LIB_PATH;
52
joinPath(vector<string> & paths)53 std::string joinPath(vector<string> &paths)
54 {
55 std::string res;
56 for (int i = 0; i < paths.size(); ++i) {
57 if (i == 0) {
58 res = paths[i];
59 } else {
60 res += SEPARATOR + paths[i];
61 }
62 }
63 return res;
64 }
65
impl_SetUpSoPath(KStringPtr & soPath)66 void impl_SetUpSoPath(KStringPtr &soPath)
67 {
68 ES2PANDA_LIB_PATH = std::string(soPath.c_str());
69 }
70 KOALA_INTEROP_V1(SetUpSoPath, KStringPtr);
71
FindLibrary()72 void* FindLibrary() {
73 std::vector<std::string> pathArray;
74 char* envValue = getenv("PANDA_SDK_PATH");
75 if (envValue) {
76 pathArray = {envValue, PLUGIN_DIR, LIB_DIR, LIB_ES2PANDA_PUBLIC};
77 } else if (!ES2PANDA_LIB_PATH.empty()) {
78 pathArray = {ES2PANDA_LIB_PATH, LIB_DIR, LIB_ES2PANDA_PUBLIC};
79 } else {
80 pathArray = {LIB_ES2PANDA_PUBLIC};
81 }
82 return loadLibrary(joinPath(pathArray));
83 }
84
GetImpl()85 es2panda_Impl *GetImpl() {
86 if (impl) {
87 return impl;
88 }
89 auto library = FindLibrary();
90 if (!library) {
91 std::cout << "Cannot find " << LIB_ES2PANDA_PUBLIC << endl;
92 }
93 auto symbol = findSymbol(library, "es2panda_GetImpl");
94 if (!symbol) {
95 std::cout << "Cannot find Impl Entry point" << endl;
96 }
97 impl = reinterpret_cast<es2panda_Impl *(*)(int)>(symbol)(ES2PANDA_LIB_VERSION);
98 return impl;
99 }
100
intToState(KInt state)101 es2panda_ContextState intToState(KInt state)
102 {
103 return es2panda_ContextState(state);
104 }
105
getString(KStringPtr ptr)106 string getString(KStringPtr ptr) {
107 return ptr.data();
108 }
109
getStringCopy(KStringPtr & ptr)110 char* getStringCopy(KStringPtr& ptr) {
111 return strdup(ptr.c_str());
112 }
113
unpackUInt(const KByte * bytes)114 inline KUInt unpackUInt(const KByte* bytes) {
115 const KUInt BYTE_0 = 0;
116 const KUInt BYTE_1 = 1;
117 const KUInt BYTE_2 = 2;
118 const KUInt BYTE_3 = 3;
119
120 const KUInt BYTE_1_SHIFT = 8;
121 const KUInt BYTE_2_SHIFT = 16;
122 const KUInt BYTE_3_SHIFT = 24;
123 return (
124 bytes[BYTE_0]
125 | (bytes[BYTE_1] << BYTE_1_SHIFT)
126 | (bytes[BYTE_2] << BYTE_2_SHIFT)
127 | (bytes[BYTE_3] << BYTE_3_SHIFT)
128 );
129 }
130
impl_CreateConfig(KInt argc,KStringArray argvPtr)131 KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) {
132 const std::size_t headerLen = 4;
133
134 const char** argv = new const char*[argc];
135 std::size_t position = headerLen;
136 std::size_t strLen;
137 for (std::size_t i = 0; i < static_cast<std::size_t>(argc); ++i) {
138 strLen = unpackUInt(argvPtr + position);
139 position += headerLen;
140 argv[i] = strdup(std::string(reinterpret_cast<const char*>(argvPtr + position), strLen).c_str());
141 position += strLen;
142 }
143 return GetImpl()->CreateConfig(argc, argv);
144 }
KOALA_INTEROP_2(CreateConfig,KNativePointer,KInt,KStringArray)145 KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray)
146
147 KNativePointer impl_DestroyConfig(KNativePointer configPtr) {
148 auto config = reinterpret_cast<es2panda_Config*>(configPtr);
149 GetImpl()->DestroyConfig(config);
150 return nullptr;
151 }
KOALA_INTEROP_1(DestroyConfig,KNativePointer,KNativePointer)152 KOALA_INTEROP_1(DestroyConfig, KNativePointer, KNativePointer)
153
154 KNativePointer impl_DestroyContext(KNativePointer contextPtr) {
155 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
156 GetImpl()->DestroyContext(context);
157 return nullptr;
158 }
KOALA_INTEROP_1(DestroyContext,KNativePointer,KNativePointer)159 KOALA_INTEROP_1(DestroyContext, KNativePointer, KNativePointer)
160
161 KNativePointer impl_UpdateCallExpression(
162 KNativePointer contextPtr,
163 KNativePointer nodePtr,
164 KNativePointer calleePtr,
165 KNativePointerArray argumentsPtr,
166 KInt argumentsLen,
167 KNativePointer typeParamsPtr,
168 KBoolean optionalT,
169 KBoolean trailingCommaT
170 ) {
171 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
172 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
173 auto callee = reinterpret_cast<es2panda_AstNode*>(calleePtr);
174 auto arguments = reinterpret_cast<es2panda_AstNode**>(argumentsPtr);
175 auto typeParams = reinterpret_cast<es2panda_AstNode*>(typeParamsPtr);
176 auto optional = static_cast<bool>(optionalT);
177 auto trailingComma = static_cast<bool>(trailingCommaT);
178
179 auto nn = GetImpl()->CreateCallExpression(
180 context, callee, arguments, argumentsLen, typeParams, optional, trailingComma
181 );
182 GetImpl()->AstNodeSetOriginalNode(context, nn, node);
183 return nn;
184 }
KOALA_INTEROP_8(UpdateCallExpression,KNativePointer,KNativePointer,KNativePointer,KNativePointer,KNativePointerArray,KInt,KNativePointer,KBoolean,KBoolean)185 KOALA_INTEROP_8(UpdateCallExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer, KBoolean, KBoolean)
186
187 KInt impl_IdentifierIdentifierFlags(KNativePointer contextPtr, KNativePointer nodePtr) {
188 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
189 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
190
191 return
192 (GetImpl()->IdentifierIsOptionalConst(context, node) ? (1 << 0) : 0) |
193 (GetImpl()->IdentifierIsReferenceConst(context, node) ? (1 << 1) : 0) |
194 (GetImpl()->IdentifierIsTdzConst(context, node) ? (1 << 2) : 0);
195 }
196 KOALA_INTEROP_2(IdentifierIdentifierFlags, KInt, KNativePointer, KNativePointer)
197
198 /*
199 TODO: NOT FROM API (shouldn't be there)
200 -----------------------------------------------------------------------------------------------------------------------------
201 */
202
203 es2panda_AstNode * cachedParentNode;
204 es2panda_Context * cachedContext;
205
changeParent(es2panda_AstNode * child)206 static void changeParent(es2panda_AstNode *child)
207 {
208 GetImpl()->AstNodeSetParent(cachedContext, child, cachedParentNode);
209 }
210
SetRightParent(es2panda_AstNode * node,void * arg)211 static void SetRightParent(es2panda_AstNode *node, void *arg)
212 {
213 es2panda_Context *ctx = static_cast<es2panda_Context *>(arg);
214 cachedContext = ctx;
215 cachedParentNode = node;
216
217 GetImpl()->AstNodeIterateConst(ctx, node, changeParent);
218 }
219
impl_AstNodeUpdateAll(KNativePointer contextPtr,KNativePointer programPtr)220 KNativePointer impl_AstNodeUpdateAll(KNativePointer contextPtr, KNativePointer programPtr) {
221 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
222 auto program = reinterpret_cast<es2panda_AstNode*>(programPtr);
223
224 GetImpl()->AstNodeForEach(program, SetRightParent, context);
225 return program;
226 }
KOALA_INTEROP_2(AstNodeUpdateAll,KNativePointer,KNativePointer,KNativePointer)227 KOALA_INTEROP_2(AstNodeUpdateAll, KNativePointer, KNativePointer, KNativePointer)
228
229 KNativePointer impl_AstNodeUpdateChildren(KNativePointer contextPtr, KNativePointer nodePtr) {
230 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
231 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
232 cachedParentNode = node;
233
234 GetImpl()->AstNodeIterateConst(context, node, changeParent);
235 return node;
236 }
237 KOALA_INTEROP_2(AstNodeUpdateChildren, KNativePointer, KNativePointer, KNativePointer)
238
239 std::vector<void*> cachedChildren;
240
visitChild(es2panda_AstNode * node)241 static void visitChild(es2panda_AstNode *node) {
242 cachedChildren.emplace_back(node);
243 }
244
impl_AstNodeChildren(KNativePointer contextPtr,KNativePointer nodePtr)245 KNativePointer impl_AstNodeChildren(
246 KNativePointer contextPtr,
247 KNativePointer nodePtr
248 ) {
249 auto context = reinterpret_cast<es2panda_Context*>(contextPtr);
250 auto node = reinterpret_cast<es2panda_AstNode*>(nodePtr);
251 cachedContext = context;
252 cachedChildren.clear();
253
254 GetImpl()->AstNodeIterateConst(context, node, visitChild);
255 return new std::vector(cachedChildren);
256 }
257 KOALA_INTEROP_2(AstNodeChildren, KNativePointer, KNativePointer, KNativePointer)
258
259 /*
260 -----------------------------------------------------------------------------------------------------------------------------
261 */
262