package typechecking;
//TODO:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import parser.ASTadditiveSetExpression;
import parser.ASTaggregate;
import parser.ASTaggregateElement;
import parser.ASTaggregateElements;
import parser.ASTarithmeticTerm;
import parser.ASTatom;
import parser.ASTbasicSort;
import parser.ASTbody;
import parser.ASTchoice_element;
import parser.ASTchoice_elements;
import parser.ASTchoice_rule;
import parser.ASTconcatenation;
import parser.ASTcondition;
import parser.ASTconstantTerm;
import parser.ASTconstantTermList;
import parser.ASTcurlyBrackets;
import parser.ASTdisjunction;
import parser.ASTdisplay;
import parser.ASTextendedNonRelAtom;
import parser.ASTextendedSimpleAtomList;
import parser.ASTfunctionalSymbol;
import parser.ASThead;
import parser.ASTidentifierRange;
import parser.ASTmultiplicativeSetExpression;
import parser.ASTnonRelAtom;
import parser.ASTnumericRange;
import parser.ASTpredSymbol;
import parser.ASTprogramRule;
import parser.ASTprogramRules;
import parser.ASTsetExpression;
import parser.ASTsimpleAtom;
import parser.ASTsortExpression;
import parser.ASTsortExpressionList;
import parser.ASTsymbolicFunction;
import parser.ASTsymbolicTerm;
import parser.ASTterm;
import parser.ASTtermList;
import parser.ASTunarySetExpression;
import parser.ASTunlabeledProgramCrRule;
import parser.ASTunlabeledProgramRule;
import parser.ParseException;
import parser.SimpleNode;
import parser.SparcTranslatorTreeConstants;
import sorts.BuiltIn;
import sorts.Condition;
import translating.InstanceGenerator;
/**
* Recursive descent typechecking implementation
*/
public class TypeChecker {
// mapping from sort names to sort expressions assigned to the sorts
private HashMap<String, ASTsortExpression> sortNameToExpression;
// mapping from predicate names to a list of names of sorts describing
// arguments
private HashMap<String, ArrayList<String>> predicateArgumentSorts;
// mapping from constants to their values
protected HashMap<String, Long> constantsMapping;
// name of SPARC file (used for error reporting).
private String inputFileName = "";
// List of all terms occuring in brackets
private HashSet<String> curlyBracketTerms;
// List of all defined record names
private HashSet<String> definedRecordNames;
// used for checking if sort contains a number
private InstanceGenerator gen;
public boolean ignoreLineNumbers;
/**
* Constructor
*
* @param sortNameToExpression
* @param predicateArgumentSorts
* @param constantsMapping
*/
public TypeChecker(HashMap<String, ASTsortExpression> sortNameToExpression,
HashMap<String, ArrayList<String>> predicateArgumentSorts,
HashMap<String, Long> constantsMapping,
HashSet<String> curlyBracketTerms,
HashSet<String> definedRecordNames,
InstanceGenerator gen
) {
this.sortNameToExpression = sortNameToExpression;
this.predicateArgumentSorts = predicateArgumentSorts;
this.constantsMapping = constantsMapping;
this.curlyBracketTerms = curlyBracketTerms;
this.definedRecordNames = definedRecordNames;
this.gen=gen;
this.ignoreLineNumbers=false;
}
/**
* Input file name setter (file name is used for error reporting)
*
* @param inputFileName
*/
public void setInputFileName(String fileName) {
this.inputFileName = fileName;
}
/**
* Do typechecking of collections of rules given by parent AST node (each of
* the rules is a child of given rules node)
*
* @param rules
* @throws ParseException
* if type violation occurs
*/
public void checkRules(ASTprogramRules rules) throws ParseException {
for (int i = 0; i < rules.jjtGetNumChildren(); i++) {
checkProgramRule((ASTprogramRule) rules.jjtGetChild(i));
}
}
/**
* Do typechecking of a rule given by AST node.
*
* @param rule
* to be checked
* @throws ParseException
* if type violation occurs
*/
private void checkProgramRule(ASTprogramRule rule) throws ParseException {
if (((SimpleNode) rule.jjtGetChild(0)).getId() == SparcTranslatorTreeConstants.JJTUNLABELEDPROGRAMRULE) {
checkUnlabeledProgramRule((ASTunlabeledProgramRule) rule
.jjtGetChild(0));
} else if (((SimpleNode) rule.jjtGetChild(0)).getId() == SparcTranslatorTreeConstants.JJTUNLABELEDPROGRAMCRRULE) {
checkUnlabeledProgramCrRule((ASTunlabeledProgramCrRule) rule
.jjtGetChild(0));
}
}
/**
* Fetch variables from given node
*
* @param n
* node to explore
* describes a language of string each of which may be used as a
* substitution for given variable
*/
private HashSet<String> fetchVariableNames(SimpleNode n) {
HashSet<String> result = new HashSet<String>();
if (n.getId() == SparcTranslatorTreeConstants.JJTVAR) {
result.add(n.image);
}
for (int i = 0; i < n.jjtGetNumChildren(); i++) {
result.addAll((fetchVariableNames((SimpleNode) (n.jjtGetChild(i)))));
}
return result;
}
/**
* Do typechecking of an unlabeled rule given by AST node.
*
* @param rule
* to be checked
* @throws ParseException
* if type violation occurs
*/
private void checkUnlabeledProgramRule(ASTunlabeledProgramRule rule)
throws ParseException {
if (rule.image.trim().equals(":~")) {// weak constraint
HashSet<String> varsInParams = null;
// System.out.println(rule.jjtGetNumChildren());
if (rule.jjtGetNumChildren() > 1)
varsInParams = fetchVariableNames((SimpleNode) rule
.jjtGetChild(1));
else
varsInParams = new HashSet<String>();
HashSet<String> varsInBody = fetchVariableNames((SimpleNode) rule
.jjtGetChild(0));
for (String s : varsInParams) {
if (!varsInBody.contains(s)) {
throw new ParseException(inputFileName + ": "
+ "variable in weak constraint paramethers"
+(ignoreLineNumbers ?"": " at line " + rule.getBeginLine() + ", column "
+ rule.getBeginColumn())
+ " does not occur in the body");
}
}
checkBody(((ASTbody) (rule.jjtGetChild(0))));
} else if (rule.jjtGetNumChildren() > 0
&& ((SimpleNode) rule.jjtGetChild(0)).getId() == SparcTranslatorTreeConstants.JJTPREDSYMBOL) {
/*
* image contain the name of a predicate and range of integers from
* its argument, p(1..3) results into "p 1 3" image
*/
ASTpredSymbol pred = (ASTpredSymbol) rule.jjtGetChild(0);
String[] range = rule.image.split(" ");
String predicateName = range[0];
if (!predicateArgumentSorts.containsKey(predicateName)
|| predicateArgumentSorts.get(predicateName).size() > 1) {
throw new ParseException(inputFileName + ": " + "predicate "
+ predicateName + " of arity 1 at "+(ignoreLineNumbers?"": "line "
+ pred.getBeginLine() + ", column "
+ pred.getBeginColumn()) + " was not declared");
}
int from = Integer.parseInt(range[1]);
int to = Integer.parseInt(range[2]);
for (int i = from; i <= to; i++) {
ASTterm term = new ASTterm((long)i);
if (!checkTerm(
term,
sortNameToExpression.get(predicateArgumentSorts.get(
predicateName).get(0)))) {
throw new ParseException(inputFileName + ": "
+ "Argument number " + 1 + " of predicate "
+ predicateName + "/1" + ", \"" + from + ".." + to
+ "\"," + (ignoreLineNumbers?"":" at line " + pred.getBeginLine()
+ ", column " + pred.getBeginColumn())
+ " violates definition of sort " + "\""
+ predicateArgumentSorts.get(predicateName).get(0)
+ "\"");
}
}
} else if (rule.jjtGetNumChildren() > 1) {
checkHead((ASThead) (rule.jjtGetChild(0)));
checkBody((ASTbody) (rule.jjtGetChild(1)));
} else if (((SimpleNode) rule.jjtGetChild(0)).getId() == SparcTranslatorTreeConstants.JJTHEAD) {
checkHead((ASThead) (rule.jjtGetChild(0)));
} else {
checkBody((ASTbody) (rule.jjtGetChild(0)));
}
}
/**
* Do typechecking of a rule body given by AST node.
*
* @param body
* to be checked
* @throws ParseException
* if type violation occurs
*/
private void checkBody(ASTbody body) throws ParseException {
for (int i = 0; i < body.jjtGetNumChildren(); i++) {
checkAtom((ASTatom) (body.jjtGetChild(i)));
}
}
/**
* Do typechecking of an atom given by AST node.
*
* @param atom
* to be checked
* @throws ParseException
* if type violation occurs
*/
public void checkAtom(ASTatom atom) throws ParseException {
if (((SimpleNode) atom.jjtGetChild(0)).getId() == SparcTranslatorTreeConstants.JJTAGGREGATE) {
checkAggregate((ASTaggregate) atom.jjtGetChild(0));
} else if (((SimpleNode) atom.jjtGetChild(0)).getId() == SparcTranslatorTreeConstants.JJTEXTENDEDNONRELATOM) {
checkExtendedNonRelAtom((ASTextendedNonRelAtom) atom.jjtGetChild(0));
}
}
/**
* Do typechecking of an extended non -relational atom given by AST node.
* Relational atom is atom of the form [term_1] [relation] [term_2].
*
* @param atom
* to be checked
* @throws ParseException
* if type violation occurs
*/
private void checkExtendedNonRelAtom(ASTextendedNonRelAtom atom) //HERE
throws ParseException {
ASTpredSymbol pred = (ASTpredSymbol) atom.jjtGetChild(0);
ASTtermList list = null;
if (atom.jjtGetNumChildren() == 1) {// 0- arity predicate
list = new ASTtermList(SparcTranslatorTreeConstants.JJTTERMLIST);
} else {
list = (ASTtermList) (atom.jjtGetChild(1));
}
checkAtomTermList(list, (pred.hasPoundSign()?"#":"")+ pred.image, pred.getBeginLine(),
pred.getBeginColumn());
}
boolean isNumber(String s) {
for(int i=0;i<s.length();i++) {
if(!Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
}
boolean containsNumber(HashSet<String> termSet) {
for (String s:termSet) {
if(isNumber(s)) {
return true;
}
}
return false;
}
/**
* Do typechecking of a predicate given by name and given in form of a term
* list
*
* @param termList
* list of arguments of given predicate
* @param predicateName
* name of predicate
* @param beginLine
* line of the source file where predicate occurs
* @param beginColumn
* column of the source file where predicate occurs
* @throws ParseException
* if an undeclared predicate found
*/
private void checkAtomTermList(ASTtermList termList, String predicateName,
int beginLine, int beginColumn) throws ParseException {
if (!predicateArgumentSorts.containsKey(predicateName)
|| predicateArgumentSorts.get(predicateName).size() != termList
.jjtGetNumChildren()) {
throw new ParseException(inputFileName + ": " + "predicate "
+ predicateName + " of arity "
+ termList.jjtGetNumChildren() + (ignoreLineNumbers?"":" at line " + beginLine
+ ", column " + beginColumn) + " was not declared");
}
ArrayList<String> sortNames=new ArrayList<String>();
for (String sortName : predicateArgumentSorts.get(predicateName)) {
sortNames.add(sortName);
}
checkTermListWithEx(termList, sortNames, predicateName, beginLine,
beginColumn);
}
// mapping between sort names and boolean values
// isNumeric[s] is true iff s contains at least one number
HashMap<String, Boolean> isNumeric=null;
/**
* Do typechecking of a predicate given by name and given in form of a term
* list
*
* @param termList
* list of arguments of given predicate
* @param predicateName
* name of predicate
* @param sortExpressionList
* list of sort expressions to be used for typechecking of given
* term list
* @param beginLine
* line of the source file where predicate occurs
* @param beginColumn
* column of the source file where predicate occurs
* @throws ParseException
* if sort violation occurs
*/
private void checkTermListWithEx(ASTtermList termList,
ArrayList<String> sortNames, String predicateName,
int beginLine, int beginColumn) throws ParseException {
for (int i = 0; i < termList.jjtGetNumChildren(); i++) {
ASTterm termToCheck = (ASTterm) termList.jjtGetChild(i);
String sortName = predicateArgumentSorts.get(predicateName).get(i);
ASTsortExpression sortExpression=sortNameToExpression.get(sortName);
SimpleNode child=(SimpleNode) termToCheck.jjtGetChild(0);
if(child.getId()==SparcTranslatorTreeConstants.JJTARITHMETICTERM) {
// Check if term is evaluable arithmetic term and replace it
// by its value if it is true
TermEvaluator te=new TermEvaluator((ASTarithmeticTerm)child);
if(te.isEvaluable()) {
termToCheck=new ASTterm(te.evaluate());
}
// check if corresponding sort contains at least one number!
boolean hasNumber=false;
if(isNumeric==null) {
isNumeric=new HashMap<String,Boolean>();
}
if(isNumeric.containsKey(sortName)) {
hasNumber=isNumeric.get(sortName);
}
else {
HashSet<String> instances=gen.generateInstances(sortExpression, false);
hasNumber=containsNumber(instances);
isNumeric.put(sortName, hasNumber);
}
if(!hasNumber)
{
throw new ParseException(inputFileName + ": "
+ "argument number " + (i + 1) + " of predicate "
+ predicateName + "/"
+ termList.jjtGetNumChildren() + ", \""
+ ((ASTterm) termList.jjtGetChild(i)).toString()
+ "\"," + (ignoreLineNumbers?"":" at line " + +beginLine + ", column "
+ beginColumn) + " is an arithmetic term and not a variable, but "
+ "\"" + "#" + sortName + "\""+" does not contain a number");
}
}
boolean isGround = termToCheck.isGround();
if (!isGround
&& !checkNonGroundTerm(termToCheck)
|| isGround
&& !checkTerm(termToCheck,sortExpression)) {
if (isGround)
throw new ParseException(inputFileName + ": "
+ "argument number " + (i + 1) + " of predicate "
+ predicateName + "/"
+ termList.jjtGetNumChildren() + ", \""
+ ((ASTterm) termList.jjtGetChild(i)).toString()
+ "\"," + (ignoreLineNumbers?"": " at line " + +beginLine + ", column "
+ beginColumn) + " violates definition of sort "
+ "\"" + "#"+ sortName + "\"");
else {
throw new ParseException(inputFileName + ": "
+ "non-ground term \"" + termToCheck.toString()
+ "\" occuring in program as " + +(i + 1)
+ " argument of predicate " + predicateName + "/"
+ termList.jjtGetNumChildren()
+ (ignoreLineNumbers?"": " at line " + +beginLine + ", column "
+ beginColumn)+ " is not a program term");
}
}
}
}
/**
* Check if the term with variables is a term of given progam
*
* @param termToCheck
* @param sortName
* @return true if termToCheck is a program term
* @throws ParseException
*/
private boolean checkNonGroundTerm(ASTterm termToCheck) {
SimpleNode child = (SimpleNode) termToCheck.jjtGetChild(0);
switch(child.getId()) {
case SparcTranslatorTreeConstants.JJTARITHMETICTERM:
return checkConstants(termToCheck);
case SparcTranslatorTreeConstants.JJTSYMBOLICTERM:
return checkNonGroundTerm((ASTsymbolicTerm) termToCheck
.jjtGetChild(0));
default:
return true;
}
}
private boolean checkNonGroundTerm(ASTsymbolicTerm symTerm) {
SimpleNode child0 = (SimpleNode) symTerm.jjtGetChild(0);
if (child0.getId() == SparcTranslatorTreeConstants.JJTSYMBOLICCONSTANT) {
return isDomainElement(new ASTterm(child0.image));
} else {// symbolic Function
String functionSymbol = child0.image.substring(0,
child0.image.length() - 1);
if (!definedRecordNames.contains(functionSymbol))
return false;
ASTtermList child1 = (ASTtermList) symTerm.jjtGetChild(1);
for (int i = 0; i < child1.jjtGetNumChildren(); i++) {
ASTterm term = (ASTterm) child1.jjtGetChild(i);
if (term.isGround()) {
if (!isDomainElement(term))
return false;
} else {
if (!checkNonGroundTerm(term))
return false;
}
}
return true;
}
}
/**
* Check all constants in given n (a subnode of a root of arithmetic term)
*
* @param n
* @return true if all constants are in the range 0..maxint and false
* otherwise
*/
private boolean checkConstants(SimpleNode n) {
if (n.getId() == SparcTranslatorTreeConstants.JJTATOMICARITHMETICTERM) {
if (n.jjtGetNumChildren() == 0) {
int integer = Integer.parseInt(n.image);
return integer >= 0 && integer <= BuiltIn.getMaxInt();
}
}
boolean result = true;
for (int i = 0; i < n.jjtGetNumChildren(); i++) {
result = result & checkConstants((SimpleNode) n.jjtGetChild(i));
}
return result;
}
/**
* Check if term t belongs to program domain
*
* @param t
* @return true if t is an element of program domain and false otherwise
*/
private boolean isDomainElement(ASTterm t) {
String termString = t.toString();
if (curlyBracketTerms.contains(termString))
return true;
for (ASTsortExpression se : sortNameToExpression.values()) {
if (checkTerm(t, se))
return true;
}
return false;
}
/**
* Do typechecking of an aggregate given by AST node
*
* @param agr
* aggregate to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkAggregate(ASTaggregate agr) throws ParseException {
for (int i = 0; i < agr.jjtGetNumChildren(); i++) {
if (((SimpleNode) (agr.jjtGetChild(i))).getId() == SparcTranslatorTreeConstants.JJTAGGREGATEELEMENTS) {
checkAggregateElements((ASTaggregateElements) (agr
.jjtGetChild(i)));
}
}
}
/**
* Do typechecking of an aggregate given by AST node
*
* @param agr
* aggregate to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkAggregateElements(ASTaggregateElements argelems)
throws ParseException {
for (int i = 0; i < argelems.jjtGetNumChildren(); i++) {
checkAggregateElement((ASTaggregateElement) (argelems
.jjtGetChild(i)));
}
}
/**
* Do typechecking of an aggregate element given by AST node
*
* @param agrelem
* aggregate element to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkAggregateElement(ASTaggregateElement argelem)
throws ParseException {
for (int i = 0; i < argelem.jjtGetNumChildren(); i++) {
if (((SimpleNode) (argelem.jjtGetChild(i))).getId() == SparcTranslatorTreeConstants.JJTEXTENDEDSIMPLEATOMLIST) {
checkExtendedSimpleAtomList((ASTextendedSimpleAtomList) argelem
.jjtGetChild(i));
}
}
}
/**
* Do typechecking of an extended simple atom list given by AST node
*
* @param exList
* extended simple atom list to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkExtendedSimpleAtomList(ASTextendedSimpleAtomList exList)
throws ParseException {
for (int i = 0; i < exList.jjtGetNumChildren(); i++) {
checkSimpleAtom((ASTsimpleAtom) exList.jjtGetChild(i));
}
}
/**
* Do typechecking of a simple atom given by AST node
*
* @param simpleAtom
* to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkSimpleAtom(ASTsimpleAtom simpleAtom)
throws ParseException {
if (simpleAtom.jjtGetNumChildren() > 0
&& ((SimpleNode) (simpleAtom.jjtGetChild(0))).getId() == SparcTranslatorTreeConstants.JJTEXTENDEDNONRELATOM) {
checkExtendedNonRelAtom((ASTextendedNonRelAtom) (simpleAtom
.jjtGetChild(0)));
}
}
/**
* Do typechecking of a non -relational atom given by AST node. Relational
* atom is atom of the form [term_1] [relation] [term_2].
*
* @param nonRelAtom
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkNonRelAtom(ASTnonRelAtom nonRelAtom)
throws ParseException {
ASTpredSymbol pred = (ASTpredSymbol) nonRelAtom.jjtGetChild(0);
ASTtermList list = null;
if (nonRelAtom.jjtGetNumChildren() == 1) {// 0- arity predicate
list = new ASTtermList(SparcTranslatorTreeConstants.JJTTERMLIST);
} else {
list = (ASTtermList) (nonRelAtom.jjtGetChild(1));
}
checkAtomTermList(list, (pred.hasPoundSign()?"#":"")+pred.image, pred.getBeginLine(),
pred.getBeginColumn());
}
/**
* Do typechecking of a rule head given by AST node
*
* @param head
* to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkHead(ASThead head) throws ParseException {
if (((SimpleNode) (head.jjtGetChild(0))).getId() == SparcTranslatorTreeConstants.JJTDISJUNCTION) {
checkDisjunction((ASTdisjunction) (head.jjtGetChild(0)));
} else {
checkChoiceRule((ASTchoice_rule) (head.jjtGetChild(0)));
}
}
/**
* Do typechecking of choice rule given by AST node
*
* @param choice_rule
* to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkChoiceRule(ASTchoice_rule choice_rule)
throws ParseException {
for (int i = 0; i < choice_rule.jjtGetNumChildren(); i++) {
if (((SimpleNode) (choice_rule.jjtGetChild(i))).getId() == SparcTranslatorTreeConstants.JJTCHOICE_ELEMENTS) {
checkChoiceElements((ASTchoice_elements) (choice_rule
.jjtGetChild(i)));
}
}
}
/**
* Do typechecking of choice rule elements given by AST node
*
* @param choice_elements
* to be checked
* @throws ParseException
* if sort violation occurs
*/
private void checkChoiceElements(ASTchoice_elements choice_elements)
throws ParseException {
for (int i = 0; i < choice_elements.jjtGetNumChildren(); i++) {
checkChoiceElement((ASTchoice_element) (choice_elements
.jjtGetChild(i)));
}
}
/**
* Do typechecking of choice rule element given by AST node
*
* @param choice_element
* to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkChoiceElement(ASTchoice_element choice_element)
throws ParseException {
for (int i = 0; i < choice_element.jjtGetNumChildren(); i++) {
if (((SimpleNode) (choice_element.jjtGetChild(i))).getId() == SparcTranslatorTreeConstants.JJTNONRELATOM) {
checkNonRelAtom((ASTnonRelAtom) choice_element.jjtGetChild(i));
}
if (((SimpleNode) (choice_element.jjtGetChild(i))).getId() == SparcTranslatorTreeConstants.JJTEXTENDEDSIMPLEATOMLIST) {
checkExtendedSimpleAtomList((ASTextendedSimpleAtomList) choice_element.jjtGetChild(i));
}
}
}
/**
* Do typechecking of disjunction in the head of some rule given by AST node
*
* @param disjunction
* to be checked
* @throws ParseException
* if sort violation occurs or undeclared predicate found
*/
private void checkDisjunction(ASTdisjunction disjunction)
throws ParseException {
for (int i = 0; i < disjunction.jjtGetNumChildren(); i++) {
checkNonRelAtom((ASTnonRelAtom) disjunction.jjtGetChild(i));
}
}
/**
* Do typechecking of unlabeled program consistency restoring rule given by
* AST node
*
* @param crrule
* consistency restoring rule to be checked
* @throws ParseException
* if sort violation occurs
*/
private void checkUnlabeledProgramCrRule(ASTunlabeledProgramCrRule crrule)
throws ParseException {
for (int i = 0; i < crrule.jjtGetNumChildren(); i++) {
if (((SimpleNode) (crrule.jjtGetChild(i))).getId() == SparcTranslatorTreeConstants.JJTHEAD) {
checkHead((ASThead) crrule.jjtGetChild(i));
} else {
checkBody((ASTbody) crrule.jjtGetChild(i));
}
}
}
/**
* Check arithmetic term for satisfying given regular expression
*
* @param term
* to be checked
* @param reg
* regular expression
* @return true if term is not valuable(i.e, it has variables) or it
* evaluates to a value satisfying pattern described by regular
* expression and false otherwise
*/
/**
* Check term for satisfying given sort expression
*
* @param symterm
* to be checked
* @param expr
* sort expression
* @return true if given term is not valuable(i.e, it has variables) or it
* evaluates to a value satisfying pattern described by sort
* expression and false otherwise
*/
private boolean checkTerm(ASTterm symterm, ASTsortExpression expr) {
if (((SimpleNode) (symterm.jjtGetChild(0))).getId() == SparcTranslatorTreeConstants.JJTVAR) {
return true;
}
//
int id = ((SimpleNode) expr.jjtGetChild(0)).getId();
switch (id) {
case SparcTranslatorTreeConstants.JJTSETEXPRESSION:
return checkTerm(symterm, (ASTsetExpression) expr.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTNUMERICRANGE:
return checkTerm(symterm, (ASTnumericRange) expr.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTIDENTIFIERRANGE:
return checkTerm(symterm, (ASTidentifierRange) expr.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTCONCATENATION:
return checkTerm(symterm, (ASTconcatenation) expr.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTFUNCTIONALSYMBOL:
return checkTerm(symterm, (ASTfunctionalSymbol) expr.jjtGetChild(0));
default:
return false;
}
}
private boolean checkTerm(ASTterm symterm, ASTfunctionalSymbol funcSymbol) {
ASTsortExpressionList elist = (ASTsortExpressionList) (funcSymbol
.jjtGetChild(0));
String initprefix = funcSymbol.image.substring(0, funcSymbol.image.indexOf('('));
ASTcondition cond = null;
if(funcSymbol.jjtGetNumChildren()>1) {
cond=(ASTcondition)funcSymbol.jjtGetChild(1);
}
return checkTerm(symterm,initprefix,elist,cond);
}
private boolean checkTerm(ASTterm symterm, ASTconcatenation conc) {
String termString = symterm.toString();
if (termString.indexOf(')') != -1)
return false;
int termLength = termString.length();
int basicSortLength = conc.jjtGetNumChildren();
int calculatedDp[][] = new int[termLength][basicSortLength];
for (int i = 0; i < termLength; i++) {
Arrays.fill(calculatedDp[i], -1);
}
return checkConcatenation(termString, conc, 0, 0, calculatedDp);
}
private boolean checkConcatenation(String term, ASTconcatenation conc,
int stringIndex, int basicSortIndex, int calculatedDp[][]) {
// length
int termLength = term.length();
int concLength = conc.jjtGetNumChildren();
int result = 0;
if (basicSortIndex == concLength && stringIndex == termLength) {
return true;
}
if (basicSortIndex == concLength || stringIndex == termLength) {
return false;
}
if (calculatedDp[stringIndex][basicSortIndex] != -1)
return calculatedDp[stringIndex][basicSortIndex] != 0;
for (int tryLength = 1; termLength - tryLength >= concLength-basicSortIndex-1 && stringIndex + tryLength<=termLength; tryLength++) {
if (checkTerm(new ASTterm(term.substring(stringIndex,
stringIndex + tryLength)),
(ASTbasicSort) conc.jjtGetChild(basicSortIndex))
&& checkConcatenation(term, conc, stringIndex + tryLength,
basicSortIndex + 1, calculatedDp)) {
result = 1;
break;
}
}
return (calculatedDp[stringIndex][basicSortIndex] = result) > 0;
}
private boolean checkTerm(ASTterm term, ASTbasicSort basicSort) {
int id = ((SimpleNode) basicSort.jjtGetChild(0)).getId();
switch (id) {
case SparcTranslatorTreeConstants.JJTNUMERICRANGE:
return checkTerm(term, (ASTnumericRange) basicSort.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTIDENTIFIERRANGE:
return checkTerm(term,
(ASTidentifierRange) basicSort.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTCONCATENATION:
return checkTerm(term, (ASTconcatenation) basicSort.jjtGetChild(0));
case SparcTranslatorTreeConstants.JJTSORTNAME:
return checkTerm(term,
sortNameToExpression.get(((ASTsortExpression) basicSort
.jjtGetChild(0)).image));
case SparcTranslatorTreeConstants.JJTCONSTANTTERMLIST:
return checkTerm(term,(ASTconstantTermList)basicSort
.jjtGetChild(0));
default:
return false;
}
}
private boolean checkTerm(ASTterm symterm, ASTidentifierRange range) {
String termString = symterm.toString();
if (termString.indexOf('(') != -1)
return false;
String[] rangeStrings = range.image.split(" ");
return termString.length() >= rangeStrings[0].length()
&& termString.length() <= rangeStrings[1].length()
&& termString.compareTo(rangeStrings[0]) >= 0
&& termString.compareTo(rangeStrings[1]) <= 0;
}
private boolean checkTerm(ASTterm symterm, ASTnumericRange range) {
String termString = symterm.toString();
if (termString.indexOf('(') != -1)
return false;
for (char c : termString.toCharArray()) {
if (Character.isLetter(c))
return false;
}
String[] rangeStrings = range.image.split(" ");
int value = Integer.parseInt(symterm.toString());
return value >= Integer.parseInt(rangeStrings[0])
&& value <= Integer.parseInt(rangeStrings[1]);
}
private boolean checkTerm(ASTterm symterm, ASTsetExpression setExpr) {
// TODO Auto-generated method stub
return checkTerm(symterm,
(ASTadditiveSetExpression) setExpr.jjtGetChild(0));
}
/**
* Check term for satisfying given sort expression
*
* @param term
* to be checked
* @param expr
* sort expression
* @return true if given term is not valuable(i.e, it has variables) or it
* evaluates to a value satisfying pattern described by additive
* sort expression and false otherwise
*/
private boolean checkTerm(ASTterm symterm, ASTadditiveSetExpression expr) {
boolean result = false;
for (int i = 0; i < expr.jjtGetNumChildren(); i++) {
boolean curBelong = (expr.image.charAt(i) == '+');
if (curBelong) {
if (checkTerm(symterm,
(ASTmultiplicativeSetExpression) expr.jjtGetChild(i))) {
result = true;
}
} else {
if (checkTerm(symterm,
(ASTmultiplicativeSetExpression) expr.jjtGetChild(i))) {
result = false;
}
}
}
return result;
}
/**
* Check term for satisfying given sort expression
*
* @param term
* to be checked
* @param expr
* sort expression
* @return true if given term is not valuable(i.e, it has variables) or it
* evaluates to a value satisfying pattern described by
* multiplicative sort expression and false otherwise
* @throws ParseException
* if comparison between incomparable elements occurs (e.g, 1>a)
*/
private boolean checkTerm(ASTterm term, ASTmultiplicativeSetExpression expr){
boolean result = true;
for (int i = 0; i < expr.jjtGetNumChildren(); i++) {
if (!checkTerm(term, (ASTunarySetExpression) expr.jjtGetChild(0))) {
result = false;
}
}
return result;
}
/**
* Check term for satisfying given unary sort expression
*
* @param term
* to be checked
* @param expr
* unary sort expression
* @return true if given term is not valuable(i.e, it has variables) or it
* evaluates to a value satisfying pattern described by unary sort
* expression and false otherwise
* @throws ParseException
* if comparison between incomparable elements occurs (e.g, 1>a)
*/
boolean checkTerm(ASTterm term, ASTunarySetExpression expr) {
SimpleNode child = (SimpleNode) expr.jjtGetChild(0);
switch (child.getId()) {
case SparcTranslatorTreeConstants.JJTSORTNAME:
return checkTerm(term,
(ASTsortExpression) sortNameToExpression.get(child.image));
case SparcTranslatorTreeConstants.JJTCURLYBRACKETS:
return checkTerm(term, (ASTcurlyBrackets) child);
case SparcTranslatorTreeConstants.JJTSETEXPRESSION:
return checkTerm(term, (ASTsetExpression) child);
case SparcTranslatorTreeConstants.JJTFUNCTIONALSYMBOL:
return checkTerm(term,(ASTfunctionalSymbol)child);
default:
return false;
}
}
private boolean checkTerm(ASTterm term, ASTcurlyBrackets curLyBrackets) {
ASTconstantTermList constList = (ASTconstantTermList) curLyBrackets
.jjtGetChild(0);
return checkTerm(term,constList);
}
private boolean checkTerm(ASTterm term, ASTconstantTermList constList) {
String termString = term.toString();
boolean result = false;
for (int i = 0; i < constList.jjtGetNumChildren(); i++) {
ASTconstantTerm curTerm = (ASTconstantTerm) constList
.jjtGetChild(i);
if (curTerm.toString().compareTo(termString) == 0) {
result = true;
break;
}
}
return result;
}
/**
* Check term for being a symbolic function with given name and arguments
* satisfying patterns specified by sort expression list
*
* @param term
* to be checked
* @param termName
* pattern name
* @param exprList
* sort expression list of patterns
* @return false if term is not symbolic or it has name different from
* termName or some of its arguments does not satisfy corresponding
* expression from the provided list
* @throws ParseException
* if order comparison between two unordered elements occurs
*/
boolean checkTerm(ASTterm term, String termName,
ASTsortExpressionList exprList,ASTcondition cond) {
if (((SimpleNode) term.jjtGetChild(0)).getId() != SparcTranslatorTreeConstants.JJTSYMBOLICTERM) {
return false;
} else {
return checkTerm((ASTsymbolicTerm) term.jjtGetChild(0), termName,
exprList,cond);
}
}
/**
* Check term for being a symbolic function with given name and arguments
* satisfying patterns specified by sort expression list
*
* @param term
* to be checked
* @param termName
* pattern name
* @param exprList
* sort expression list of patterns
* @return false it has name different from termName or some of its
* arguments does not satisfy corresponding expression from the
* provided list
* @throws ParseException
* if order comparison between two unordered elements occurs
*/
private boolean checkTerm(ASTsymbolicTerm term, String termName,
ASTsortExpressionList exprList,ASTcondition cond) {
if (term.jjtGetNumChildren() == 1) {
return false;
} else {
// TODO:
boolean result = checkSymbolicTermName(
(ASTsymbolicFunction) (term.jjtGetChild(0)), termName)
&& checkTermList((ASTtermList) term.jjtGetChild(1),
exprList)
&& checkCondition(cond,
(ASTtermList) term.jjtGetChild(1));
return result;
}
}
/**
* Check if condition is met for given term list Condition specifies
* relation between some two elements of term list
*
* @param conditionStr
* AST node representing the condition
* @param termList
* @return true if condition is met
* @throws ParseException
* if condition specify less or greater relation between
* different types of terms (arithmetic and symbolic)
*/
private boolean checkCondition(ASTcondition cond, ASTtermList termList) {
//create list of strings from term list:
if(cond!=null) {
ArrayList<String> terms=new ArrayList<String>();
for(int i=0;i<termList.jjtGetNumChildren();i++) {
ASTterm curTerm=(ASTterm)termList.jjtGetChild(i);
terms.add(curTerm.toString());
}
Condition condition=new Condition();
return condition.check(cond, terms);
}
else
return true;
}
/**
* Check each element of term list for satisfying pattern described by
* corresponding element of sort expression list
*
* @param termList
* term list
* @param exprList
* sort expression list (consisting of special sort expession, sortNames)
* @return true if each element of term list satisfies pattern described by
* corresponding element of
* @throws ParseException
*/
private boolean checkTermList(ASTtermList termList,
ASTsortExpressionList exprList) {
if (termList.jjtGetNumChildren() != exprList.jjtGetNumChildren()) {
return false;
} else {
boolean result = true;
for (int i = 0; i < termList.jjtGetNumChildren(); i++) {
if (!checkTerm((ASTterm) termList.jjtGetChild(i),
sortNameToExpression.get(((SimpleNode)exprList.jjtGetChild(i)).image))) {
result = false;
}
}
return result;
}
}
private boolean checkSymbolicTermName(ASTsymbolicFunction symbol,
String termName) {
return symbol.image.substring(0, symbol.image.length() - 1).equals(
termName);
}
/**
* Given an ast representing display section of a program, typecheck every atom occuring in it
* @param display - AST representing display section of the program
* @throws ParseException
*/
public void checkDisplay(ASTdisplay display) throws ParseException{
for(int i=0;i<display.jjtGetNumChildren(); i++) {
ASTnonRelAtom atom = (ASTnonRelAtom) display.jjtGetChild(i);
ASTpredSymbol ps = (ASTpredSymbol) atom.jjtGetChild(0);
if(atom.jjtGetNumChildren() ==1) {
// we only need to check that corresponding predicate or sort name exists
// we need to check that such a sort name was defined!
if(!predicateArgumentSorts.containsKey((ps.hasPoundSign()?"#":"") + ps.image)) {
throw new ParseException(inputFileName + ": "
+ "the " + (ps.hasPoundSign()?"sort ":"predicate ") + "\"" + ps.image
+ "\"," + (ignoreLineNumbers?"":"occurring at line " + +ps.getBeginLine() + ", column "
+ ps.getBeginColumn()) + " is not defined by the program");
}
} else {
checkNonRelAtom(atom);
}
}
}
}