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