MacroWorker.java
package dev.civl.mc.transform.common;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import dev.civl.abc.ast.IF.AST;
import dev.civl.abc.ast.IF.ASTFactory;
import dev.civl.abc.ast.node.IF.ASTNode;
import dev.civl.abc.ast.node.IF.ASTNode.NodeKind;
import dev.civl.abc.ast.node.IF.SequenceNode;
import dev.civl.abc.ast.node.IF.declaration.VariableDeclarationNode;
import dev.civl.abc.ast.node.IF.expression.ExpressionNode;
import dev.civl.abc.ast.node.IF.statement.BlockItemNode;
import dev.civl.abc.ast.node.IF.type.TypeNode;
import dev.civl.abc.ast.type.IF.StandardBasicType;
import dev.civl.abc.ast.type.IF.StandardBasicType.BasicTypeKind;
import dev.civl.abc.ast.type.IF.Type;
import dev.civl.abc.ast.type.IF.Type.TypeKind;
import dev.civl.abc.token.IF.Formation;
import dev.civl.abc.token.IF.Macro;
import dev.civl.abc.token.IF.MacroExpansion;
import dev.civl.abc.token.IF.Source;
import dev.civl.abc.token.IF.SyntaxException;
import dev.civl.mc.config.IF.CIVLConfiguration;
import dev.civl.mc.transform.IF.MacroTransformer;
/**
* Recovers macros.
*/
public class MacroWorker extends BaseWorker {
private CIVLConfiguration config;
public MacroWorker(ASTFactory astFactory, CIVLConfiguration config) {
super(MacroTransformer.LONG_NAME, astFactory);
this.identifierPrefix = "$macro_";
this.config = config;
}
@Override
protected AST transformCore(AST unit) throws SyntaxException {
if (!this.hasHeader(unit, Pthread2CIVLWorker.PTHREAD_HEADER)
|| !config.svcomp())
return unit;
SequenceNode<BlockItemNode> root = unit.getRootNode();
AST newAst;
List<BlockItemNode> newExternalList = new ArrayList<>();
Map<String, VariableDeclarationNode> macroVars = new HashMap<>();
unit.release();
for (ASTNode child : root) {
if (child != null)
recoverMacro(child, macroVars);
}
for (BlockItemNode inputVar : macroVars.values())
newExternalList.add(inputVar);
for (BlockItemNode child : root) {
if (child != null) {
newExternalList.add(child);
child.parent().removeChild(child.childIndex());
}
}
root = nodeFactory.newSequenceNode(root.getSource(), "TranslationUnit",
newExternalList);
newAst = astFactory.newAST(root, unit.getSourceFiles(),
unit.isWholeProgram());
// newAst.prettyPrint(System.out, true);
return newAst;
}
private void recoverMacro(ASTNode node,
Map<String, VariableDeclarationNode> macros) {
String sourceFile = node.getSource().getFirstToken().getSourceFile()
.getName();
Formation formation;
if (sourceFile.endsWith(".h") || sourceFile.endsWith(".cvh")
|| sourceFile.endsWith(".cvl"))
return;
formation = node.getSource().getFirstToken().getFormation();
if (formation instanceof MacroExpansion) {
if (node.nodeKind() == NodeKind.EXPRESSION) {
Type type = ((ExpressionNode) node).getType();
if (type.kind() == TypeKind.POINTER)
return;
if (type instanceof StandardBasicType) {
if (((StandardBasicType) type).getBasicTypeKind() == BasicTypeKind.BOOL)
return;
}
MacroExpansion expansion = (MacroExpansion) formation;
Macro macro = expansion.getMacro();
String name = macro.getName();
ExpressionNode idNode;
Source source = node.getSource();
if (!macros.containsKey(name)) {
VariableDeclarationNode newInputVar;
TypeNode typeNode = typeNode(source, type);
typeNode.setInputQualified(true);
newInputVar = nodeFactory.newVariableDeclarationNode(
source,
nodeFactory.newIdentifierNode(source, name),
typeNode);
macros.put(name, newInputVar);
}
idNode = this.identifierExpression(source, name);
node.parent().setChild(node.childIndex(), idNode);
}
} else {
for (ASTNode child : node.children()) {
if (child != null) {
this.recoverMacro(child, macros);
}
}
}
}
}