package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.elaboration.query.QExists; import org.simantics.scl.compiler.elaboration.query.Query; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationMode; import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; import org.simantics.scl.compiler.types.exceptions.UnificationException; import org.simantics.scl.compiler.types.kinds.Kinds; public class EWhen extends SimplifiableExpression { public Query query; public Expression action; public Variable[] variables; public EWhen(Query query, Expression action) { this.query = query; this.action = action; } public EWhen(long location, Query query, Expression action, Variable[] variables) { if(variables == null) throw new NullPointerException(); if(location == Locations.NO_LOCATION) new Exception().printStackTrace(); this.location = location; this.query = query; this.action = action; this.variables = variables; } @Override protected void updateType() throws MatchException { setType(Types.UNIT); } @Override public Expression checkBasicType(TypingContext context, Type requiredType) { try { Types.unify(requiredType, Types.UNIT); } catch (UnificationException e) { context.typeError(location, requiredType, Types.UNIT); return this; } for(Variable variable : variables) variable.setType(Types.metaVar(Kinds.STAR)); query.checkType(context); action.checkIgnoredType(context); // Compile query return compile(context); } public Expression compile(TypingContext context) { try { QueryCompilationContext queryCompilationContext = new QueryCompilationContext(context, QueryCompilationMode.ITERATE, null, action); new QExists(variables, query).generate(queryCompilationContext); return queryCompilationContext.getContinuation(); } catch(UnsolvableQueryException e) { context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage()); return new EError(getLocation()); } } @Override public Expression resolve(TranslationContext context) { context.pushExistentialFrame(); query = query.resolve(context); action = action.resolve(context); variables = context.popExistentialFrame(); return this; } @Override public Expression replace(ReplaceContext context) { Variable[] newVariables = new Variable[variables.length]; for(int i=0;i