Skip to content

Commit

Permalink
Passing section-paragraph map to intermediate AST build functions for…
Browse files Browse the repository at this point in the history
… use in RETCALL construction
  • Loading branch information
avishek-sen-gupta committed Nov 19, 2024
1 parent e1d073d commit 70cfe8b
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,21 @@ public enum SemanticCategory {
DIALECT,
PROGRAM,
METADATA,
PLACEHOLDER, LOOP, SYMBOL, TRANSACTION_START, TRANSACTION, TRANSACTION_END, DECISION_BRANCH, COMPARISON, ADDRESS, RELATIONAL, FUNCTION, REFERENCE, DEREFERENCE, NULL, ITERATION, CODE_ROOT
PLACEHOLDER,
LOOP,
SYMBOL,
TRANSACTION_START,
TRANSACTION,
TRANSACTION_END,
DECISION_BRANCH,
COMPARISON,
ADDRESS,
RELATIONAL,
FUNCTION,
REFERENCE,
DEREFERENCE,
NULL,
ITERATION,
BLOCK_BOUNDARY,
CODE_ROOT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.smojol.common.transpiler;

import com.google.common.collect.ImmutableList;
import org.smojol.common.ast.SemanticCategory;

public class RetCallTranspilerNode extends TranspilerNode {
private final String fallthroughTarget;

public RetCallTranspilerNode(String fallthroughTarget, TranspilerCodeBlockNode body) {
super(ImmutableList.of(), ImmutableList.of(SemanticCategory.BLOCK_BOUNDARY));
this.fallthroughTarget = fallthroughTarget;
}

@Override
public String description() {
return String.format("callret (\"%s\")", fallthroughTarget);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ public BuildTranspilerASTTask(ParseTree rawAST, CobolDataStructure dataStructure

public TranspilerNode run() {
FlowNode flowRoot = new IntermediateASTNodeBuilder(rawAST, dataStructures, symbolTable).build();
return TranspilerTreeBuilder.flowToTranspiler(flowRoot, dataStructures);
return TranspilerTreeBuilder.flowToTranspiler(flowRoot, dataStructures, new SectionParagraphMap(flowRoot));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.smojol.toolkit.analysis.task.transpiler;

import lombok.Getter;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.smojol.common.ast.FlowNode;
import org.smojol.common.ast.FlowNodeType;
import org.smojol.common.navigation.FlowNodeNavigator;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Getter
public class SectionParagraphMap {
private final Map<FlowNode, List<FlowNode>> sectionParagraphsPairs;
private final Map<FlowNode, FlowNode> paragraphToSectionMap;

public SectionParagraphMap(FlowNode flowRoot) {
List<FlowNode> sectionFlowNodes = new FlowNodeNavigator(flowRoot).findAllByCondition(fn -> fn.type() == FlowNodeType.SECTION);
sectionParagraphsPairs = sectionFlowNodes.stream()
.map(sfn -> (Pair<FlowNode, List<FlowNode>>) ImmutablePair.of(sfn, new FlowNodeNavigator(sfn).findAllByCondition(n -> n.type() == FlowNodeType.PARAGRAPH)))
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
paragraphToSectionMap = sectionFlowNodes.stream().flatMap(sfn ->
new FlowNodeNavigator(sfn).findAllByCondition(n -> n.type() == FlowNodeType.PARAGRAPH).stream()
.map(para -> ImmutablePair.of(para, sfn))
).collect(Collectors.toMap(Pair::getLeft, Pair::getRight));

}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package org.smojol.toolkit.transpiler;

import org.smojol.common.ast.FlowNode;
import org.smojol.common.transpiler.*;
import org.smojol.common.transpiler.DetachedTranspilerCodeBlockNode;
import org.smojol.common.transpiler.IfTranspilerNode;
import org.smojol.common.transpiler.TranspilerCodeBlockNode;
import org.smojol.common.transpiler.TranspilerNode;
import org.smojol.common.vm.expression.CobolExpression;
import org.smojol.common.vm.expression.ExpandedEvaluation;
import org.smojol.common.vm.expression.TestActionPair;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.task.transpiler.SectionParagraphMap;
import org.smojol.toolkit.ast.EvaluateFlowNode;

import java.util.List;
Expand All @@ -15,19 +19,19 @@
import static org.smojol.common.list.CarCdr.tail;

public class EvaluateNodeTranslator {
public static TranspilerNode build(EvaluateFlowNode n, CobolDataStructure dataStructures) {
public static TranspilerNode build(EvaluateFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
ExpandedEvaluation deconstructedRepresentation = n.getDeconstructedRepresentation();
List<TestActionPair> clauses = deconstructedRepresentation.testActionPairs();
TranspilerCodeBlockNode elseBody = new DetachedTranspilerCodeBlockNode(deconstructedRepresentation.elseBody().stream().map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures)).toList());
return recursiveOr(head(clauses), tail(clauses), dataStructures, elseBody);
TranspilerCodeBlockNode elseBody = new DetachedTranspilerCodeBlockNode(deconstructedRepresentation.elseBody().stream().map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures, sectionParagraphMap)).toList());
return recursiveOr(head(clauses), tail(clauses), dataStructures, elseBody, sectionParagraphMap);
}

private static TranspilerNode recursiveOr(Optional<TestActionPair> current, List<TestActionPair> remaining, CobolDataStructure dataStructures, TranspilerCodeBlockNode elseBody) {
private static TranspilerNode recursiveOr(Optional<TestActionPair> current, List<TestActionPair> remaining, CobolDataStructure dataStructures, TranspilerCodeBlockNode elseBody, SectionParagraphMap sectionParagraphMap) {
TranspilerExpressionBuilder builder = new TranspilerExpressionBuilder(dataStructures);
CobolExpression test = current.get().test();
List<FlowNode> bodyStatements = current.get().actions();
TranspilerCodeBlockNode transpilerBody = new DetachedTranspilerCodeBlockNode(bodyStatements.stream().map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures)).toList());
TranspilerCodeBlockNode transpilerBody = new DetachedTranspilerCodeBlockNode(bodyStatements.stream().map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures, sectionParagraphMap)).toList());
if (remaining.isEmpty()) return new IfTranspilerNode(builder.build(test), transpilerBody, elseBody);
return new IfTranspilerNode(builder.build(test), transpilerBody, recursiveOr(head(remaining), tail(remaining), dataStructures, elseBody));
return new IfTranspilerNode(builder.build(test), transpilerBody, recursiveOr(head(remaining), tail(remaining), dataStructures, elseBody, sectionParagraphMap));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
import org.smojol.common.transpiler.*;
import org.smojol.common.vm.expression.CobolExpression;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.task.transpiler.SectionParagraphMap;
import org.smojol.toolkit.ast.ConditionalStatementFlowNode;
import org.smojol.toolkit.ast.IfFlowNode;

public class IfTranspilerNodeBuilder {
public static TranspilerNode build(IfFlowNode n, CobolDataStructure dataStructures) {
public static TranspilerNode build(IfFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
CobolExpression condition = n.getConditionExpression();
TranspilerExpressionBuilder nodeBuilder = new TranspilerExpressionBuilder(dataStructures);
TranspilerNode transpilerCondition = nodeBuilder.build(condition);
TranspilerCodeBlockNode ifThenBlock = new DetachedTranspilerCodeBlockNode(n.getIfThenBlock().astChildren().stream().map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures)).toList());
TranspilerCodeBlockNode ifElseBlock = n.getIfElseBlock() != null ? new DetachedTranspilerCodeBlockNode(n.getIfElseBlock().astChildren().stream().filter(c -> c instanceof ConditionalStatementFlowNode).map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures)).toList()) : new TranspilerCodeBlockNode();
TranspilerCodeBlockNode ifThenBlock = new DetachedTranspilerCodeBlockNode(n.getIfThenBlock().astChildren().stream().map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures, sectionParagraphMap)).toList());
TranspilerCodeBlockNode ifElseBlock = n.getIfElseBlock() != null ? new DetachedTranspilerCodeBlockNode(n.getIfElseBlock().astChildren().stream().filter(c -> c instanceof ConditionalStatementFlowNode).map(stmt -> TranspilerTreeBuilder.flowToTranspiler(stmt, dataStructures, sectionParagraphMap)).toList()) : new TranspilerCodeBlockNode();
return new IfTranspilerNode(transpilerCondition, ifThenBlock, ifElseBlock);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,36 @@
import org.smojol.common.ast.FlowNode;
import org.smojol.common.ast.FlowNodeType;
import org.smojol.common.transpiler.LabelledTranspilerCodeBlockNode;
import org.smojol.common.transpiler.TranspilerCodeBlockNode;
import org.smojol.common.transpiler.TranspilerNode;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.task.transpiler.SectionParagraphMap;
import org.smojol.toolkit.ast.ParagraphFlowNode;
import org.smojol.toolkit.ast.ParagraphsFlowNode;
import org.smojol.toolkit.ast.ProcedureDivisionBodyFlowNode;
import org.smojol.toolkit.ast.SectionFlowNode;

import java.util.List;
import java.util.Map;

public class LabelledTranspilerCodeBlockNodeBuilder {
public static TranspilerNode build(SectionFlowNode n, CobolDataStructure dataStructures) {
return labelledBlock(n, dataStructures, ImmutableMap.of("type", FlowNodeType.SECTION));
public static TranspilerNode build(SectionFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return labelledBlock(n, dataStructures, ImmutableMap.of("type", FlowNodeType.SECTION), sectionParagraphMap);
}

private static LabelledTranspilerCodeBlockNode labelledBlock(FlowNode n, CobolDataStructure dataStructures, Map<String, Object> properties) {
List<TranspilerNode> childTranspilerNodes = n.astChildren().stream().map(child -> TranspilerTreeBuilder.flowToTranspiler(child, dataStructures)).toList();
private static LabelledTranspilerCodeBlockNode labelledBlock(FlowNode n, CobolDataStructure dataStructures, Map<String, Object> properties, SectionParagraphMap sectionParagraphMap) {
List<TranspilerNode> childTranspilerNodes = n.astChildren().stream().map(child -> TranspilerTreeBuilder.flowToTranspiler(child, dataStructures, sectionParagraphMap)).toList();
return new LabelledTranspilerCodeBlockNode(n.name(), childTranspilerNodes, properties);
}

public static TranspilerNode build(ParagraphFlowNode n, CobolDataStructure dataStructures) {
return labelledBlock(n, dataStructures, ImmutableMap.of("type", FlowNodeType.PARAGRAPH));
public static TranspilerNode build(ParagraphFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return labelledBlock(n, dataStructures, ImmutableMap.of("type", FlowNodeType.PARAGRAPH), sectionParagraphMap);
}

public static TranspilerNode build(ProcedureDivisionBodyFlowNode n, CobolDataStructure dataStructures) {
return labelledBlock(n, dataStructures, ImmutableMap.of("type", FlowNodeType.PROCEDURE_DIVISION_BODY));
public static TranspilerNode build(ProcedureDivisionBodyFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return labelledBlock(n, dataStructures, ImmutableMap.of("type", FlowNodeType.PROCEDURE_DIVISION_BODY), sectionParagraphMap);
}

public static TranspilerNode build(ParagraphsFlowNode n, CobolDataStructure dataStructures) {
List<TranspilerNode> childTranspilerNodes = n.astChildren().stream().map(child -> TranspilerTreeBuilder.flowToTranspiler(child, dataStructures)).toList();
return new TranspilerCodeBlockNode(childTranspilerNodes);
}
// public static TranspilerNode build(ParagraphsFlowNode n, CobolDataStructure dataStructures) {
// List<TranspilerNode> childTranspilerNodes = n.astChildren().stream().map(child -> TranspilerTreeBuilder.flowToTranspiler(child, dataStructures, sectionParagraphMap)).toList();
// return new TranspilerCodeBlockNode(childTranspilerNodes);
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import org.smojol.common.transpiler.*;
import org.smojol.common.vm.expression.FlowIteration;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.task.transpiler.SectionParagraphMap;
import org.smojol.toolkit.ast.ConditionalStatementFlowNode;
import org.smojol.toolkit.ast.PerformInlineFlowNode;
import org.smojol.toolkit.ast.PerformProcedureFlowNode;
Expand Down Expand Up @@ -34,15 +35,15 @@ private static TranspilerNode toTranspilerLoop(FlowIteration loop, TranspilerNod
);
}

public static TranspilerNode build(PerformInlineFlowNode n, CobolDataStructure dataStructures) {
public static TranspilerNode build(PerformInlineFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
List<FlowIteration> nestedLoops = n.getNestedLoops();
if (nestedLoops.isEmpty()) return body(n, dataStructures);
return recurse(nestedLoops, body(n, dataStructures), dataStructures);
if (nestedLoops.isEmpty()) return body(n, dataStructures, sectionParagraphMap);
return recurse(nestedLoops, body(n, dataStructures, sectionParagraphMap), dataStructures);
}

private static TranspilerNode body(FlowNode node, CobolDataStructure dataStructures) {
private static TranspilerNode body(FlowNode node, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
List<FlowNode> inlineStatements = node.astChildren().stream().filter(n -> n instanceof ConditionalStatementFlowNode).toList();
List<TranspilerNode> inlineTranspilerNodes = inlineStatements.stream().map(istmt -> TranspilerTreeBuilder.flowToTranspiler(istmt, dataStructures)).toList();
List<TranspilerNode> inlineTranspilerNodes = inlineStatements.stream().map(istmt -> TranspilerTreeBuilder.flowToTranspiler(istmt, dataStructures, sectionParagraphMap)).toList();
return new TranspilerCodeBlockNode(inlineTranspilerNodes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.smojol.common.transpiler.*;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.analysis.task.transpiler.SectionParagraphMap;
import org.smojol.toolkit.ast.SearchFlowNode;
import org.smojol.toolkit.ast.SearchWhenFlowNode;

Expand All @@ -11,19 +12,19 @@
import static org.smojol.common.list.CarCdr.tail;

public class SearchWhenNodeTranslator {
public static TranspilerNode build(SearchFlowNode n, CobolDataStructure dataStructures) {
public static TranspilerNode build(SearchFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
TranspilerExpressionBuilder nodeBuilder = new TranspilerExpressionBuilder(dataStructures);
List<SearchWhenFlowNode> phrases = n.getWhenPhrases().stream().map(node -> (SearchWhenFlowNode) node).toList();
return new ListIterationTranspilerNode(nodeBuilder.build(n.getSearchExpression()), build(head(phrases).get(), tail(phrases), dataStructures));
return new ListIterationTranspilerNode(nodeBuilder.build(n.getSearchExpression()), build(head(phrases).get(), tail(phrases), dataStructures, sectionParagraphMap));
}

private static TranspilerNode build(SearchWhenFlowNode n, List<SearchWhenFlowNode> remaining, CobolDataStructure dataStructures) {
private static TranspilerNode build(SearchWhenFlowNode n, List<SearchWhenFlowNode> remaining, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
TranspilerExpressionBuilder nodeBuilder = new TranspilerExpressionBuilder(dataStructures);
TranspilerNode transpilerCondition = nodeBuilder.build(n.getConditionExpression());
TranspilerCodeBlockNode whenBlock = new DetachedTranspilerCodeBlockNode(n.getWhenFlowNodes().stream().map(node -> TranspilerTreeBuilder.flowToTranspiler(node, dataStructures)).toList());
TranspilerCodeBlockNode whenBlock = new DetachedTranspilerCodeBlockNode(n.getWhenFlowNodes().stream().map(node -> TranspilerTreeBuilder.flowToTranspiler(node, dataStructures, sectionParagraphMap)).toList());
// whenBlock.add(new BreakTranspilerNode());
whenBlock.add(new JumpTranspilerNode(new ExitIterationScopeLocationNode()));
if (head(remaining).isEmpty()) return new IfTranspilerNode(transpilerCondition, whenBlock);
return new IfTranspilerNode(transpilerCondition, whenBlock, new DetachedTranspilerCodeBlockNode(build(head(remaining).get(), tail(remaining), dataStructures)));
return new IfTranspilerNode(transpilerCondition, whenBlock, new DetachedTranspilerCodeBlockNode(build(head(remaining).get(), tail(remaining), dataStructures, sectionParagraphMap)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,33 @@
import org.smojol.common.transpiler.TranspilerCodeBlockNode;
import org.smojol.common.transpiler.TranspilerNode;
import org.smojol.common.vm.structure.CobolDataStructure;
import org.smojol.toolkit.ast.*;
import org.smojol.toolkit.analysis.task.transpiler.SectionParagraphMap;
import org.smojol.toolkit.ast.ParagraphsFlowNode;
import org.smojol.toolkit.ast.SectionFlowNode;
import org.smojol.toolkit.ast.SentenceFlowNode;

import java.util.List;
import java.util.Map;

public class TranspilerCodeBlockNodeBuilder {
public static TranspilerNode build(SectionFlowNode n, CobolDataStructure dataStructures) {
return block(n, dataStructures);
public static TranspilerNode build(SectionFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return block(n, dataStructures, sectionParagraphMap);
}

private static TranspilerCodeBlockNode block(FlowNode n, CobolDataStructure dataStructures, Map<String, Object> additionalAttributes) {
List<TranspilerNode> childTranspilerNodes = n.astChildren().stream().map(child -> TranspilerTreeBuilder.flowToTranspiler(child, dataStructures)).toList();
private static TranspilerCodeBlockNode block(FlowNode n, CobolDataStructure dataStructures, Map<String, Object> additionalAttributes, SectionParagraphMap sectionParagraphMap) {
List<TranspilerNode> childTranspilerNodes = n.astChildren().stream().map(child -> TranspilerTreeBuilder.flowToTranspiler(child, dataStructures, sectionParagraphMap)).toList();
return new TranspilerCodeBlockNode(childTranspilerNodes, additionalAttributes);
}

private static TranspilerCodeBlockNode block(FlowNode n, CobolDataStructure dataStructures) {
return block(n, dataStructures, ImmutableMap.of());
private static TranspilerCodeBlockNode block(FlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return block(n, dataStructures, ImmutableMap.of(), sectionParagraphMap);
}

public static TranspilerNode build(ParagraphsFlowNode n, CobolDataStructure dataStructures) {
return block(n, dataStructures);
public static TranspilerNode build(ParagraphsFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return block(n, dataStructures, sectionParagraphMap);
}

public static TranspilerNode build(SentenceFlowNode n, CobolDataStructure dataStructures) {
return block(n, dataStructures, ImmutableMap.of("type", FlowNodeType.SENTENCE));
public static TranspilerNode build(SentenceFlowNode n, CobolDataStructure dataStructures, SectionParagraphMap sectionParagraphMap) {
return block(n, dataStructures, ImmutableMap.of("type", FlowNodeType.SENTENCE), sectionParagraphMap);
}
}
Loading

0 comments on commit 70cfe8b

Please sign in to comment.