/** | |
* 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"; | |
} | |
} |