1/* 2 * Copyright (c) 2024-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 16import { 17 AbstractInvokeExpr, 18 AliasTypeExpr, 19 ArkCastExpr, 20 ArkConditionExpr, 21 ArkInstanceInvokeExpr, 22 ArkStaticInvokeExpr, 23 BinaryOperator, 24 NormalBinaryOperator, 25 RelationalBinaryOperator, 26 UnaryOperator, 27} from '../base/Expr'; 28import { ArkCaughtExceptionRef, ArkInstanceFieldRef, ArkParameterRef, ArkThisRef, GlobalRef } from '../base/Ref'; 29import { Value } from '../base/Value'; 30import * as ts from 'ohos-typescript'; 31import { Local } from '../base/Local'; 32import { ArkAliasTypeDefineStmt, ArkAssignStmt, ArkIfStmt, ArkInvokeStmt, ArkReturnStmt, ArkReturnVoidStmt, ArkThrowStmt, Stmt } from '../base/Stmt'; 33import { AliasType, BooleanType, ClassType, Type, UnclearReferenceType, UnknownType, VoidType } from '../base/Type'; 34import { ValueUtil } from './ValueUtil'; 35import { AliasTypeSignature, ClassSignature, FieldSignature, MethodSignature, MethodSubSignature } from '../model/ArkSignature'; 36 37import { IRUtils } from './IRUtils'; 38import { ArkMethod } from '../model/ArkMethod'; 39import { buildArkMethodFromArkClass } from '../model/builder/ArkMethodBuilder'; 40import { ArkSignatureBuilder } from '../model/builder/ArkSignatureBuilder'; 41import { COMPONENT_BRANCH_FUNCTION, COMPONENT_CREATE_FUNCTION, COMPONENT_IF, COMPONENT_POP_FUNCTION, COMPONENT_REPEAT } from './EtsConst'; 42import { FullPosition, LineColPosition } from '../base/Position'; 43import { ModelUtils } from './ModelUtils'; 44import { Builtin } from './Builtin'; 45import { DEFAULT, PROMISE } from './TSConst'; 46import { buildGenericType, buildModifiers, buildTypeParameters } from '../model/builder/builderUtils'; 47import { ArkValueTransformer } from './ArkValueTransformer'; 48import { ImportInfo } from '../model/ArkImport'; 49import { AbstractTypeExpr } from '../base/TypeExpr'; 50import { buildNormalArkClassFromArkMethod } from '../model/builder/ArkClassBuilder'; 51import { ArkClass } from '../model/ArkClass'; 52import { ModifierType } from '../model/ArkBaseModel'; 53 54export type ValueAndStmts = { 55 value: Value; 56 valueOriginalPositions: FullPosition[]; // original positions of value and its uses 57 stmts: Stmt[]; 58}; 59 60export class DummyStmt extends Stmt { 61 constructor(text: string) { 62 super(); 63 this.text = text; 64 } 65 66 public toString(): string { 67 return this.text!; 68 } 69} 70 71export class ArkIRTransformer { 72 public static readonly DUMMY_LOOP_INITIALIZER_STMT = 'LoopInitializer'; 73 public static readonly DUMMY_CONDITIONAL_OPERATOR = 'ConditionalOperator'; 74 public static readonly DUMMY_CONDITIONAL_OPERATOR_IF_TRUE_STMT = ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR + 'IfTrue'; 75 public static readonly DUMMY_CONDITIONAL_OPERATOR_IF_FALSE_STMT = ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR + 'IfFalse'; 76 public static readonly DUMMY_CONDITIONAL_OPERATOR_END_STMT = ArkIRTransformer.DUMMY_CONDITIONAL_OPERATOR + 'End'; 77 78 private sourceFile: ts.SourceFile; 79 private declaringMethod: ArkMethod; 80 private inBuilderMethod = false; 81 private builderMethodContextFlag = false; 82 private stmtsHaveOriginalText: Set<Stmt> = new Set(); 83 private arkValueTransformer: ArkValueTransformer; 84 85 constructor(sourceFile: ts.SourceFile, declaringMethod: ArkMethod) { 86 this.sourceFile = sourceFile; 87 this.declaringMethod = declaringMethod; 88 this.inBuilderMethod = ModelUtils.isArkUIBuilderMethod(declaringMethod); 89 this.arkValueTransformer = new ArkValueTransformer(this, sourceFile, this.declaringMethod); 90 } 91 92 public getLocals(): Set<Local> { 93 return this.arkValueTransformer.getLocals(); 94 } 95 96 public getGlobals(): Map<string, GlobalRef> | null { 97 return this.arkValueTransformer.getGlobals(); 98 } 99 100 public getThisLocal(): Local { 101 return this.arkValueTransformer.getThisLocal(); 102 } 103 104 public getAliasTypeMap(): Map<string, [AliasType, ArkAliasTypeDefineStmt]> { 105 return this.arkValueTransformer.getAliasTypeMap(); 106 } 107 108 public prebuildStmts(): Stmt[] { 109 const stmts: Stmt[] = []; 110 let index = 0; 111 for (const methodParameter of this.declaringMethod.getParameters()) { 112 const parameterRef = new ArkParameterRef(index, methodParameter.getType()); 113 stmts.push(new ArkAssignStmt(this.arkValueTransformer.addNewLocal(methodParameter.getName(), parameterRef.getType()), parameterRef)); 114 index++; 115 } 116 117 const thisRef = new ArkThisRef(this.arkValueTransformer.getThisLocal().getType() as ClassType); 118 stmts.push(new ArkAssignStmt(this.arkValueTransformer.getThisLocal(), thisRef)); 119 return stmts; 120 } 121 122 public tsNodeToStmts(node: ts.Node): Stmt[] { 123 let stmts: Stmt[] = []; 124 if (ts.isExpressionStatement(node)) { 125 stmts = this.expressionStatementToStmts(node); 126 } else if (ts.isTypeAliasDeclaration(node)) { 127 stmts = this.typeAliasDeclarationToStmts(node); 128 } else if (ts.isBlock(node)) { 129 stmts = this.blockToStmts(node); 130 } else if (ts.isForStatement(node)) { 131 stmts = this.forStatementToStmts(node); 132 } else if (ts.isForInStatement(node) || ts.isForOfStatement(node)) { 133 stmts = this.rangeForStatementToStmts(node); 134 } else if (ts.isWhileStatement(node)) { 135 stmts = this.whileStatementToStmts(node); 136 } else if (ts.isDoStatement(node)) { 137 stmts = this.doStatementToStmts(node); 138 } else if (ts.isVariableStatement(node)) { 139 stmts = this.variableStatementToStmts(node); 140 } else if (ts.isVariableDeclarationList(node)) { 141 stmts = this.variableDeclarationListToStmts(node); 142 } else if (ts.isIfStatement(node)) { 143 stmts = this.ifStatementToStmts(node); 144 } else if (ts.isBreakStatement(node) || ts.isContinueStatement(node)) { 145 stmts = this.gotoStatementToStmts(node); 146 } else if (ts.isThrowStatement(node)) { 147 stmts = this.throwStatementToStmts(node); 148 } else if (ts.isCatchClause(node)) { 149 stmts = this.catchClauseToStmts(node); 150 } else if (ts.isReturnStatement(node)) { 151 stmts = this.returnStatementToStmts(node); 152 } else if (ts.isFunctionDeclaration(node)) { 153 stmts = this.functionDeclarationToStmts(node); 154 } else if (ts.isExportAssignment(node)) { 155 stmts = this.expressionInExportToStmts(node.expression); 156 } else if (ts.isClassDeclaration(node)) { 157 stmts = this.classDeclarationToStmts(node); 158 } else if (ts.isParameter(node)) { 159 stmts = this.parameterPropertyToStmts(node); 160 } 161 162 this.mapStmtsToTsStmt(stmts, node); 163 if (stmts.length > 0) { 164 IRUtils.setComments(stmts[0], node, this.sourceFile, this.declaringMethod.getDeclaringArkFile().getScene().getOptions()); 165 } 166 return stmts; 167 } 168 169 public tsNodeToValueAndStmts(node: ts.Node): ValueAndStmts { 170 return this.arkValueTransformer.tsNodeToValueAndStmts(node); 171 } 172 173 private functionDeclarationToStmts(functionDeclarationNode: ts.FunctionDeclaration): Stmt[] { 174 const declaringClass = this.declaringMethod.getDeclaringArkClass(); 175 const arkMethod = new ArkMethod(); 176 if (this.builderMethodContextFlag) { 177 ModelUtils.implicitArkUIBuilderMethods.add(arkMethod); 178 } 179 buildArkMethodFromArkClass(functionDeclarationNode, declaringClass, arkMethod, this.sourceFile, this.declaringMethod); 180 return []; 181 } 182 183 private classDeclarationToStmts(node: ts.ClassDeclaration): Stmt[] { 184 const cls = new ArkClass(); 185 const declaringArkNamespace = this.declaringMethod.getDeclaringArkClass().getDeclaringArkNamespace(); 186 if (declaringArkNamespace) { 187 cls.setDeclaringArkNamespace(declaringArkNamespace); 188 } 189 cls.setDeclaringArkFile(this.declaringMethod.getDeclaringArkFile()); 190 buildNormalArkClassFromArkMethod(node, cls, this.sourceFile, this.declaringMethod); 191 return []; 192 } 193 194 // This is only used to add class property assign stmts into constructor when it is with parameter property. 195 private parameterPropertyToStmts(paramNode: ts.ParameterDeclaration): Stmt[] { 196 if (paramNode.modifiers === undefined || !ts.isIdentifier(paramNode.name)) { 197 return []; 198 } 199 const fieldName = paramNode.name.text; 200 const arkClass = this.declaringMethod.getDeclaringArkClass(); 201 const fieldSignature = arkClass.getFieldWithName(fieldName)?.getSignature(); 202 const paramLocal = Array.from(this.getLocals()).find(local => local.getName() === fieldName); 203 if (fieldSignature === undefined || paramLocal === undefined) { 204 return []; 205 } 206 const leftOp = new ArkInstanceFieldRef(this.getThisLocal(), fieldSignature); 207 const fieldAssignStmt = new ArkAssignStmt(leftOp, paramLocal); 208 fieldAssignStmt.setOperandOriginalPositions([FullPosition.DEFAULT, FullPosition.DEFAULT, FullPosition.DEFAULT]); 209 210 // If the parameter has initializer, the related stmts should be added into class instance init method. 211 const instInitMethodCfg = arkClass.getInstanceInitMethod().getBody()?.getCfg(); 212 const instInitStmts = instInitMethodCfg?.getStartingBlock()?.getStmts(); 213 if (paramNode.initializer && instInitStmts && instInitMethodCfg) { 214 const { 215 value: instanceInitValue, 216 valueOriginalPositions: instanceInitPositions, 217 stmts: instanceInitStmts, 218 } = this.tsNodeToValueAndStmts(paramNode.initializer); 219 const instanceAssignStmt = new ArkAssignStmt(leftOp, instanceInitValue); 220 instanceAssignStmt.setOperandOriginalPositions([FullPosition.DEFAULT, FullPosition.DEFAULT, ...instanceInitPositions]); 221 const newInstanceInitStmts = [...instanceInitStmts, instanceAssignStmt]; 222 223 // All these stmts will be added into instance init method, while that method has completed the building. So all new stmts should set cfg here. 224 newInstanceInitStmts.forEach(stmt => stmt.setCfg(instInitMethodCfg)); 225 226 // The last stmt of instance init method is return stmt, so all the initializer stmts should be added before return stmt. 227 instInitStmts.splice(instInitStmts.length - 1, 0, ...newInstanceInitStmts); 228 } 229 return [fieldAssignStmt]; 230 } 231 232 private returnStatementToStmts(returnStatement: ts.ReturnStatement): Stmt[] { 233 const stmts: Stmt[] = []; 234 if (returnStatement.expression) { 235 let { value: exprValue, valueOriginalPositions: exprPositions, stmts: exprStmts } = this.tsNodeToValueAndStmts(returnStatement.expression); 236 exprStmts.forEach(stmt => stmts.push(stmt)); 237 if (IRUtils.moreThanOneAddress(exprValue)) { 238 ({ value: exprValue, valueOriginalPositions: exprPositions, stmts: exprStmts } = this.generateAssignStmtForValue(exprValue, exprPositions)); 239 exprStmts.forEach(stmt => stmts.push(stmt)); 240 } 241 const returnStmt = new ArkReturnStmt(exprValue); 242 returnStmt.setOperandOriginalPositions(exprPositions); 243 stmts.push(returnStmt); 244 if (this.declaringMethod.getSubSignature().getReturnType() instanceof UnknownType) { 245 this.declaringMethod.getSubSignature().setReturnType(exprValue.getType()); 246 } 247 return stmts; 248 } 249 stmts.push(new ArkReturnVoidStmt()); 250 if (this.declaringMethod.getSubSignature().getReturnType() instanceof UnknownType) { 251 if (this.declaringMethod.containsModifier(ModifierType.ASYNC)) { 252 const promise = this.declaringMethod.getDeclaringArkFile().getScene().getSdkGlobal(PROMISE); 253 if (promise instanceof ArkClass) { 254 this.declaringMethod.getSubSignature().setReturnType(new ClassType(promise.getSignature())); 255 } else { 256 this.declaringMethod.getSubSignature().setReturnType(new UnclearReferenceType(PROMISE, [VoidType.getInstance()])); 257 } 258 } else { 259 this.declaringMethod.getSubSignature().setReturnType(VoidType.getInstance()); 260 } 261 } 262 return stmts; 263 } 264 265 private blockToStmts(block: ts.Block): Stmt[] { 266 const stmts: Stmt[] = []; 267 for (const statement of block.statements) { 268 this.tsNodeToStmts(statement).forEach(stmt => stmts.push(stmt)); 269 } 270 return stmts; 271 } 272 273 private expressionStatementToStmts(expressionStatement: ts.ExpressionStatement): Stmt[] { 274 const exprNode = expressionStatement.expression; 275 const { value: exprValue, valueOriginalPositions: exprPositions, stmts: stmts } = this.tsNodeToValueAndStmts(exprNode); 276 if (exprValue instanceof AbstractInvokeExpr) { 277 this.addInvokeStmts(exprValue, exprPositions, stmts); 278 } else if (this.shouldGenerateExtraAssignStmt(exprNode)) { 279 const { stmts: exprStmts } = this.generateAssignStmtForValue(exprValue, exprPositions); 280 exprStmts.forEach(stmt => stmts.push(stmt)); 281 } 282 return stmts; 283 } 284 285 private addInvokeStmts(invokeExpr: AbstractInvokeExpr, exprPositions: FullPosition[], stmts: Stmt[]): void { 286 const invokeStmt = new ArkInvokeStmt(invokeExpr); 287 invokeStmt.setOperandOriginalPositions(exprPositions); 288 stmts.push(invokeStmt); 289 290 let hasRepeat: boolean = false; 291 for (const stmt of stmts) { 292 if (stmt instanceof ArkAssignStmt && stmt.getRightOp() instanceof ArkStaticInvokeExpr) { 293 const rightOp = stmt.getRightOp() as ArkStaticInvokeExpr; 294 if (rightOp.getMethodSignature().getMethodSubSignature().getMethodName() === COMPONENT_REPEAT) { 295 const createMethodSignature = ArkSignatureBuilder.buildMethodSignatureFromClassNameAndMethodName( 296 COMPONENT_REPEAT, 297 COMPONENT_CREATE_FUNCTION 298 ); 299 const createInvokeExpr = new ArkStaticInvokeExpr(createMethodSignature, rightOp.getArgs()); 300 stmt.setRightOp(createInvokeExpr); 301 hasRepeat = true; 302 } 303 } 304 } 305 if (hasRepeat) { 306 const popMethodSignature = ArkSignatureBuilder.buildMethodSignatureFromClassNameAndMethodName(COMPONENT_REPEAT, COMPONENT_POP_FUNCTION); 307 const popInvokeExpr = new ArkStaticInvokeExpr(popMethodSignature, []); 308 const popInvokeStmt = new ArkInvokeStmt(popInvokeExpr); 309 stmts.push(popInvokeStmt); 310 } 311 } 312 313 private shouldGenerateExtraAssignStmt(expression: ts.Expression): boolean { 314 if (ts.isParenthesizedExpression(expression)) { 315 return this.shouldGenerateExtraAssignStmt(expression.expression); 316 } 317 if ( 318 (ts.isBinaryExpression(expression) && 319 (expression.operatorToken.kind === ts.SyntaxKind.FirstAssignment || 320 ArkValueTransformer.isCompoundAssignmentOperator(expression.operatorToken.kind))) || 321 ts.isEtsComponentExpression(expression) || 322 ts.isVoidExpression(expression) || 323 ts.isNewExpression(expression) || 324 ts.isCallExpression(expression) || 325 (ts.isPrefixUnaryExpression(expression) && 326 (expression.operator === ts.SyntaxKind.PlusPlusToken || expression.operator === ts.SyntaxKind.MinusMinusToken)) || 327 (ts.isPostfixUnaryExpression(expression) && 328 (expression.operator === ts.SyntaxKind.PlusPlusToken || expression.operator === ts.SyntaxKind.MinusMinusToken)) 329 ) { 330 return false; 331 } 332 333 return true; 334 } 335 336 private typeAliasDeclarationToStmts(typeAliasDeclaration: ts.TypeAliasDeclaration): Stmt[] { 337 const aliasName = typeAliasDeclaration.name.text; 338 const rightOp = typeAliasDeclaration.type; 339 let rightType = this.arkValueTransformer.resolveTypeNode(rightOp); 340 if (rightType instanceof AbstractTypeExpr) { 341 rightType = rightType.getType(); 342 } 343 344 const aliasType = new AliasType(aliasName, rightType, new AliasTypeSignature(aliasName, this.declaringMethod.getSignature())); 345 if (typeAliasDeclaration.typeParameters) { 346 const genericTypes = buildTypeParameters(typeAliasDeclaration.typeParameters, this.sourceFile, this.declaringMethod); 347 aliasType.setGenericTypes(genericTypes); 348 aliasType.setOriginalType(buildGenericType(rightType, aliasType)); 349 rightType = aliasType.getOriginalType(); 350 } 351 352 let expr = this.generateAliasTypeExpr(rightOp, aliasType); 353 354 if ((ts.isTypeQueryNode(rightOp) || ts.isTypeReferenceNode(rightOp)) && rightOp.typeArguments) { 355 let realGenericTypes: Type[] = []; 356 rightOp.typeArguments.forEach(typeArgument => { 357 realGenericTypes.push(this.arkValueTransformer.resolveTypeNode(typeArgument)); 358 }); 359 expr.setRealGenericTypes(realGenericTypes); 360 } 361 362 const modifiers = typeAliasDeclaration.modifiers ? buildModifiers(typeAliasDeclaration) : 0; 363 aliasType.setModifiers(modifiers); 364 365 const aliasTypeDefineStmt = new ArkAliasTypeDefineStmt(aliasType, expr); 366 const leftPosition = FullPosition.buildFromNode(typeAliasDeclaration.name, this.sourceFile); 367 const rightPosition = FullPosition.buildFromNode(rightOp, this.sourceFile); 368 const operandOriginalPositions = [leftPosition, rightPosition]; 369 aliasTypeDefineStmt.setOperandOriginalPositions(operandOriginalPositions); 370 371 this.getAliasTypeMap().set(aliasName, [aliasType, aliasTypeDefineStmt]); 372 373 return [aliasTypeDefineStmt]; 374 } 375 376 private generateAliasTypeExpr(rightOp: ts.TypeNode, aliasType: AliasType): AliasTypeExpr { 377 let rightType = aliasType.getOriginalType(); 378 let expr: AliasTypeExpr; 379 if (ts.isImportTypeNode(rightOp)) { 380 expr = this.resolveImportTypeNode(rightOp); 381 } else if (ts.isTypeQueryNode(rightOp)) { 382 const localName = rightOp.exprName.getText(this.sourceFile); 383 const originalLocal = Array.from(this.arkValueTransformer.getLocals()).find(local => local.getName() === localName); 384 if (originalLocal === undefined || rightType instanceof UnclearReferenceType) { 385 expr = new AliasTypeExpr(new Local(localName, rightType), true); 386 } else { 387 expr = new AliasTypeExpr(originalLocal, true); 388 } 389 } else if (ts.isTypeReferenceNode(rightOp)) { 390 // For type A = B<number> stmt and B is also an alias type with the same scope of A, 391 // rightType here is AliasType with real generic type number. 392 // The originalObject in expr should be the object without real generic type, so try to find it in this scope. 393 if (rightType instanceof AliasType) { 394 const existAliasType = this.getAliasTypeMap().get(rightType.getName()); 395 if (existAliasType) { 396 expr = new AliasTypeExpr(existAliasType[0], false); 397 } else { 398 expr = new AliasTypeExpr(rightType, false); 399 } 400 } else { 401 expr = new AliasTypeExpr(rightType, false); 402 } 403 } else { 404 expr = new AliasTypeExpr(rightType, false); 405 406 // 对于type A = {x:1, y:2}语句,当前阶段即可精确获取ClassType类型,需找到对应的ArkClass作为originalObject 407 // 对于其他情况此处为UnclearReferenceTye并由类型推导进行查找和处理 408 if (rightType instanceof ClassType) { 409 const classObject = ModelUtils.getClassWithName(rightType.getClassSignature().getClassName(), this.declaringMethod.getDeclaringArkClass()); 410 if (classObject) { 411 expr.setOriginalObject(classObject); 412 } 413 } 414 } 415 return expr; 416 } 417 418 private resolveImportTypeNode(importTypeNode: ts.ImportTypeNode): AliasTypeExpr { 419 const importType = 'typeAliasDefine'; 420 let importFrom = ''; 421 let importClauseName = ''; 422 423 if (ts.isLiteralTypeNode(importTypeNode.argument)) { 424 if (ts.isStringLiteral(importTypeNode.argument.literal)) { 425 importFrom = importTypeNode.argument.literal.text; 426 } 427 } 428 429 const importQualifier = importTypeNode.qualifier; 430 if (importQualifier !== undefined) { 431 importClauseName = importQualifier.getText(this.sourceFile); 432 } 433 434 let importInfo = new ImportInfo(); 435 importInfo.build(importClauseName, importType, importFrom, LineColPosition.buildFromNode(importTypeNode, this.sourceFile), 0); 436 importInfo.setDeclaringArkFile(this.declaringMethod.getDeclaringArkFile()); 437 438 return new AliasTypeExpr(importInfo, importTypeNode.isTypeOf); 439 } 440 441 public switchStatementToValueAndStmts(switchStatement: ts.SwitchStatement): ValueAndStmts[] { 442 const valueAndStmtsOfSwitchAndCases: ValueAndStmts[] = []; 443 const exprStmts: Stmt[] = []; 444 let { value: exprValue, valueOriginalPositions: exprPositions, stmts: exprTempStmts } = this.tsNodeToValueAndStmts(switchStatement.expression); 445 exprTempStmts.forEach(stmt => exprStmts.push(stmt)); 446 if (IRUtils.moreThanOneAddress(exprValue)) { 447 ({ value: exprValue, valueOriginalPositions: exprPositions, stmts: exprTempStmts } = this.generateAssignStmtForValue(exprValue, exprPositions)); 448 exprTempStmts.forEach(stmt => exprStmts.push(stmt)); 449 } 450 valueAndStmtsOfSwitchAndCases.push({ 451 value: exprValue, 452 valueOriginalPositions: exprPositions, 453 stmts: exprStmts, 454 }); 455 456 for (const clause of switchStatement.caseBlock.clauses) { 457 if (ts.isCaseClause(clause)) { 458 const clauseStmts: Stmt[] = []; 459 let { value: clauseValue, valueOriginalPositions: clausePositions, stmts: clauseTempStmts } = this.tsNodeToValueAndStmts(clause.expression); 460 clauseTempStmts.forEach(stmt => clauseStmts.push(stmt)); 461 if (IRUtils.moreThanOneAddress(clauseValue)) { 462 ({ 463 value: clauseValue, 464 valueOriginalPositions: clausePositions, 465 stmts: clauseTempStmts, 466 } = this.generateAssignStmtForValue(clauseValue, clausePositions)); 467 clauseTempStmts.forEach(stmt => clauseStmts.push(stmt)); 468 } 469 valueAndStmtsOfSwitchAndCases.push({ 470 value: clauseValue, 471 valueOriginalPositions: clausePositions, 472 stmts: clauseStmts, 473 }); 474 } 475 } 476 return valueAndStmtsOfSwitchAndCases; 477 } 478 479 private forStatementToStmts(forStatement: ts.ForStatement): Stmt[] { 480 const stmts: Stmt[] = []; 481 if (forStatement.initializer) { 482 this.tsNodeToValueAndStmts(forStatement.initializer).stmts.forEach(stmt => stmts.push(stmt)); 483 } 484 const dummyInitializerStmt = new DummyStmt(ArkIRTransformer.DUMMY_LOOP_INITIALIZER_STMT); 485 stmts.push(dummyInitializerStmt); 486 487 if (forStatement.condition) { 488 const { value: conditionValue, stmts: conditionStmts } = this.arkValueTransformer.conditionToValueAndStmts(forStatement.condition); 489 conditionStmts.forEach(stmt => stmts.push(stmt)); 490 stmts.push(new ArkIfStmt(conditionValue as ArkConditionExpr)); 491 } else { 492 // The omitted condition always evaluates to true. 493 const trueConstant = ValueUtil.getBooleanConstant(true); 494 const conditionExpr = new ArkConditionExpr(trueConstant, trueConstant, RelationalBinaryOperator.Equality); 495 stmts.push(new ArkIfStmt(conditionExpr)); 496 } 497 if (forStatement.incrementor) { 498 this.tsNodeToValueAndStmts(forStatement.incrementor).stmts.forEach(stmt => stmts.push(stmt)); 499 } 500 return stmts; 501 } 502 503 private rangeForStatementToStmts(forOfStatement: ts.ForOfStatement | ts.ForInStatement): Stmt[] { 504 const stmts: Stmt[] = []; 505 let { value: iterableValue, valueOriginalPositions: iterablePositions, stmts: iterableStmts } = this.tsNodeToValueAndStmts(forOfStatement.expression); 506 iterableStmts.forEach(stmt => stmts.push(stmt)); 507 if (!(iterableValue instanceof Local)) { 508 ({ 509 value: iterableValue, 510 valueOriginalPositions: iterablePositions, 511 stmts: iterableStmts, 512 } = this.generateAssignStmtForValue(iterableValue, iterablePositions)); 513 iterableStmts.forEach(stmt => stmts.push(stmt)); 514 } 515 const iteratorMethodSubSignature = new MethodSubSignature(Builtin.ITERATOR_FUNCTION, [], Builtin.ITERATOR_CLASS_TYPE); 516 const iteratorMethodSignature = new MethodSignature(ClassSignature.DEFAULT, iteratorMethodSubSignature); 517 const iteratorInvokeExpr = new ArkInstanceInvokeExpr(iterableValue as Local, iteratorMethodSignature, []); 518 const iteratorInvokeExprPositions = [iterablePositions[0], ...iterablePositions]; 519 const { 520 value: iterator, 521 valueOriginalPositions: iteratorPositions, 522 stmts: iteratorStmts, 523 } = this.generateAssignStmtForValue(iteratorInvokeExpr, iteratorInvokeExprPositions); 524 iteratorStmts.forEach(stmt => stmts.push(stmt)); 525 (iterator as Local).setType(Builtin.ITERATOR_CLASS_TYPE); 526 527 const nextMethodSubSignature = new MethodSubSignature(Builtin.ITERATOR_NEXT, [], Builtin.ITERATOR_RESULT_CLASS_TYPE); 528 const nextMethodSignature = new MethodSignature(ClassSignature.DEFAULT, nextMethodSubSignature); 529 const iteratorNextInvokeExpr = new ArkInstanceInvokeExpr(iterator as Local, nextMethodSignature, []); 530 const iteratorNextInvokeExprPositions = [iteratorPositions[0], ...iteratorPositions]; 531 const { 532 value: iteratorResult, 533 valueOriginalPositions: iteratorResultPositions, 534 stmts: iteratorResultStmts, 535 } = this.generateAssignStmtForValue(iteratorNextInvokeExpr, iteratorNextInvokeExprPositions); 536 iteratorResultStmts.forEach(stmt => stmts.push(stmt)); 537 (iteratorResult as Local).setType(Builtin.ITERATOR_RESULT_CLASS_TYPE); 538 const doneFieldSignature = new FieldSignature(Builtin.ITERATOR_RESULT_DONE, Builtin.ITERATOR_RESULT_CLASS_SIGNATURE, BooleanType.getInstance(), false); 539 const doneFieldRef = new ArkInstanceFieldRef(iteratorResult as Local, doneFieldSignature); 540 const doneFieldRefPositions = [iteratorResultPositions[0], ...iteratorResultPositions]; 541 const { 542 value: doneFlag, 543 valueOriginalPositions: doneFlagPositions, 544 stmts: doneFlagStmts, 545 } = this.generateAssignStmtForValue(doneFieldRef, doneFieldRefPositions); 546 doneFlagStmts.forEach(stmt => stmts.push(stmt)); 547 (doneFlag as Local).setType(BooleanType.getInstance()); 548 const conditionExpr = new ArkConditionExpr(doneFlag, ValueUtil.getBooleanConstant(true), RelationalBinaryOperator.Equality); 549 const conditionExprPositions = [doneFlagPositions[0], ...doneFlagPositions, FullPosition.DEFAULT]; 550 const ifStmt = new ArkIfStmt(conditionExpr); 551 ifStmt.setOperandOriginalPositions(conditionExprPositions); 552 stmts.push(ifStmt); 553 554 const valueFieldSignature = new FieldSignature( 555 Builtin.ITERATOR_RESULT_VALUE, 556 Builtin.ITERATOR_RESULT_CLASS_SIGNATURE, 557 UnknownType.getInstance(), 558 false 559 ); 560 const valueFieldRef = new ArkInstanceFieldRef(iteratorResult as Local, valueFieldSignature); 561 const valueFieldRefPositions = [iteratorResultPositions[0], ...iteratorResultPositions]; 562 const { 563 value: yieldValue, 564 valueOriginalPositions: yieldValuePositions, 565 stmts: yieldValueStmts, 566 } = this.generateAssignStmtForValue(valueFieldRef, valueFieldRefPositions); 567 yieldValueStmts.forEach(stmt => stmts.push(stmt)); 568 569 const castExpr = new ArkCastExpr(yieldValue, UnknownType.getInstance()); 570 const castExprPositions = [yieldValuePositions[0], ...yieldValuePositions]; 571 const initializerNode = forOfStatement.initializer; 572 if (ts.isVariableDeclarationList(initializerNode)) { 573 const isConst = (initializerNode.flags & ts.NodeFlags.Const) !== 0; 574 const { 575 value: initValue, 576 valueOriginalPositions: initOriPos, 577 stmts: initStmts, 578 } = this.arkValueTransformer.variableDeclarationToValueAndStmts(initializerNode.declarations[0], isConst, false); 579 const assignStmt = new ArkAssignStmt(initValue, castExpr); 580 assignStmt.setOperandOriginalPositions([...initOriPos, ...castExprPositions]); 581 stmts.push(assignStmt); 582 initStmts.forEach(stmt => stmts.push(stmt)); 583 } else { 584 // initializer maybe an expression 585 const { value: initValue, valueOriginalPositions: initOriPos, stmts: initStmts } = this.tsNodeToValueAndStmts(initializerNode); 586 const assignStmt = new ArkAssignStmt(initValue, castExpr); 587 assignStmt.setOperandOriginalPositions([...initOriPos, ...castExprPositions]); 588 initStmts.forEach(stmt => stmts.push(stmt)); 589 stmts.push(assignStmt); 590 } 591 return stmts; 592 } 593 594 private whileStatementToStmts(whileStatement: ts.WhileStatement): Stmt[] { 595 const stmts: Stmt[] = []; 596 const dummyInitializerStmt = new DummyStmt(ArkIRTransformer.DUMMY_LOOP_INITIALIZER_STMT); 597 stmts.push(dummyInitializerStmt); 598 599 const { value: conditionExpr, stmts: conditionStmts } = this.arkValueTransformer.conditionToValueAndStmts(whileStatement.expression); 600 conditionStmts.forEach(stmt => stmts.push(stmt)); 601 stmts.push(new ArkIfStmt(conditionExpr as ArkConditionExpr)); 602 return stmts; 603 } 604 605 private doStatementToStmts(doStatement: ts.DoStatement): Stmt[] { 606 const stmts: Stmt[] = []; 607 const { value: conditionExpr, stmts: conditionStmts } = this.arkValueTransformer.conditionToValueAndStmts(doStatement.expression); 608 conditionStmts.forEach(stmt => stmts.push(stmt)); 609 stmts.push(new ArkIfStmt(conditionExpr as ArkConditionExpr)); 610 return stmts; 611 } 612 613 private variableStatementToStmts(variableStatement: ts.VariableStatement): Stmt[] { 614 return this.variableDeclarationListToStmts(variableStatement.declarationList); 615 } 616 617 private variableDeclarationListToStmts(variableDeclarationList: ts.VariableDeclarationList): Stmt[] { 618 return this.arkValueTransformer.variableDeclarationListToValueAndStmts(variableDeclarationList).stmts; 619 } 620 621 private ifStatementToStmts(ifStatement: ts.IfStatement): Stmt[] { 622 const stmts: Stmt[] = []; 623 if (this.inBuilderMethod) { 624 const { 625 value: conditionExpr, 626 valueOriginalPositions: conditionExprPositions, 627 stmts: conditionStmts, 628 } = this.arkValueTransformer.conditionToValueAndStmts(ifStatement.expression); 629 conditionStmts.forEach(stmt => stmts.push(stmt)); 630 const createMethodSignature = ArkSignatureBuilder.buildMethodSignatureFromClassNameAndMethodName(COMPONENT_IF, COMPONENT_CREATE_FUNCTION); 631 const { 632 value: conditionLocal, 633 valueOriginalPositions: conditionLocalPositions, 634 stmts: assignConditionStmts, 635 } = this.generateAssignStmtForValue(conditionExpr, conditionExprPositions); 636 assignConditionStmts.forEach(stmt => stmts.push(stmt)); 637 const createInvokeExpr = new ArkStaticInvokeExpr(createMethodSignature, [conditionLocal]); 638 const createInvokeExprPositions = [conditionLocalPositions[0], ...conditionLocalPositions]; 639 const { stmts: createStmts } = this.generateAssignStmtForValue(createInvokeExpr, createInvokeExprPositions); 640 createStmts.forEach(stmt => stmts.push(stmt)); 641 const branchMethodSignature = ArkSignatureBuilder.buildMethodSignatureFromClassNameAndMethodName(COMPONENT_IF, COMPONENT_BRANCH_FUNCTION); 642 const branchInvokeExpr = new ArkStaticInvokeExpr(branchMethodSignature, [ValueUtil.getOrCreateNumberConst(0)]); 643 const branchInvokeExprPositions = [conditionLocalPositions[0], FullPosition.DEFAULT]; 644 const branchInvokeStmt = new ArkInvokeStmt(branchInvokeExpr); 645 branchInvokeStmt.setOperandOriginalPositions(branchInvokeExprPositions); 646 stmts.push(branchInvokeStmt); 647 this.tsNodeToStmts(ifStatement.thenStatement).forEach(stmt => stmts.push(stmt)); 648 if (ifStatement.elseStatement) { 649 const branchElseMethodSignature = ArkSignatureBuilder.buildMethodSignatureFromClassNameAndMethodName(COMPONENT_IF, COMPONENT_BRANCH_FUNCTION); 650 const branchElseInvokeExpr = new ArkStaticInvokeExpr(branchElseMethodSignature, [ValueUtil.getOrCreateNumberConst(1)]); 651 const branchElseInvokeExprPositions = [FullPosition.buildFromNode(ifStatement.elseStatement, this.sourceFile), FullPosition.DEFAULT]; 652 const branchElseInvokeStmt = new ArkInvokeStmt(branchElseInvokeExpr); 653 branchElseInvokeStmt.setOperandOriginalPositions(branchElseInvokeExprPositions); 654 stmts.push(branchElseInvokeStmt); 655 656 this.tsNodeToStmts(ifStatement.elseStatement).forEach(stmt => stmts.push(stmt)); 657 } 658 const popMethodSignature = ArkSignatureBuilder.buildMethodSignatureFromClassNameAndMethodName(COMPONENT_IF, COMPONENT_POP_FUNCTION); 659 const popInvokeExpr = new ArkStaticInvokeExpr(popMethodSignature, []); 660 const popInvokeStmt = new ArkInvokeStmt(popInvokeExpr); 661 stmts.push(popInvokeStmt); 662 } else { 663 const { 664 value: conditionExpr, 665 valueOriginalPositions: conditionExprPositions, 666 stmts: conditionStmts, 667 } = this.arkValueTransformer.conditionToValueAndStmts(ifStatement.expression); 668 conditionStmts.forEach(stmt => stmts.push(stmt)); 669 const ifStmt = new ArkIfStmt(conditionExpr as ArkConditionExpr); 670 ifStmt.setOperandOriginalPositions(conditionExprPositions); 671 stmts.push(ifStmt); 672 } 673 return stmts; 674 } 675 676 private gotoStatementToStmts(gotoStatement: ts.BreakStatement | ts.ContinueStatement): Stmt[] { 677 return []; 678 } 679 680 private throwStatementToStmts(throwStatement: ts.ThrowStatement): Stmt[] { 681 const stmts: Stmt[] = []; 682 const { value: throwValue, valueOriginalPositions: throwValuePositions, stmts: throwStmts } = this.tsNodeToValueAndStmts(throwStatement.expression); 683 throwStmts.forEach(stmt => stmts.push(stmt)); 684 const throwStmt = new ArkThrowStmt(throwValue); 685 throwStmt.setOperandOriginalPositions(throwValuePositions); 686 stmts.push(throwStmt); 687 return stmts; 688 } 689 690 private catchClauseToStmts(catchClause: ts.CatchClause): Stmt[] { 691 const stmts: Stmt[] = []; 692 if (catchClause.variableDeclaration) { 693 const { 694 value: catchValue, 695 valueOriginalPositions: catchOriPos, 696 stmts: catchStmts, 697 } = this.arkValueTransformer.variableDeclarationToValueAndStmts(catchClause.variableDeclaration, false, false); 698 const caughtExceptionRef = new ArkCaughtExceptionRef(UnknownType.getInstance()); 699 const assignStmt = new ArkAssignStmt(catchValue, caughtExceptionRef); 700 assignStmt.setOperandOriginalPositions(catchOriPos); 701 stmts.push(assignStmt); 702 catchStmts.forEach(stmt => stmts.push(stmt)); 703 } 704 return stmts; 705 } 706 707 private expressionInExportToStmts(expression: ts.Node): Stmt[] { 708 if (ts.isNewExpression(expression) || ts.isObjectLiteralExpression(expression)) { 709 return this.newClassInExportToStmts(expression); 710 } 711 return []; 712 } 713 714 private newClassInExportToStmts(expression: ts.NewExpression | ts.ObjectLiteralExpression): Stmt[] { 715 let stmts: Stmt[] = []; 716 let { value: rightValue, valueOriginalPositions: rightPositions, stmts: rightStmts } = this.tsNodeToValueAndStmts(expression); 717 rightStmts.forEach(stmt => stmts.push(stmt)); 718 let leftValue = this.arkValueTransformer.addNewLocal(DEFAULT); 719 let leftPositions = rightPositions; 720 const assignStmt = new ArkAssignStmt(leftValue, rightValue); 721 assignStmt.setOperandOriginalPositions([...leftPositions, ...rightPositions]); 722 stmts.push(assignStmt); 723 return stmts; 724 } 725 726 public mapStmtsToTsStmt(stmts: Stmt[], node: ts.Node): void { 727 for (const stmt of stmts) { 728 if (!this.stmtsHaveOriginalText.has(stmt)) { 729 this.stmtsHaveOriginalText.add(stmt); 730 stmt.setOriginPositionInfo(LineColPosition.buildFromNode(node, this.sourceFile)); 731 stmt.setOriginalText(node.getText(this.sourceFile)); 732 } 733 } 734 } 735 736 public static tokenToUnaryOperator(token: ts.SyntaxKind): UnaryOperator | null { 737 switch (token) { 738 case ts.SyntaxKind.MinusToken: 739 return UnaryOperator.Neg; 740 case ts.SyntaxKind.TildeToken: 741 return UnaryOperator.BitwiseNot; 742 case ts.SyntaxKind.ExclamationToken: 743 return UnaryOperator.LogicalNot; 744 default: 745 } 746 return null; 747 } 748 749 public static tokenToBinaryOperator(token: ts.SyntaxKind): BinaryOperator | null { 750 switch (token) { 751 case ts.SyntaxKind.QuestionQuestionToken: 752 return NormalBinaryOperator.NullishCoalescing; 753 case ts.SyntaxKind.AsteriskAsteriskToken: 754 return NormalBinaryOperator.Exponentiation; 755 case ts.SyntaxKind.SlashToken: 756 return NormalBinaryOperator.Division; 757 case ts.SyntaxKind.PlusToken: 758 return NormalBinaryOperator.Addition; 759 case ts.SyntaxKind.MinusToken: 760 return NormalBinaryOperator.Subtraction; 761 case ts.SyntaxKind.AsteriskToken: 762 return NormalBinaryOperator.Multiplication; 763 case ts.SyntaxKind.PercentToken: 764 return NormalBinaryOperator.Remainder; 765 case ts.SyntaxKind.LessThanLessThanToken: 766 return NormalBinaryOperator.LeftShift; 767 case ts.SyntaxKind.GreaterThanGreaterThanToken: 768 return NormalBinaryOperator.RightShift; 769 case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: 770 return NormalBinaryOperator.UnsignedRightShift; 771 case ts.SyntaxKind.AmpersandToken: 772 return NormalBinaryOperator.BitwiseAnd; 773 case ts.SyntaxKind.BarToken: 774 return NormalBinaryOperator.BitwiseOr; 775 case ts.SyntaxKind.CaretToken: 776 return NormalBinaryOperator.BitwiseXor; 777 case ts.SyntaxKind.AmpersandAmpersandToken: 778 return NormalBinaryOperator.LogicalAnd; 779 case ts.SyntaxKind.BarBarToken: 780 return NormalBinaryOperator.LogicalOr; 781 case ts.SyntaxKind.LessThanToken: 782 return RelationalBinaryOperator.LessThan; 783 case ts.SyntaxKind.LessThanEqualsToken: 784 return RelationalBinaryOperator.LessThanOrEqual; 785 case ts.SyntaxKind.GreaterThanToken: 786 return RelationalBinaryOperator.GreaterThan; 787 case ts.SyntaxKind.GreaterThanEqualsToken: 788 return RelationalBinaryOperator.GreaterThanOrEqual; 789 case ts.SyntaxKind.EqualsEqualsToken: 790 return RelationalBinaryOperator.Equality; 791 case ts.SyntaxKind.ExclamationEqualsToken: 792 return RelationalBinaryOperator.InEquality; 793 case ts.SyntaxKind.EqualsEqualsEqualsToken: 794 return RelationalBinaryOperator.StrictEquality; 795 case ts.SyntaxKind.ExclamationEqualsEqualsToken: 796 return RelationalBinaryOperator.StrictInequality; 797 default: 798 } 799 return null; 800 } 801 802 public generateAssignStmtForValue(value: Value, valueOriginalPositions: FullPosition[]): ValueAndStmts { 803 const leftOp = this.arkValueTransformer.generateTempLocal(value.getType()); 804 const leftOpPosition = valueOriginalPositions[0]; 805 const assignStmt = new ArkAssignStmt(leftOp, value); 806 assignStmt.setOperandOriginalPositions([leftOpPosition, ...valueOriginalPositions]); 807 return { 808 value: leftOp, 809 valueOriginalPositions: [leftOpPosition], 810 stmts: [assignStmt], 811 }; 812 } 813 814 public generateIfStmtForValues( 815 leftValue: Value, 816 leftOpOriginalPositions: FullPosition[], 817 rightValue: Value, 818 rightOpOriginalPositions: FullPosition[] 819 ): Stmt[] { 820 const stmts: Stmt[] = []; 821 if (IRUtils.moreThanOneAddress(leftValue)) { 822 const { 823 value: tempLeftValue, 824 valueOriginalPositions: tempLeftPositions, 825 stmts: leftStmts, 826 } = this.generateAssignStmtForValue(leftValue, leftOpOriginalPositions); 827 leftStmts.forEach(stmt => stmts.push(stmt)); 828 leftValue = tempLeftValue; 829 leftOpOriginalPositions = tempLeftPositions; 830 } 831 if (IRUtils.moreThanOneAddress(rightValue)) { 832 const { 833 value: tempRightValue, 834 valueOriginalPositions: tempRightPositions, 835 stmts: rightStmts, 836 } = this.generateAssignStmtForValue(rightValue, rightOpOriginalPositions); 837 rightStmts.forEach(stmt => stmts.push(stmt)); 838 rightValue = tempRightValue; 839 rightOpOriginalPositions = tempRightPositions; 840 } 841 842 const conditionExpr = new ArkConditionExpr(leftValue, rightValue, RelationalBinaryOperator.Equality); 843 const conditionPositions = [...leftOpOriginalPositions, ...rightOpOriginalPositions]; 844 const ifStmt = new ArkIfStmt(conditionExpr); 845 ifStmt.setOperandOriginalPositions([...conditionPositions]); 846 stmts.push(ifStmt); 847 return stmts; 848 } 849 850 public setBuilderMethodContextFlag(builderMethodContextFlag: boolean): void { 851 this.builderMethodContextFlag = builderMethodContextFlag; 852 } 853} 854