-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.Just;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.let;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.newVar;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.seq;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tuple;\r
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.common.names.Names;\r
-import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
-import org.simantics.scl.compiler.elaboration.query.QExists;\r
-import org.simantics.scl.compiler.elaboration.query.Query;\r
-import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;\r
-import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationMode;\r
-import org.simantics.scl.compiler.elaboration.query.compilation.UnsolvableQueryException;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.parsing.parser.SCLTerminals;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class ESelect extends SimplifiableExpression {\r
-\r
- private final Type ARRAY_LIST = Types.con("ArrayList", "T"); \r
- \r
- int selectVariant;\r
- Expression expression;\r
- Query query;\r
- Variable[] variables;\r
- \r
- public ESelect(int selectVariant, Expression expression, Query query) {\r
- this.selectVariant = selectVariant;\r
- this.expression = expression;\r
- this.query = query;\r
- }\r
-\r
- @Override\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs,\r
- TIntHashSet refs) {\r
- expression.collectRefs(allRefs, refs);\r
- query.collectRefs(allRefs, refs);\r
- }\r
-\r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- expression.collectVars(allVars, vars);\r
- query.collectVars(allVars, vars);\r
- }\r
- \r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support collectEffects.");\r
- }\r
-\r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(selectVariant==SCLTerminals.SELECT_FIRST \r
- ? Types.apply(Types.MAYBE, expression.getType()) \r
- : Types.list(expression.getType()));\r
- }\r
- \r
- @Override\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- Type componentType;\r
- switch(selectVariant) {\r
- case SCLTerminals.SELECT:\r
- case SCLTerminals.SELECT_DISTINCT:\r
- try {\r
- componentType = Types.unifyApply(Types.LIST, requiredType);\r
- } catch (MatchException e) {\r
- context.getErrorLog().log(location, "Select expression produces a list of values.");\r
- return new EError(location);\r
- }\r
- break;\r
- case SCLTerminals.SELECT_FIRST:\r
- try {\r
- componentType = Types.unifyApply(Types.MAYBE, requiredType);\r
- } catch (MatchException e) {\r
- context.getErrorLog().log(location, "Select first expression produces an optional value.");\r
- return new EError(location);\r
- }\r
- break;\r
- default: throw new InternalCompilerError();\r
- }\r
- for(Variable variable : variables)\r
- variable.setType(Types.metaVar(Kinds.STAR));\r
- expression.checkType(context, componentType);\r
- query.checkType(context);\r
- \r
- // Compile query\r
- Type elType = expression.getType();\r
- Expression result;\r
- if(selectVariant == SCLTerminals.SELECT_FIRST) {\r
- QueryCompilationContext queryCompilationContext =\r
- new QueryCompilationContext(context, QueryCompilationMode.GET_FIRST,\r
- expression.getType(),\r
- Just(expression));\r
- try {\r
- new QExists(variables, query).generate(queryCompilationContext);\r
- } catch (UnsolvableQueryException e) {\r
- context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage());\r
- return new EError(getLocation());\r
- }\r
- result = queryCompilationContext.getContinuation();\r
- }\r
- else {\r
- Variable accumulator = newVar("accum", Types.apply(ARRAY_LIST, elType));\r
- result =\r
- apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_freeze, elType,\r
- var(accumulator));\r
- Expression innerExpression = \r
- apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_add, elType,\r
- var(accumulator), expression);\r
- try {\r
- QueryCompilationContext queryCompilationContext =\r
- new QueryCompilationContext(context, QueryCompilationMode.ITERATE, null, innerExpression);\r
- new QExists(variables, query).generate(queryCompilationContext);\r
- result = seq(queryCompilationContext.getContinuation(), result);\r
- } catch(UnsolvableQueryException e) {\r
- context.getErrorLog().log(getLocation(), "Failed to compile the query.\n" + e.getMessage());\r
- return new EError(getLocation());\r
- }\r
- result = let(accumulator,\r
- apply(context.getCompilationContext(), Types.PROC, Names.ArrayList_new, elType, tuple()),\r
- result\r
- );\r
- }\r
- return loc(location, result);\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- expression.collectFreeVariables(vars);\r
- query.collectFreeVariables(vars);\r
- for(Variable variable : variables)\r
- vars.remove(variable);\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- context.pushExistentialFrame();\r
- expression = expression.resolve(context);\r
- query = query.resolve(context);\r
- variables = context.popExistentialFrame();\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- return decorator.decorate(this);\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- expression.setLocationDeep(loc);\r
- query.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- @Override\r
- public void accept(ExpressionVisitor visitor) {\r
- visitor.visit(this);\r
- }\r
-\r
- @Override\r
- public void forVariables(VariableProcedure procedure) {\r
- expression.forVariables(procedure);\r
- query.forVariables(procedure);\r
- }\r
- \r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- throw new UnsupportedOperationException();\r
- }\r
- \r
- @Override\r
- public Expression accept(ExpressionTransformer transformer) {\r
- return transformer.transform(this);\r
- }\r
-\r
-}\r
+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<Object> allRefs,
+ TIntHashSet refs) {
+ expression.collectRefs(allRefs, refs);
+ query.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ expression.collectVars(allVars, vars);
+ query.collectVars(allVars, vars);
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> 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<Variable> 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);
+ }
+
+}