X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fexpressions%2FESelect.java;h=09079377f0a0a11afe61147fb0827865300c4ba1;hp=6c45daa87c21d44af38d49b3515b3a27c9056e3b;hb=6dfe20b0f514b91337fcac4de0267ffd8268be07;hpb=1b4d8b692f40d946deb5db8280eb4ca5b36a75a7 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESelect.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESelect.java index 6c45daa87..09079377f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESelect.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ESelect.java @@ -1,196 +1,163 @@ -package org.simantics.scl.compiler.elaboration.expressions; - -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.Just; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.let; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.newVar; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.seq; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tuple; -import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var; - -import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; -import org.simantics.scl.compiler.common.names.Names; -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.internal.parsing.parser.SCLTerminals; -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.kinds.Kinds; - -import gnu.trove.map.hash.TObjectIntHashMap; -import gnu.trove.set.hash.THashSet; -import gnu.trove.set.hash.TIntHashSet; - -public class ESelect extends SimplifiableExpression { - - private final Type ARRAY_LIST = Types.con("ArrayList", "T"); - - int selectVariant; - Expression expression; - Query query; - Variable[] variables; - - public ESelect(int selectVariant, Expression expression, Query query) { - this.selectVariant = selectVariant; - this.expression = expression; - this.query = query; - } - - @Override - public void collectRefs(TObjectIntHashMap allRefs, - TIntHashSet refs) { - expression.collectRefs(allRefs, refs); - query.collectRefs(allRefs, refs); - } - - @Override - public void collectVars(TObjectIntHashMap allVars, - TIntHashSet vars) { - expression.collectVars(allVars, vars); - query.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(selectVariant==SCLTerminals.SELECT_FIRST - ? Types.apply(Types.MAYBE, expression.getType()) - : Types.list(expression.getType())); - } - - @Override - public Expression checkBasicType(TypingContext context, Type requiredType) { - Type componentType; - switch(selectVariant) { - case SCLTerminals.SELECT: - case SCLTerminals.SELECT_DISTINCT: - try { - componentType = Types.unifyApply(Types.LIST, requiredType); - } catch (MatchException e) { - context.getErrorLog().log(location, "Select expression produces a list of values."); - return new EError(location); - } - break; - case SCLTerminals.SELECT_FIRST: - try { - componentType = Types.unifyApply(Types.MAYBE, requiredType); - } catch (MatchException e) { - context.getErrorLog().log(location, "Select first expression produces an optional value."); - return new EError(location); - } - break; - default: throw new InternalCompilerError(); - } - for(Variable variable : variables) - variable.setType(Types.metaVar(Kinds.STAR)); - expression.checkType(context, componentType); - query.checkType(context); - - // Compile query - Type elType = expression.getType(); - Expression result; - if(selectVariant == SCLTerminals.SELECT_FIRST) { - QueryCompilationContext queryCompilationContext = - new QueryCompilationContext(context, QueryCompilationMode.GET_FIRST, - expression.getType(), - Just(expression)); - try { - new QExists(variables, query).generate(queryCompilationContext); - } catch (UnsolvableQueryException e) { - context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage()); - return new EError(getLocation()); - } - result = queryCompilationContext.getContinuation(); - } - else { - Variable accumulator = newVar("accum", Types.apply(ARRAY_LIST, elType)); - result = - apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_freeze, elType, - var(accumulator)); - Expression innerExpression = - apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_add, elType, - var(accumulator), expression); - try { - QueryCompilationContext queryCompilationContext = - new QueryCompilationContext(context, QueryCompilationMode.ITERATE, null, innerExpression); - new QExists(variables, query).generate(queryCompilationContext); - result = seq(queryCompilationContext.getContinuation(), result); - } catch(UnsolvableQueryException e) { - context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage()); - return new EError(getLocation()); - } - result = let(accumulator, - apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_new, elType, tuple()), - result - ); - } - return loc(location, result); - } - - @Override - public void collectFreeVariables(THashSet vars) { - expression.collectFreeVariables(vars); - query.collectFreeVariables(vars); - for(Variable variable : variables) - vars.remove(variable); - } - - @Override - public Expression resolve(TranslationContext context) { - context.pushExistentialFrame(); - expression = expression.resolve(context); - query = query.resolve(context); - variables = context.popExistentialFrame(); - return this; - } - - @Override - public Expression decorate(ExpressionDecorator decorator) { - return decorator.decorate(this); - } - - @Override - public void setLocationDeep(long loc) { - if(location == Locations.NO_LOCATION) { - location = loc; - expression.setLocationDeep(loc); - query.setLocationDeep(loc); - } - } - - @Override - public void accept(ExpressionVisitor visitor) { - visitor.visit(this); - } - - @Override - public void forVariables(VariableProcedure procedure) { - expression.forVariables(procedure); - query.forVariables(procedure); - } - - @Override - public Expression simplify(SimplificationContext context) { - throw new UnsupportedOperationException(); - } - - @Override - public Expression accept(ExpressionTransformer transformer) { - return transformer.transform(this); - } - -} +package org.simantics.scl.compiler.elaboration.expressions; + +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.Just; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.let; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.newVar; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.seq; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tuple; +import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var; + +import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; +import org.simantics.scl.compiler.common.names.Names; +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.parsing.parser.SCLTerminals; +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.kinds.Kinds; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.TIntHashSet; + +public class ESelect extends SimplifiableExpression { + + private final Type ARRAY_LIST = Types.con("ArrayList", "T"); + + int selectVariant; + public Expression expression; + public Query query; + public Variable[] variables; + + public ESelect(int selectVariant, Expression expression, Query query) { + this.selectVariant = selectVariant; + this.expression = expression; + this.query = query; + } + + @Override + public void collectVars(TObjectIntHashMap allVars, + TIntHashSet vars) { + expression.collectVars(allVars, vars); + query.collectVars(allVars, vars); + } + + @Override + protected void updateType() throws MatchException { + setType(selectVariant==SCLTerminals.SELECT_FIRST + ? Types.apply(Types.MAYBE, expression.getType()) + : Types.list(expression.getType())); + } + + @Override + public Expression checkBasicType(TypingContext context, Type requiredType) { + Type componentType; + switch(selectVariant) { + case SCLTerminals.SELECT: + case SCLTerminals.SELECT_DISTINCT: + try { + componentType = Types.unifyApply(Types.LIST, requiredType); + } catch (MatchException e) { + context.getErrorLog().log(location, "Select expression produces a list of values."); + return new EError(location); + } + break; + case SCLTerminals.SELECT_FIRST: + try { + componentType = Types.unifyApply(Types.MAYBE, requiredType); + } catch (MatchException e) { + context.getErrorLog().log(location, "Select first expression produces an optional value."); + return new EError(location); + } + break; + default: throw new InternalCompilerError(); + } + for(Variable variable : variables) + variable.setType(Types.metaVar(Kinds.STAR)); + expression.checkType(context, componentType); + query.checkType(context); + + // Compile query + Type elType = expression.getType(); + Expression result; + if(selectVariant == SCLTerminals.SELECT_FIRST) { + QueryCompilationContext queryCompilationContext = + new QueryCompilationContext(context, QueryCompilationMode.GET_FIRST, + expression.getType(), + Just(expression)); + try { + new QExists(variables, query).generate(queryCompilationContext); + } catch (UnsolvableQueryException e) { + context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage()); + return new EError(getLocation()); + } + result = queryCompilationContext.getContinuation(); + } + else { + Variable accumulator = newVar("accum", Types.apply(ARRAY_LIST, elType)); + result = + apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_freeze, elType, + var(accumulator)); + Expression innerExpression = + apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_add, elType, + var(accumulator), expression); + try { + QueryCompilationContext queryCompilationContext = + new QueryCompilationContext(context, QueryCompilationMode.ITERATE, null, innerExpression); + new QExists(variables, query).generate(queryCompilationContext); + result = seq(queryCompilationContext.getContinuation(), result); + } catch(UnsolvableQueryException e) { + context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage()); + return new EError(getLocation()); + } + result = let(accumulator, + apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_new, elType, tuple()), + result + ); + } + return loc(location, result); + } + + @Override + public Expression resolve(TranslationContext context) { + context.pushExistentialFrame(); + expression = expression.resolve(context); + query = query.resolve(context); + variables = context.popExistentialFrame(); + return this; + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + location = loc; + expression.setLocationDeep(loc); + query.setLocationDeep(loc); + } + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public Expression simplify(SimplificationContext context) { + throw new UnsupportedOperationException(); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } + +}