BlockStatementControlFlowFlatteningNode.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { injectable, inject } from 'inversify';
  2. import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
  3. import * as ESTree from 'estree';
  4. import { TStatement } from '../../types/node/TStatement';
  5. import { IOptions } from '../../interfaces/options/IOptions';
  6. import { initializable } from '../../decorators/Initializable';
  7. import { AbstractCustomNode } from '../AbstractCustomNode';
  8. import { Nodes } from '../../node/Nodes';
  9. import { NodeUtils } from '../../node/NodeUtils';
  10. import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
  11. @injectable()
  12. export class BlockStatementControlFlowFlatteningNode extends AbstractCustomNode {
  13. /**
  14. * @type {ESTree.Statement[]}
  15. */
  16. @initializable()
  17. private blockStatementBody: ESTree.Statement[];
  18. /**
  19. * @type {number[]}
  20. */
  21. @initializable()
  22. private originalKeysIndexesInShuffledArray: number[];
  23. /**
  24. * @type {number[]}
  25. */
  26. @initializable()
  27. private shuffledKeys: number[];
  28. /**
  29. * @param options
  30. */
  31. constructor (
  32. @inject(ServiceIdentifiers.IOptions) options: IOptions
  33. ) {
  34. super(options);
  35. }
  36. /***
  37. * @param blockStatementBody
  38. * @param shuffledKeys
  39. * @param originalKeysIndexesInShuffledArray
  40. */
  41. public initialize (
  42. blockStatementBody: ESTree.Statement[],
  43. shuffledKeys: number[],
  44. originalKeysIndexesInShuffledArray: number[]
  45. ): void {
  46. this.blockStatementBody = blockStatementBody;
  47. this.shuffledKeys = shuffledKeys;
  48. this.originalKeysIndexesInShuffledArray = originalKeysIndexesInShuffledArray;
  49. }
  50. /**
  51. * @returns {TStatement[]}
  52. */
  53. protected getNodeStructure (): TStatement[] {
  54. const controllerIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
  55. const indexIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
  56. const structure: ESTree.BlockStatement = Nodes.getBlockStatementNode([
  57. Nodes.getVariableDeclarationNode([
  58. Nodes.getVariableDeclaratorNode(
  59. Nodes.getIdentifierNode(controllerIdentifierName),
  60. Nodes.getCallExpressionNode(
  61. Nodes.getMemberExpressionNode(
  62. Nodes.getLiteralNode(
  63. this.originalKeysIndexesInShuffledArray.join('|')
  64. ),
  65. Nodes.getIdentifierNode('split')
  66. ),
  67. [
  68. Nodes.getLiteralNode('|')
  69. ]
  70. )
  71. ),
  72. Nodes.getVariableDeclaratorNode(
  73. Nodes.getIdentifierNode(indexIdentifierName),
  74. Nodes.getLiteralNode(0)
  75. )
  76. ]),
  77. Nodes.getWhileStatementNode(
  78. Nodes.getLiteralNode(true),
  79. Nodes.getBlockStatementNode([
  80. Nodes.getSwitchStatementNode(
  81. Nodes.getMemberExpressionNode(
  82. Nodes.getIdentifierNode(controllerIdentifierName),
  83. Nodes.getUpdateExpressionNode(
  84. '++',
  85. Nodes.getIdentifierNode(indexIdentifierName)
  86. ),
  87. true
  88. ),
  89. this.shuffledKeys.map((key: number, index: number) => {
  90. return Nodes.getSwitchCaseNode(
  91. Nodes.getLiteralNode(String(index)),
  92. [
  93. this.blockStatementBody[key],
  94. Nodes.getContinueStatement()
  95. ]
  96. );
  97. })
  98. ),
  99. Nodes.getBreakStatement()
  100. ])
  101. )
  102. ]);
  103. NodeUtils.parentize(structure);
  104. return [structure];
  105. }
  106. }