--- /dev/null
+package org.simantics.scl.compiler.elaboration.rules;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.query.Query;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+public class TransformationRule extends Symbol {
+ public static final TransformationRule[] EMPTY_ARRAY = new TransformationRule[0];
+
+ public final boolean isAbstract;
+ public final Name name;
+ public final TransformationRule[] extendsRules;
+ public final THashMap<SectionName, Query[]> sections;
+ public final Variable[] variables;
+ private Type effect;
+
+ public TransformationRule(boolean isAbstract,
+ Name name,
+ TransformationRule[] extendsRules,
+ THashMap<SectionName, Query[]> sections,
+ Variable[] variables) {
+ this.isAbstract = isAbstract;
+ this.name = name;
+ this.extendsRules = extendsRules;
+ this.sections = sections;
+ this.variables = variables;
+ }
+
+ public void checkType(final TypingContext context) {
+ for(Variable variable : variables)
+ if(variable.getType() == null)
+ variable.setType(Types.metaVar(Kinds.STAR));
+ sections.forEachValue(new TObjectProcedure<Query[]>() {
+
+ @Override
+ public boolean execute(Query[] queries) {
+ for(Query query : queries)
+ query.checkType(context);
+ return true;
+ }
+ });
+ /*System.out.println("-------------------------------");
+ System.out.println(this);
+ System.out.println("-------------------------------");*/
+ }
+
+ public void setEffect(Type effect) {
+ this.effect = effect;
+ }
+
+ public Type getEffect() {
+ return effect;
+ }
+
+ public boolean forEachSection(TObjectObjectProcedure<SectionName, Query[]> procedure) {
+ if(extendsRules.length == 0)
+ return sections.forEachEntry(procedure);
+ else {
+ THashSet<TransformationRule> visitedRules = new THashSet<TransformationRule>();
+ return forEachSection(procedure, visitedRules);
+ }
+ }
+
+ private boolean forEachSection(
+ TObjectObjectProcedure<SectionName, Query[]> procedure,
+ THashSet<TransformationRule> visitedRules) {
+ if(visitedRules.add(this)) {
+ for(TransformationRule rule : extendsRules)
+ if(!rule.forEachSection(procedure, visitedRules))
+ return false;
+ return sections.forEachEntry(procedure);
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ new ExpressionToStringVisitor(b).visit(this);
+ return b.toString();
+ }
+}