blob: c71d4a476029f4c6d1eac219ec32d156e13b98fb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 University of Illinois at Urbana-Champaign and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.tests.analysis.types;
import java.io.ByteArrayInputStream;
import junit.framework.TestCase;
import org.eclipse.photran.internal.core.analysis.types.Type;
import org.eclipse.photran.internal.core.analysis.types.TypeChecker;
import org.eclipse.photran.internal.core.lexer.LexerFactory;
import org.eclipse.photran.internal.core.lexer.SourceForm;
import org.eclipse.photran.internal.core.parser.ASTAssignmentStmtNode;
import org.eclipse.photran.internal.core.parser.ASTExecutableProgramNode;
import org.eclipse.photran.internal.core.parser.ASTMainProgramNode;
import org.eclipse.photran.internal.core.parser.IExpr;
import org.eclipse.photran.internal.core.parser.Parser;
/**
* Fortran type checker unit tests
*
* @author Stoyan Gaydarov
*/
public class TypeCheckerTestCase extends TestCase
{
/** Parses a Fortran expression. Does not bind identifiers, etc. */
private Type getType(String expression) throws Exception
{
// We can only parse entire programs, so we embed the expression in
// a parseable program, then extract the expression from the program's AST
String program = "a = " + expression + "\nend";
ASTExecutableProgramNode ast = new Parser().parse(LexerFactory.createLexer(new ByteArrayInputStream(program.getBytes()), null, "<literal text>", SourceForm.UNPREPROCESSED_FREE_FORM, true /*false*/));
assertNotNull(ast);
ASTMainProgramNode mainProg = (ASTMainProgramNode)ast.getProgramUnitList().get(0);
ASTAssignmentStmtNode assignmentStmt = (ASTAssignmentStmtNode)mainProg.getBody().get(0);
IExpr exprNode = assignmentStmt.getRhs();
return TypeChecker.getTypeOf(exprNode);
}
private String character = "\"Stoyan\""; // used for character type
public void testConstantExpressionTypes() throws Exception
{
assertEquals(Type.INTEGER, getType("3"));
assertEquals(Type.REAL, getType("3.0"));
assertEquals(Type.CHARACTER, getType(character));
assertEquals(Type.DOUBLEPRECISION, getType("3.0D+00"));
assertEquals(Type.COMPLEX, getType("(3,3)"));
assertEquals(Type.LOGICAL, getType(".true."));
}
public void testUnaryExpressionTypes() throws Exception
{
assertEquals(Type.INTEGER, getType("-3"));
assertEquals(Type.INTEGER, getType("+3"));
assertEquals(Type.TYPE_ERROR, getType(".NOT. 3"));
assertEquals(Type.REAL, getType("-3.0"));
assertEquals(Type.REAL, getType("+3.0"));
assertEquals(Type.TYPE_ERROR, getType(".NOT. 3.0"));
assertEquals(Type.DOUBLEPRECISION, getType("-3.0D+00"));
assertEquals(Type.DOUBLEPRECISION, getType("+3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType(".NOT. 3.0D+00"));
assertEquals(Type.COMPLEX, getType("-(3,3)"));
assertEquals(Type.COMPLEX, getType("+(3,3)"));
assertEquals(Type.TYPE_ERROR, getType(".NOT. (3,3)"));
assertEquals(Type.TYPE_ERROR, getType("-" + character)); //??
assertEquals(Type.TYPE_ERROR, getType("+" + character)); //??
assertEquals(Type.TYPE_ERROR, getType(".NOT. " + character));
assertEquals(Type.TYPE_ERROR, getType("-.true."));
assertEquals(Type.TYPE_ERROR, getType("+.true."));
assertEquals(Type.LOGICAL, getType(".NOT. .true."));
}
public void testConcatOperations() throws Exception
{
assertEquals(Type.UNKNOWN, getType(character + " // " + "1"));
assertEquals(Type.UNKNOWN, getType(character + " // " + "3.2"));
assertEquals(Type.UNKNOWN, getType(character + " // " + "43.3D+00"));
assertEquals(Type.UNKNOWN, getType(character + " // " + "(6,7)"));
assertEquals(Type.UNKNOWN, getType(character + " // " + ".true."));
assertEquals(Type.CHARACTER, getType(character + " // " + character));
}
public void testGEOperator() throws Exception
{
testComparasonOperations(" .GE. ");
}
public void testGTOperator() throws Exception
{
testComparasonOperations(" .GT. ");
}
public void testLEOperator() throws Exception
{
testComparasonOperations(" .LE. ");
}
public void testLTOperator() throws Exception
{
testComparasonOperations(" .LT. ");
}
public void testNEOperator() throws Exception
{
testComparasonOperations(" .NE. ");
}
public void testEQOperator() throws Exception
{
testComparasonOperations(" .EQ. ");
}
private void testComparasonOperations(String op) throws Exception
{
if(op.equals(" .EQ. ") || op.equals(" .NE. "))
{
assertEquals(Type.LOGICAL, getType("8" + op + "(4,5)"));
assertEquals(Type.LOGICAL, getType("3.6" + op + "(3,8)"));
assertEquals(Type.LOGICAL, getType("3.2D+00" + op + "(4,9)"));
assertEquals(Type.LOGICAL, getType("(4,8)" + op + "7"));
assertEquals(Type.LOGICAL, getType("(4,3)" + op + "5.4"));
assertEquals(Type.LOGICAL, getType("(4,6)" + op + "(4,9)"));
assertEquals(Type.LOGICAL, getType("(3,0)" + op + "3.0D+00"));
}
else
{
assertEquals(Type.TYPE_ERROR, getType("8" + op + "(4,5)"));
assertEquals(Type.TYPE_ERROR, getType("3.6" + op + "(3,8)"));
assertEquals(Type.TYPE_ERROR, getType("3.2D+00" + op + "(4,9)"));
assertEquals(Type.TYPE_ERROR, getType("(4,8)" + op + "7"));
assertEquals(Type.TYPE_ERROR, getType("(4,3)" + op + "5.4"));
assertEquals(Type.TYPE_ERROR, getType("(4,6)" + op + "(4,9)"));
assertEquals(Type.TYPE_ERROR, getType("(3,0)" + op + "3.0D+00"));
}
assertEquals(Type.LOGICAL, getType("9" + op + "3"));
assertEquals(Type.LOGICAL, getType("5" + op + "3.0"));
assertEquals(Type.LOGICAL, getType("4" + op + "2.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("3" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("1" + op + character));
assertEquals(Type.LOGICAL, getType("3.0" + op + "7"));
assertEquals(Type.LOGICAL, getType("3.3" + op + "3.5"));
assertEquals(Type.LOGICAL, getType("4.0" + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("3.2" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("4.1" + op + character));
assertEquals(Type.LOGICAL, getType("3.1D+00" + op + "7"));
assertEquals(Type.LOGICAL, getType("4.0D+00" + op + "5.4"));
assertEquals(Type.LOGICAL, getType("5.0D+00" + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("3.8D+00" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("2.1D+00" + op + character));
assertEquals(Type.TYPE_ERROR, getType("(3,3)" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("(2,1)" + op + character));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "7"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "5.4"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "(4,9)"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + character));
assertEquals(Type.TYPE_ERROR, getType(character + op + "7"));
assertEquals(Type.TYPE_ERROR, getType(character + op + "5.4"));
assertEquals(Type.TYPE_ERROR, getType(character + op + "(4,9)"));
assertEquals(Type.TYPE_ERROR, getType(character + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType(character + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType(character + op + "c"));
}
public void testLogicalOperations() throws Exception
{
assertEquals(Type.LOGICAL, getType(".true. .AND. .true."));
assertEquals(Type.TYPE_ERROR, getType("1 .AND. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.3 .AND. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.2D+00 .AND. .true."));
assertEquals(Type.TYPE_ERROR, getType("(3,4) .AND. .true."));
assertEquals(Type.TYPE_ERROR, getType(character + " .AND. .true."));
assertEquals(Type.LOGICAL, getType(".true. .OR. .true."));
assertEquals(Type.TYPE_ERROR, getType("1 .OR. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.3 .OR. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.2D+00 .OR. .true."));
assertEquals(Type.TYPE_ERROR, getType("(3,4) .OR. .true."));
assertEquals(Type.TYPE_ERROR, getType(character + " .OR. .true."));
assertEquals(Type.LOGICAL, getType(".true. .EQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("1 .EQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.3 .EQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.2D+00 .EQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("(3,4) .EQV. .true."));
assertEquals(Type.TYPE_ERROR, getType(character + " .EQV. .true."));
assertEquals(Type.LOGICAL, getType(".true. .NEQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("1 .NEQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.3 .NEQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("4.2D+00 .NEQV. .true."));
assertEquals(Type.TYPE_ERROR, getType("(3,4) .NEQV. .true."));
assertEquals(Type.TYPE_ERROR, getType(character + " .NEQV. .true."));
}
public void testAddExpressionTypes() throws Exception
{
testOpExpressionTypes("+");
}
public void testSubtractExpressionTypes() throws Exception
{
testOpExpressionTypes("-");
}
public void testMultiplyExpressionTypes() throws Exception
{
testOpExpressionTypes("*");
}
public void testDivisionExpressionTypes() throws Exception
{
testOpExpressionTypes("/");
}
public void testPowerExpressionTypes() throws Exception
{
testOpExpressionTypes("**");
}
private void testOpExpressionTypes(String op) throws Exception
{
assertEquals(Type.INTEGER, getType("9" + op + "3"));
assertEquals(Type.REAL, getType("5" + op + "3.0"));
assertEquals(Type.COMPLEX, getType("8" + op + "(4,5)"));
assertEquals(Type.DOUBLEPRECISION, getType("4" + op + "2.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("3" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("1" + op + character));
assertEquals(Type.REAL, getType("3.0" + op + "7"));
assertEquals(Type.REAL, getType("3.3" + op + "3.5"));
assertEquals(Type.COMPLEX, getType("3.6" + op + "(3,8)"));
assertEquals(Type.DOUBLEPRECISION, getType("4.0" + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("3.2" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("4.1" + op + character));
assertEquals(Type.COMPLEX, getType("(4,8)" + op + "7"));
assertEquals(Type.COMPLEX, getType("(4,3)" + op + "5.4"));
assertEquals(Type.COMPLEX, getType("(4,6)" + op + "(4,9)"));
assertEquals(Type.COMPLEX, getType("(3,0)" + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("(3,3)" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("(2,1)" + op + character));
assertEquals(Type.DOUBLEPRECISION, getType("3.1D+00" + op + "7"));
assertEquals(Type.DOUBLEPRECISION, getType("4.0D+00" + op + "5.4"));
assertEquals(Type.COMPLEX, getType("3.2D+00" + op + "(4,9)"));
assertEquals(Type.DOUBLEPRECISION, getType("5.0D+00" + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType("3.8D+00" + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType("2.1D+00" + op + character));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "7"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "5.4"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "(4,9)"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType(".true." + op + character));
assertEquals(Type.TYPE_ERROR, getType(character + op + "7"));
assertEquals(Type.TYPE_ERROR, getType(character + op + "5.4"));
assertEquals(Type.TYPE_ERROR, getType(character + op + "(4,9)"));
assertEquals(Type.TYPE_ERROR, getType(character + op + "3.0D+00"));
assertEquals(Type.TYPE_ERROR, getType(character + op + ".true."));
assertEquals(Type.TYPE_ERROR, getType(character + op + "c"));
}
}