package org.simantics.scl.compiler.elaboration.relations; import java.util.ArrayList; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.query.QExists; import org.simantics.scl.compiler.elaboration.query.Query; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException; import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.internal.parsing.Symbol; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; public class ConcreteRelation extends Symbol implements SCLRelation { public final String name; public Variable[] parameters; private int requiredVariablesMask = 0xffffffff; public static class QuerySection { public final int pattern; public final double selectivity; public final Variable[] existentials; public final Query query; public Type effect; public QuerySection(int pattern, double selectivity, Variable[] existentials, Query query) { this.pattern = pattern; this.selectivity = selectivity; this.existentials = existentials; this.query = query; } } private ArrayList sections = new ArrayList(4); public Query enforceSection; public Type writingEffect; Type[] parameterTypes; public TVar[] typeVariables = TVar.EMPTY_ARRAY; public int phase; public ConcreteRelation(String name) { this.name = name; } public void addSection(int pattern, double selectivity, Variable[] existentials, Query query) { sections.add(new QuerySection(pattern, selectivity, existentials, query)); requiredVariablesMask &= pattern; } public QuerySection getSection(int pattern) { for(QuerySection section : sections) if((section.pattern | pattern) == pattern) return section; return null; } public ArrayList getSections() { return sections; } @Override public TVar[] getTypeVariables() { return typeVariables; } @Override public Type[] getParameterTypes() { if(parameterTypes == null) { parameterTypes = new Type[parameters.length]; for(int i=0;i freeVariables = new ArrayList(parameters.length); for(int i=0;i>i)&1) == 0) freeVariables.add(parameters[i]); } for(Variable variable : section.existentials) { Variable newVariable = new Variable(variable.getName(), variable.getType()); replaceContext.varMap.put(variable, new EVariable(newVariable)); freeVariables.add(newVariable); } try { new QExists(freeVariables, section.query.replace(replaceContext)).generate(context); } catch (UnsolvableQueryException e) { throw new InternalCompilerError(e); } } @Override public Expression generateEnforce(long location, EnforcingContext context, Type[] typeParameters, Variable[] parameters) { if(this.typeVariables.length != typeParameters.length) throw new InternalCompilerError(location, "Invalid number of type parameters given."); if(this.parameters.length != parameters.length) throw new InternalCompilerError(location, "Invalid number of parameters given."); ReplaceContext replaceContext = new ReplaceContext(context.getTypingContext()); for(int i=0;i