• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 <algorithm>
17 #include <cstddef>
18 #include <iostream>
19 #include <ostream>
20 #include <string>
21 #include "util.h"
22 #include "public/es2panda_lib.h"
23 
24 // NOLINTBEGIN
25 
26 /**
27  * Covered C API List:
28  *   bool (*IsVariableDeclaration)(es2panda_AstNode *ast);
29  *   void (*AstNodeIterateConst)(es2panda_Context *context, es2panda_AstNode *classInstance, NodeTraverser cb);
30  *   bool (*IsMethodDefinition)(es2panda_AstNode *ast);
31  *   es2panda_AstNode *(*MethodDefinitionFunction)(es2panda_Context *context, es2panda_AstNode *classInstance);
32  *   char *(*IdentifierName)(es2panda_Context *context, es2panda_AstNode *classInstance);
33  *   es2panda_AstNode *(*ScriptFunctionId)(es2panda_Context *context, es2panda_AstNode *classInstance);
34  *   void (*AstNodeSetParent)(es2panda_Context *context, es2panda_AstNode *classInstance, es2panda_AstNode *parent);
35  *   char *(*AstNodeDumpJSONConst)(es2panda_Context *context, es2panda_AstNode *classInstance);
36  *   es2panda_AstNode *(*ScriptFunctionBody)(es2panda_Context *context, es2panda_AstNode *classInstance);
37  *   es2panda_AstNode *(*CreateIdentifier1)(es2panda_Context *context, char *name);
38  *   es2panda_AstNode *(*CreateVariableDeclarator1)(es2panda_Context *context, Es2pandaVariableDeclaratorFlag flag,
39  *                                                  es2panda_AstNode *ident, es2panda_AstNode *init);
40  *   es2panda_AstNode *(*VariableDeclaratorInit)(es2panda_Context *context, es2panda_AstNode *classInstance);
41  *   es2panda_AstNode **(*VariableDeclarationDeclaratorsConst)(es2panda_Context *context,
42  *                                                             es2panda_AstNode *classInstance, size_t *returnTypeLen);
43  *   es2panda_AstNode *(*CreateVariableDeclaration)(es2panda_Context *context, Es2pandaVariableDeclarationKind kind,
44  *                                                  es2panda_AstNode **declarators, size_t declaratorsLen);
45  *   void (*BlockStatementSetStatements)(es2panda_Context *context, es2panda_AstNode *classInstance,
46  *                                       es2panda_AstNode **statementList, size_t statementListLen);
47  *   void (*AstNodeForEach)(es2panda_AstNode *ast, void (*func)(es2panda_AstNode *, void *), void *arg);
48  *   es2panda_Scope *(*AstNodeRebind)(es2panda_Context *ctx, es2panda_AstNode *node);
49  *   void *(*AllocMemory)(es2panda_Context *context, size_t numberOfElements, size_t sizeOfElement);
50  *   es2panda_AstNode *(*ProgramAst)(es2panda_Program *program);
51  *   es2panda_Program *(*ContextProgram)(es2panda_Context *context);
52  *   char *(*AstNodeDumpEtsSrcConst)(es2panda_Context *context, es2panda_AstNode *classInstance);
53  *   es2panda_Config *(*CreateConfig)(int argc, char const *const *argv);
54  *   es2panda_Context *(*CreateContextFromString)(es2panda_Config *config, const char *source, char const *file_name);
55  *   es2panda_Context *(*ProceedToState)(es2panda_Context *context, es2panda_ContextState state);
56  *   es2panda_ContextState (*ContextState)(es2panda_Context *context);
57  *   void (*DestroyConfig)(es2panda_Config *config);
58  *
59  */
60 static es2panda_Impl *impl = nullptr;
61 
62 static auto source = std::string("function main() { \nlet a = 5;\n }");
63 
64 static es2panda_AstNode *letStatement = nullptr;
65 static es2panda_AstNode *mainScriptFunc = nullptr;
66 static es2panda_Context *ctx = nullptr;
67 
68 es2panda_AstNode *parNode = nullptr;
69 es2panda_Context *newCtx = nullptr;
70 
FindLet(es2panda_AstNode * ast)71 static void FindLet(es2panda_AstNode *ast)
72 {
73     if (!impl->IsVariableDeclaration(ast)) {
74         impl->AstNodeIterateConst(ctx, ast, FindLet);
75         return;
76     }
77     letStatement = ast;
78 }
79 
FindMainDef(es2panda_AstNode * ast)80 static void FindMainDef(es2panda_AstNode *ast)
81 {
82     if (!impl->IsMethodDefinition(ast)) {
83         impl->AstNodeIterateConst(ctx, ast, FindMainDef);
84         return;
85     }
86     auto scriptFunc = impl->MethodDefinitionFunction(ctx, ast);
87     if (scriptFunc == nullptr ||
88         std::string("main") != impl->IdentifierName(ctx, impl->ScriptFunctionId(ctx, scriptFunc))) {
89         impl->AstNodeIterateConst(ctx, ast, FindMainDef);
90         return;
91     }
92     mainScriptFunc = scriptFunc;
93 }
94 
changeParent(es2panda_AstNode * child)95 static void changeParent(es2panda_AstNode *child)
96 {
97     impl->AstNodeSetParent(newCtx, child, parNode);
98 }
99 
SetRightParent(es2panda_AstNode * node,void * arg)100 static void SetRightParent(es2panda_AstNode *node, void *arg)
101 {
102     es2panda_Context *context = static_cast<es2panda_Context *>(arg);
103     newCtx = context;
104     parNode = node;
105     impl->AstNodeIterateConst(context, node, changeParent);
106 }
107 
ChangeAst(es2panda_Context * context,es2panda_AstNode * ast)108 static bool ChangeAst(es2panda_Context *context, es2panda_AstNode *ast)
109 {
110     std::cout << impl->AstNodeDumpJSONConst(context, ast) << std::endl;
111     size_t n = 0;
112     ctx = context;
113     impl->AstNodeIterateConst(context, ast, FindLet);
114     impl->AstNodeIterateConst(context, ast, FindMainDef);
115     if (mainScriptFunc == nullptr || letStatement == nullptr) {
116         return false;
117     }
118     auto mainFuncBody = impl->ScriptFunctionBody(context, mainScriptFunc);
119     std::cout << impl->AstNodeDumpJSONConst(context, mainScriptFunc) << std::endl;
120     std::cout << impl->AstNodeDumpJSONConst(context, letStatement) << std::endl;
121 
122     std::string className = std::string("b");
123     auto *memForName = static_cast<char *>(impl->AllocMemory(context, className.size() + 1, 1));
124     std::copy_n(className.c_str(), className.size() + 1, memForName);
125 
126     auto varIdent = impl->CreateIdentifier1(context, memForName);
127     auto declarator = impl->CreateVariableDeclarator1(
128         context, Es2pandaVariableDeclaratorFlag::VARIABLE_DECLARATOR_FLAG_LET, varIdent,
129         impl->VariableDeclaratorInit(context, impl->VariableDeclarationDeclaratorsConst(context, letStatement, &n)[0]));
130     auto declaration = impl->CreateVariableDeclaration(
131         context, Es2pandaVariableDeclarationKind::VARIABLE_DECLARATION_KIND_LET, &declarator, 1);
132 
133     es2panda_AstNode *newMainStatements[1] = {declaration};
134     impl->BlockStatementSetStatements(context, mainFuncBody, newMainStatements, 1U);
135     impl->AstNodeForEach(ast, SetRightParent, context);
136     std::cout << impl->AstNodeDumpJSONConst(context, ast) << std::endl;
137 
138     impl->AstNodeRebind(context, declaration);
139 
140     std::cout << impl->AstNodeDumpEtsSrcConst(context, ast) << std::endl;
141     return true;
142 }
143 
main(int argc,char ** argv)144 int main(int argc, char **argv)
145 {
146     if (argc < MIN_ARGC) {
147         return INVALID_ARGC_ERROR_CODE;
148     }
149 
150     if (GetImpl() == nullptr) {
151         return NULLPTR_IMPL_ERROR_CODE;
152     }
153     impl = GetImpl();
154     std::cout << "LOAD SUCCESS" << std::endl;
155     const char **args = const_cast<const char **>(&(argv[1]));
156     auto config = impl->CreateConfig(argc - 1, args);
157     auto context = impl->CreateContextFromString(config, source.data(), argv[argc - 1]);
158     if (context == nullptr) {
159         std::cerr << "FAILED TO CREATE CONTEXT" << std::endl;
160         return NULLPTR_CONTEXT_ERROR_CODE;
161     }
162 
163     impl->ProceedToState(context, ES2PANDA_STATE_PARSED);
164     CheckForErrors("PARSE", context);
165 
166     impl->ProceedToState(context, ES2PANDA_STATE_BOUND);
167     CheckForErrors("BOUND", context);
168 
169     auto ast = impl->ProgramAst(context, impl->ContextProgram(context));
170     if (!ChangeAst(context, ast)) {
171         return TEST_ERROR_CODE;
172     }
173 
174     impl->ProceedToState(context, ES2PANDA_STATE_CHECKED);
175     CheckForErrors("CHECKED", context);
176 
177     impl->AstNodeRecheck(context, ast);
178 
179     impl->ProceedToState(context, ES2PANDA_STATE_LOWERED);
180     CheckForErrors("LOWERED", context);
181 
182     impl->ProceedToState(context, ES2PANDA_STATE_ASM_GENERATED);
183     CheckForErrors("ASM", context);
184 
185     impl->ProceedToState(context, ES2PANDA_STATE_BIN_GENERATED);
186     CheckForErrors("BIN", context);
187     if (impl->ContextState(context) == ES2PANDA_STATE_ERROR) {
188         return PROCEED_ERROR_CODE;
189     }
190     impl->DestroyConfig(config);
191 
192     return 0;
193 }
194 // NOLINTEND
195