UNPKG

@specs-feup/clava

Version:

A C/C++ source-to-source compiler written in Typescript

68 lines (58 loc) 2.02 kB
import { Joinpoint, Loop } from "../../Joinpoints.js"; import ClavaJoinPoints from "../ClavaJoinPoints.js"; export default function DoToWhileStmt($doStmt: Loop, labelSuffix: number | string) { // do statements have an unconditional first iteration const firstIterStmts = $doStmt.scopeNodes.map(($stmt) => $stmt.copy()); const firstIterScope = ClavaJoinPoints.scope(...firstIterStmts); $doStmt.insertBefore(firstIterScope); // convert continues in first iteration to jumps to beginning of loop const localContinues = [...findLocalContinue(firstIterScope)]; if (localContinues.length > 0) { const $labelDecl = ClavaJoinPoints.labelDecl( `__do_loop_head_${labelSuffix}` ); $doStmt.insertBefore(ClavaJoinPoints.labelStmt($labelDecl)); for (const $continue of localContinues) { $continue.replaceWith(ClavaJoinPoints.gotoStmt($labelDecl)); } } // convert breaks in first iteration to jumps to after loop const localBreaks = [...findLocalBreak(firstIterScope)]; if (localBreaks.length > 0) { const $labelDecl = ClavaJoinPoints.labelDecl( `__do_loop_end_${labelSuffix}` ); $doStmt.insertAfter(ClavaJoinPoints.emptyStmt()); $doStmt.insertAfter(ClavaJoinPoints.labelStmt($labelDecl)); for (const $break of localBreaks) { $break.replaceWith(ClavaJoinPoints.gotoStmt($labelDecl)); } } const $while = ClavaJoinPoints.whileStmt($doStmt.cond, $doStmt.body); $doStmt.replaceWith($while); return $while; } function* findLocalBreak($jp: Joinpoint): Generator<Joinpoint> { if ($jp.astName === "BreakStmt") { yield $jp; return; } if ($jp instanceof Loop) { return; } for (const $child of $jp.children) { yield* findLocalBreak($child); } } function* findLocalContinue($jp: Joinpoint): Generator<Joinpoint> { if ($jp.astName === "ContinueStmt") { yield $jp; return; } if ($jp instanceof Loop) { return; } for (const $child of $jp.children) { yield* findLocalContinue($child); } }