X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fchr%2Fast%2FCHRAstAtom.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fchr%2Fast%2FCHRAstAtom.java;h=031d8edd84d2e733f99292f6ea7561759d2534a6;hp=0000000000000000000000000000000000000000;hb=d9a283acefae11c2cc094ed1c7b74759f8166f17;hpb=747231cca0974ca9ed5f78caa6517ee9dcb8e4fc diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstAtom.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstAtom.java new file mode 100644 index 000000000..031d8edd8 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/ast/CHRAstAtom.java @@ -0,0 +1,143 @@ +package org.simantics.scl.compiler.elaboration.chr.ast; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + +import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation; +import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.expressions.EApply; +import org.simantics.scl.compiler.elaboration.expressions.EBinary; +import org.simantics.scl.compiler.elaboration.expressions.EConstant; +import org.simantics.scl.compiler.elaboration.expressions.ERecord; +import org.simantics.scl.compiler.elaboration.expressions.EVar; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment; +import org.simantics.scl.compiler.environment.AmbiguousNameException; +import org.simantics.scl.compiler.environment.Environments; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.types.Types; + +public class CHRAstAtom extends CHRAstQuery { + public Expression expression; + public boolean remove; + + public CHRAstAtom(Expression expression, boolean remove) { + this.expression = expression; + this.remove = remove; + } + + @Override + public void accept(CHRAstQueryVisitor visitor) { + visitor.visit(this); + } + + public static CHRAstQuery atom(Expression expression) { + boolean remove = false; + if(expression instanceof EVar) { + EVar var = (EVar)expression; + if(var.name.equals("True")) { + CHRAstConjunction query = new CHRAstConjunction(Collections.emptyList()); + query.location = expression.location; + return query; + } + } + else if(expression instanceof EBinary) { + EBinary binary = (EBinary)expression; + if(binary.negation != null && binary.rights.isEmpty()) { + remove = true; + expression = binary.left; + } + // If query is marked for removal, it must be an atom + } + else if(expression instanceof EApply) { + EApply apply = (EApply)expression; + if(apply.function instanceof EVar && ((EVar)apply.function).name.equals("not")) { + Expression subExpression; + if(apply.parameters.length == 1) + subExpression = apply.parameters[0]; + else + subExpression = new EApply( + Locations.combine(apply.parameters[0].location, apply.parameters[apply.parameters.length-1].location), + apply.parameters[0], + Arrays.copyOfRange(apply.parameters, 1, apply.parameters.length)); + CHRAstNegation query = new CHRAstNegation(atom(subExpression)); + query.location = expression.location; + return query; + } + else if(apply.function instanceof EConstant) { + Name valueName = ((EConstant)apply.function).getValue().getName(); + if(valueName.module.equals(Types.BUILTIN) && valueName.name.startsWith("(")) { + CHRAstQuery[] conjuncts = new CHRAstQuery[apply.parameters.length]; + for(int i=0;i literals) { + literals.add( + isConstraint(context, expression) ? + convertConstraint(remove, expression) : + convertExpression(isHead, expression)); + } + + private static boolean isConstraint(TranslationContext context, Expression expression) { + if(expression instanceof EApply) + expression = ((EApply)expression).function; + else if(expression instanceof ERecord) + expression = ((ERecord)expression).constructor; + if(!(expression instanceof EVar)) + return false; + String name = ((EVar)expression).name; + if(TranslationContext.isConstructorName(name)) + return true; + try { + return Environments.getRelation(context.getEnvironment(), name) != null; + } catch (AmbiguousNameException e) { + return true; + } + } + + private static CHRLiteral convertExpression(boolean isHead, Expression expression) { + if(isHead) + return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false); + else + return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false); + } + + private static CHRLiteral convertConstraint(boolean remove, Expression expression) { + long location = expression.location; + Expression[] parameters; + FieldAssignment[] fields = null; + if(expression instanceof EApply) { + EApply apply = (EApply)expression; + parameters = apply.parameters; + expression = apply.function; + } + else if(expression instanceof ERecord) { + ERecord record = (ERecord)expression; + parameters = null; + fields = record.fields; + expression = record.constructor; + } + else // if(expression instanceof EVar) + parameters = Expression.EMPTY_ARRAY; + EVar var = (EVar)expression; // this should succeed because of isConstraint test + CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name), + parameters, remove, false); + literal.fields = fields; + return literal; + } +}