X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fexpressions%2FEWhen.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fexpressions%2FEWhen.java;h=e7907f3578e62599536bfd89687bebc78e55ab4c;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EWhen.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EWhen.java new file mode 100644 index 000000000..e7907f357 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EWhen.java @@ -0,0 +1,175 @@ +package org.simantics.scl.compiler.elaboration.expressions; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +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.internal.elaboration.utils.ExpressionDecorator; +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; + 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 + public void collectRefs(TObjectIntHashMap allRefs, + TIntHashSet refs) { + query.collectRefs(allRefs, refs); + action.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + query.collectVars(allVars, vars); + action.collectVars(allVars, vars); + } + + @Override + public void collectEffects(THashSet effects) { + throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support collectEffects."); + } + + @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.checkType(context, Types.UNIT); + + // 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 void collectFreeVariables(THashSet vars) { + action.collectFreeVariables(vars); + query.collectFreeVariables(vars); + for(Variable var : variables) + vars.remove(var); + } + + @Override + public Expression resolve(TranslationContext context) { + context.pushExistentialFrame(); + query = query.resolve(context); + action = action.resolve(context); + variables = context.popExistentialFrame(); + return this; + } + + @Override + public Expression decorate(ExpressionDecorator decorator) { + return decorator.decorate(this); + } + + @Override + public Expression replace(ReplaceContext context) { + Variable[] newVariables = new Variable[variables.length]; + for(int i=0;i