MFASTBuilderWorker.java
package edu.udel.cis.vsl.abc.front.fortran.astgen;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import edu.udel.cis.vsl.abc.ast.IF.AST;
import edu.udel.cis.vsl.abc.ast.IF.ASTFactory;
import edu.udel.cis.vsl.abc.ast.node.IF.ASTNode;
import edu.udel.cis.vsl.abc.ast.node.IF.IdentifierNode;
import edu.udel.cis.vsl.abc.ast.node.IF.NodeFactory;
import edu.udel.cis.vsl.abc.ast.node.IF.PairNode;
import edu.udel.cis.vsl.abc.ast.node.IF.PragmaNode;
import edu.udel.cis.vsl.abc.ast.node.IF.SequenceNode;
import edu.udel.cis.vsl.abc.ast.node.IF.compound.CompoundInitializerNode;
import edu.udel.cis.vsl.abc.ast.node.IF.compound.DesignationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.FieldDeclarationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.FunctionDeclarationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.InitializerNode;
import edu.udel.cis.vsl.abc.ast.node.IF.declaration.VariableDeclarationNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.CastNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.CompoundLiteralNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.ExpressionNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.FloatingConstantNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.FunctionCallNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.IdentifierExpressionNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.IntegerConstantNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.OperatorNode;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.OperatorNode.Operator;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.QuantifiedExpressionNode.Quantifier;
import edu.udel.cis.vsl.abc.ast.node.IF.expression.SizeofNode;
import edu.udel.cis.vsl.abc.ast.node.IF.label.OrdinaryLabelNode;
import edu.udel.cis.vsl.abc.ast.node.IF.omp.OmpExecutableNode;
import edu.udel.cis.vsl.abc.ast.node.IF.omp.OmpForNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.BlockItemNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.BlockItemNode.BlockItemKind;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.CompoundStatementNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.ForLoopInitializerNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.ReturnNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.StatementNode;
import edu.udel.cis.vsl.abc.ast.node.IF.statement.StatementNode.StatementKind;
import edu.udel.cis.vsl.abc.ast.node.IF.type.FunctionTypeNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.PointerTypeNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.TypeNode;
import edu.udel.cis.vsl.abc.ast.node.IF.type.TypeNode.TypeNodeKind;
import edu.udel.cis.vsl.abc.ast.node.common.type.CommonTypedefNameNode;
import edu.udel.cis.vsl.abc.ast.type.IF.StandardBasicType.BasicTypeKind;
import edu.udel.cis.vsl.abc.config.IF.Configuration;
import edu.udel.cis.vsl.abc.config.IF.Configurations.Language;
import edu.udel.cis.vsl.abc.front.IF.CivlcTokenConstant;
import edu.udel.cis.vsl.abc.front.IF.Front;
import edu.udel.cis.vsl.abc.front.IF.ParseException;
import edu.udel.cis.vsl.abc.front.IF.PreprocessorException;
import edu.udel.cis.vsl.abc.front.common.astgen.LibraryASTFactory;
import edu.udel.cis.vsl.abc.front.common.astgen.PragmaFactory;
import edu.udel.cis.vsl.abc.front.common.astgen.PragmaHandler;
import edu.udel.cis.vsl.abc.front.fortran.ptree.MFPUtils;
import edu.udel.cis.vsl.abc.front.fortran.ptree.MFPUtils.PRPair;
import edu.udel.cis.vsl.abc.front.fortran.ptree.MFTree;
import edu.udel.cis.vsl.abc.token.IF.CivlcToken;
import edu.udel.cis.vsl.abc.token.IF.CivlcToken.TokenVocabulary;
import edu.udel.cis.vsl.abc.token.IF.CivlcTokenSequence;
import edu.udel.cis.vsl.abc.token.IF.Formation;
import edu.udel.cis.vsl.abc.token.IF.Source;
import edu.udel.cis.vsl.abc.token.IF.SourceFile;
import edu.udel.cis.vsl.abc.token.IF.StringToken;
import edu.udel.cis.vsl.abc.token.IF.SyntaxException;
import edu.udel.cis.vsl.abc.token.IF.TokenFactory;
public class MFASTBuilderWorker {
// Static fields
private static enum FORTRAN_ARRAY_DESCRIPTOR_KIND {
ORIGIN, RESHAPE, SECTION_ARG, SECTION_FULL
}
/**
* The source information for nodes inserted by {@link MFASTWorker}
*/
static final private String SRC_INFO = "Fortran2CivlTransformer";
private static final String FORTRAN_ARRAY_ARG_PREFIX = "__ARG_";
private static final String FORTRAN_ARRAY_LOCAL_PREFIX = "__L_";
private static final String FORTRAN_ARRAY_PARAM_PREFIX = "__";
private static final String FORTRAN_ATTR_TARGET_PREFIX = "__TARGET_";
private static final String FORTRAN_COMMON_BLOCK_PREFIX = "__FCB_";
private static final String FORTRAN_INTENT_OUT_PREFIX = "__OUT_";
private static final String FORTRAN_FUNCTION_RETURN_PREFIX = "__RTN_";
private static final String FORTRAN_EMPTY_PREFIX = "";
// Dynamic fields
/**
* The path directing to the source file containing the entry of the
* translation unit processed by <code>this</code> {@link MFASTWorker}
*/
private String filePath;
/**
* The input FORTRAN parse tree
*/
private MFTree ptree;
private ASTFactory astFactory;
private NodeFactory nodeFactory;
private TokenFactory tokenFactory;
private PragmaFactory pragmaFactory;
private LibraryASTFactory libFactory;
private Source dummySrc = null;
private MFScopeManager scopes = null;
private boolean isInputVarDecl = false;
private boolean isOutputVarDecl = false;
/**
* The list storing all program units involved in the FORTRAN program
*/
private ArrayList<BlockItemNode> programUnits;
/**
* The list storing all dummy function/subroutine declarations
*/
private HashMap<String, FunctionDeclarationNode> funcDeclNodes;
private List<BlockItemNode> inputOutputVarDeclNodes;
private List<BlockItemNode> commonVarDeclNodes = new LinkedList<>();
/**
* The root node of the output CIVL AST.
*/
private SequenceNode<BlockItemNode> root;
/**
* Stores all involved {@link SourceFile}s
*/
private HashMap<Integer, SourceFile> srcFiles;
/**
* Stores all involved Fortran Formats with their unique IDs
*/
private HashMap<String, String> formats;
/**
* Indicates whether the FORTRAN program entry (<code>PROGRAM</code>)
* appears
*/
private boolean hasProgramEntry = false;
/**
* Indicates whether CIVL-C <strong>math</strong> library implementation is
* involved in this transformation.
*/
private boolean useMATH = false;
/**
* Indicates whether CIVL-C <strong>omp</strong> library implementation is
* involved in this transformation.
*/
private boolean useOMP = false;
/**
* Indicates whether CIVL-C <strong>stdio</strong> library implementation is
* involved in this transformation.
*/
private boolean useSTDIO = false;
/**
* Indicates whether CIVL-C <strong>stdlib</strong> library implementation
* is involved in this transformation.
*/
private boolean useSTDLIB = false;
/**
* Indicates whether CIVL-C <strong>civlc</strong> library implementation is
* involved in this transformation.
*/
private boolean useCIVLC = false;
/**
* Indicates whether CIVL-C <strong>fortran_array</strong> library
* implementation is involved in this transformation.
*/
private boolean useFORTRAN_ARRAY = false;
/**
* Tracks the formation associated with the parent scope of the current file
* scope (e.g., FORTRAN's 'INCLUDE' statements will import a code segment
* from a file named as the statement specified.)
*/
private Stack<Formation> formations = new Stack<>();
private HashSet<String> freedGlobalArrays = new HashSet<>();
private Stack<String> freedArrays = new Stack<>();
private Stack<VariableDeclarationNode> arraySectionDecls = new Stack<>();
/**
* Tracks the program unit name involved in this translation task.
*/
private Stack<IdentifierNode> puIdStack = new Stack<>();
private HashMap<String, PragmaHandler> pragmaMap = new HashMap<>();
private HashMap<String, ExpressionNode> commonblockMemberMap = new HashMap<>();
// Constructor
public MFASTBuilderWorker(Configuration config, MFTree parseTree,
ASTFactory astFactory, String filePath,
PragmaFactory pragmaFactory) {
this.ptree = parseTree;
this.filePath = filePath;
this.astFactory = astFactory;
this.nodeFactory = astFactory.getNodeFactory();
this.tokenFactory = astFactory.getTokenFactory();
this.pragmaFactory = pragmaFactory;
this.libFactory = new LibraryASTFactory(
// CIVL Library Implementation Preprocessor
Front.newPreprocessor(Language.C, config,
tokenFactory.newFileIndexer(), tokenFactory),
// CIVL Library Implementation Parser
Front.newParser(Language.C),
// CIVL Library Implementation ASTBuilder
Front.newASTBuilder(Language.C, config, astFactory));
this.programUnits = new ArrayList<BlockItemNode>();
this.funcDeclNodes = new HashMap<String, FunctionDeclarationNode>();
this.inputOutputVarDeclNodes = new ArrayList<BlockItemNode>();
this.srcFiles = new HashMap<>();
this.formats = new HashMap<>();
}
// Helper private functions
// For a given library name, add all nodes from CIVL's implementation
private void addLibASTNodes(String libName)
throws PreprocessorException, ParseException, SyntaxException {
List<BlockItemNode> libNodes = new ArrayList<BlockItemNode>();
AST libAST = libFactory.getASTofLibrary(libName);
SequenceNode<BlockItemNode> libRoot = libAST.getRootNode();
libAST.release();
for (BlockItemNode node : libRoot) {
node.remove();
libNodes.add(node);
}
root.insertChildren(0, libNodes);
for (SourceFile srcFile : libAST.getSourceFiles())
srcFiles.put(srcFiles.size(), srcFile);
}
// For involved libraries, Add all nodes from CIVL's implementation
private void addLibASTNodes()
throws PreprocessorException, ParseException, SyntaxException {
if (useFORTRAN_ARRAY)
addLibASTNodes(LibraryASTFactory.FORTRAN_ARRAY);
else if (useSTDIO) // stdio.h is included in FORTRAN_ARRAY
addLibASTNodes(LibraryASTFactory.STDIO);
if (useSTDLIB)
addLibASTNodes(LibraryASTFactory.STDLIB);
if (useMATH)
addLibASTNodes(LibraryASTFactory.MATH);
if (useOMP)
addLibASTNodes(LibraryASTFactory.OMP);
if (useCIVLC)
addLibASTNodes(LibraryASTFactory.CIVLC);
}
// private void addCommonBlockUnions(SequenceNode<BlockItemNode> root) {
// boolean isStruct = false;
// List<BlockItemNode> commonblockVars = new LinkedList<>();
//
// for (Entry<String, List<StructureOrUnionTypeNode>> block :
// commonblockViewMap
// .entrySet()) {
// String blockName = block.getKey();
// List<StructureOrUnionTypeNode> blockViews = block.getValue();
// List<FieldDeclarationNode> fieldDecls = new LinkedList<>();
//
// for (StructureOrUnionTypeNode view : blockViews) {
// String viewFieldName = view.getTag().name()
// .substring(FORTRAN_COMMON_BLOCK_PREFIX.length());
// IdentifierNode viewFieldIdNode = nodeFactory.newIdentifierNode(
// view.getTag().getSource(), viewFieldName);
// FieldDeclarationNode viewDeclNode = nodeFactory
// .newFieldDeclarationNode(view.getSource(),
// viewFieldIdNode, view);
//
// fieldDecls.add(viewDeclNode);
// }
//
// IdentifierNode commonblockTypeIdNode = nodeFactory
// .newIdentifierNode(dummySrc,
// FORTRAN_COMMON_BLOCK_PREFIX + blockName);
// IdentifierNode commonblockVarIdNode = nodeFactory
// .newIdentifierNode(dummySrc, blockName);
// SequenceNode<FieldDeclarationNode> commonblockViewStructs = nodeFactory
// .newSequenceNode(dummySrc, "CommonBlockViewDecls",
// fieldDecls);
// StructureOrUnionTypeNode commonblockUnionTypeNode = nodeFactory
// .newStructOrUnionTypeNode(dummySrc, isStruct,
// commonblockTypeIdNode, commonblockViewStructs);
// VariableDeclarationNode commonblockVarDeclNode = nodeFactory
// .newVariableDeclarationNode(dummySrc, commonblockVarIdNode,
// commonblockUnionTypeNode);
//
// commonblockVars.add(commonblockVarDeclNode);
// }
// root.insertChildren(0, commonblockVars);
// }
// Find the left-most token contained by the given parse tree node
private CivlcToken findLToken(MFTree pNode) {
int index = 0;
int numChildren = pNode.numChildren();
CivlcToken[] tokens = pNode.cTokens();
if (tokens != null && tokens.length > 0)
return tokens[index];
else if (numChildren > 0) {
MFTree tmpNode = null;
CivlcToken tmpToken = null;
while (index < numChildren) {
tmpNode = pNode.getChildByIndex(index);
if (tmpNode != null) {
tmpToken = findLToken(tmpNode);
if (tmpToken != null)
return tmpToken;
}
index++;
}
}
return null;
}
// Find the right-most token contained by the given parse tree node
private CivlcToken findRToken(MFTree pNode) {
int index = 0;
int numChildren = pNode.numChildren();
CivlcToken[] tokens = pNode.cTokens();
if (tokens != null && (index = tokens.length - 1) >= 0)
return tokens[index];
else if ((index = numChildren - 1) >= 0) {
MFTree tmpNode = null;
CivlcToken tmpToken = null;
while (index >= 0) {
tmpNode = pNode.getChildByIndex(index);
if (tmpNode != null) {
tmpToken = findRToken(tmpNode);
if (tmpToken != null)
return tmpToken;
}
index--;
}
}
return null;
}
private String getName(MFTree variable) {
CivlcToken[] tokens;
while (variable.prp() != MFPUtils.T_IDENT && variable.numChildren() > 0)
variable = variable.getChildByIndex(0);
tokens = variable.cTokens();
while (tokens.length < 1)
tokens = variable.cTokens();
return tokens[0].getText();
}
// Generate CIVL Source for given parse tree (or sub-tree).
private Source newSource(MFTree... pNodes) {
Source source = null;
CivlcToken lToken = null, rToken = null, tmpToken = null;
int ctr = 0;
int numSrcNodes = pNodes.length;
for (ctr = 0; ctr < numSrcNodes; ctr++)
if (pNodes[ctr] != null) {
tmpToken = findLToken(pNodes[ctr]);
if (tmpToken != null) {
lToken = tmpToken;
break;
}
}
for (ctr = numSrcNodes - 1; ctr > 0; ctr--)
if (pNodes[ctr] != null) {
tmpToken = findRToken(pNodes[ctr]);
if (tmpToken != null) {
rToken = tmpToken;
break;
}
}
if (lToken == null)
source = tokenFactory.newSource(tokenFactory.newCivlcToken(
CivlcTokenConstant.ABSENT, SRC_INFO, formations.peek(),
TokenVocabulary.FORTRAN));
else if (rToken == null)
source = tokenFactory.newSource(lToken);
else
source = tokenFactory.newSource(lToken, rToken);
return source;
}
/**
* R603: name
*
* @param progId
* @return
*/
private IdentifierNode translateIdentifier(MFTree id) {
Source src = newSource(id);
String name = getName(id);
IdentifierNode idNode = nodeFactory.newIdentifierNode(src, name);
return idNode;
}
private IdentifierNode translateIdentifierLabel(MFTree label) {
String C_LABEL_PREFIX = "L";
Source src = newSource(label);
String name = C_LABEL_PREFIX + (label.cTokens())[0].getText();
return nodeFactory.newIdentifierNode(src, name);
}
/**
* R1401: main program <br>
* R1529: function subprogram<br>
* R1534: subroutine subprogram<br>
* Note1: Both `PROGRAM` and `SUBROUTINE` will return 'void'<br>
* Note2: All FORTRAN arguments are passed-by-reference, so scalar types of
* parameters will be casted to their corresponding pointer type.
*
* @param prefix
* @param params
* @param formalMap
* @param prp
* @return {@link FunctionTypeNode} based on given info.
*/
private FunctionTypeNode translateFunctionType(MFTree prefix, MFTree name,
MFTree params, PRPair prp) {
Source funcSrc = newSource(prefix, name, params);
TypeNode returnTypeNode = null;
List<VariableDeclarationNode> formalNodes = new LinkedList<>();
SequenceNode<VariableDeclarationNode> formalsNode = null;
boolean hasFormals = params != null;
if (prp == MFPUtils.MAIN_PROGRAM)
returnTypeNode = nodeFactory.newBasicTypeNode(funcSrc,
BasicTypeKind.INT);
else if (prp == MFPUtils.SUBROUTINE_SUBPROGRAM)
returnTypeNode = nodeFactory.newVoidTypeNode(funcSrc);
else if (prp == MFPUtils.FUNCTION_SUBPROGRAM) {
if (prefix != null) {
for (int i = 0; i < prefix.numChildren(); i++) {
MFTree prefixSpec = prefix.getChildByIndex(i);
if (prefixSpec.numChildren() > 0) {
prefixSpec = prefixSpec.getChildByIndex(0);
assert prefixSpec
.prp() == MFPUtils.DECLARATION_TYPE_SPEC;
returnTypeNode = translateType(
prefixSpec.getChildByIndex(0));
break;
}
}
}
if (returnTypeNode == null)
returnTypeNode = nodeFactory.newVoidTypeNode(funcSrc);
} else
assert false;
if (hasFormals) {
int numFormals = params.numChildren();
MFTree formal = null;
Source formalSrc = null;
TypeNode dummyFormalType = null;
IdentifierNode formalNameNode = null;
VariableDeclarationNode formalNode = null;
// Types of parameters are unknown in this scope
// Assigns default implicit types
// I, J, K, L, M, or N initials imply `INTEGER`
// other ones imply `REAL`
// unless `IMPLICIT` statements used.
for (int i = 0; i < numFormals; i++) {
formal = params.getChildByIndex(i);
while (formal.numChildren() > 0)
formal = formal.getChildByIndex(0);
formalSrc = newSource(formal);
formalNameNode = translateIdentifier(formal);
dummyFormalType = scopes
.getTypeByParIdent(formalNameNode.name(), formalSrc);
// Because all FORTRAN parameters are passed-by-reference,
// scalar types are converted to corresponding pointer-types.
dummyFormalType = nodeFactory.newPointerTypeNode(formalSrc,
dummyFormalType);
formalNode = nodeFactory.newVariableDeclarationNode(formalSrc,
formalNameNode, dummyFormalType);
scopes.addDeclParameter(formalNameNode.name(), formalNode);
formalNodes.add(formalNode);
}
}
formalsNode = nodeFactory.newSequenceNode(newSource(params), "Formals",
formalNodes);
return nodeFactory.newFunctionTypeNode(funcSrc, returnTypeNode,
formalsNode, hasFormals);
}
private TypeNode translateType(MFTree typeSpec) {
Source src = newSource(typeSpec);
TypeNode typeNode = null;
PRPair prp = typeSpec.prp();
if (prp == MFPUtils.INTRINSIC_TYPE_SPEC) {
int kind = typeSpec.kind();
if (kind == MFPUtils.TYPE_INT)
typeNode = nodeFactory.newBasicTypeNode(src, BasicTypeKind.INT);
else if (kind == MFPUtils.TYPE_REAL) {
if (typeSpec.numChildren() == 2)
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.FLOAT);
else {
final int REAL_SELECT_AS_DOUBLE = 8;
MFTree kindSelector = typeSpec.getChildByIndex(2);
String byteStr = getName(kindSelector.getChildByIndex(1));
switch (Integer.parseInt(byteStr)) {
case REAL_SELECT_AS_DOUBLE :
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.DOUBLE);
break;
default :
}
}
} else if (kind == MFPUtils.TYPE_DBL)
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.DOUBLE);
else if (kind == MFPUtils.TYPE_CPLX)
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.FLOAT_COMPLEX);
else if (kind == MFPUtils.TYPE_DCPLX)
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.DOUBLE_COMPLEX);
else if (kind == MFPUtils.TYPE_BOOL)
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.BOOL);
else if (kind == MFPUtils.TYPE_CHAR)
typeNode = nodeFactory.newBasicTypeNode(src,
BasicTypeKind.CHAR);
else
assert false;
} else if (prp == MFPUtils.T_TYPE) {
MFTree derivedTypeSpec = typeSpec.getParent().getChildByIndex(1);
MFTree derivedTypeName = derivedTypeSpec.getChildByIndex(0);
IdentifierNode derivedTypeNameNode = translateIdentifier(
derivedTypeName);
typeNode = nodeFactory.newStructOrUnionTypeNode(src,
true /* isStruct */, derivedTypeNameNode, null);
scopes.addDerivedType(derivedTypeNameNode.name());
} else
assert false;
return typeNode;
}
private InitializerNode translateInitializer(MFTree init)
throws SyntaxException {
MFTree initVal = init.getChildByIndex(0);
return translateExpr(initVal);
}
private CompoundLiteralNode createArrayDimInfoNode(Source src,
ExpressionNode dimInfo[][]) {
int LBND = 0, UBND = 1, STRD = 2, DIM_INFO_SIZE = 3;
LinkedList<PairNode<DesignationNode, InitializerNode>> lbndNodes = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
LinkedList<PairNode<DesignationNode, InitializerNode>> ubndNodes = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
LinkedList<PairNode<DesignationNode, InitializerNode>> strdNodes = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
LinkedList<PairNode<DesignationNode, InitializerNode>> dimInfoNode = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
ExpressionNode numDimNode = nodeFactory.newIntConstantNode(dummySrc,
dimInfo.length);
ExpressionNode dimInfoSize = nodeFactory.newIntConstantNode(dummySrc,
DIM_INFO_SIZE);
TypeNode subDimInfoTypeNode = nodeFactory.newArrayTypeNode(dummySrc,
nodeFactory.newBasicTypeNode(dummySrc, BasicTypeKind.INT),
numDimNode);
TypeNode dimInfoTypeNode = nodeFactory.newArrayTypeNode(dummySrc,
subDimInfoTypeNode, dimInfoSize);
CompoundLiteralNode dimInfoLiteralNode = null;
for (int d = 0; d < dimInfo.length; d++) {
ExpressionNode lbndNode = dimInfo[d][LBND];
ExpressionNode ubndNode = dimInfo[d][UBND];
ExpressionNode strdNode = dimInfo[d][STRD];
if (lbndNode == null || ubndNode == null || strdNode == null) {
return null;
}
lbndNodes.add(nodeFactory.newPairNode(lbndNode.getSource(), null,
lbndNode.copy()));
ubndNodes.add(nodeFactory.newPairNode(ubndNode.getSource(), null,
ubndNode.copy()));
strdNodes.add(nodeFactory.newPairNode(strdNode.getSource(), null,
strdNode.copy()));
}
dimInfoNode.add(nodeFactory.newPairNode(src, null,
nodeFactory.newCompoundInitializerNode(src, lbndNodes)));
dimInfoNode.add(nodeFactory.newPairNode(src, null,
nodeFactory.newCompoundInitializerNode(src, ubndNodes)));
dimInfoNode.add(nodeFactory.newPairNode(src, null,
nodeFactory.newCompoundInitializerNode(src, strdNodes)));
dimInfoLiteralNode = nodeFactory.newCompoundLiteralNode(src,
dimInfoTypeNode,
nodeFactory.newCompoundInitializerNode(src, dimInfoNode));
return dimInfoLiteralNode;
}
private VariableDeclarationNode createArrayDesc(Source src,
IdentifierNode varNameNode, ExpressionNode dimInfo[][],
TypeNode baseTypeNode, FORTRAN_ARRAY_DESCRIPTOR_KIND kind,
boolean isGlobal) {
if (dimInfo == null && baseTypeNode == null) {
TypeNode fArrDescType = genArrDescType(src);
Source ssrcArrDescSrc = varNameNode.getSource();
String ssrcArrDescName = varNameNode.name()
.substring(FORTRAN_ARRAY_ARG_PREFIX.length());
IdentifierNode ssrcArrDescId = nodeFactory
.newIdentifierNode(ssrcArrDescSrc, ssrcArrDescName);
ExpressionNode ssrcArrDescIdExpr = nodeFactory
.newIdentifierExpressionNode(ssrcArrDescSrc, ssrcArrDescId);
String farr_desc = "farr_section_full";
List<ExpressionNode> args = Arrays.asList(ssrcArrDescIdExpr);
IdentifierNode farrDescNode = nodeFactory.newIdentifierNode(src,
farr_desc);
ExpressionNode funcIdNode = nodeFactory
.newIdentifierExpressionNode(dummySrc, farrDescNode);
FunctionCallNode farrDescCallNode = nodeFactory
.newFunctionCallNode(src, funcIdNode, args, null);
if (isGlobal) {
freedGlobalArrays.add(varNameNode.name());
} else {
freedArrays.push(varNameNode.name());
}
return nodeFactory.newVariableDeclarationNode(src, varNameNode,
fArrDescType, farrDescCallNode);
}
// Translate Fortran Array into CIVL-Fortran-array-desc:
// Fortran: TYPE VARNAME(LBND:RBND:STRD, ..)
// CIVL: farr_desc VARNAME =
// farr_create(sizeof(TYPE), NUMDIM,
// (int[3][NUMDIM]){{LBND,..}, {RBND, ..}, {STRD,..}});
// TODO: Handle incomplete array type and attribute!
String farr_desc = null;
List<ExpressionNode> args = null;
// Type:
TypeNode fArrDescType = genArrDescType(src);
// Init:
// -- sizeof(TYPE)
SizeofNode sizeofNode = nodeFactory.newSizeofNode(dummySrc,
baseTypeNode);
// -- NUMDIM
ExpressionNode numDimNode = nodeFactory.newIntConstantNode(dummySrc,
dimInfo.length);
// -- (int[3][NUMDIM]){{LBND,..}, {RBND, ..}, {STRD,..}}
CompoundLiteralNode dimInfoNode = createArrayDimInfoNode(src, dimInfo);
if (dimInfoNode == null)
kind = FORTRAN_ARRAY_DESCRIPTOR_KIND.SECTION_FULL;
switch (kind) {
case ORIGIN :
farr_desc = "farr_create";
args = Arrays.asList(sizeofNode, numDimNode, dimInfoNode);
break;
case RESHAPE :
// srcName = "_" + varName
Source rsrcArrDescSrc = varNameNode.getSource();
String rsrcArrDescName = FORTRAN_ARRAY_PARAM_PREFIX
+ varNameNode.name();
IdentifierNode rsrcArrDescId = nodeFactory
.newIdentifierNode(rsrcArrDescSrc, rsrcArrDescName);
ExpressionNode rsrcArrDescIdExpr = nodeFactory
.newIdentifierExpressionNode(rsrcArrDescSrc,
rsrcArrDescId);
farr_desc = "farr_reshape";
args = Arrays.asList(rsrcArrDescIdExpr, numDimNode,
dimInfoNode);
break;
case SECTION_ARG :
// srcName = varName.
Source ssrcArrDescSrc = varNameNode.getSource();
String ssrcArrDescName = varNameNode.name()
.substring(FORTRAN_ARRAY_ARG_PREFIX.length());
IdentifierNode ssrcArrDescId = nodeFactory
.newIdentifierNode(ssrcArrDescSrc, ssrcArrDescName);
ExpressionNode ssrcArrDescIdExpr = nodeFactory
.newIdentifierExpressionNode(ssrcArrDescSrc,
ssrcArrDescId);
farr_desc = "farr_section";
args = Arrays.asList(ssrcArrDescIdExpr, dimInfoNode);
break;
case SECTION_FULL :
Source fsrcArrDescSrc = varNameNode.getSource();
String fsrcArrDescName = "__" + varNameNode.name();
IdentifierNode fsrcArrDescId = nodeFactory
.newIdentifierNode(fsrcArrDescSrc, fsrcArrDescName);
ExpressionNode fsrcArrDescIdExpr = nodeFactory
.newIdentifierExpressionNode(fsrcArrDescSrc,
fsrcArrDescId);
farr_desc = "farr_section_full";
args = Arrays.asList(fsrcArrDescIdExpr);
break;
}
IdentifierNode farrDescNode = nodeFactory.newIdentifierNode(src,
farr_desc);
ExpressionNode funcIdNode = nodeFactory
.newIdentifierExpressionNode(dummySrc, farrDescNode);
FunctionCallNode farrDescCallNode = nodeFactory.newFunctionCallNode(src,
funcIdNode, args, null);
freedArrays.push(varNameNode.name());
return nodeFactory.newVariableDeclarationNode(src, varNameNode,
fArrDescType, farrDescCallNode);
}
private BlockItemNode createArrayDestroy(String arrayVarName) {
String FARR_DESTROY = "farr_destroy";
IdentifierNode arrIdNode = nodeFactory.newIdentifierNode(dummySrc,
arrayVarName);
ExpressionNode arrIdExprNode = nodeFactory
.newIdentifierExpressionNode(dummySrc, arrIdNode);
IdentifierNode farrDestroyNode = nodeFactory.newIdentifierNode(dummySrc,
FARR_DESTROY);
ExpressionNode funcIdNode = nodeFactory
.newIdentifierExpressionNode(dummySrc, farrDestroyNode);
FunctionCallNode farrDestroyCallNode = nodeFactory.newFunctionCallNode(
dummySrc, funcIdNode, Arrays.asList(arrIdExprNode), null);
return nodeFactory.newExpressionStatementNode(farrDestroyCallNode);
}
private ExpressionNode[][] processArrayDimInfo(MFTree arrSpec)
throws SyntaxException {
int LBND = 0, UBND = 1, STRD = 2;
int arrDimNum = arrSpec.numChildren();
ExpressionNode[][] dimInfo = new ExpressionNode[arrDimNum][3];
useFORTRAN_ARRAY = true;
for (int d = 0; d < arrDimNum; d++) {
MFTree dimSpec = arrSpec.getChildByIndex(d);
Source src = newSource(dimSpec);
switch (dimSpec.kind()) {
case MFPUtils.ASE_1X : // (1 :) *
case MFPUtils.ASE_NN : // <null> : <null>
dimInfo[d][LBND] = nodeFactory.newIntConstantNode(src, 1);
break;
case MFPUtils.ASE_LU : // Expr0 : Expr1
dimInfo[d][UBND] = translateExpr(
dimSpec.getChildByIndex(1));
case MFPUtils.ASE_LN : // Expr0 : <null>
case MFPUtils.ASE_LX : // Expr0 : *
dimInfo[d][LBND] = translateExpr(
dimSpec.getChildByIndex(0));
break;
case MFPUtils.ASE_RK : // ..
break; // TODO:
case MFPUtils.ASE_1U : // (1 :) Expr0
dimSpec = dimSpec.getChildByIndex(0);
default : // Expr
dimInfo[d][LBND] = nodeFactory.newIntConstantNode(src, 1);
dimInfo[d][UBND] = translateExpr(dimSpec);
break;
}
dimInfo[d][STRD] = nodeFactory.newIntConstantNode(src, 1);
}
return dimInfo;
}
private void processDummyFuncOrSubrDeclaration(String funcName,
FunctionDeclarationNode dummyDeclNode) {
if (!funcDeclNodes.containsKey(funcName)) {
funcDeclNodes.put(funcName, dummyDeclNode);
programUnits.add(0, dummyDeclNode);
}
}
private ExpressionNode createArraySubscript(Source src,
IdentifierNode varIdNode, ExpressionNode idxInfo[],
TypeNode baseTypeNode) {
// Translate Fortran Array Subscript into CIVL style:
// (int*) farr_subscript()
// Fortran: VARNAME(IDX0, .., IDXN)
// CIVL: *(TYPE*) farr_subscript(VARNAME,
// int[NUMDIM]{IDX0, IDXN});
// TODO: Handle incomplete array type and attribute!
String FARR_SUBSCRIPT = "farr_subscript";
// int array for indices:
ExpressionNode idxNode = null;
TypeNode idxInfoTypeNode = nodeFactory.newArrayTypeNode(dummySrc,
nodeFactory.newBasicTypeNode(dummySrc, BasicTypeKind.INT),
nodeFactory.newIntConstantNode(dummySrc, idxInfo.length));
LinkedList<PairNode<DesignationNode, InitializerNode>> idxInfoNodes = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
for (int d = 0; d < idxInfo.length; d++) {
idxNode = idxInfo[d].copy();
idxInfoNodes.add(nodeFactory.newPairNode(idxNode.getSource(), null,
idxNode));
}
CompoundLiteralNode idxInfoLiteralNode = nodeFactory
.newCompoundLiteralNode(src, idxInfoTypeNode, nodeFactory
.newCompoundInitializerNode(src, idxInfoNodes));
ExpressionNode isDirectNode = nodeFactory.newIntConstantNode(dummySrc,
0);
// Call on farr_subscript
ExpressionNode arrayIdExprNode = nodeFactory
.newIdentifierExpressionNode(varIdNode.getSource(),
varIdNode.copy());
IdentifierNode farrSubscriptNode = nodeFactory.newIdentifierNode(src,
FARR_SUBSCRIPT);
ExpressionNode funcIdNode = nodeFactory.newIdentifierExpressionNode(
varIdNode.getSource(), farrSubscriptNode);
FunctionCallNode farrSubscriptCallNode = nodeFactory
.newFunctionCallNode(src, funcIdNode,
Arrays.asList(arrayIdExprNode, idxInfoLiteralNode,
isDirectNode),
null);
// Cast returned value to corresponding pointer
CastNode ptrToArraySubscriptNode = nodeFactory.newCastNode(src,
nodeFactory.newPointerTypeNode(dummySrc, baseTypeNode),
farrSubscriptCallNode);
// De-reference the pointer to the corresponding array element.
return nodeFactory.newOperatorNode(src, Operator.DEREFERENCE,
ptrToArraySubscriptNode);
}
private ExpressionNode createNullConstantNode(Source src,
TypeNode pointerType) throws SyntaxException {
ExpressionNode int0Node = nodeFactory.newIntegerConstantNode(dummySrc,
"0");
TypeNode voidTypeNode = nodeFactory.newVoidTypeNode(dummySrc);
TypeNode voidPtrNode = nodeFactory.newPointerTypeNode(dummySrc,
voidTypeNode);
ExpressionNode nullConstNode = nodeFactory.newCastNode(dummySrc,
voidPtrNode, int0Node);
return nodeFactory.newCastNode(src, pointerType.copy(), nullConstNode);
}
// R801: type declaration stmt
private List<BlockItemNode> translateTypeDeclaration(MFTree decl,
String varNamePrefix) throws SyntaxException {
final int idxDeclSpec = 1;
final int idxDeclAttrSpecStart = 2;
int numDeclChildren = decl.numChildren();
int idxDeclEntities = numDeclChildren - 1;
MFTree declSpec = decl.getChildByIndex(idxDeclSpec);
MFTree declEntities = decl.getChildByIndex(idxDeclEntities);
int numDeclObj = declEntities.numChildren();
boolean[] sharedAttrs = new boolean[MFScopeManager.NUM_ATTR_ALL];
ArrayList<BlockItemNode> declNodes = new ArrayList<>();
Source src = newSource(decl);
TypeNode baseTypeNode = translateType(declSpec.getChildByIndex(0));
TypeNode sharedTypeNode = baseTypeNode;
ExpressionNode sharedDimInfo[][] = null;
// Process shared type info
if (numDeclChildren > 3) {
for (int i = idxDeclAttrSpecStart; i < idxDeclEntities; i++) {
MFTree attrSpec = decl.getChildByIndex(i);
switch (attrSpec.kind()) {
case MFPUtils.ATTR_DIMENSION :
// TODO: handling dimension(*)
sharedDimInfo = processArrayDimInfo(
attrSpec.getChildByIndex(1));
sharedTypeNode = genArrDescType(src);
sharedAttrs[MFScopeManager.ATTR_VAR_DIMENSION] = true;
// processArrayType(src, dimInfo, baseTypeNode.copy());
break;
case MFPUtils.ATTR_INTENT :
// TODO: handling intent stmt
MFTree intentSpec = attrSpec.getChildByIndex(1)
.getChildByIndex(0);
String specStr = this.getName(intentSpec);
sharedAttrs[MFScopeManager.ATTR_ARG_INTENT_IN] = specStr
.contains("IN");
sharedAttrs[MFScopeManager.ATTR_ARG_INTENT_OUT] = specStr
.contains("OUT");
break;
case MFPUtils.ATTR_ALLOCATABLE :
sharedAttrs[MFScopeManager.ATTR_VAR_ALLOCATABLE] = true;
break;
case MFPUtils.ATTR_POINTER :
sharedAttrs[MFScopeManager.ATTR_VAR_POINTER] = true;
break;
case MFPUtils.ATTR_TARGET :
sharedAttrs[MFScopeManager.ATTR_VAR_TARGET] = true;
break;
case MFPUtils.ATTR_ACCESS :
case MFPUtils.ATTR_ASYNCHRONOUS :
case MFPUtils.ATTR_BIND :
case MFPUtils.ATTR_CODIMENSION :
case MFPUtils.ATTR_CONTIGUOUS :
case MFPUtils.ATTR_EXTERNAL :
case MFPUtils.ATTR_INTRINSIC :
case MFPUtils.ATTR_OPTIONAL :
case MFPUtils.ATTR_PARAMETER :
case MFPUtils.ATTR_PROTECTED :
case MFPUtils.ATTR_SAVE :
case MFPUtils.ATTR_VALUE :
case MFPUtils.ATTR_VOLATILE :
case MFPUtils.ATTR_OTHER :
default :
System.err.println(attrSpec.prp());
assert false;
}
}
if (!sharedAttrs[MFScopeManager.ATTR_VAR_DIMENSION]) {
// No DIMENSION/CODIMENSION, scalar type
if (sharedAttrs[MFScopeManager.ATTR_VAR_ALLOCATABLE] || //
sharedAttrs[MFScopeManager.ATTR_VAR_POINTER] || //
sharedAttrs[MFScopeManager.ATTR_VAR_TARGET]) {
// Reference to scalar type
sharedTypeNode = nodeFactory.newPointerTypeNode(src,
baseTypeNode.copy());
} // else Value of scalar type
}
}
// Process CIVL type qualifier primitive for shared type
sharedTypeNode.setInputQualified(isInputVarDecl);
sharedTypeNode.setOutputQualified(isOutputVarDecl);
// Process each var. decl.
assert numDeclObj > 0;
for (int i = 0; i < numDeclObj; i++) {
TypeNode actualTypeNode = null;
ExpressionNode actualDimInfo[][] = null;
MFTree declEntity = declEntities.getChildByIndex(i);
MFTree declName = declEntity.getChildByIndex(0);
IdentifierNode nameNode = translateIdentifier(declName);
VariableDeclarationNode declNode = null;
InitializerNode initNode = null;
String varName = varNamePrefix + nameNode.name().toUpperCase();
if (sharedDimInfo != null) {
// Copy shared dimension info to actual dimension info
actualDimInfo = new ExpressionNode[sharedDimInfo.length][3];
for (int r = 0; r < sharedDimInfo.length; r++) {
for (int n = 0; n < sharedDimInfo[r].length; n++) {
if (sharedDimInfo[r][n] == null) {
actualDimInfo[r][n] = null;
} else {
actualDimInfo[r][n] = sharedDimInfo[r][n].copy();
}
}
}
}
actualTypeNode = sharedTypeNode.copy();
// Process shared attributes for each var.
for (int iAttr = 0; iAttr < sharedAttrs.length; iAttr++) {
if (sharedAttrs[iAttr]) {
scopes.setAttrByIdent(varName, iAttr);
}
}
// TODO: Special handling for each attr.
// Process specifications for each var.
// ArraySpec, CoArraySpec, CharLen, Initialization
for (int j = 1; j < declEntity.numChildren(); j++) {
MFTree spec = declEntity.getChildByIndex(j);
PRPair prp = spec.prp();
if (prp == MFPUtils.ARRAY_SPEC
|| prp == MFPUtils.COARRAY_SPEC) {
/*
* Fortran 2018: 8.2 Type declaration statement: Item.2 The
* type declaration statement also specifies the attributes
* whose keywords appear in the attr-spec, except that the
* DIMENSION attribute may be specified or overridden for an
* entity by the appearance of array-spec in its
* entity-decl, and the CODIMENSION attribute may be
* specified or overridden for an entity by the appearance
* of coarray-spec in its entity-decl.
*/
actualDimInfo = processArrayDimInfo(spec);
actualTypeNode = genArrDescType(src);
} else if (prp == MFPUtils.CHAR_LENGTH) {
assert false;
} else if (prp == MFPUtils.INITIALIZATION) {
initNode = translateInitializer(spec);
if (scopes.hasAttr(varName,
MFScopeManager.ATTR_VAR_TARGET)) {
// Var. w/ TARGET shall be translated as pointer type
// Its init expr is assigne to an intermediate var.
String targetValVarName = FORTRAN_ATTR_TARGET_PREFIX
+ varName;
IdentifierNode tvVarIdNode = nodeFactory
.newIdentifierNode(src, targetValVarName);
IdentifierExpressionNode tvVarExprNode = nodeFactory
.newIdentifierExpressionNode(src,
tvVarIdNode.copy());
TypeNode tvVarTypeNode = baseTypeNode.copy();
VariableDeclarationNode tvVarDeclNode = nodeFactory
.newVariableDeclarationNode(src, tvVarIdNode,
tvVarTypeNode, initNode);
declNodes.add(tvVarDeclNode);
scopes.addDeclVariable(targetValVarName, tvVarDeclNode);
initNode = nodeFactory.newOperatorNode(src,
Operator.ADDRESSOF, tvVarExprNode);
}
} else
assert false;
}
if (scopes.isParameterVar(varName)) {
// Formals
// Get parameter decl. w/ its implicit type
declNode = scopes.getDeclByParIdent(varName);
if (actualDimInfo != null) {
// Array typed parameters
// 1. Update parameter type decl.
// - change its identifier for reshaping
declNode.setIdentifier(nodeFactory.newIdentifierNode(
dummySrc, FORTRAN_ARRAY_PARAM_PREFIX + varName));
// - change its type as: farr_desc
declNode.setTypeNode(genArrDescType(src));
scopes.addDeclParameter(
FORTRAN_ARRAY_PARAM_PREFIX + varName, declNode);
// 2. Insert new local var. decl. for reshaping
/*
* e.g., farr_desc PAR_ID = farr_reshape(__PAR_ID, rank,
* reshap_dim_info);
*/
// - form the local var. decl. for reshaping
declNode = createArrayDesc(src, nameNode, actualDimInfo,
baseTypeNode.copy(),
FORTRAN_ARRAY_DESCRIPTOR_KIND.RESHAPE,
/* isCommon */ false);
// - add the local reshaping decl. to the returned list
declNodes.add(declNode);
scopes.addDeclArray(varName, baseTypeNode);
scopes.addDeclParameter(varName, declNode);
/*
* Only the inserted local variable 'varName', whose
* identifier has no prefix (as the parameter identifier in
* original source code), shall be accessed in the current
* programing unit scope. Thus, the changed parameter
* identifier, which has a prefix, is not recorded in
* 'scopes'
*/
} else if (actualTypeNode.kind() == TypeNodeKind.BASIC) {
// Scalar typed parameters
// Parameters are passed by references, so that their
// types are changed to corresponding pointer types
declNode.setTypeNode(nodeFactory.newPointerTypeNode(src,
actualTypeNode));
} else {
// Other types
// Update the type declared in its parameter decl.
declNode.setTypeNode(actualTypeNode);
}
if (sharedAttrs[MFScopeManager.ATTR_ARG_INTENT_OUT]) {
if (!sharedAttrs[MFScopeManager.ATTR_ARG_INTENT_IN]) {
// SUBR(type *OUT_ARG) {
// type ARG
// ..
// *OUT_ARG = ARG
String outArgName = FORTRAN_INTENT_OUT_PREFIX + varName;
VariableDeclarationNode dummyArgDeclNode = nodeFactory
.newVariableDeclarationNode(
declNode.getSource(),
declNode.getIdentifier().copy(),
actualTypeNode.copy());
scopes.updateParameterIdentfier(varName, outArgName);
varName = outArgName;
scopes.addDeclVariable(outArgName, dummyArgDeclNode);
}
}
} else {
if (actualDimInfo != null) {
// Array typed locals
declNode = createArrayDesc(src, nameNode, actualDimInfo,
baseTypeNode.copy(),
FORTRAN_ARRAY_DESCRIPTOR_KIND.ORIGIN,
/* isCommon */ false);
scopes.addDeclArray(varName, baseTypeNode);
} else {
// Non-array types
if (sharedAttrs[MFScopeManager.ATTR_VAR_TARGET]) {
// Var. w/ TARGET attr will be translated as:
// TYPE _PREFIX_ID = INIT_EXPR;
// TYPE* ID;
// *ID = _PREFIX_ID;
declNode = nodeFactory.newVariableDeclarationNode(src,
nameNode, actualTypeNode.copy(), initNode);
} else {
declNode = nodeFactory.newVariableDeclarationNode(src,
nameNode, actualTypeNode, initNode);
}
}
declNodes.add(declNode);
}
// Both formals/locals are collected as variables.
scopes.addDeclVariable(varName, declNode);
}
if (isInputVarDecl || isOutputVarDecl) {
// $input/$output variables shall be in root scope
isInputVarDecl = false;
isOutputVarDecl = false;
inputOutputVarDeclNodes.addAll(declNodes);
for (BlockItemNode itemNode : declNodes) {
VariableDeclarationNode declNode = (VariableDeclarationNode) itemNode;
scopes.setDeclGlobal(declNode.getName());
}
return new ArrayList<>();
} else
return declNodes;
}
private ExpressionNode translateConstantChar(Source source, MFTree constant)
throws SyntaxException {
CivlcToken strToken = constant.getChildByIndex(0).cTokens()[0];
String constantText = strToken.getText().replace('\'', '\"');
return nodeFactory.newStringLiteralNode(source, constantText,
tokenFactory.newStringToken(strToken).getStringLiteral());
}
private ExpressionNode translateConstantFloating(Source source,
MFTree constant) throws SyntaxException {
String constantText = constant.getChildByIndex(0).cTokens()[0].getText()
.toUpperCase();
int eIdx = constantText.indexOf('D'); // for double
String suffix = "l";
if (eIdx < 0) {
eIdx = constantText.indexOf('E');
suffix = "f";
}
if (eIdx > 0) {
String baseStr = constantText.substring(0, eIdx);
String exp10Str = constantText.substring(eIdx + 1);
double base = Double.valueOf(baseStr);
double exp10 = Double.valueOf(exp10Str);
double result = base * Math.pow(10.0, exp10);
constantText = Double.toString(result);
}
constantText += suffix;
return nodeFactory.newFloatingConstantNode(source, constantText);
}
private ExpressionNode translateConstantInteger(Source source,
MFTree constant) throws SyntaxException {
String constantText = constant.getChildByIndex(0).cTokens()[0]
.getText();
return nodeFactory.newIntegerConstantNode(source, constantText);
}
private ExpressionNode translateConstantLogical(Source source,
MFTree constant) {
if (constant.getChildByIndex(0).prp() == MFPUtils.T_TRUE)
return nodeFactory.newBooleanConstantNode(source, true);
else
return nodeFactory.newBooleanConstantNode(source, false);
}
private ExpressionNode translateOperatorExpression(Source source,
MFTree exprStmt) throws SyntaxException {
PRPair prp = exprStmt.prp();
Operator op = null;
LinkedList<ExpressionNode> argNodes = null;
if (prp == MFPUtils.PART_REF) {
return translateExprPartRef(exprStmt);
} else if (prp == MFPUtils.ASSIGNMENT_STMT) {
ExpressionNode lhsExprNode = translateExpr(
exprStmt.getChildByIndex(1));
ExpressionNode rhsExprNode = translateExpr(
exprStmt.getChildByIndex(2));
op = Operator.ASSIGN;
argNodes = new LinkedList<>();
argNodes.add(lhsExprNode);
argNodes.add(rhsExprNode);
return nodeFactory.newOperatorNode(source, op, argNodes);
} else if (prp == MFPUtils.LEVEL_3_EXPR) {
ExpressionNode lhsExprNode = translateExpr(
exprStmt.getChildByIndex(0));
ExpressionNode rhsExprNode = translateExpr(
exprStmt.getChildByIndex(2));
prp = exprStmt.getChildByIndex(1).prp();
if (prp == MFPUtils.T_GE)
op = Operator.GTE;
else if (prp == MFPUtils.T_GT)
op = Operator.GT;
else if (prp == MFPUtils.T_EQ || prp == MFPUtils.T_EQ_EQ)
op = Operator.EQUALS;
else if (prp == MFPUtils.T_LT)
op = Operator.LT;
else if (prp == MFPUtils.T_LE)
op = Operator.LTE;
else if (prp == MFPUtils.T_NE)
op = Operator.NEQ;
else
assert false;
argNodes = new LinkedList<ExpressionNode>();
argNodes.add(lhsExprNode);
argNodes.add(rhsExprNode);
return nodeFactory.newOperatorNode(source, op, argNodes);
} else if (prp == MFPUtils.ADD_OPERAND) {
Source src = newSource(exprStmt);
MFTree addOperand = exprStmt.getChildByIndex(0);
MFTree val = addOperand;
ExpressionNode lhsExprNode = null;
ExpressionNode rhsExprNode = null;
if (exprStmt.kind() == MFPUtils.ADD_OPERAND_SIGN) {
op = Operator.UNARYPLUS;
val = exprStmt.getChildByIndex(1);
if (exprStmt.getChildByIndex(0).prp() == MFPUtils.T_MINUS)
op = Operator.UNARYMINUS;
return nodeFactory.newOperatorNode(src, op, translateExpr(val));
}
prp = addOperand.prp();
if (prp == MFPUtils.ADD_OPERAND) {
op = Operator.UNARYPLUS;
val = val.getChildByIndex(1);
lhsExprNode = translateExpr(val);
if (addOperand.getChildByIndex(0).prp() == MFPUtils.T_MINUS)
op = Operator.UNARYMINUS;
lhsExprNode = nodeFactory.newOperatorNode(src, op, lhsExprNode);
} else
lhsExprNode = translateExpr(val);
for (int i = 1; i < exprStmt.numChildren(); i++) {
addOperand = exprStmt.getChildByIndex(i);
op = Operator.PLUS;
val = addOperand.getChildByIndex(1);
rhsExprNode = translateExpr(val);
if (addOperand.getChildByIndex(0).prp() == MFPUtils.T_MINUS)
op = Operator.MINUS;
lhsExprNode = nodeFactory.newOperatorNode(src, op, lhsExprNode,
rhsExprNode);
}
return lhsExprNode;
} else if (prp == MFPUtils.MULT_OPERAND) {
Source src = newSource(exprStmt);
MFTree multOperand = exprStmt.getChildByIndex(0);
MFTree val = multOperand;
ExpressionNode lhsExprNode = translateExpr(val);
if (lhsExprNode.parent() != null) {
lhsExprNode.remove();
}
ExpressionNode rhsExprNode = null;
if (exprStmt.kind() == MFPUtils.MULT_OPERAND_POW) {
Source powSrc = newSource(exprStmt.getChildByIndex(1));
IdentifierNode powFuncNameNode = nodeFactory
.newIdentifierNode(powSrc, "pow");
ExpressionNode powFuncNode = nodeFactory
.newIdentifierExpressionNode(powSrc, powFuncNameNode);
useMATH = true;
val = exprStmt.getChildByIndex(2);
rhsExprNode = translateExpr(val);
return nodeFactory.newFunctionCallNode(src, powFuncNode,
Arrays.asList(lhsExprNode, rhsExprNode), null);
}
for (int i = 1; i < exprStmt.numChildren(); i++) {
multOperand = exprStmt.getChildByIndex(i);
op = Operator.TIMES;
val = multOperand.getChildByIndex(1);
rhsExprNode = translateExpr(val);
if (multOperand.getChildByIndex(0).prp() == MFPUtils.T_SLASH)
op = Operator.DIV;
lhsExprNode = nodeFactory.newOperatorNode(src, op, lhsExprNode,
rhsExprNode);
}
return lhsExprNode;
} else if (prp == MFPUtils.AND_OPERAND) {
Source src = newSource(exprStmt);
int kind = exprStmt.kind();
if (kind == MFPUtils.LAO_LST) {
MFTree val = exprStmt.getChildByIndex(0);
ExpressionNode lhsExprNode = translateExpr(val);
ExpressionNode rhsExprNode = null;
for (int i = 1; i < exprStmt.numChildren(); i++) {
op = Operator.LAND;
val = exprStmt.getChildByIndex(i);
rhsExprNode = translateExpr(val);
lhsExprNode = nodeFactory.newOperatorNode(src, op,
lhsExprNode, rhsExprNode);
}
return lhsExprNode;
} else { // kind == MFPUtils.LAO_NOT
MFTree val = exprStmt.getChildByIndex(1);
ExpressionNode unaryExprNode = translateExpr(val);
return nodeFactory.newOperatorNode(src, Operator.NOT,
unaryExprNode);
}
} else if (prp == MFPUtils.OR_OPERAND) {
Source src = newSource(exprStmt);
MFTree val = exprStmt.getChildByIndex(0);
ExpressionNode lhsExprNode = translateExpr(val);
ExpressionNode rhsExprNode = null;
for (int i = 1; i < exprStmt.numChildren(); i++) {
op = Operator.LOR;
val = exprStmt.getChildByIndex(i);
rhsExprNode = translateExpr(val);
lhsExprNode = nodeFactory.newOperatorNode(src, op, lhsExprNode,
rhsExprNode);
}
return lhsExprNode;
} else
assert false;
return null;
}
private ExpressionNode translateExprDataRef(Source src, MFTree refs) {
int numDataRefs = refs.numChildren();
MFTree hostName = refs.getChildByIndex(0).getChildByIndex(0);
MFTree refName = null;
IdentifierNode hostNameNode = null;
ExpressionNode refExpr = null;
assert numDataRefs > 0;
hostNameNode = translateIdentifier(hostName);
refExpr = nodeFactory.newIdentifierExpressionNode(newSource(hostName),
hostNameNode);
for (int i = 1; i < numDataRefs; i++) {
refName = refs.getChildByIndex(i).getChildByIndex(0);
refExpr = nodeFactory.newDotNode(src, refExpr,
translateIdentifier(refName));
}
return refExpr;
}
int dummyFuncRefArgsCtr = 0;
static final String FUNC_REF_ARG_PREFIX = "__FUNCREF_ARG_";
private LinkedList<BlockItemNode> dummyFuncRefArgs = new LinkedList<>();
private LinkedList<BlockItemNode> dummyFuncRefArrayArgPreStmts = new LinkedList<>();
private LinkedList<BlockItemNode> dummyFuncRefArrayArgPostStmts = new LinkedList<>();
private ExpressionNode translateExprFuncRef(MFTree funcRef)
throws SyntaxException {
int numArrayArgs = 0;
Source src = newSource(funcRef);
List<BlockItemNode> itemNodes = new LinkedList<>();
MFTree funcName = funcRef.getChildByIndex(0);
Boolean hasArgList = funcRef.numChildren() > 1;
IdentifierNode funcIdNode = translateIdentifier(funcName);
ExpressionNode funcRefNode = nodeFactory
.newIdentifierExpressionNode(src, funcIdNode);
List<ExpressionNode> actualCallArgNodes = new LinkedList<ExpressionNode>();
List<VariableDeclarationNode> dummyFuncDeclFormalNodes = new LinkedList<VariableDeclarationNode>();
SequenceNode<VariableDeclarationNode> formalsNode = null;
TypeNode formalTypeNode = null;
TypeNode tempNode = null;
if (hasArgList) {
MFTree args = funcRef.getChildByIndex(1);
int numArgs = args.numChildren();
for (int i = 0; i < numArgs; i++) {
MFTree arg = args.getChildByIndex(i).getChildByIndex(0);
Source argSrc = newSource(arg);
ExpressionNode argNode = translateExpr(arg);
IdentifierNode formalNameNode = nodeFactory.newIdentifierNode(
argNode.getSource(), "__civl_dummy_arg_" + i);
Boolean notSection = arraySectionDecls.isEmpty();
while (!arraySectionDecls.isEmpty())
itemNodes.add(0, arraySectionDecls.pop());
switch (argNode.expressionKind()) {
case OPERATOR :
if (((OperatorNode) argNode)
.getOperator() == Operator.DEREFERENCE) {
argNode = ((OperatorNode) argNode).getArgument(0)
.copy();
argNode.remove();
if (argNode instanceof IdentifierExpressionNode) {
// Arg is an identifier w/ a scalar type
formalTypeNode = analyzeRawExprType(argNode);
tempNode = formalTypeNode;
if (tempNode.kind() == TypeNodeKind.BASIC) {
if (!scopes.isParameterVar(
((IdentifierExpressionNode) argNode)
.getIdentifier().name())) {
argNode = nodeFactory.newOperatorNode(
src, Operator.ADDRESSOF,
argNode);
}
formalTypeNode = nodeFactory
.newPointerTypeNode(
argNode.getSource(),
formalTypeNode.copy());
}
} else if (argNode instanceof CastNode) {
formalTypeNode = ((CastNode) argNode)
.getCastType();
}
} else {
formalTypeNode = analyzeRawExprType(argNode).copy();
argNode = processExprInFuncRefArgs(formalTypeNode,
argNode);
}
break;
case IDENTIFIER_EXPRESSION :
tempNode = analyzeRawExprType(argNode);
formalTypeNode = tempNode;
if (tempNode.kind() == TypeNodeKind.BASIC) {
if (!scopes.isParameterVar(
((IdentifierExpressionNode) argNode)
.getIdentifier().name())) {
argNode = nodeFactory.newOperatorNode(src,
Operator.ADDRESSOF, argNode);
}
formalTypeNode = nodeFactory.newPointerTypeNode(src,
tempNode);
}
if (notSection && tempNode
.kind() == TypeNodeKind.TYPEDEF_NAME) {
// Array type arg
// TODO: if this FuncRef is in an expression,
// then a dummy variable is required for
// removing side-effects caused by
// inserting wraps of array type args.
IdentifierNode arrayArgIdNode = nodeFactory
.newIdentifierNode(src,
FORTRAN_ARRAY_ARG_PREFIX
+ ((IdentifierExpressionNode) argNode)
.getIdentifier()
.name());
VariableDeclarationNode arrayArgVarDeclNode = createArrayDesc(
dummySrc, arrayArgIdNode, null, null,
FORTRAN_ARRAY_DESCRIPTOR_KIND.SECTION_ARG,
/* isCommon */ false);
dummyFuncRefArrayArgPreStmts
.add(arrayArgVarDeclNode);
argNode = nodeFactory.newIdentifierExpressionNode(
src, arrayArgIdNode.copy());
numArrayArgs++;
}
if (tempNode.kind() == TypeNodeKind.ARRAY)
assert false;
break;
case CONSTANT :
argNode = argNode.copy();
tempNode = analyzeRawExprType(argNode);
formalTypeNode = nodeFactory
.newPointerTypeNode(dummySrc, tempNode);
argNode = translateExprArg(argNode);
break;
default :
assert false;
}
actualCallArgNodes.add(argNode);
dummyFuncDeclFormalNodes
.add(nodeFactory.newVariableDeclarationNode(argSrc,
formalNameNode, formalTypeNode.copy()));
}
}
formalsNode = nodeFactory.newSequenceNode(src,
"DummySubroutineFormalDeclList", dummyFuncDeclFormalNodes);
FunctionCallNode callNode = nodeFactory.newFunctionCallNode(src,
funcRefNode, actualCallArgNodes, null);
FunctionTypeNode dummyFuncTypeNode = nodeFactory.newFunctionTypeNode(
src, nodeFactory.newVoidTypeNode(src), formalsNode, false);
FunctionDeclarationNode dummyFuncDeclNode = nodeFactory
.newFunctionDeclarationNode(src, funcIdNode.copy(),
dummyFuncTypeNode, null);
processDummyFuncOrSubrDeclaration(getName(funcName), dummyFuncDeclNode);
while (numArrayArgs > 0) {
itemNodes.add(createArrayDestroy(freedArrays.pop()));
numArrayArgs--;
}
return callNode;
}
private ExpressionNode processExprInFuncRefArgs(TypeNode exprType,
ExpressionNode argNode) {
// Expressions, which are replaced with pointers to
// intermediate arg var.
// e.g. <code> foo(x+1,y+1.0) </code> is translated as
// <code>
// int __FUNCREF_ARG_0 = x+1;
// float __FUNCREF_ARG_1 = y+1.0;
// foo(&__FUNCREF_ARG_0, &__FUNCREF_ARG_1);
// </code>
Source src = argNode.getSource();
String funcRefArgName = FUNC_REF_ARG_PREFIX + dummyFuncRefArgsCtr;
IdentifierNode argIdNode = nodeFactory.newIdentifierNode(src,
funcRefArgName);
ExpressionNode argIdExprNode = nodeFactory
.newIdentifierExpressionNode(src, argIdNode.copy());
ExpressionNode addrOfArgNode = nodeFactory.newOperatorNode(src,
Operator.ADDRESSOF, argIdExprNode);
VariableDeclarationNode argDeclNode = nodeFactory
.newVariableDeclarationNode(dummySrc, argIdNode,
exprType.copy(), argNode);
dummyFuncRefArgs.add(argDeclNode);
dummyFuncRefArgsCtr++;
return addrOfArgNode;
}
private TypeNode analyzeRawExprType(ExpressionNode exprNode) {
TypeNode rawExprTypeNode = null;
switch (exprNode.expressionKind()) {
case OPERATOR :
if (((OperatorNode) exprNode)
.getOperator() == Operator.DEREFERENCE) {
exprNode = ((OperatorNode) exprNode).getArgument(0).copy();
exprNode.remove();
if (exprNode instanceof IdentifierExpressionNode) {
// Arg is an identifier w/ a scalar type
rawExprTypeNode = scopes.getTypeByVarIdent(
((IdentifierExpressionNode) exprNode)
.getIdentifier().name(),
exprNode.getSource());
if (rawExprTypeNode.kind() == TypeNodeKind.POINTER)
rawExprTypeNode = ((PointerTypeNode) rawExprTypeNode)
.referencedType();
} else if (exprNode instanceof CastNode)
rawExprTypeNode = ((CastNode) exprNode).getCastType();
} else {
OperatorNode opExprNode = (OperatorNode) exprNode;
TypeNode tempTypeNode = null;
rawExprTypeNode = analyzeRawExprType(
opExprNode.getArgument(0));
for (int i = 1; i < opExprNode
.getNumberOfArguments(); i++) {
tempTypeNode = analyzeRawExprType(
((OperatorNode) exprNode).getArgument(i));
assert (rawExprTypeNode.kind() == tempTypeNode.kind());
}
}
break;
case IDENTIFIER_EXPRESSION :
String varName = ((IdentifierExpressionNode) exprNode)
.getIdentifier().name();
rawExprTypeNode = scopes.getTypeByVarIdent(varName,
exprNode.getSource());
if (rawExprTypeNode.kind() == TypeNodeKind.POINTER)
rawExprTypeNode = ((PointerTypeNode) rawExprTypeNode)
.referencedType();
if (rawExprTypeNode.kind() == TypeNodeKind.TYPEDEF_NAME) {
if (!scopes.hasArrayType(varName)) {
assert false;
}
}
if (rawExprTypeNode.kind() == TypeNodeKind.ARRAY)
assert false;
break;
case CONSTANT :
if (exprNode instanceof IntegerConstantNode)
rawExprTypeNode = nodeFactory.newBasicTypeNode(
exprNode.getSource(), BasicTypeKind.INT);
else if (exprNode instanceof FloatingConstantNode)
rawExprTypeNode = nodeFactory.newBasicTypeNode(
exprNode.getSource(), BasicTypeKind.FLOAT);
else
assert false;
break;
default :
assert false;
}
if (rawExprTypeNode.parent() != null)
rawExprTypeNode = rawExprTypeNode.copy();
rawExprTypeNode.setInputQualified(false);
rawExprTypeNode.setOutputQualified(false);
return rawExprTypeNode;
}
private ExpressionNode translateExprPartRef(MFTree exprStmt)
throws SyntaxException {
Source src = newSource(exprStmt);
MFTree varId = exprStmt.getChildByIndex(0);
MFTree subscripts = exprStmt.getChildByIndex(1);
int numDim = subscripts.numChildren();
IdentifierNode varIdNode = translateIdentifier(varId);
String varIdStr = varIdNode.name().toUpperCase();
ExpressionNode varExprNode = nodeFactory
.newIdentifierExpressionNode(newSource(varId), varIdNode);
if (numDim > 0) {
// Array unit/section subscript
Boolean isUnit = true;
ExpressionNode idxNodes[][] = new ExpressionNode[numDim][3];
TypeNode arrayElementTypeNode = scopes
.getArrayBaseTypeByIdent(varIdStr).copy();
MFTree subscript, lowerIndex, upperIndex, stride;
for (int i = 0; i < numDim; i++) {
subscript = subscripts.getChildByIndex(i);
lowerIndex = subscript.getChildByIndex(0);
idxNodes[i][0] = translateExpr(lowerIndex);
if (subscript.numChildren() > 1) {
isUnit = false;
upperIndex = subscript.getChildByIndex(1);
idxNodes[i][1] = translateExpr(upperIndex);
if (subscript.numChildren() > 2) {
stride = subscript.getChildByIndex(2);
idxNodes[i][2] = translateExpr(stride);
} else // Section stride is 1 by default
idxNodes[i][2] = nodeFactory
.newIntConstantNode(dummySrc, 1);
}
}
if (isUnit) {
ExpressionNode unitIdxNodes[] = new ExpressionNode[numDim];
for (int i = 0; i < numDim; i++)
unitIdxNodes[i] = idxNodes[i][0];
return createArraySubscript(src, varIdNode, unitIdxNodes,
arrayElementTypeNode);
} else {
String arraySectionName = "__arg_" + varIdStr;
IdentifierNode argArraySectionId = nodeFactory
.newIdentifierNode(dummySrc, arraySectionName);
VariableDeclarationNode argArraySectionDecl = createArrayDesc(
dummySrc, argArraySectionId, idxNodes,
arrayElementTypeNode,
FORTRAN_ARRAY_DESCRIPTOR_KIND.SECTION_ARG,
/* isCommon */ false);
arraySectionDecls.push(argArraySectionDecl);
scopes.addDeclVariable(arraySectionName, argArraySectionDecl);
return nodeFactory.newIdentifierExpressionNode(dummySrc,
argArraySectionId.copy());
}
// TODO: common block tranformation
}
return (OperatorNode) varExprNode;
}
private ExpressionNode translateExprStructure(Source src,
MFTree structConstructor) throws SyntaxException {
MFTree derivedTypeName = structConstructor.getChildByIndex(0);
MFTree derivedTypeVals = structConstructor.getChildByIndex(1);
IdentifierNode derivedTypeNameNode = translateIdentifier(
derivedTypeName);
TypeNode derivedTypeNode = nodeFactory.newStructOrUnionTypeNode(
newSource(derivedTypeName), true /* isStruct */,
derivedTypeNameNode, null);
LinkedList<PairNode<DesignationNode, InitializerNode>> structureLiteralNode = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
for (int i = 0; i < derivedTypeVals.numChildren(); i++) {
MFTree fieldVal = derivedTypeVals.getChildByIndex(i)
.getChildByIndex(0);
ExpressionNode fieldExprNode = translateExpr(fieldVal);
structureLiteralNode.add(nodeFactory.newPairNode(
fieldExprNode.getSource(), null, fieldExprNode));
}
return nodeFactory.newCompoundLiteralNode(src, derivedTypeNode,
nodeFactory.newCompoundInitializerNode(
newSource(derivedTypeVals), structureLiteralNode));
}
private ExpressionNode translateExprVariable(Source src, MFTree ref,
boolean isPureDeisgnator) throws SyntaxException {
boolean hasSubscriptsOrArgs = ref.numChildren() > 1;
MFTree refName = ref.getChildByIndex(0);
String refNameText = getName(refName).toUpperCase();
Source refNameSrc = newSource(refName);
ExpressionNode refExprNode = null;
if (scopes.isDerivedType(refNameText)) {
return translateExprStructure(src, ref);
}
if (currentFunctionName != null
&& currentFunctionName.equals(refNameText)
&& !hasSubscriptsOrArgs)
refNameText = FORTRAN_FUNCTION_RETURN_PREFIX + refNameText;
refName.setNodeName(refNameText);
if (hasSubscriptsOrArgs) {
if (!isPureDeisgnator) {
MFTree subscriptsOrArgs = ref.getChildByIndex(1);
if (refNameText.equals("MOD") || refNameText.equals("MODULO")) {
List<ExpressionNode> argNodes = new LinkedList<ExpressionNode>();
assert subscriptsOrArgs.numChildren() == 2;
for (int i = 0; i < subscriptsOrArgs.numChildren(); i++) {
MFTree arg = subscriptsOrArgs.getChildByIndex(i);
argNodes.add(translateExpr(arg.getChildByIndex(0)));
}
return nodeFactory.newOperatorNode(src, Operator.MOD,
argNodes);
} else if (refNameText.equals("MAX"))
return replaceFunctionMax(src, ref);
else if (refNameText.equals("ABS"))
return replaceFunctionAbs(src, ref);
else if (refNameText.equals("PRESENT"))
return replaceFunctionPresent(src, ref);
else if (refNameText.equals("SIN") || //
refNameText.equals("COS") || //
refNameText.equals("ATAN") || //
refNameText.equals("SQRT"))
return processMathFunction(refNameText.toLowerCase(), ref);
}
if (scopes.hasArrayType(refNameText)) {
// Array Subscription.
refExprNode = translateOperatorExpression(src, ref);
} else {
// Function reference
refExprNode = translateExprFuncRef(ref);
}
} else {
// Scalar Variable
refExprNode = nodeFactory.newIdentifierExpressionNode(src,
translateIdentifier(refName));
if ((scopes.isParameterVar(refNameText)
&& !(scopes.getTypeByVarIdent(refNameText,
refNameSrc) instanceof CommonTypedefNameNode))
|| scopes.hasAttr(refNameText,
MFScopeManager.ATTR_VAR_POINTER))
// Dereference when it is a parameter with scalar type.
refExprNode = nodeFactory.newOperatorNode(
refExprNode.getSource(), Operator.DEREFERENCE,
refExprNode);
else if (commonblockMemberMap.containsKey(refNameText))
refExprNode = commonblockMemberMap.get(refNameText).copy();
}
if (!hasSubscriptsOrArgs && !scopes.isDeclaredVar(refNameText)
&& !scopes.isParameterVar(refNameText)
&& !refNameText.startsWith("_"))
scopes.addUndeclaredIdent(refNameText);
return refExprNode;
}
private ExpressionNode replaceFunctionAbs(Source src, MFTree absCall)
throws SyntaxException {
MFTree arg = absCall.getChildByIndex(1).getChildByIndex(0)
.getChildByIndex(0);
ExpressionNode exprNode = translateExpr(arg);
ExpressionNode negExprNode = nodeFactory.newOperatorNode(src,
Operator.UNARYMINUS, exprNode.copy());
ExpressionNode int0Node = nodeFactory.newIntConstantNode(src, 0);
ExpressionNode condExprNode = nodeFactory.newOperatorNode(src,
Operator.GTE, exprNode.copy(), int0Node.copy());
return nodeFactory.newOperatorNode(src, Operator.CONDITIONAL,
Arrays.asList(condExprNode, exprNode, negExprNode));
}
private ExpressionNode processMathFunction(String funcName, MFTree call)
throws SyntaxException {
Source src = newSource(call);
MFTree arg = call.getChildByIndex(1).getChildByIndex(0)
.getChildByIndex(0);
ExpressionNode argNode = translateExpr(arg);
IdentifierNode funcNameNode = nodeFactory.newIdentifierNode(src,
funcName);
ExpressionNode atanFuncNode = nodeFactory
.newIdentifierExpressionNode(src, funcNameNode);
useMATH = true;
return nodeFactory.newFunctionCallNode(src, atanFuncNode,
Arrays.asList(argNode), null);
}
private ExpressionNode replaceFunctionMax(Source src, MFTree maxCall)
throws SyntaxException {
MFTree arg0 = maxCall.getChildByIndex(1).getChildByIndex(0)
.getChildByIndex(0);
MFTree arg1 = maxCall.getChildByIndex(1).getChildByIndex(1)
.getChildByIndex(0);
ExpressionNode Expr0Node = translateExpr(arg0);
ExpressionNode Expr1Node = translateExpr(arg1);
ExpressionNode condExprNode = nodeFactory.newOperatorNode(src,
Operator.GTE, Expr0Node.copy(), Expr1Node.copy());
return nodeFactory.newOperatorNode(src, Operator.CONDITIONAL,
Arrays.asList(condExprNode, Expr0Node, Expr1Node));
}
private ExpressionNode translateExprConstants(MFTree constant)
throws SyntaxException {
Source src = newSource(constant);
PRPair tConstPrp = constant.prp();
ExpressionNode constantExprNode = null;
if (tConstPrp == MFPUtils.SIGNED_REAL_LITERAL_CONSTANT)
constant = constant.getChildByIndex(0);
tConstPrp = constant.prp();
if (tConstPrp == MFPUtils.INT_LITERAL_CONSTANT)
constantExprNode = translateConstantInteger(src, constant);
else if (tConstPrp == MFPUtils.REAL_LITERAL_CONSTANT)
return translateConstantFloating(src, constant);
else if (tConstPrp == MFPUtils.CHAR_LITERAL_CONSTANT)
return translateConstantChar(src, constant);
else if (tConstPrp == MFPUtils.LOGICAL_LITERAL_CONSTANT)
return translateConstantLogical(src, constant);
else
assert false;
return constantExprNode;
}
private ExpressionNode translateExprArg(ExpressionNode exprArgNode) {
Source src = exprArgNode.getSource();
ExpressionNode indexNode = nodeFactory.newIntConstantNode(src, 0);
ExpressionNode extentNode = nodeFactory.newIntConstantNode(src, 1);
TypeNode exprArgType = analyzeRawExprType(exprArgNode);
TypeNode exprArgCompoundLiteTypeNode = nodeFactory.newArrayTypeNode(src,
exprArgType, extentNode);
CompoundInitializerNode exprArgCompoundInitNode = nodeFactory
.newCompoundInitializerNode(src, Arrays.asList(
nodeFactory.newPairNode(src, null, exprArgNode)));
CompoundLiteralNode exprArgCompoundLiteNode = nodeFactory
.newCompoundLiteralNode(src, exprArgCompoundLiteTypeNode,
exprArgCompoundInitNode);
OperatorNode exprArgValueNode = nodeFactory.newOperatorNode(src,
Operator.SUBSCRIPT, exprArgCompoundLiteNode, indexNode);
return nodeFactory.newOperatorNode(src, Operator.ADDRESSOF,
exprArgValueNode);
}
private ExpressionNode replaceFunctionPresent(Source src,
MFTree presentCall) throws SyntaxException {
MFTree varExpr = presentCall.getChildByIndex(1).getChildByIndex(0)
.getChildByIndex(0);
ExpressionNode varExprNode = translateExpr(varExpr);
IdentifierExpressionNode varIdExprNode = (IdentifierExpressionNode) varExprNode;
IdentifierNode varIdNode = varIdExprNode.getIdentifier();
TypeNode varTypeNode = scopes.getTypeByVarIdent(varIdNode.name(),
varIdNode.getSource());
ExpressionNode presentNode = nodeFactory.newOperatorNode(src,
Operator.EQUALS, varExprNode,
createNullConstantNode(src, varTypeNode));
return presentNode;
}
private List<BlockItemNode> translateDerivedTypeDef(MFTree derivedTypeDef) {
Source src = newSource(derivedTypeDef);
LinkedList<BlockItemNode> derivedTypeDefNodes = new LinkedList<>();
MFTree derivedTypeStmt = derivedTypeDef.getChildByIndex(0);
MFTree derivedTypeName = derivedTypeStmt.getChildByIndex(2);
MFTree derivedTypeParam = derivedTypeStmt.getChildByIndex(3);
MFTree derivedTypeAttrs = derivedTypeStmt.getChildByIndex(4);
IdentifierNode derivedTypeNameNode = null;
List<FieldDeclarationNode> compNodes = new LinkedList<>();
SequenceNode<FieldDeclarationNode> componentsNode = null;
derivedTypeNameNode = translateIdentifier(derivedTypeName);
if (derivedTypeParam.prp() != MFPUtils.ABSENT)
assert false;
if (derivedTypeAttrs.prp() != MFPUtils.ABSENT)
assert false;
for (int i = 1; i < derivedTypeDef.numChildren() - 1; i++) {
MFTree compOrTypeParam = derivedTypeDef.getChildByIndex(i);
if (compOrTypeParam.prp() == MFPUtils.DATA_COMPONENT_DEF_STMT) {
compNodes.addAll(translateCompDecls(compOrTypeParam));
} else
assert false;
}
componentsNode = nodeFactory.newSequenceNode(newSource(derivedTypeDef),
"DerivedTypeMembers", compNodes);
derivedTypeDefNodes.add(nodeFactory.newStructOrUnionTypeNode(src,
true /* isStruct */, derivedTypeNameNode, componentsNode));
return derivedTypeDefNodes;
}
private List<FieldDeclarationNode> translateCompDecls(
MFTree compOrTypeParam) {
Source src = newSource(compOrTypeParam);
LinkedList<FieldDeclarationNode> compNodes = new LinkedList<>();
MFTree compType = compOrTypeParam.getChildByIndex(1);
MFTree compEntities = compOrTypeParam.getChildByIndex(2);
MFTree compTypeAttr = compOrTypeParam.getChildByIndex(3);
TypeNode rawTypeNode = translateType(compType.getChildByIndex(0));
if (compTypeAttr.prp() != MFPUtils.ABSENT)
assert false;
for (int i = 0; i < compEntities.numChildren(); i++) {
MFTree compEntity = compEntities.getChildByIndex(i);
MFTree compName = compEntity.getChildByIndex(0);
if (compEntity.getChildByIndex(1).prp() != MFPUtils.ABSENT)
assert false;
if (compEntity.getChildByIndex(2).prp() != MFPUtils.ABSENT)
assert false;
if (compEntity.getChildByIndex(3).prp() != MFPUtils.ABSENT)
assert false;
if (compEntity.getChildByIndex(4).prp() != MFPUtils.ABSENT)
assert false;
compNodes.add(nodeFactory.newFieldDeclarationNode(src,
translateIdentifier(compName), rawTypeNode.copy()));
}
if (compTypeAttr.prp() != MFPUtils.ABSENT)
assert false;
return compNodes;
}
private ExpressionNode translateExpr(MFTree exprStmt)
throws SyntaxException {
Source src = newSource(exprStmt);
PRPair prp = exprStmt.prp();
ExpressionNode exprNode = null;
if (prp == MFPUtils.ASSIGNMENT_STMT)
return translateOperatorExpression(src, exprStmt);
else if (prp == MFPUtils.VARIABLE) {
assert exprStmt.getChildByIndex(0).prp() == MFPUtils.DESIGNATOR;
MFTree ref = exprStmt.getChildByIndex(0).getChildByIndex(0)
.getChildByIndex(0);
return translateExprVariable(newSource(ref), ref, true);
} else if (prp == MFPUtils.PRIMARY) {
MFTree primary = exprStmt.getChildByIndex(0);
PRPair tmpPrp = primary.prp();
if (tmpPrp == MFPUtils.DESIGNATOR_OR_FUNC_REF) {
MFTree refs = primary.getChildByIndex(0);
MFTree ref = refs.getChildByIndex(0);
if (refs.numChildren() > 1)
return translateExprDataRef(newSource(refs), refs);
return translateExprVariable(newSource(ref), ref, false);
} else if (tmpPrp == MFPUtils.LITERAL_CONSTANT) {
MFTree constant = exprStmt.getChildByIndex(0)
.getChildByIndex(0);
return translateExprConstants(constant);
} else if (tmpPrp == MFPUtils.ARRAY_CONSTRUCTOR) {
MFTree acSpec = exprStmt.getChildByIndex(0).getChildByIndex(0);
return translateArrayConstructor(acSpec);
} else if (tmpPrp == MFPUtils.STRUCTURE_CONSTRUCTOR)
assert false;
else if (tmpPrp == MFPUtils.EXPR)
assert false;
else
return translateExpr(primary);
} else if (prp == MFPUtils.MULT_OPERAND || //
prp == MFPUtils.ADD_OPERAND || //
prp == MFPUtils.LEVEL_3_EXPR || //
prp == MFPUtils.AND_OPERAND || //
prp == MFPUtils.OR_OPERAND)
return translateOperatorExpression(src, exprStmt);
else if (prp == MFPUtils.QUANTIFIED_EXPR) {
MFTree quantifier = exprStmt.getChildByIndex(0);
MFTree boundVarType = exprStmt.getChildByIndex(1);
MFTree boundVarNames = exprStmt.getChildByIndex(2);
MFTree boundVarName = null;
MFTree rExpr = null;
MFTree pExpr = exprStmt.getChildByIndex(3);
Quantifier q = null;
TypeNode boundVarTypeNode = null;
IdentifierNode boundVarIdNode = null;
List<VariableDeclarationNode> boundVarTypeDeclNodes = new LinkedList<>();
SequenceNode<VariableDeclarationNode> boundVarTypeDeclsNode = null;
List<PairNode<SequenceNode<VariableDeclarationNode>, ExpressionNode>> boundVariableList = new LinkedList<>();
SequenceNode<PairNode<SequenceNode<VariableDeclarationNode>, ExpressionNode>> boundVarDeclsNode = null;
ExpressionNode restrictExprNode = null;
ExpressionNode predExprNode = null;
switch (getName(quantifier)) {
case "$FORALL" :
q = Quantifier.FORALL;
break;
case "$EXISTS" :
q = Quantifier.EXISTS;
break;
case "$UNIFORM" :
q = Quantifier.UNIFORM;
break;
default :
assert false;
}
boundVarTypeNode = translateType(boundVarType);
for (int i = 0; i < boundVarNames.numChildren(); i++) {
boundVarName = boundVarNames.getChildByIndex(i);
boundVarIdNode = translateIdentifier(
boundVarName.getChildByIndex(0));
boundVarTypeDeclNodes.add(nodeFactory
.newVariableDeclarationNode(newSource(boundVarName),
boundVarIdNode, boundVarTypeNode.copy()));
}
boundVarTypeDeclsNode = nodeFactory.newSequenceNode(src,
"Binder List", boundVarTypeDeclNodes);
boundVariableList.add(
nodeFactory.newPairNode(src, boundVarTypeDeclsNode, null));
boundVarDeclsNode = nodeFactory.newSequenceNode(src,
"bound variable declaration list", boundVariableList);
if (exprStmt.numChildren() > 4) {
// Process restrict Expr, if it exits
rExpr = pExpr;
pExpr = exprStmt.getChildByIndex(4);
restrictExprNode = translateExpr(rExpr);
}
predExprNode = translateExpr(pExpr);
return nodeFactory.newQuantifiedExpressionNode(src, q,
boundVarDeclsNode, restrictExprNode, predExprNode, null);
} else
assert false;
return exprNode;
}
private BlockItemNode translateStmtExpr(MFTree exprStmt)
throws SyntaxException {
ExpressionNode exprNode = translateExpr(exprStmt);
if (exprNode == null)
return nodeFactory.newNullStatementNode(newSource(exprStmt));
else
return nodeFactory.newExpressionStatementNode(exprNode);
}
private List<BlockItemNode> translateStmtPrint(MFTree printStmt)
throws SyntaxException {
LinkedList<BlockItemNode> printfNodes = new LinkedList<>();
MFTree print = printStmt.getChildByIndex(1);
Source src = newSource(printStmt);
Source printSrc = newSource(print);
MFTree outputFormat = printStmt.getChildByIndex(2);
MFTree outputFormatId = outputFormat.getChildByIndex(0);
MFTree outputList = printStmt.getChildByIndex(3);
IdentifierNode printfIdNode = nodeFactory.newIdentifierNode(printSrc,
"printf");
ExpressionNode printfFuncNode = nodeFactory
.newIdentifierExpressionNode(printSrc, printfIdNode);
ExpressionNode formatNode = null;
FunctionCallNode printfCallNode = null;
LinkedList<ExpressionNode> printfArgNodes = new LinkedList<>();
String formatStr = "\"";
StringToken formatToken = null;
useSTDIO = true;
while (outputFormatId.numChildren() != 0)
outputFormatId = outputFormatId.getChildByIndex(0);
for (int j = 0; j < outputList.numChildren(); j++) {
MFTree outputItem = outputList.getChildByIndex(j);
ExpressionNode printfArgNode = translateExpr(
outputItem.getChildByIndex(0));
printfArgNodes.add(printfArgNode);
}
if (outputFormatId.prp() == MFPUtils.T_ASTERISK) {
for (int j = 0; j < outputList.numChildren(); j++)
formatStr += "%s ";
} else {
String fmtKey = getName(outputFormatId);
if (formats.containsKey(fmtKey))
formatStr += formats.get(fmtKey);
else
assert false;
}
formatStr += "\\n\"";
formatToken = tokenFactory.newStringToken(tokenFactory.newCivlcToken(0,
formatStr, print.cTokens()[0].getFormation(),
TokenVocabulary.FORTRAN));
formatNode = nodeFactory.newStringLiteralNode(src, formatStr,
formatToken.getStringLiteral());
printfArgNodes.add(0, formatNode);
printfCallNode = nodeFactory.newFunctionCallNode(src, printfFuncNode,
printfArgNodes, null);
printfNodes.add(nodeFactory.newExpressionStatementNode(printfCallNode));
return printfNodes;
}
private List<BlockItemNode> translateStmtReturn(MFTree returnStmt) {
Source src = newSource(returnStmt);
ExpressionNode returnExprNode = null;
List<BlockItemNode> itemNodes = new LinkedList<>();
if (!freedArrays.isEmpty())
for (int i = freedArrays.size() - 1; i >= 0; i--)
itemNodes.add(createArrayDestroy(freedArrays.get(i)));
if (currentFunctionName != null) {
returnExprNode = nodeFactory.newIdentifierExpressionNode(src,
nodeFactory.newIdentifierNode(src,
FORTRAN_FUNCTION_RETURN_PREFIX
+ currentFunctionName));
}
itemNodes.add(nodeFactory.newReturnNode(src, returnExprNode));
return itemNodes;
}
private List<BlockItemNode> translateStmtStop(MFTree stopStmt) {
assert stopStmt.numChildren() < 3; // No code no quiet
int defaultStopCode = 0;
List<BlockItemNode> stopNodes = new LinkedList<>();
Source stopSrc = newSource(stopStmt);
String exitFuncName = "exit";
IdentifierNode exitFuncIdNode = nodeFactory.newIdentifierNode(stopSrc,
exitFuncName);
IdentifierExpressionNode exitFuncRefExprNode = nodeFactory
.newIdentifierExpressionNode(stopSrc, exitFuncIdNode);
List<ExpressionNode> argNodes = Arrays.asList(
nodeFactory.newIntConstantNode(stopSrc, defaultStopCode));
FunctionCallNode exitCallNode = nodeFactory.newFunctionCallNode(stopSrc,
exitFuncRefExprNode, argNodes, null);
useSTDLIB = true;
if (!freedArrays.isEmpty())
for (int i = freedArrays.size() - 1; i >= 0; i--)
stopNodes.add(createArrayDestroy(freedArrays.get(i)));
stopNodes.add(nodeFactory.newReturnNode(stopSrc, null));
stopNodes.add((BlockItemNode) nodeFactory
.newExpressionStatementNode(exitCallNode));
return stopNodes;
}
private List<BlockItemNode> translateStmtWrite(MFTree writeStmt)
throws SyntaxException {
LinkedList<BlockItemNode> printfNodes = new LinkedList<>();
MFTree write = writeStmt.getChildByIndex(1);
Source src = newSource(writeStmt);
Source printSrc = newSource(write);
MFTree outputList = writeStmt.getChildByIndex(3);
IdentifierNode printfIdNode = nodeFactory.newIdentifierNode(printSrc,
"printf");
ExpressionNode printfFuncNode = nodeFactory
.newIdentifierExpressionNode(printSrc, printfIdNode);
ExpressionNode formatNode = null;
FunctionCallNode printfCallNode = null;
LinkedList<ExpressionNode> printfArgNodes = new LinkedList<>();
String formatStr = "\"";
StringToken formatToken = null;
useSTDIO = true;
for (int j = 0; j < outputList.numChildren(); j++) {
MFTree outputItem = outputList.getChildByIndex(j);
ExpressionNode printfArgNode = translateExpr(
outputItem.getChildByIndex(0));
printfArgNodes.add(printfArgNode);
formatStr += "%s ";
}
formatStr += "\"";
formatToken = tokenFactory.newStringToken(tokenFactory.newCivlcToken(0,
formatStr, write.cTokens()[0].getFormation(),
TokenVocabulary.FORTRAN));
formatNode = nodeFactory.newStringLiteralNode(src, formatStr,
formatToken.getStringLiteral());
printfArgNodes.add(0, formatNode);
printfCallNode = nodeFactory.newFunctionCallNode(src, printfFuncNode,
printfArgNodes, null);
printfNodes.add(nodeFactory.newExpressionStatementNode(printfCallNode));
return printfNodes;
}
private BlockItemNode translateStmtIf(MFTree ifConstruct)
throws SyntaxException, ParseException {
// TODO: else if & else
// int numOfChildren = ifConstruct.numChildren();
// PRPair prp = ifConstruct.prp();
MFTree cond = ifConstruct.getChildByIndex(2);
MFTree block = ifConstruct.getChildByIndex(3);
ExpressionNode condExprNode = null;
StatementNode trueBranchNode = null;
StatementNode falseBranchNode = null;
StatementNode ifStmtNode = null;
condExprNode = translateExpr(cond);
if (block.prp() == MFPUtils.ACTION_STMT)
trueBranchNode = nodeFactory.newCompoundStatementNode(
newSource(block), translateBlockItem(
block.getChildByIndex(0), FORTRAN_EMPTY_PREFIX));
if (falseBranchNode == null)
ifStmtNode = nodeFactory.newIfNode(newSource(ifConstruct),
condExprNode, trueBranchNode);
// else
// ifStmtNode = nodeFactory.newIfNode(newSource(ifConstruct),
// condExprNode, trueBranchNode, falseBranchNode);
return ifStmtNode;
}
private List<BlockItemNode> translateStmtParameter(MFTree parameterStmt)
throws SyntaxException {
MFTree consts = parameterStmt.getChildByIndex(2);
int numConsts = consts.numChildren();
List<BlockItemNode> implicitConstDecls = new LinkedList<>();
for (int i = 0; i < numConsts; i++) {
MFTree constant = consts.getChildByIndex(0);
MFTree constName = constant.getChildByIndex(0);
MFTree constVal = constant.getChildByIndex(1);
String constNameText = getName(constName);
VariableDeclarationNode constVarDeclNode = scopes
.getDeclByVarIdent(constNameText);
ExpressionNode constInitValNode = translateExpr(constVal);
if (constVarDeclNode == null) {
// The variable associated w/ parameter stmt is NOT declared.
assert !scopes.isImplicitNone();
Source parameterSrc = newSource(parameterStmt);
IdentifierNode constNameNode = nodeFactory
.newIdentifierNode(parameterSrc, constNameText);
constVarDeclNode = nodeFactory.newVariableDeclarationNode(
parameterSrc, constNameNode,
scopes.getImplicitType(constNameText, parameterSrc),
constInitValNode);
implicitConstDecls.add(constVarDeclNode);
scopes.addDeclVariable(constNameText, constVarDeclNode);
} else {
// The variable associated w/ parameter stmt is declared.
constVarDeclNode.setInitializer(constInitValNode);
constVarDeclNode.getTypeNode().setConstQualified(true);
}
}
return implicitConstDecls;
}
private BlockItemNode translateStmtGoto(MFTree gotoStmt) {
MFTree targetLabel = gotoStmt
.getChildByIndex(gotoStmt.numChildren() - 1);
return nodeFactory.newGotoNode(newSource(gotoStmt),
translateIdentifierLabel(targetLabel));
}
private BlockItemNode translateStmtExit(MFTree exitStmt) {
return nodeFactory.newBreakNode(newSource(exitStmt));
}
private ExpressionNode translateArrayConstructor(MFTree acSpec)
throws SyntaxException {
MFTree acType = acSpec.getChildByIndex(0);
MFTree acVals = acSpec.getChildByIndex(1);
TypeNode arrayLiteralType = null;
LinkedList<PairNode<DesignationNode, InitializerNode>> arrayLiteralNode = new LinkedList<PairNode<DesignationNode, InitializerNode>>();
Boolean hasExplicitType = acType.prp() != MFPUtils.ABSENT;
if (hasExplicitType) {
assert false; // Has explicit type for array literals
}
for (int i = 0; i < acVals.numChildren(); i++) {
MFTree acVal = acVals.getChildByIndex(i).getChildByIndex(0);
ExpressionNode constantNode = null;
if (acVal.prp() == MFPUtils.AC_IMPLIED_DO) {
assert false; // Not an expr
} else
constantNode = translateExpr(acVal);
if (arrayLiteralType == null)
arrayLiteralType = analyzeRawExprType(constantNode);
arrayLiteralNode.add(nodeFactory
.newPairNode(constantNode.getSource(), null, constantNode));
}
return nodeFactory.newCompoundLiteralNode(newSource(acSpec),
arrayLiteralType, nodeFactory.newCompoundInitializerNode(
newSource(acVals), arrayLiteralNode));
}
/**
* R507: declaration construct <br>
* R508: specification construct <br>
* R513: other specification stmt <br>
* TODO: R1510 generic stmt
*
* @param item
* @param argsMap
* @param funcTypeNode
* @return
* @throws SyntaxException
* @throws ParseException
*/
private List<BlockItemNode> translateBlockItem(MFTree item,
String varNamePrefix) throws SyntaxException, ParseException {
MFTree label = item.getChildByIndex(0);
List<BlockItemNode> itemNodes = new ArrayList<BlockItemNode>();
PRPair prp = item.prp();
if (prp == MFPUtils.ACCESS_STMT)
assert false;
else if (prp == MFPUtils.ALLOCATABLE_STMT)
assert false;
else if (prp == MFPUtils.ASYNCHRONOUS_STMT)
assert false;
else if (prp == MFPUtils.BIND_STMT)
assert false;
else if (prp == MFPUtils.CODIMENSION_STMT)
assert false;
else if (prp == MFPUtils.COMMON_STMT)
itemNodes.addAll(translateStmtCommon(item));
else if (prp == MFPUtils.DATA_STMT)
itemNodes.addAll(translateStmtData(item));
else if (prp == MFPUtils.DERIVED_TYPE_DEF) {
itemNodes.addAll(translateDerivedTypeDef(item));
} else if (prp == MFPUtils.DIMENSION_STMT)
itemNodes.addAll(translateStmtDimension(item));
else if (prp == MFPUtils.ENTRY_STMT)
assert false;
else if (prp == MFPUtils.ENUM_DEF)
assert false;
else if (prp == MFPUtils.EQUIVALENCE_STMT)
assert false;
else if (prp == MFPUtils.EXTERNAL_STMT)
assert false;
else if (prp == MFPUtils.FORMAT_STMT)
assert false;
else if (prp == MFPUtils.INTENT_STMT)
assert false;
else if (prp == MFPUtils.INTERFACE_BLOCK)
assert false;
else if (prp == MFPUtils.INTRINSIC_STMT)
assert false;
else if (prp == MFPUtils.NAMELIST_STMT)
assert false;
else if (prp == MFPUtils.OPTIONAL_STMT)
assert false;
else if (prp == MFPUtils.PARAMETER_STMT)
itemNodes.addAll(translateStmtParameter(item));
else if (prp == MFPUtils.POINTER_DECL)
assert false;
else if (prp == MFPUtils.PROCEDURE_DECLARATION_STMT)
assert false;
else if (prp == MFPUtils.PROTECTED_STMT)
assert false;
else if (prp == MFPUtils.SAVE_STMT)
assert false;
else if (prp == MFPUtils.TARGET_STMT)
assert false;
else if (prp == MFPUtils.TYPE_DECLARATION_STMT) {
itemNodes.addAll(translateTypeDeclaration(item, varNamePrefix));
} else if (prp == MFPUtils.VOLATILE_STMT)
assert false;
else if (prp == MFPUtils.VALUE_STMT)
assert false;
else if (prp == MFPUtils.STMT_FUCNTION_STMT)
assert false;
else if (prp == MFPUtils.ALLOCATE_STMT)
itemNodes.addAll(translateStmtAllocate(item));
else if (prp == MFPUtils.ASSIGNMENT_STMT) {
BlockItemNode exprStmtNode = translateStmtExpr(item);
if (dummyFuncRefArgs.size() > 0) {
itemNodes.addAll(dummyFuncRefArgs);
dummyFuncRefArgs.clear();
}
if (dummyFuncRefArrayArgPreStmts.size() > 0) {
itemNodes.addAll(dummyFuncRefArrayArgPreStmts);
dummyFuncRefArrayArgPreStmts.clear();
}
itemNodes.add(exprStmtNode);
if (dummyFuncRefArrayArgPostStmts.size() > 0) {
itemNodes.addAll(dummyFuncRefArrayArgPostStmts);
dummyFuncRefArrayArgPostStmts.clear();
}
} else if (prp == MFPUtils.BACKSPACE_STMT)
assert false;
else if (prp == MFPUtils.CALL_STMT)
itemNodes.addAll(translateStmtCall(item));
else if (prp == MFPUtils.CLOSE_STMT)
assert false;
else if (prp == MFPUtils.COMPUTED_GOTO_STMT)
assert false;
else if (prp == MFPUtils.CONTINUE_STMT)
itemNodes.add((BlockItemNode) nodeFactory
.newNullStatementNode(newSource(item)));
else if (prp == MFPUtils.CYCLE_STMT)
itemNodes.add((BlockItemNode) nodeFactory
.newContinueNode(newSource(item)));
else if (prp == MFPUtils.DEALLOCATE_STMT)
assert false;
else if (prp == MFPUtils.ENDFILE_STMT)
assert false;
else if (prp == MFPUtils.EXIT_STMT)
itemNodes.add(translateStmtExit(item));
else if (prp == MFPUtils.FLUSH_STMT)
assert false;
else if (prp == MFPUtils.FORALL_STMT)
assert false;
else if (prp == MFPUtils.GOTO_STMT)
itemNodes.add(translateStmtGoto(item));
else if (prp == MFPUtils.IF_STMT)
itemNodes.add(translateStmtIf(item));
else if (prp == MFPUtils.INQUIRE_STMT)
assert false;
else if (prp == MFPUtils.LOCK_STMT)
assert false;
else if (prp == MFPUtils.NULLIFY_STMT)
assert false;
else if (prp == MFPUtils.OPEN_STMT)
assert false;
else if (prp == MFPUtils.POINTER_ASSIGNMENT_STMT)
itemNodes.addAll(translateStmtPointerAssignment(item));
else if (prp == MFPUtils.PRINT_STMT)
itemNodes.addAll(translateStmtPrint(item));
else if (prp == MFPUtils.READ_STMT)
assert false;
else if (prp == MFPUtils.RETURN_STMT)
itemNodes.addAll(translateStmtReturn(item));
else if (prp == MFPUtils.REWIND_STMT)
assert false;
else if (prp == MFPUtils.STOP_STMT)
itemNodes.addAll(translateStmtStop(item));
else if (prp == MFPUtils.SYNC_ALL_STMT)
assert false;
else if (prp == MFPUtils.SYNC_IMAGES_STMT)
assert false;
else if (prp == MFPUtils.SYNC_MEMORY_STMT)
assert false;
else if (prp == MFPUtils.UNLOCK_STMT)
assert false;
else if (prp == MFPUtils.WAIT_STMT)
assert false;
else if (prp == MFPUtils.WHERE_STMT)
assert false;
else if (prp == MFPUtils.WRITE_STMT)
itemNodes.addAll(translateStmtWrite(item));
else if (prp == MFPUtils.FAIL_IMAGE_STMT)
assert false;
else if (prp == MFPUtils.SYNC_TEAM_STMT)
assert false;
else if (prp == MFPUtils.EVENT_POST_STMT)
assert false;
else if (prp == MFPUtils.EVENT_WAIT_STMT)
assert false;
else if (prp == MFPUtils.FORM_TEAM_STMT)
assert false;
else if (prp == MFPUtils.PRAGMA_STMT)
itemNodes.add((BlockItemNode) processPragma(item));
else if (prp == MFPUtils.PRAGMA_TYPE_QUALIFIER_STMT)
itemNodes.add((BlockItemNode) processPragma(item));
else {
System.err.println(prp.toString());
assert false;
}
if (label.prp() == MFPUtils.LABEL && !label.isNullToken(0)) {
StatementNode labelledStmtNode = (StatementNode) itemNodes.get(0);
IdentifierNode lblIdNode = translateIdentifierLabel(label);
OrdinaryLabelNode lblDeclNode = nodeFactory
.newStandardLabelDeclarationNode(newSource(label),
lblIdNode, labelledStmtNode);
itemNodes.set(0, nodeFactory.newLabeledStatementNode(
newSource(item), lblDeclNode, labelledStmtNode));
}
return itemNodes;
}
private List<BlockItemNode> translateStmtPointerAssignment(
MFTree stmtPtrAssign) throws SyntaxException {
Source src = newSource(stmtPtrAssign);
List<BlockItemNode> itemNodes = new LinkedList<>();
MFTree varPointer = stmtPtrAssign.getChildByIndex(1);
MFTree valTarget = stmtPtrAssign.getChildByIndex(2);
ExpressionNode varPointerIdNode = translateExprDataRef(src, varPointer);
ExpressionNode valTargetExprNode = translateExpr(valTarget);
OperatorNode exprPtrAssignNode = nodeFactory.newOperatorNode(src,
Operator.ASSIGN, varPointerIdNode, valTargetExprNode);
assert scopes.hasAttr(getName(varPointer),
MFScopeManager.ATTR_VAR_POINTER) && //
scopes.hasAttr(getName(valTarget),
MFScopeManager.ATTR_VAR_TARGET);
itemNodes
.add(nodeFactory.newExpressionStatementNode(exprPtrAssignNode));
return itemNodes;
}
private List<BlockItemNode> translateStmtData(MFTree stmtData)
throws SyntaxException {
Source src = newSource(stmtData);
List<BlockItemNode> itemNodes = new LinkedList<>();
MFTree dataInitSet, dataVars, dataVals, dataVar, dataVal;
TypeNode dataVarTypeNode;
IdentifierNode dataVarIdNode;
ExpressionNode dataValExprNode;
VariableDeclarationNode dataVarDeclNode;
for (int i = 2; i < stmtData.numChildren(); i++) {
dataInitSet = stmtData.getChildByIndex(i);
dataVals = dataInitSet.getChildByIndex(0);
dataVars = dataInitSet.getChildByIndex(1);
if (dataVals.numChildren() == 1) {
dataVal = dataVals.getChildByIndex(0).getChildByIndex(0);
dataValExprNode = translateExprConstants(dataVal);
for (int j = 0; j < dataVars.numChildren(); j++) {
dataVar = dataVars.getChildByIndex(j);
while (dataVar.numChildren() > 0)
dataVar = dataVar.getChildByIndex(0);
dataVarIdNode = this.translateIdentifier(dataVar);
dataVarTypeNode = scopes.getTypeByVarIdent(
dataVarIdNode.name(), dataVarIdNode.getSource());
if (dataVarTypeNode.kind() == TypeNodeKind.ARRAY) {
assert false;
} else {
dataVarDeclNode = nodeFactory
.newVariableDeclarationNode(src, dataVarIdNode,
dataVarTypeNode,
dataValExprNode.copy());
itemNodes.add(dataVarDeclNode);
scopes.addDeclVariable(dataVarIdNode.name(),
dataVarDeclNode);
}
}
} else
assert false;
}
return itemNodes;
}
private List<BlockItemNode> translateStmtDimension(MFTree stmtDim)
throws SyntaxException {
Source arraySrc;
List<BlockItemNode> itemNodes = new LinkedList<>();
MFTree declDims = stmtDim.getChildByIndex(2);
MFTree declDim, arrayId, arrayDims;
int numDeclDims = declDims.numChildren();
String arrayName;
ExpressionNode dimInfo[][];
TypeNode arrayBaseTypeNode;
IdentifierNode arrayIdNode;
VariableDeclarationNode arrayDeclNode;
FORTRAN_ARRAY_DESCRIPTOR_KIND arrDescKind = FORTRAN_ARRAY_DESCRIPTOR_KIND.ORIGIN;
for (int i = 0; i < numDeclDims; i++) {
declDim = declDims.getChildByIndex(i);
arraySrc = newSource(declDim);
arrayId = declDim.getChildByIndex(0);
arrayName = getName(arrayId);
arrayDims = declDim.getChildByIndex(1);
dimInfo = processArrayDimInfo(arrayDims);
arrayBaseTypeNode = scopes.getArrayBaseTypeByIdent(arrayName);
arrayIdNode = translateIdentifier(arrayId);
if (scopes.isParameterVar(arrayName)) {
// A parameter named as {arrayName} shall have a
// corresponding array type if the variable is
// associated with a Dimension Statement.
// Then, the actual variable 'X' used will be reshaped
// from its original parameter, which is wrapped as '__X'.
VariableDeclarationNode formalDeclNode = scopes
.getDeclByParIdent(arrayName);
formalDeclNode.setIdentifier(nodeFactory.newIdentifierNode(
dummySrc, FORTRAN_ARRAY_PARAM_PREFIX + arrayName));
formalDeclNode.setTypeNode(genArrDescType(arraySrc));
arrDescKind = FORTRAN_ARRAY_DESCRIPTOR_KIND.RESHAPE;
} else if (scopes.isDeclaredVar(arrayName)) {
// A local variable named as {arrayName} shall have a
// corresponding array type if the variable is
// associated with a Dimension Statement.
// The out-dated declaration shall be updated.
VariableDeclarationNode localDeclNode = scopes
.getDeclByVarIdent(arrayName);
localDeclNode.setIdentifier(nodeFactory.newIdentifierNode(
dummySrc, FORTRAN_ARRAY_LOCAL_PREFIX + arrayName));
localDeclNode.setTypeNode(genArrDescType(arraySrc));
} // else do nothing additional for newly declared variables
arrayDeclNode = createArrayDesc(arraySrc, arrayIdNode, dimInfo,
arrayBaseTypeNode.copy(), arrDescKind,
/* isCommon */ false);
scopes.addDeclVariable(arrayName, arrayDeclNode);
itemNodes.add(arrayDeclNode);
}
return itemNodes;
}
private List<BlockItemNode> translateBlockItems(MFTree execPart)
throws SyntaxException, ParseException {
int numExec = execPart.numChildren();
OmpExecutableNode ompExecNode = null;
List<BlockItemNode> itemNodes = new LinkedList<>();
for (int i = 0; i < numExec; i++) {
MFTree execCstr = execPart.getChildByIndex(i);
PRPair prp = execCstr.prp();
StatementNode stmtNode = null;
// Extract the child from EXECUTION_PART_CONSTRUCT
if (prp == MFPUtils.EXECUTION_PART_CONSTRUCT) {
execCstr = execCstr.getChildByIndex(0);
prp = execCstr.prp();
}
// Extract the child from EXECUTABLE_CONSTRUCT
if (prp == MFPUtils.EXECUTABLE_CONSTRUCT) {
execCstr = execCstr.getChildByIndex(0);
prp = execCstr.prp();
}
if (prp == MFPUtils.ACTION_STMT) {
List<BlockItemNode> tmpItemNodes = translateBlockItem(
execCstr.getChildByIndex(0), FORTRAN_EMPTY_PREFIX);
if (tmpItemNodes.size() == 1 && tmpItemNodes.get(0)
.blockItemKind() == BlockItemKind.STATEMENT)
stmtNode = (StatementNode) tmpItemNodes.get(0);
else
itemNodes.addAll(tmpItemNodes);
} else if (prp == MFPUtils.ASSOCIATE_CONSTRUCT)
assert false;
else if (prp == MFPUtils.BLOCK_CONSTRUCT)
assert false;
else if (prp == MFPUtils.CASE_CONSTRUCT)
assert false;
else if (prp == MFPUtils.CRITICAL_CONSTRUCT)
assert false;
else if (prp == MFPUtils.DO_CONSTRUCT)
itemNodes.add(translateConstructDo(execCstr));
else if (prp == MFPUtils.FORALL_CONSTRUCT)
assert false;
else if (prp == MFPUtils.IF_CONSTRUCT)
itemNodes.add(translateConstructIf(execCstr));
else if (prp == MFPUtils.SELECT_TYPE_CONSTRUCT)
assert false;
else if (prp == MFPUtils.WHERE_CONSTRUCT)
assert false;
else if (prp == MFPUtils.PRAGMA_STMT)
stmtNode = (StatementNode) processPragma(execCstr);
else if (prp == MFPUtils.FORMAT_STMT)
processStmtFormat(execCstr);
else
assert false;
if (stmtNode != null)
if (ompExecNode != null) {
ompExecNode.setStatementNode(stmtNode);
ompExecNode = null;
} else {
itemNodes.add(stmtNode);
if (stmtNode.statementKind() == StatementKind.OMP) {
ompExecNode = (OmpExecutableNode) stmtNode;
if (ompExecNode.isComplete())
ompExecNode = null;
}
}
}
return itemNodes;
}
private ASTNode translateCIVLPrimitives(MFTree civl_stmt)
throws SyntaxException {
MFTree civlKey = civl_stmt;
if (civlKey.numChildren() > 0)
civlKey = civlKey.getChildByIndex(0);
String keyStr = getName(civlKey).toLowerCase();
useCIVLC = true;
switch (keyStr) {
case "$input" :
isInputVarDecl = true;
return null;
case "$output" :
isOutputVarDecl = true;
return null;
case "$assume" :
case "$assert" :
int numArgs = civl_stmt.numChildren() - 1;
assert numArgs >= 0;
Source civlKeySrc = newSource(civlKey);
IdentifierNode civlFuncIDNode = nodeFactory
.newIdentifierNode(civlKeySrc, keyStr);
ExpressionNode civlFuncIDExprNode = nodeFactory
.newIdentifierExpressionNode(civlKeySrc,
civlFuncIDNode);
ExpressionNode[] civlFuncArgNodes = new ExpressionNode[numArgs];
for (int i = 0; i < numArgs; i++)
civlFuncArgNodes[i] = translateExpr(
civl_stmt.getChildByIndex(i + 1));
return nodeFactory.newFunctionCallNode(newSource(civl_stmt),
civlFuncIDExprNode, Arrays.asList(civlFuncArgNodes),
null);
default :
throw new SyntaxException(
"Syntax Error: invalid CIVL-F primitive: '" + keyStr
+ "'",
newSource(civl_stmt));
}
}
private ASTNode translatePragma(MFTree pragma_stmt)
throws SyntaxException, ParseException {
Source src = newSource(pragma_stmt);
IdentifierNode pragmaNameNode = translateIdentifier(
pragma_stmt.getChildByIndex(0));
String pragmaName = pragmaNameNode.name().toUpperCase();
PragmaNode pragmaNode = null;
PragmaHandler pHandler = null;
if (pragmaName.equals("CVL")) {
return translateCIVLPrimitives(pragma_stmt.getChildByIndex(1));
} else if (pragmaName.equals("OMP")) {
CivlcTokenSequence pragmaTokens = ptree
.getTokenSourceProducer(pragma_stmt.getChildByIndex(1));
CivlcToken pragmaEndToken = (CivlcToken) pragma_stmt
.getChildByIndex(2).cTokens()[0];
pragmaNode = nodeFactory.newPragmaNode(src, pragmaNameNode,
pragmaTokens, pragmaEndToken);
} else {// pragma not supported
throw new SyntaxException("Unsupported pragma: " + pragmaName, src);
}
pHandler = pragmaMap.get(pragmaName);
if (pHandler == null) {
pHandler = pragmaFactory.newHandler(pragmaName, ptree);
pragmaMap.put(pragmaName, pHandler);
}
pragmaNameNode.setEntity(pHandler);
// TODO: Scope is null, not used in Fortran impl.
return pHandler.processPragmaNode(pragmaNode, null);
}
private StatementNode translateConstructDo(MFTree doConstruct)
throws SyntaxException, ParseException {
IdentifierNode doVarIdNode = null;
ExpressionNode doVarExprNode = null;
ForLoopInitializerNode initNode = null;
ExpressionNode condNode = null;
ExpressionNode stepNode = null;
MFTree doStmt = doConstruct.getChildByIndex(0);
MFTree doBody = doConstruct.getChildByIndex(1);
MFTree doEnd = doConstruct.getChildByIndex(2).getChildByIndex(0);
StatementNode bodyNode = null;
boolean hasDoCtrl = doStmt.numChildren() > 4;
boolean hasDoEndStmt = doEnd.numChildren() > 4;
// Proc Do Stmt
if (hasDoCtrl) {
MFTree doCtrl = doStmt.getChildByIndex(4);
MFTree doVar = doCtrl.getChildByIndex(0);
MFTree doVarInit = doCtrl.getChildByIndex(1);
MFTree doVarCond = doCtrl.getChildByIndex(2);
Source doCtrlSrc = newSource(doCtrl);
ExpressionNode stepValNode = null;
doVarIdNode = translateIdentifier(doVar);
doVarExprNode = nodeFactory.newIdentifierExpressionNode(doCtrlSrc,
doVarIdNode);
initNode = nodeFactory.newOperatorNode(doCtrlSrc, Operator.ASSIGN,
doVarExprNode.copy(), translateExpr(doVarInit));
condNode = nodeFactory.newOperatorNode(doCtrlSrc, Operator.LTE,
doVarExprNode.copy(), translateExpr(doVarCond));
if (doCtrl.numChildren() < 4)
stepValNode = nodeFactory.newIntConstantNode(doCtrlSrc, 1);
else
stepValNode = translateExpr(doCtrl.getChildByIndex(3));
stepNode = nodeFactory.newOperatorNode(doCtrlSrc, Operator.PLUSEQ,
doVarExprNode.copy(), stepValNode);
if (!scopes.isDeclaredVar(doVarIdNode.name())
&& !scopes.isParameterVar(doVarIdNode.name())) {
scopes.addUndeclaredIdent(doVarIdNode.name());
}
}
// Proc Do End
if (hasDoEndStmt) {
MFTree doEndLabel = doEnd.getChildByIndex(0);
MFTree doEndAction = doEnd.getChildByIndex(4);
MFTree dummyExecConstruct = new MFTree(
MFPUtils.EXECUTABLE_CONSTRUCT);
String lblTxt = getName(doEndLabel);
// Proc End Do
if (!scopes.hasLabel(lblTxt)) {
doEndLabel.release();
doEndAction.getChildByIndex(0).setChild(0, doEndLabel);
doEndAction.release();
dummyExecConstruct.addChild(doEndAction);
doBody.addChild(dummyExecConstruct);
scopes.addLabel(lblTxt);
}
}
// Proc Body
bodyNode = translateBody(null, doBody, null, doConstruct.prp());
// Gen Civl For Loop
return nodeFactory.newForLoopNode(newSource(doConstruct), initNode,
condNode, stepNode, bodyNode, null);
}
private void processStmtFormat(MFTree formatStmt) {
MFTree formatKey = formatStmt.getChildByIndex(0);
MFTree formatVal = formatStmt.getChildByIndex(2);
MFTree formatItems = formatVal.getChildByIndex(0);
int numFormatItems = formatItems.numChildren();
String fmtKey = getName(formatKey);
String fmtPattern = "";
for (int i = 0; i < numFormatItems; i++) {
String fmtItemText = getName(
formatItems.getChildByIndex(i).getChildByIndex(0));
if (fmtItemText.startsWith("'") || fmtItemText.startsWith("\"")) {
fmtPattern += fmtItemText.substring(1,
fmtItemText.length() - 1);
} else {
fmtPattern += " %s";
}
}
formats.put(fmtKey, fmtPattern);
}
/**
* R863: implicit stmt
*
* @param spec
* @param puScope
*/
private void processStmtImplicit(MFTree stmt) {
int indexImplicitSpec = 2;
MFTree spec = stmt.getChildByIndex(indexImplicitSpec);
if (spec.prp() == MFPUtils.IMPLICIT_SPEC) {
MFTree implicitSpec, typeSpec, letterSpecs, letterSpec;
char charStart, charEnd;
TypeNode implicitTypeNode = null;
for (int i = 0; i < spec.numChildren(); i++) {
implicitSpec = spec.getChildByIndex(i);
typeSpec = implicitSpec.getChildByIndex(0).getChildByIndex(0);
implicitTypeNode = translateType(typeSpec);
letterSpecs = implicitSpec.getChildByIndex(1);
for (int j = 0; j < letterSpecs.numChildren(); j++) {
letterSpec = letterSpecs.getChildByIndex(j);
charStart = getName(letterSpec.getChildByIndex(0))
.charAt(0);
charEnd = letterSpec.numChildren() == 1
? charStart
: getName(letterSpec.getChildByIndex(1)).charAt(0);
scopes.setImplicitType(charStart, charEnd,
implicitTypeNode);
}
}
} else if (spec.prp() == MFPUtils.IMPLICIT_NONE_SPEC) {
switch (spec.kind()) {
case MFPUtils.NONE_PURE :
scopes.setImplicitNone();
break;
case MFPUtils.NONE_EXTN :
case MFPUtils.NONE_TYPE :
default :
assert false;
}
}
}
private void processStmtUse(MFTree useStmt) {
MFTree useModule = useStmt.getChildByIndex(2);
String moduleName = getName(useModule);
switch (moduleName) {
case "OMP_LIB" :
useOMP = true;
break;
default :
// assert false;
}
}
private ASTNode processPragma(MFTree pragma)
throws SyntaxException, ParseException {
ASTNode pragmaNode = translatePragma(pragma);
if (pragmaNode == null)
return null;
else if (pragmaNode instanceof ExpressionNode)
return nodeFactory
.newExpressionStatementNode((ExpressionNode) pragmaNode);
else if (pragmaNode instanceof StatementNode)
return (StatementNode) pragmaNode;
else
assert false;
return null;
}
private BlockItemNode translateConstructIf(MFTree ifConstruct)
throws SyntaxException, ParseException {
int numChildren = ifConstruct.numChildren();
int numBlock = numChildren / 2;
MFTree condStmt = null;
MFTree condExpr = null;
MFTree block = null;
PRPair condPrp = null;
ExpressionNode condExprNode = null;
StatementNode trueBranchNode = null;
StatementNode falseBranchNode = null;
StatementNode ifStmtNode = null;
for (int i = (numBlock - 1) * 2; i >= 0; i -= 2) {
condStmt = ifConstruct.getChildByIndex(i);
block = ifConstruct.getChildByIndex(i + 1);
condPrp = condStmt.prp();
if (condPrp == MFPUtils.ELSE_STMT) // else_stmt
falseBranchNode = nodeFactory.newCompoundStatementNode(
newSource(block), translateBlockItems(block));
else {
condExpr = condStmt.getChildByIndex(condStmt.numChildren() - 2);
condExprNode = translateExpr(condExpr);
trueBranchNode = nodeFactory.newCompoundStatementNode(
newSource(block), translateBlockItems(block));
if (condPrp == MFPUtils.IF_THEN_STMT) // if_stmt
ifStmtNode = nodeFactory.newIfNode(newSource(ifConstruct),
condExprNode, trueBranchNode, falseBranchNode);
else // else_if_stmt
falseBranchNode = nodeFactory.newIfNode(
newSource(ifConstruct), condExprNode,
trueBranchNode, falseBranchNode);
}
}
return ifStmtNode;
}
private String currentFunctionName = null;
private List<BlockItemNode> processSpecPart(MFTree specPart,
String varNamePrefix) throws SyntaxException, ParseException {
List<BlockItemNode> itemNodes = new LinkedList<>();
int numSpec = specPart.numChildren();
for (int i = 0; i < numSpec; i++) {
MFTree spec = specPart.getChildByIndex(i);
PRPair prp = spec.prp();
if (prp == MFPUtils.DECLARATION_CONSTRUCT)
itemNodes.addAll(translateBlockItem(spec.getChildByIndex(0),
varNamePrefix));
else if (prp == MFPUtils.IMPLICIT_STMT)
processStmtImplicit(spec);
else if (prp == MFPUtils.PARAMETER_STMT)
assert false;
else if (prp == MFPUtils.FORMAT_STMT)
assert false;
else if (prp == MFPUtils.ENTRY_STMT)
assert false;
else if (prp == MFPUtils.IMPORT_STMT)
assert false;
else if (prp == MFPUtils.USE_STMT)
processStmtUse(spec);
else
assert false;
}
return itemNodes;
}
/**
* R504: specification part <br>
* R509: execution part <br>
* TODO: R511: internal subprogram part<br>
*
* @param specPart
* @param execPart
* @param puScope
* @param funcTypeNode
* @param BodyPrp
* @return
* @throws SyntaxException
* @throws ParseException
*/
private CompoundStatementNode translateBody(MFTree specPart,
MFTree execPart, FunctionTypeNode funcTypeNode, PRPair BodyPrp)
throws SyntaxException, ParseException {
int indexEndSpec = -1;
// init
dummyFuncRefArgsCtr = 0;
if (BodyPrp == MFPUtils.MAIN_PROGRAM) {
Source src = null;
List<BlockItemNode> itemNodes = new LinkedList<>();
OmpExecutableNode ompExecNode = null;
// Process specification_part
if (specPart != null) {
itemNodes.addAll(
processSpecPart(specPart, FORTRAN_EMPTY_PREFIX));
}
indexEndSpec = itemNodes.size();
// Process execution_part
if (execPart != null)
itemNodes.addAll(translateBlockItems(execPart));
// Transformation caused by Omp pragma.
int numItemNode = itemNodes.size();
boolean isChanged = false;
for (int i = 0; i < numItemNode; i++) {
BlockItemNode itemNode = itemNodes.get(i);
if (itemNode != null && itemNode instanceof OmpExecutableNode) {
ompExecNode = (OmpExecutableNode) itemNode;
if (!ompExecNode.isComplete()) {
isChanged = true;
if (ompExecNode instanceof OmpForNode) {
OmpForNode ompForNode = (OmpForNode) ompExecNode;
int collapse = ompForNode.collapse();
if (collapse == 1) {
StatementNode forStmtNode = (StatementNode) itemNodes
.get(i + 1);
itemNodes.set(i + 1, null);
ompForNode.setStatementNode(forStmtNode);
} else {
ArrayList<BlockItemNode> forStmtNodes = new ArrayList<>(
collapse);
CompoundStatementNode stmtsNode;
src = itemNodes.get(i + 1).getSource();
for (int j = 1; j < collapse; j++) {
StatementNode forStmtNode = (StatementNode) itemNodes
.get(i + j);
itemNodes.set(i + j, null);
forStmtNodes.add(forStmtNode);
}
stmtsNode = nodeFactory
.newCompoundStatementNode(src,
forStmtNodes);
ompForNode.setStatementNode(stmtsNode);
}
itemNodes.set(i, ompForNode);
} else {
StatementNode stmtNode = (StatementNode) itemNodes
.get(i + 1);
itemNodes.set(i + 1, null);
ompExecNode.setStatementNode(stmtNode);
itemNodes.set(i, ompExecNode);
}
}
}
}
if (isChanged) {
// Clean up 'null' elements in the old list
LinkedList<BlockItemNode> newItemNodes = new LinkedList<>();
for (int i = 0; i < numItemNode; i++) {
BlockItemNode itemNode = itemNodes.get(i);
if (itemNode != null)
newItemNodes.add(itemNode);
}
itemNodes = newItemNodes;
}
if (!scopes.isImplicitNone()) {
for (String undeclIdent : scopes.getUndeclaredIdents()) {
IdentifierNode identNode = nodeFactory
.newIdentifierNode(dummySrc, undeclIdent);
TypeNode typeNode = scopes.getImplicitType(undeclIdent,
dummySrc);
VariableDeclarationNode implicitVarDeclNode = nodeFactory
.newVariableDeclarationNode(dummySrc, identNode,
typeNode);
itemNodes.add(indexEndSpec, implicitVarDeclNode);
}
}
if (itemNodes.size() > 0 && itemNodes
.get(itemNodes.size() - 1) instanceof ReturnNode) {
freedArrays.clear();
for (String gArrName : freedGlobalArrays)
itemNodes.add(itemNodes.size() - 1,
createArrayDestroy(gArrName));
} else {
while (!freedArrays.isEmpty())
itemNodes.add(createArrayDestroy(freedArrays.pop()));
for (String gArrName : freedGlobalArrays)
itemNodes.add(createArrayDestroy(gArrName));
}
removeDummyVarDeclForFunction(itemNodes, indexEndSpec);
return nodeFactory.newCompoundStatementNode(
newSource(specPart, execPart), itemNodes);
} else if (BodyPrp == MFPUtils.SUBROUTINE_SUBPROGRAM || //
BodyPrp == MFPUtils.FUNCTION_SUBPROGRAM) {
Source src = null;
List<BlockItemNode> itemNodes = new LinkedList<>();
VariableDeclarationNode rtnVarDeclNode = null;
OmpExecutableNode ompExecNode = null;
// Process specification_part
if (specPart != null) {
int numSpec = specPart.numChildren();
src = newSource(specPart);
for (int i = 0; i < numSpec; i++) {
MFTree spec = specPart.getChildByIndex(i);
PRPair prp = spec.prp();
if (prp == MFPUtils.DECLARATION_CONSTRUCT)
itemNodes.addAll(translateBlockItem(
spec.getChildByIndex(0), FORTRAN_EMPTY_PREFIX));
else if (prp == MFPUtils.IMPLICIT_STMT)
processStmtImplicit(spec);
else if (prp == MFPUtils.PARAMETER_STMT)
assert false;
else if (prp == MFPUtils.FORMAT_STMT)
assert false;
else if (prp == MFPUtils.ENTRY_STMT)
assert false;
else if (prp == MFPUtils.IMPORT_STMT)
assert false;
else if (prp == MFPUtils.USE_STMT)
assert false;
else
assert false;
}
}
if (BodyPrp == MFPUtils.FUNCTION_SUBPROGRAM) {
// Process return variable declaration
IdentifierNode newRtnVarIdentNode = null;
Boolean hasNoReturnType = funcTypeNode.getReturnType().kind()
.equals(TypeNodeKind.VOID);
// Check func. rtn. val. decl.
for (BlockItemNode itemNode : itemNodes) {
if (itemNode instanceof VariableDeclarationNode) {
VariableDeclarationNode varDeclNode = (VariableDeclarationNode) itemNode;
if (varDeclNode.getName().equals(currentFunctionName)) {
rtnVarDeclNode = varDeclNode;
break;
}
}
}
if (hasNoReturnType) {
// Rtn. Type must be defined in func. body
assert rtnVarDeclNode != null;
// Update rtn. var. name
IdentifierNode oldRtnVarIdentNode = rtnVarDeclNode
.getIdentifier();
TypeNode rtnVarTypeNode = rtnVarDeclNode.getTypeNode()
.copy();
oldRtnVarIdentNode.remove();
newRtnVarIdentNode = nodeFactory.newIdentifierNode(
oldRtnVarIdentNode.getSource(),
FORTRAN_FUNCTION_RETURN_PREFIX
+ currentFunctionName);
rtnVarDeclNode.setIdentifier(newRtnVarIdentNode);
// Update func. type
funcTypeNode.setReturnType(rtnVarTypeNode);
} else if (rtnVarDeclNode == null) {
// Rtn. Type has been defined in func. stmt.
// Rtn. var. does not defined in func. body
newRtnVarIdentNode = nodeFactory.newIdentifierNode(
funcTypeNode.getSource(),
FORTRAN_FUNCTION_RETURN_PREFIX
+ currentFunctionName);
rtnVarDeclNode = nodeFactory.newVariableDeclarationNode(
funcTypeNode.getSource(), newRtnVarIdentNode,
funcTypeNode.getReturnType().copy());
// Add rtn. var. decl.
itemNodes.add(rtnVarDeclNode);
} else {
rtnVarDeclNode.setIdentifier(nodeFactory.newIdentifierNode(
funcTypeNode.getSource(),
FORTRAN_FUNCTION_RETURN_PREFIX
+ currentFunctionName));
}
}
indexEndSpec = itemNodes.size();
// Process execution_part
if (execPart != null)
itemNodes.addAll(translateBlockItems(execPart));
// Transformation caused by Omp pragma.
int numItemNode = itemNodes.size();
boolean isChanged = false;
for (int i = 0; i < numItemNode; i++) {
BlockItemNode itemNode = itemNodes.get(i);
if (itemNode != null && itemNode instanceof OmpExecutableNode) {
ompExecNode = (OmpExecutableNode) itemNode;
if (!ompExecNode.isComplete()) {
isChanged = true;
if (ompExecNode instanceof OmpForNode) {
OmpForNode ompForNode = (OmpForNode) ompExecNode;
int collapse = ompForNode.collapse();
if (collapse == 1) {
StatementNode forStmtNode = (StatementNode) itemNodes
.get(i + 1);
itemNodes.set(i + 1, null);
ompForNode.setStatementNode(forStmtNode);
} else {
ArrayList<BlockItemNode> forStmtNodes = new ArrayList<>(
collapse);
CompoundStatementNode stmtsNode;
src = itemNodes.get(i + 1).getSource();
for (int j = 1; j < collapse; j++) {
StatementNode forStmtNode = (StatementNode) itemNodes
.get(i + j);
itemNodes.set(i + j, null);
forStmtNodes.add(forStmtNode);
}
stmtsNode = nodeFactory
.newCompoundStatementNode(src,
forStmtNodes);
ompForNode.setStatementNode(stmtsNode);
}
itemNodes.set(i, ompForNode);
} else {
StatementNode stmtNode = (StatementNode) itemNodes
.get(i + 1);
itemNodes.set(i + 1, null);
ompExecNode.setStatementNode(stmtNode);
itemNodes.set(i, ompExecNode);
}
}
}
}
if (isChanged) {
// Clean up 'null' elements in the old list
LinkedList<BlockItemNode> newItemNodes = new LinkedList<>();
for (int i = 0; i < numItemNode; i++) {
BlockItemNode itemNode = itemNodes.get(i);
if (itemNode != null)
newItemNodes.add(itemNode);
}
itemNodes = newItemNodes;
}
if (!scopes.isImplicitNone()) {
for (String undeclIdent : scopes.getUndeclaredIdents()) {
IdentifierNode identNode = nodeFactory
.newIdentifierNode(dummySrc, undeclIdent);
TypeNode typeNode = scopes.getImplicitType(undeclIdent,
dummySrc);
VariableDeclarationNode implicitVarDeclNode = nodeFactory
.newVariableDeclarationNode(dummySrc, identNode,
typeNode);
itemNodes.add(indexEndSpec, implicitVarDeclNode);
}
}
if (itemNodes.get(itemNodes.size() - 1) instanceof ReturnNode) {
freedArrays.clear();
} else {
while (!freedArrays.isEmpty())
itemNodes.add(createArrayDestroy(freedArrays.pop()));
}
for (String outArgName : scopes
.getAllIntentOutParameterIdentifiers()) {
// Make actual argument references the dummy argument
String dummyArgName = outArgName
.substring(FORTRAN_INTENT_OUT_PREFIX.length());
IdentifierExpressionNode outArgIdExprNode = nodeFactory
.newIdentifierExpressionNode(dummySrc, nodeFactory
.newIdentifierNode(dummySrc, outArgName));
IdentifierExpressionNode dummyArgIdExprNode = nodeFactory
.newIdentifierExpressionNode(dummySrc, nodeFactory
.newIdentifierNode(dummySrc, dummyArgName));
ExpressionNode derefOutArgExprNode = nodeFactory
.newOperatorNode(dummySrc, Operator.DEREFERENCE,
outArgIdExprNode);
ExpressionNode argAssignExprNode = nodeFactory.newOperatorNode(
dummySrc, Operator.ASSIGN, derefOutArgExprNode,
dummyArgIdExprNode);
itemNodes.add(nodeFactory
.newExpressionStatementNode(argAssignExprNode));
}
if (rtnVarDeclNode != null)
itemNodes.add(nodeFactory.newReturnNode(src,
nodeFactory.newIdentifierExpressionNode(src,
nodeFactory.newIdentifierNode(src,
FORTRAN_FUNCTION_RETURN_PREFIX
+ currentFunctionName))));
removeDummyVarDeclForFunction(itemNodes, indexEndSpec);
return nodeFactory.newCompoundStatementNode(
newSource(specPart, execPart), itemNodes);
} else if (BodyPrp == MFPUtils.DO_CONSTRUCT
|| BodyPrp == MFPUtils.IF_STMT) {
Source src = null;
List<BlockItemNode> itemNodes = new LinkedList<>();
OmpExecutableNode ompExecNode = null;
// Process execution_part
if (execPart != null)
itemNodes.addAll(translateBlockItems(execPart));
// Transformation caused by Omp pragma.
int numItemNode = itemNodes.size();
boolean isChanged = false;
for (int i = 0; i < numItemNode; i++) {
BlockItemNode itemNode = itemNodes.get(i);
if (itemNode != null && itemNode instanceof OmpExecutableNode) {
ompExecNode = (OmpExecutableNode) itemNode;
if (!ompExecNode.isComplete()) {
isChanged = true;
if (ompExecNode instanceof OmpForNode) {
OmpForNode ompForNode = (OmpForNode) ompExecNode;
int collapse = ompForNode.collapse();
if (collapse == 1) {
StatementNode forStmtNode = (StatementNode) itemNodes
.get(i + 1);
itemNodes.set(i + 1, null);
ompForNode.setStatementNode(forStmtNode);
} else {
ArrayList<BlockItemNode> forStmtNodes = new ArrayList<>(
collapse);
CompoundStatementNode stmtsNode;
src = itemNodes.get(i + 1).getSource();
for (int j = 1; j < collapse; j++) {
StatementNode forStmtNode = (StatementNode) itemNodes
.get(i + j);
itemNodes.set(i + j, null);
forStmtNodes.add(forStmtNode);
}
stmtsNode = nodeFactory
.newCompoundStatementNode(src,
forStmtNodes);
ompForNode.setStatementNode(stmtsNode);
}
itemNodes.set(i, ompForNode);
} else {
StatementNode stmtNode = (StatementNode) itemNodes
.get(i + 1);
itemNodes.set(i + 1, null);
ompExecNode.setStatementNode(stmtNode);
itemNodes.set(i, ompExecNode);
}
}
}
}
if (isChanged) {
// Clean up 'null' elements in the old list
LinkedList<BlockItemNode> newItemNodes = new LinkedList<>();
for (int i = 0; i < numItemNode; i++) {
BlockItemNode itemNode = itemNodes.get(i);
if (itemNode != null)
newItemNodes.add(itemNode);
}
itemNodes = newItemNodes;
}
return nodeFactory.newCompoundStatementNode(
newSource(specPart, execPart), itemNodes);
} else
assert false;
return null;
}
private void removeDummyVarDeclForFunction(List<BlockItemNode> nodes,
int end) {
BlockItemNode itemNode;
for (int i = 0; i < end; i++) {
itemNode = nodes.get(i);
if (itemNode instanceof VariableDeclarationNode
&& funcDeclNodes.keySet().contains(
((VariableDeclarationNode) itemNode).getName())) {
nodes.remove(i);
end--;
}
}
}
private BlockItemNode translateProgramFunction(MFTree function, PRPair prp)
throws SyntaxException, ParseException {
BlockItemNode funcItem = null;
int numChildren = function.numChildren();
String funcNameText = null;
MFTree funcPrfx = function.getChildByIndex(0);
MFTree funcStmt = function.getChildByIndex(1);
MFTree funcName = null;
MFTree funcArgs = null;
// MFTree funcRtrn = null;
MFTree specPart = function.getChildByIndex(2);
MFTree execPart = numChildren > 4 ? function.getChildByIndex(3) : null;
Source src = newSource(function);
IdentifierNode nameNode = null;
FunctionTypeNode typeNode = null;
CompoundStatementNode bodyNode = null;
FunctionDeclarationNode dummyFuncDeclNode = null;
commonBlockName2NumObjs.clear();
// Check Function Label
if (funcStmt.getChildByIndex(0).numChildren() > 0) {
// Translate Function Label
assert false;
}
// Translate Function Name
funcName = funcStmt.getChildByIndex(2);
nameNode = translateIdentifier(funcName);
funcNameText = getName(funcName);
scopes.enterProgramUnitScope(funcNameText, null);
puIdStack.push(nameNode);
// Translate Function Arg. List
if (funcStmt.numChildren() > 3)
funcArgs = funcStmt.getChildByIndex(3);
// Translate Function Type
typeNode = translateFunctionType(funcPrfx, funcName, funcArgs, prp);
scopes.setProgramUnitType(typeNode);
if (funcDeclNodes.containsKey(funcNameText)) {
// Func. decl. has been created when any of its calls was processed.
// Then, func. type info is updated based on func. def.
dummyFuncDeclNode = funcDeclNodes.get(funcNameText);
dummyFuncDeclNode.setTypeNode(typeNode);
} else {
// Func. decl. has not been added
// Then, the decl. is created based on func. def.
dummyFuncDeclNode = nodeFactory.newFunctionDeclarationNode(src,
translateIdentifier(funcName), typeNode.copy(), null);
processDummyFuncOrSubrDeclaration(funcNameText, dummyFuncDeclNode);
}
// Check function prefix
if (funcPrfx != null) {
// Process funcPrfx:
for (int i = 0; i < funcPrfx.numChildren(); i++) {
MFTree prefixSpec = funcPrfx.getChildByIndex(i);
int prefixSpecKind = prefixSpec.kind();
if (prefixSpec.numChildren() > 0) {
// Omitted, prefix for return type has been processed.
} else if (prefixSpecKind == MFPUtils.PFX_PURE) {
scopes.setAttrByIdent(funcNameText,
MFScopeManager.ATTR_FUNC_PURE);
} else if (prefixSpecKind == MFPUtils.PFX_RECURSIVE) {
scopes.setAttrByIdent(funcNameText,
MFScopeManager.ATTR_FUNC_RECURSIVE);
} else
assert false;
}
}
// TODO: suffix
currentFunctionName = funcNameText;
bodyNode = translateBody(specPart, execPart, typeNode, prp);
funcItem = nodeFactory.newFunctionDefinitionNode(src, nameNode,
typeNode.copy(), null, bodyNode);
// Update possible function decl type info
if (currentFunctionName != null
&& funcDeclNodes.containsKey(currentFunctionName))
this.funcDeclNodes.get(this.currentFunctionName)
.setTypeNode(typeNode.copy());
commonblockMemberMap = new HashMap<>();
currentFunctionName = null;
puIdStack.pop();
return funcItem;
}
/**
* R1401: main program <br>
* R1529: function subprogram
*
* @param progUnit
* @param rule
* @return
* @throws SyntaxException
* @throws ParseException
*/
private BlockItemNode translateProgramMain(MFTree progUnit, PRPair prp)
throws SyntaxException, ParseException {
BlockItemNode puItem = null;
int numChildren = progUnit.numChildren();
MFTree progStmt = progUnit.getChildByIndex(0);
MFTree progId = progStmt.getChildByIndex(2);
MFTree args = null;
MFTree specPart = progUnit.getChildByIndex(1);
MFTree execPart = numChildren > 3 ? progUnit.getChildByIndex(2) : null;
Source src = newSource(progUnit);
IdentifierNode nameNode;
FunctionTypeNode typeNode;
CompoundStatementNode bodyNode = null;
commonBlockName2NumObjs.clear();
if (prp == MFPUtils.MAIN_PROGRAM)
nameNode = nodeFactory.newIdentifierNode(newSource(progId), "main");
else
nameNode = translateIdentifier(progId);
scopes.enterProgramUnitScope(nameNode.name(), null);
puIdStack.push(nameNode);
if (progStmt.numChildren() > 3)
args = progStmt.getChildByIndex(3);
// TODO: prefix, suffix
typeNode = translateFunctionType(null, progId, args, prp);
scopes.setProgramUnitType(typeNode);
bodyNode = translateBody(specPart, execPart, null, prp);
puItem = nodeFactory.newFunctionDefinitionNode(src, nameNode, typeNode,
null, bodyNode);
commonblockMemberMap = new HashMap<>();
puIdStack.pop();
return puItem;
}
/**
* R502: program unit<br>
* R503: external subprogram
*
* @param ptree
* the root of a FORTRAN parse tree
* @param scope
* the root scope
* @return a {@link List} of {@link BlockItemNode} representing each program
* unit.
* @throws SyntaxException
* @throws ParseException
*/
private List<BlockItemNode> translateProgramUnit(MFTree ptree)
throws SyntaxException, ParseException {
PRPair prp = ptree.prp();
List<BlockItemNode> itemNodes = new LinkedList<>();
List<BlockItemNode> programUnits = new LinkedList<>();
// Get the kind of program unit 'ptree'
if (prp == MFPUtils.MAIN_PROGRAM)
programUnits.add(translateProgramMain(ptree, prp));
else if (prp == MFPUtils.SUBROUTINE_SUBPROGRAM)
programUnits.add(translateProgramMain(ptree, prp));
else if (prp == MFPUtils.FUNCTION_SUBPROGRAM)
programUnits.add(translateProgramFunction(ptree, prp));
else if (prp == MFPUtils.MODULE_SUBPROGRAM)
assert false;
else if (prp == MFPUtils.SUBROUTINE_SUBPROGRAM)
assert false;
else if (prp == MFPUtils.BLOCK_DATA)
assert false;
else if (prp == MFPUtils.MODULE)
itemNodes.addAll(translateModule(ptree));
else
assert false;
scopes.exitProgramUnitScope();
itemNodes.addAll(programUnits);
return itemNodes;
}
private List<BlockItemNode> translateModule(MFTree module)
throws SyntaxException, ParseException {
List<BlockItemNode> itemNodes = new LinkedList<>();
MFTree moduleStmt = module.getChildByIndex(0);
MFTree moduleName = moduleStmt.getChildByIndex(2);
MFTree moduleSpec = module.getChildByIndex(1);
MFTree moduleSubProgram = module.getChildByIndex(2);
String moduleNameStr = getName(moduleName);
itemNodes.addAll(processSpecPart(moduleSpec, moduleNameStr));
if (moduleSubProgram.prp() != MFPUtils.ABSENT) {
assert false; // TODO: process module subprograms
}
return itemNodes;
}
private List<BlockItemNode> translateStmtAllocate(MFTree allocateStmt) {
// Source src = newSource(allocateStmt);
List<BlockItemNode> itemNodes = new LinkedList<>();
// TODO:
return itemNodes;
}
private List<BlockItemNode> translateStmtCall(MFTree callStmt)
throws SyntaxException {
int numArrayArgs = 0;
Source src = newSource(callStmt);
List<BlockItemNode> itemNodes = new LinkedList<>();
MFTree funcRef = callStmt.getChildByIndex(2).getChildByIndex(0)
.getChildByIndex(0);
MFTree funcName = funcRef.getChildByIndex(0);
Boolean hasArgList = funcRef.numChildren() > 1;
IdentifierNode funcIdNode = translateIdentifier(funcName);
ExpressionNode funcRefNode = nodeFactory
.newIdentifierExpressionNode(src, funcIdNode);
List<ExpressionNode> actualCallArgNodes = new LinkedList<ExpressionNode>();
List<VariableDeclarationNode> dummyFuncDeclFormalNodes = new LinkedList<VariableDeclarationNode>();
SequenceNode<VariableDeclarationNode> formalsNode = null;
String argName;
TypeNode formalTypeNode = null;
TypeNode tempNode = null;
if (hasArgList) {
MFTree args = funcRef.getChildByIndex(1);
int numArgs = args.numChildren();
for (int i = 0; i < numArgs; i++) {
MFTree arg = args.getChildByIndex(i).getChildByIndex(0);
Source argSrc = newSource(arg);
ExpressionNode argNode = translateExpr(arg);
IdentifierNode formalNameNode = nodeFactory.newIdentifierNode(
argNode.getSource(), "__civl_dummy_arg_" + i);
Boolean notSection = arraySectionDecls.isEmpty();
while (!arraySectionDecls.isEmpty()) {
itemNodes.add(arraySectionDecls.pop());
numArrayArgs++;
}
switch (argNode.expressionKind()) {
case OPERATOR :
if (((OperatorNode) argNode)
.getOperator() == Operator.DEREFERENCE) {
argNode = ((OperatorNode) argNode).getArgument(0)
.copy();
argNode.remove();
if (argNode instanceof IdentifierExpressionNode) {
// Arg is an identifier w/ a scalar type
argName = ((IdentifierExpressionNode) argNode)
.getIdentifier().name();
formalTypeNode = scopes
.getTypeByVarIdent(argName, argSrc)
.copy();
tempNode = formalTypeNode;
if (tempNode.kind() == TypeNodeKind.BASIC) {
if (!scopes.isParameterVar(argName))
argNode = nodeFactory.newOperatorNode(
src, Operator.ADDRESSOF,
argNode);
formalTypeNode = nodeFactory
.newPointerTypeNode(
argNode.getSource(),
formalTypeNode.copy());
}
} else if (argNode instanceof CastNode) {
formalTypeNode = ((CastNode) argNode)
.getCastType();
}
} else
assert false;
break;
case IDENTIFIER_EXPRESSION :
argName = ((IdentifierExpressionNode) argNode)
.getIdentifier().name();
formalTypeNode = scopes
.getTypeByVarIdent(argName, argSrc).copy();
tempNode = formalTypeNode;
if (tempNode.kind() == TypeNodeKind.BASIC) {
argNode = nodeFactory.newOperatorNode(src,
Operator.ADDRESSOF, argNode);
formalTypeNode = nodeFactory.newPointerTypeNode(
argNode.getSource(), formalTypeNode.copy());
}
if (notSection && tempNode
.kind() == TypeNodeKind.TYPEDEF_NAME) {
IdentifierNode arrayArgIdNode = nodeFactory
.newIdentifierNode(argNode.getSource(),
FORTRAN_ARRAY_ARG_PREFIX + argName);
VariableDeclarationNode arrayArgVarDeclNode = createArrayDesc(
dummySrc, arrayArgIdNode, null, null,
FORTRAN_ARRAY_DESCRIPTOR_KIND.SECTION_ARG,
/* isCommon */ false);
itemNodes.add(arrayArgVarDeclNode);
argNode = nodeFactory.newIdentifierExpressionNode(
src, arrayArgIdNode.copy());
numArrayArgs++;
}
if (tempNode.kind() == TypeNodeKind.ARRAY)
assert false;
break;
case CONSTANT :
argNode = argNode.copy();
if (argNode instanceof IntegerConstantNode) {
tempNode = nodeFactory.newBasicTypeNode(
argNode.getSource(), BasicTypeKind.INT);
formalTypeNode = nodeFactory
.newPointerTypeNode(dummySrc, tempNode);
} else
assert false;
break;
default :
assert false;
}
actualCallArgNodes.add(argNode);
dummyFuncDeclFormalNodes
.add(nodeFactory.newVariableDeclarationNode(argSrc,
formalNameNode, formalTypeNode.copy()));
}
}
formalsNode = nodeFactory.newSequenceNode(src,
"DummySubroutineFormalDeclList", dummyFuncDeclFormalNodes);
FunctionCallNode callNode = nodeFactory.newFunctionCallNode(src,
funcRefNode, actualCallArgNodes, null);
FunctionTypeNode dummyFuncTypeNode = nodeFactory.newFunctionTypeNode(
src, nodeFactory.newVoidTypeNode(src), formalsNode, false);
FunctionDeclarationNode dummyFuncDeclNode = nodeFactory
.newFunctionDeclarationNode(src, funcIdNode.copy(),
dummyFuncTypeNode, null);
processDummyFuncOrSubrDeclaration(getName(funcName), dummyFuncDeclNode);
itemNodes.add((BlockItemNode) nodeFactory
.newExpressionStatementNode(callNode));
while (numArrayArgs > 0) {
itemNodes.add(createArrayDestroy(freedArrays.pop()));
numArrayArgs--;
}
return itemNodes;
}
private HashMap<String, Integer> commonBlockName2NumObjs = new HashMap<>();
private List<BlockItemNode> translateStmtCommon(MFTree commonStmt)
throws SyntaxException {
final int INDEX_FIRST_COMMON_BLOCK = 2;
List<BlockItemNode> itemNodes = new LinkedList<>();
// Iterates each group of a commonBlockName and its objects
for (int i = INDEX_FIRST_COMMON_BLOCK; i < commonStmt
.numChildren(); i++) {
MFTree cBlock = commonStmt.getChildByIndex(i);
MFTree cBObjs = cBlock.getChildByIndex(0);
Source srcCBlock = newSource(cBlock);
//Source srcCBObjs = newSource(cBObjs);
String cBName = getName(cBlock);
int numCBObjs = cBObjs.numChildren();
int cBOIdx = 0;
/*
* Note that: a same commonBlockName may occur multiple times
* Successive appearance in a same scope unit are regarded as
* continuation of the list for that specific commonBlcokName
*/
if (commonBlockName2NumObjs.containsKey(cBName)) {
cBOIdx = commonBlockName2NumObjs.get(cBName);
}
for (int j = 0; j < numCBObjs; j++) {
MFTree cBObj = cBObjs.getChildByIndex(j);
MFTree cBOId = cBObj.getChildByIndex(0);
Source srcCBObj = newSource(cBObj);
Source srcCBOId = newSource(cBOId);
String gCBOName = FORTRAN_COMMON_BLOCK_PREFIX + //
cBName + "_" + cBOIdx;
String lCBOName = getName(cBOId);
IdentifierNode gCBOIdNode = nodeFactory
.newIdentifierNode(srcCBlock, gCBOName);
IdentifierNode lCBOIdNode = nodeFactory
.newIdentifierNode(srcCBOId, lCBOName);
TypeNode cBVarTypeNode = scopes
.getTypeByVarIdent(lCBOName, srcCBOId).copy();
VariableDeclarationNode gCBOVarDeclNode = null;
VariableDeclarationNode lCBOVarDeclNode = null;
if (cBObj.numChildren() > 1) {
// Array type (as Fortran array descriptor struct)
MFTree arraySpec = cBObj.getChildByIndex(1);
ExpressionNode dimInfo[][] = processArrayDimInfo(
arraySpec.getChildByIndex(0));
cBVarTypeNode = genArrDescType(srcCBObj);
gCBOVarDeclNode = createArrayDesc(srcCBObj, gCBOIdNode,
dimInfo, cBVarTypeNode.copy(),
FORTRAN_ARRAY_DESCRIPTOR_KIND.ORIGIN,
/* isCommon */ true);
lCBOVarDeclNode = nodeFactory.newVariableDeclarationNode(
srcCBObj, lCBOIdNode, cBVarTypeNode);
} else {
// Scalar Type
gCBOVarDeclNode = nodeFactory.newVariableDeclarationNode(
srcCBObj, gCBOIdNode, cBVarTypeNode.copy());
lCBOVarDeclNode = nodeFactory.newVariableDeclarationNode(
srcCBObj, lCBOIdNode, cBVarTypeNode);
}
// Collect global common blk. var. decl.
commonVarDeclNodes.add(gCBOVarDeclNode);
// Collect local common blk. var. decl.
/*
* each local decl. is initialized by being assigned with the
* global storage
*/
// TODO:
itemNodes.add(lCBOVarDeclNode);
cBOIdx++;
}
// Update the max index value
commonBlockName2NumObjs.put(cBName, cBOIdx);
}
return itemNodes;
}
private TypeNode genArrDescType(Source src) {
String FARR_DESC = "farr_desc";
IdentifierNode fArrDescNode = nodeFactory.newIdentifierNode(src,
FARR_DESC);
return nodeFactory.newTypedefNameNode(fArrDescNode, null);
}
// The driver of generating CIVL AST from FORTRAN parse tree.
private void genASTRoot() throws SyntaxException, ParseException {
int numProgUnit = this.ptree.numChildren();
Source rootSrc = newSource(this.ptree);
assert numProgUnit > 0;
this.scopes = new MFScopeManager(this.nodeFactory);
for (int i = 0; i < numProgUnit; i++)
this.programUnits.addAll(
translateProgramUnit(this.ptree.getChildByIndex(i)));
this.root = this.nodeFactory.newTranslationUnitNode(rootSrc,
this.programUnits);
}
// Interfaces or non-private functions
/**
* @return a CIVL AST generated from {@link MFTree} <code>this.root</code>
*/
public AST generateAST() {
AST civlAst = null;
SourceFile rootSrcFile = new SourceFile(new File(filePath),
srcFiles.size());
srcFiles.put(rootSrcFile.getIndex(), rootSrcFile);
formations.add(tokenFactory.newInclusion(rootSrcFile));
dummySrc = tokenFactory
.newSource(tokenFactory.newCivlcToken(CivlcTokenConstant.ABSENT,
SRC_INFO, formations.peek(), TokenVocabulary.FORTRAN));
try {
genASTRoot();
// Add global variables translated from common block.
root.insertChildren(0, commonVarDeclNodes);
// Add $input/$output variables
root.insertChildren(0, inputOutputVarDeclNodes);
addLibASTNodes();
civlAst = astFactory.newAST(root, srcFiles.values(),
hasProgramEntry);
// civlAst.prettyPrint(System.out, true);
} catch (SyntaxException | PreprocessorException | ParseException e) {
e.printStackTrace();
}
return civlAst;
}
}