package org.simantics.scl.compiler.elaboration.rules; 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; import gnu.trove.map.hash.THashMap; import gnu.trove.procedure.TObjectObjectProcedure; import gnu.trove.procedure.TObjectProcedure; import gnu.trove.set.hash.THashSet; 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 sections; public final Variable[] variables; private Type effect; public TransformationRule(boolean isAbstract, Name name, TransformationRule[] extendsRules, THashMap 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() { @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 procedure) { if(extendsRules.length == 0) return sections.forEachEntry(procedure); else { THashSet visitedRules = new THashSet(); return forEachSection(procedure, visitedRules); } } private boolean forEachSection( TObjectObjectProcedure procedure, THashSet 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(); } }