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 g_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 <ir/expression.h>
20 #include <ostream>
21 #include <string>
22 #include "test/unit/plugin/util.h"
23 #include "public/es2panda_lib.h"
24
25 // NOLINTBEGIN
26
27 /*
28 * Covered C API List:
29 * AstNodeDumpEtsSrcConst
30 * AstNodeDumpJSONConst
31 * AstNodeForEach
32 * AstNodeIterateConst
33 * AstNodeRebind
34 * AstNodeRecheck
35 * AstNodeSetParent
36 * BinaryExpressionIsArithmeticConst
37 * BinaryExpressionIsBitwiseConst
38 * BinaryExpressionIsLogicalConst
39 * BinaryExpressionIsLogicalExtendedConst
40 * BinaryExpressionLeft
41 * BinaryExpressionLeftConst
42 * BinaryExpressionOperationType
43 * BinaryExpressionOperationTypeConst
44 * BinaryExpressionOperatorTypeConst
45 * BinaryExpressionResult
46 * BinaryExpressionResultConst
47 * BinaryExpressionRight
48 * BinaryExpressionRightConst
49 * BinaryExpressionSetLeft
50 * BinaryExpressionSetOperationType
51 * BinaryExpressionSetOperator
52 * BinaryExpressionSetResult
53 * BinaryExpressionSetRight
54 * BlockStatementSetStatements
55 * ContextProgram
56 * ContextState
57 * CreateBinaryExpression
58 * CreateConfig
59 * CreateContextFromString
60 * CreateDoubleType
61 * CreateExpressionStatement
62 * CreateNumberLiteral
63 * DestroyConfig
64 * DestroyContext
65 * FunctionDeclarationFunction
66 * IdentifierName
67 * IsBinaryExpression
68 * IsFunctionDeclaration
69 * ProceedToState
70 * ProgramAst
71 * ScriptFunctionBody
72 * ScriptFunctionId
73 * UpdateBinaryExpression
74 */
75
76 static std::string source = R"(
77 function main() {
78 1 + 2;
79 }
80 )";
81
82 static es2panda_Impl *g_impl = nullptr;
83 static es2panda_AstNode *binExpr = nullptr;
84 static es2panda_AstNode *mainScriptFunc = nullptr;
85 static es2panda_Context *g_ctx = nullptr;
86
87 es2panda_AstNode *parNode = nullptr;
88 es2panda_Context *newCtx = nullptr;
89
FindBinaryExpression(es2panda_AstNode * ast)90 static void FindBinaryExpression(es2panda_AstNode *ast)
91 {
92 if (!g_impl->IsBinaryExpression(ast)) {
93 g_impl->AstNodeIterateConst(g_ctx, ast, FindBinaryExpression);
94 return;
95 }
96 binExpr = ast;
97 }
98
FindMainDef(es2panda_AstNode * ast)99 static void FindMainDef(es2panda_AstNode *ast)
100 {
101 if (!g_impl->IsFunctionDeclaration(ast)) {
102 g_impl->AstNodeIterateConst(g_ctx, ast, FindMainDef);
103 return;
104 }
105 auto scriptFunc = g_impl->FunctionDeclarationFunction(g_ctx, ast);
106 if (scriptFunc == nullptr ||
107 std::string("main") != g_impl->IdentifierName(g_ctx, g_impl->ScriptFunctionId(g_ctx, scriptFunc))) {
108 return;
109 }
110 mainScriptFunc = scriptFunc;
111 }
112
changeParent(es2panda_AstNode * child)113 static void changeParent(es2panda_AstNode *child)
114 {
115 g_impl->AstNodeSetParent(newCtx, child, parNode);
116 }
117
SetRightParent(es2panda_AstNode * node,void * arg)118 static void SetRightParent(es2panda_AstNode *node, void *arg)
119 {
120 es2panda_Context *context = static_cast<es2panda_Context *>(arg);
121 newCtx = context;
122 parNode = node;
123 g_impl->AstNodeIterateConst(context, node, changeParent);
124 }
125
SetAndGetBinaryExpressionValue(es2panda_Context * context)126 static bool SetAndGetBinaryExpressionValue(es2panda_Context *context)
127 {
128 es2panda_AstNode *leftValue = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 8));
129 g_impl->BinaryExpressionSetLeft(context, binExpr, leftValue);
130 es2panda_AstNode *rightValue = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 7));
131 g_impl->BinaryExpressionSetRight(context, binExpr, rightValue);
132 es2panda_AstNode *result = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 15));
133 g_impl->BinaryExpressionSetResult(context, binExpr, result);
134 Es2pandaTokenType operatorValue = Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_GREATER_THAN;
135 g_impl->BinaryExpressionSetOperator(context, binExpr, operatorValue);
136 es2panda_Type *doubleType = g_impl->CreateDoubleType(context);
137 g_impl->BinaryExpressionSetOperationType(context, binExpr, doubleType);
138 es2panda_AstNode *resultLeftValue = g_impl->BinaryExpressionLeft(context, binExpr);
139 if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, resultLeftValue), "8") == 0)) {
140 return false;
141 }
142 const es2panda_AstNode *leftConst = g_impl->BinaryExpressionLeftConst(context, binExpr);
143 if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, const_cast<es2panda_AstNode *>(leftConst)), "8") == 0)) {
144 return false;
145 }
146 es2panda_AstNode *resultRightValue = g_impl->BinaryExpressionRight(context, binExpr);
147 if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, resultRightValue), "7") == 0)) {
148 return false;
149 }
150 const es2panda_AstNode *rightConst = g_impl->BinaryExpressionRightConst(context, binExpr);
151 if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, const_cast<es2panda_AstNode *>(rightConst)), "7") == 0)) {
152 return false;
153 }
154 es2panda_AstNode *resultValue = g_impl->BinaryExpressionResult(context, binExpr);
155 if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, resultValue), "15") == 0)) {
156 return false;
157 }
158 const es2panda_AstNode *resultConst = g_impl->BinaryExpressionResultConst(context, binExpr);
159 if (!(strcmp(g_impl->AstNodeDumpEtsSrcConst(context, const_cast<es2panda_AstNode *>(resultConst)), "15") == 0)) {
160 return false;
161 }
162 Es2pandaTokenType operatorType = g_impl->BinaryExpressionOperatorTypeConst(context, binExpr);
163 if (operatorType != Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_GREATER_THAN) {
164 return false;
165 }
166 es2panda_Type *operationTypeVal = g_impl->BinaryExpressionOperationType(context, binExpr);
167 if (operationTypeVal != doubleType) {
168 return false;
169 }
170 const es2panda_Type *operationTypeValConst = g_impl->BinaryExpressionOperationTypeConst(context, binExpr);
171 if (operationTypeValConst != doubleType) {
172 return false;
173 }
174 return true;
175 }
176
177 /*
178 * 1 + 2
179 * is changed to
180 * 12 > 10
181 */
BinaryExpressionHandle(es2panda_Context * context,es2panda_AstNode * ast)182 static bool BinaryExpressionHandle(es2panda_Context *context, es2panda_AstNode *ast)
183 {
184 es2panda_AstNode *left = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 4));
185 es2panda_AstNode *right = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 5));
186 Es2pandaTokenType operatorType = Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_LESS_THAN;
187 es2panda_AstNode *binExpression = g_impl->CreateBinaryExpression(context, left, right, operatorType);
188 if (!g_impl->IsBinaryExpression(binExpression)) {
189 return false;
190 }
191 g_impl->AstNodeIterateConst(context, ast, FindBinaryExpression);
192 g_impl->AstNodeIterateConst(context, ast, FindMainDef);
193 if (mainScriptFunc == nullptr || binExpr == nullptr) {
194 return false;
195 }
196 auto mainFuncBody = g_impl->ScriptFunctionBody(context, mainScriptFunc);
197 es2panda_AstNode *exprStatement = g_impl->CreateExpressionStatement(context, binExpression);
198 es2panda_AstNode *newMainStatements[1] = {exprStatement};
199 g_impl->BlockStatementSetStatements(context, mainFuncBody, newMainStatements, 1U);
200 g_impl->AstNodeForEach(ast, SetRightParent, context);
201 g_impl->AstNodeIterateConst(context, ast, FindBinaryExpression);
202 if (!SetAndGetBinaryExpressionValue(context)) {
203 return false;
204 }
205 Es2pandaTokenType value = static_cast<Es2pandaTokenType>(ark::es2panda::lexer::TokenType::PUNCTUATOR_LOGICAL_AND);
206 g_impl->BinaryExpressionSetOperator(context, binExpr, value);
207 if (!g_impl->BinaryExpressionIsLogicalConst(context, binExpr) ||
208 !g_impl->BinaryExpressionIsLogicalExtendedConst(context, binExpr)) {
209 return false;
210 }
211 Es2pandaTokenType value1 = static_cast<Es2pandaTokenType>(ark::es2panda::lexer::TokenType::PUNCTUATOR_BITWISE_OR);
212 g_impl->BinaryExpressionSetOperator(context, binExpr, value1);
213 if (!g_impl->BinaryExpressionIsBitwiseConst(context, binExpr) ||
214 !g_impl->BinaryExpressionIsArithmeticConst(context, binExpr)) {
215 return false;
216 }
217 es2panda_AstNode *leftUpdate = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 12));
218 es2panda_AstNode *rightUpdate = static_cast<es2panda_AstNode *>(g_impl->CreateNumberLiteral(context, 10));
219 Es2pandaTokenType operatorUpdate = Es2pandaTokenType::TOKEN_TYPE_PUNCTUATOR_GREATER_THAN;
220 es2panda_AstNode *binExpressionUpdate =
221 g_impl->UpdateBinaryExpression(context, binExpr, leftUpdate, rightUpdate, operatorUpdate);
222 exprStatement = g_impl->CreateExpressionStatement(context, binExpressionUpdate);
223 newMainStatements[0] = {exprStatement};
224 g_impl->BlockStatementSetStatements(context, mainFuncBody, newMainStatements, 1U);
225 g_impl->AstNodeForEach(ast, SetRightParent, context);
226 std::string str(g_impl->AstNodeDumpEtsSrcConst(context, ast));
227 if (str.find("((12) > (10));") == std::string::npos) {
228 std::cout << "Fail to find update expression value." << std::endl;
229 return false;
230 }
231 return true;
232 }
233
main(int argc,char ** argv)234 int main(int argc, char **argv)
235 {
236 if (argc < MIN_ARGC) {
237 return INVALID_ARGC_ERROR_CODE;
238 }
239
240 if (GetImpl() == nullptr) {
241 return NULLPTR_IMPL_ERROR_CODE;
242 }
243
244 g_impl = GetImpl();
245
246 const char **args = const_cast<const char **>(&(argv[1]));
247 auto config = g_impl->CreateConfig(argc - 1, args);
248
249 g_ctx = g_impl->CreateContextFromString(config, source.data(), argv[argc - 1]);
250 if (g_ctx == nullptr) {
251 std::cerr << "Fail to create context." << std::endl;
252 return NULLPTR_CONTEXT_ERROR_CODE;
253 }
254
255 int retCode = Test(g_ctx, g_impl, ES2PANDA_STATE_PARSED, BinaryExpressionHandle);
256 if (retCode != 0) {
257 g_impl->DestroyConfig(config);
258 return retCode;
259 }
260
261 g_impl->DestroyConfig(config);
262
263 return 0;
264 }
265
266 // NOLINTEND
267