blob: 66df2b730fa631a527df50c088c1db8a9686a3d5 [file] [log] [blame]
/**
* Copyright (c) 2007 OptXware Research and Development LLC.
* 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:
* Daniel Varro - Initial API and implementation
*
*/
package org.eclipse.viatra2.lpgparser.typechecker;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.And;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Division;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Equals;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.GreaterThan;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.GreaterThanOrEqualTo;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.LessThan;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.LessThanOrEqualTo;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Minus;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Multiply;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Not;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.NotEquals;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Or;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Plus;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.Remainder;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ToBoolean;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ToDouble;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ToInt;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ToModelElement;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ToMultiplicity;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ToString;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.XOr;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Aggregate;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.ElementReference;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.FullyQualifiedName;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Inverse;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Multiplicity;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Name;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Source;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Target;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.modelmanagement.queryFunctions.Value;
/**
* This class contains elementary type checking rules for terms in
* GTASM programs.
*
* @author Daniel Varro
*
*/
public class TermTypeChecker {
private static ValueKind undef = ValueKind.UNDEF_LITERAL;
private static ValueKind bool = ValueKind.BOOLEAN_LITERAL;
private static ValueKind str = ValueKind.STRING_LITERAL;
private static ValueKind intg = ValueKind.INTEGER_LITERAL;
private static ValueKind dbl = ValueKind.DOUBLE_LITERAL;
private static ValueKind model = ValueKind.MODELELEMENT_LITERAL;
private static ValueKind multi = ValueKind.MULTIPLICITY_LITERAL;
private static ValueKind error = ValueKind.ERROR_LITERAL;
private final static ValueKind [][] logicalOperator = {
// undef, bool, str, intg, dbl, model, multi, error
{bool, bool, error, error, error, bool, error, undef}, // undef
{bool, bool , error, error, error, bool, error, undef}, // boolean
{error, error, error, error, error, error, error, undef}, // string
{error, error, error, error, error, error, error, undef}, // integer
{error, error, error, error, error, error, error, undef}, // double
{bool, bool, error, error, error, error, error, undef}, // model element
{undef, error, error, error, error, error, multi, undef}, // multiplicity
{undef, undef, undef, undef, undef, undef, undef, undef}, // error
};
// TODO: Check that this is different from the spec
private final static ValueKind [][] equalNotEqualOperator = {
// undef, bool, str, intg, dbl, model, multi, error
{bool, bool, bool, bool, bool, bool, bool, undef}, // undef
{bool, bool , error, error, error, bool, error, undef}, // boolean
{bool, error, bool , error, error, bool, error, undef}, // string
{bool, error, error, bool , bool , bool, error, undef}, // integer
{bool, error, error, bool , bool , bool, error, undef}, // double
{bool, bool, bool, bool, bool, bool, error, undef}, // model element
{bool, error, error, error, error, error, bool , undef}, // multiplicity
{undef, undef, undef, undef, undef, undef, undef, undef}, // error
};
private final static ValueKind [][] relationalOperator = {
// undef, bool, str, intg, dbl, model, multi, error
{bool, error, error, bool, bool, bool, bool, undef}, // undef
{error,error, error, error, error, error, error, undef}, // boolean
{error,error, error, error, error, error, error, undef}, // string
{bool, error, error, bool , bool , bool, error, undef}, // integer
{bool, error, error, bool , bool , bool, error, undef}, // double
{bool, error, error, bool, bool, bool, error, undef}, // model element
{bool, error, error, error, error, error, bool , undef}, // multiplicity
{undef, undef, undef, undef, undef, undef, undef, undef}, // error
};
private final static ValueKind [][] addOperator = {
// undef, bool, str, intg, dbl, model, multi, error
{undef, undef, str , undef, undef, undef, undef, undef}, // undef
{undef, error, str , error, error, error, error, undef}, // boolean
{str , str , str , str , str , str , str , str}, // string
{undef, error, str , intg , dbl , error, error, undef}, // integer
{undef, error, str , dbl , dbl , error, error, undef}, // double
{undef, error, str , error, error, model, error, undef}, // model element
{undef, error, str , error, error, error, error, undef}, // multiplicity
{undef, undef, str, undef, undef, undef, undef, undef}, // error
};
private final static ValueKind [][] subtractMultiplyDivideOperator = {
// undef, bool, str, intg, dbl, model, multi, error
{undef, undef, undef, undef, undef, undef, undef, undef}, // undef
{undef, error, error, error, error, error, error, undef}, // boolean
{undef, error, error, error, error, error, error, undef}, // string
{undef, error, error, intg , dbl , error, error, undef}, // integer
{undef, error, error, dbl , dbl , error, error, undef}, // double
{undef, error, error, error, error, model, error, undef}, // model element
{undef, error, error, error, error, error, error, undef}, // multiplicity
{undef, undef, undef, undef, undef, undef, undef, undef}, // error
};
private final static ValueKind [][] remainderOperator = {
// undef, bool, str, intg, dbl, model, multi, error
{undef, undef, undef, undef, undef, undef, undef, undef}, // undef
{undef, error, error, error, error, error, error, undef}, // boolean
{undef, error, error, error, error, error, error, undef}, // string
{undef, error, error, intg , error, error, error, undef}, // integer
{undef, error, error, error, error, error, error, undef}, // double
{undef, error, error, error, error, error, error, undef}, // model element
{undef, error, error, error, error, error, error, undef}, // multiplicity
{undef, undef, undef, undef, undef, undef, undef, undef}, // error
};
// ----------------------- Unary operators in terms ------------------
private final static ValueKind [] notOperator = {
// undef, bool, str, intg, dbl, model, multi, error
undef, bool, error, error, error, error, error, undef
};
private final static ValueKind [] minusOperator = {
// undef, bool, str, intg, dbl, model, multi, error
undef, error, error, intg, dbl, error, error, undef
};
// Optimistic approach is taken in case of "undef"
private final static ValueKind [] aggregate = {
// undef, bool, str, intg, dbl, model, multi, error
bool , error, error, error, error, bool , error, undef
};
private final static ValueKind [] source = {
// undef, bool, str, intg, dbl, model, multi, error
model, error, error, error, error, model, error, undef
};
private final static ValueKind [] target = {
// undef, bool, str, intg, dbl, model, multi, error
model, error, error, error, error, model, error, undef
};
private final static ValueKind [] ref = {
// undef, bool, str, intg, dbl, model, multi, error
model, error, model, error, error, error, error, undef
};
private final static ValueKind [] fqn = {
// undef, bool, str, intg, dbl, model, multi, error
str , error, error, error, error, str , error, undef
};
private final static ValueKind [] name = {
// undef, bool, str, intg, dbl, model, multi, error
str , error, error, error, error, str , error, undef
};
private final static ValueKind [] value = {
// undef, bool, str, intg, dbl, model, multi, error
str , error, error, error, error, str , error, undef
};
private final static ValueKind [] inverse = {
// undef, bool, str, intg, dbl, model, multi, error
model, error, error, error, error, model, error, undef
};
private final static ValueKind [] multiplicity = {
// undef, bool, str, intg, dbl, model, multi, error
multi, error, error, error, error, multi, error, undef
};
private final static ValueKind [] toString = {
// undef, bool, str, intg, dbl, model, multi, error
str , str , str, str , str, str , str , str
};
private final static ValueKind [] toInt = {
// undef, bool, str, intg, dbl, model, multi, error
intg , error, intg, intg, intg, error, error, undef
};
private final static ValueKind [] toDouble = {
// undef, bool, str, intg, dbl, model, multi, error
dbl , error, dbl, dbl , dbl, error, error, undef
};
private final static ValueKind [] toBoolean = {
// undef, bool, str, intg, dbl, model, multi, error
bool, bool, bool, bool, bool, error, error, undef
};
// private final static ValueKind [] toModelElement = {
// // undef, bool, str, intg, dbl, model, multi, error
// model, error, model, error, error, model, error, undef
// };
private final static ValueKind [] toMultiplicity = {
// undef, bool, str, intg, dbl, model, multi, error
multi, error, multi, error, error, error, multi, undef
};
// private final static ValueKind [] navigation = {
// // undef, bool, str, intg, dbl, model, multi, error
// model, error, error, error, error, model, error, undef
// };
/**
* Typechecking for unary operators
* @param term : current term to typecheck
* @param operand : the type of the operand
* @return {@link ValueKind}
*/
public static final ValueKind typeCheck(Term term, ValueKind operand) {
if (term instanceof Not) {return notOperator[operand.getValue()]; }
else if (term instanceof Minus) {return minusOperator[operand.getValue()]; }
else if (term instanceof Aggregate) {return aggregate[operand.getValue()]; }
else if (term instanceof Source) {return source[operand.getValue()]; }
else if (term instanceof Target) {return target[operand.getValue()]; }
else if (term instanceof ElementReference) {return ref[operand.getValue()]; }
else if (term instanceof FullyQualifiedName) {return fqn[operand.getValue()]; }
else if (term instanceof Name) {return name[operand.getValue()]; }
else if (term instanceof Value) {return value[operand.getValue()]; }
else if (term instanceof Inverse) {return inverse[operand.getValue()]; }
else if (term instanceof Multiplicity) {return multiplicity[operand.getValue()]; }
else if (term instanceof ToString) {return toString[operand.getValue()]; }
else if (term instanceof ToInt) {return toInt[operand.getValue()]; }
else if (term instanceof ToDouble) {return toDouble[operand.getValue()]; }
else if (term instanceof ToBoolean) {return toBoolean[operand.getValue()]; }
// else if (term instanceof ToModelElement) {return toModelElement[operand.getValue()]; }
else if (term instanceof ToMultiplicity) {return toMultiplicity[operand.getValue()]; }
// else if (term instanceof Navigation) {return navigation[operand.getValue()]; }
else return ValueKind.ERROR_LITERAL;
}
/**
* Typechecking for binary operators
* @param term : current term to typecheck
* @param left : the type of the left operand
* @param right : the type of the right operand
* @return {@link ValueKind}
*/
public static final ValueKind typeCheck(Term term, ValueKind left, ValueKind right) {
if (term instanceof Or) {return logicalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof XOr) {return logicalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof And) {return logicalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof Equals) {return equalNotEqualOperator[left.getValue()][right.getValue()]; }
else if (term instanceof NotEquals) {return equalNotEqualOperator[left.getValue()][right.getValue()]; }
else if (term instanceof GreaterThan) {return relationalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof LessThan) {return relationalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof GreaterThanOrEqualTo) {return relationalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof LessThanOrEqualTo) {return relationalOperator[left.getValue()][right.getValue()]; }
else if (term instanceof Plus) {return addOperator[left.getValue()][right.getValue()]; }
else if (term instanceof Minus) {return subtractMultiplyDivideOperator[left.getValue()][right.getValue()]; }
else if (term instanceof Multiply) {return subtractMultiplyDivideOperator[left.getValue()][right.getValue()]; }
else if (term instanceof Division) {return subtractMultiplyDivideOperator[left.getValue()][right.getValue()]; }
else if (term instanceof Remainder) {return remainderOperator[left.getValue()][right.getValue()]; }
else return ValueKind.ERROR_LITERAL;
}
public static final String getOperationString(Term term) {
if (term instanceof Not) {return "!"; }
else if (term instanceof Minus) {return "-"; }
else if (term instanceof Aggregate) {return "aggregation"; }
else if (term instanceof Source) {return "source"; }
else if (term instanceof Target) {return "target"; }
else if (term instanceof ElementReference) {return "ref"; }
else if (term instanceof FullyQualifiedName) {return "fqn"; }
else if (term instanceof Name) {return "name"; }
else if (term instanceof Value) {return "value"; }
else if (term instanceof Inverse) {return "inverse"; }
else if (term instanceof Multiplicity) {return "multiplicity"; }
else if (term instanceof ToString) {return "toString"; }
else if (term instanceof ToInt) {return "toInteger"; }
else if (term instanceof ToDouble) {return "toDouble"; }
else if (term instanceof ToBoolean) {return "toBoolean"; }
else if (term instanceof ToModelElement) {return "toModelElement"; }
else if (term instanceof ToMultiplicity) {return "toMultiplicity"; }
// else if (term instanceof Navigation) {return "->"; }
else if (term instanceof Or) {return "||"; }
else if (term instanceof XOr) {return "xor"; }
else if (term instanceof And) {return "&&"; }
else if (term instanceof Equals) {return "=="; }
else if (term instanceof NotEquals) {return "!="; }
else if (term instanceof GreaterThan) {return ">"; }
else if (term instanceof LessThan) {return "<"; }
else if (term instanceof GreaterThanOrEqualTo) {return ">="; }
else if (term instanceof LessThanOrEqualTo) {return "<="; }
else if (term instanceof Plus) {return "+"; }
else if (term instanceof Minus) {return "-"; }
else if (term instanceof Multiply) {return "*"; }
else if (term instanceof Division) {return "/"; }
else if (term instanceof Remainder) {return "%"; }
else return "unknown";
}
}