-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;\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.environment.Environment;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
-import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.ILambda;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\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.exceptions.UnificationException;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-import org.simantics.scl.compiler.types.util.MultiFunction;\r
-\r
-public class ESimpleLambda extends Expression {\r
- public Variable parameter;\r
- public Expression value;\r
- public Type effect = Types.NO_EFFECTS;\r
- \r
- public ESimpleLambda(Variable parameter, Expression value) {\r
- this.parameter = parameter;\r
- this.value = value;\r
- }\r
- \r
- public ESimpleLambda(Type effect, Variable parameter, Expression value) {\r
- this.parameter = parameter;\r
- this.value = value;\r
- this.effect = effect;\r
- }\r
-\r
- public ESimpleLambda(long loc, Variable parameter, Expression value) {\r
- super(loc);\r
- this.parameter = parameter;\r
- this.value = value;\r
- }\r
- \r
- public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {\r
- super(loc);\r
- this.parameter = parameter;\r
- this.value = value;\r
- this.effect = effect;\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- value.collectRefs(allRefs, refs);\r
- }\r
- \r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- value.collectVars(allVars, vars);\r
- }\r
-\r
- public Expression decomposeMatching() {\r
- value = value.decomposeMatching();\r
- return this;\r
- }\r
-\r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(Types.functionE(Types.canonical(parameter.type),\r
- effect, value.getType()));\r
- }\r
- \r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- return lambdaToVal(env, w);\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- value.collectFreeVariables(vars);\r
- vars.remove(parameter);\r
- }\r
-\r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- value = value.simplify(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- value = value.resolve(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- Variable newParameter = parameter.copy();\r
- context.varMap.put(parameter, new EVariable(newParameter));\r
- ESimpleLambda result = new ESimpleLambda(getLocation(),\r
- newParameter, \r
- effect.replace(context.tvarMap),\r
- value.replace(context));\r
- // not absolutely needed, but maybe good for performance\r
- context.varMap.remove(parameter); \r
- return result;\r
- }\r
- \r
- public Type getLocalEffect() {\r
- if(SCLCompilerConfiguration.DEBUG)\r
- if(effect == null)\r
- throw new InternalCompilerError();\r
- return effect;\r
- }\r
- \r
- public void setEffect(Type effect) {\r
- if(effect == null)\r
- throw new InternalCompilerError();\r
- this.effect = effect;\r
- }\r
- \r
- @Override\r
- public IExpression toIExpression(ExpressionInterpretationContext context) {\r
- // Find parameters of the whole function definition\r
- ArrayList<Variable> parameters = new ArrayList<Variable>(2);\r
- parameters.add(parameter);\r
- Expression cur = value;\r
- while(true) {\r
- if(cur instanceof ESimpleLambda) {\r
- ESimpleLambda lambda = (ESimpleLambda)cur;\r
- parameters.add(lambda.parameter);\r
- cur = lambda.value;\r
- }\r
- else if(cur instanceof ELambdaType) {\r
- cur = ((ELambdaType)cur).value;\r
- }\r
- else\r
- break;\r
- \r
- }\r
- \r
- // Free variables;\r
- ExpressionInterpretationContext innerContext = context.createNewContext();\r
- THashSet<Variable> freeVariables = cur.getFreeVariables();\r
- for(Variable parameter : parameters)\r
- freeVariables.remove(parameter);\r
- int i=0;\r
- int[] inheritedVariableIds = new int[freeVariables.size()];\r
- for(Variable var : freeVariables) {\r
- innerContext.push(var);\r
- inheritedVariableIds[i++] = context.getVariableId(var);\r
- }\r
- \r
- // Parameters\r
- for(Variable parameter : parameters)\r
- innerContext.push(parameter);\r
- \r
- // Construct lambda\r
- IExpression body = cur.toIExpression(innerContext); \r
- return new ILambda(inheritedVariableIds,\r
- parameters.size(),\r
- innerContext.getMaxVariableId(),\r
- body);\r
- }\r
- \r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- MultiFunction mfun;\r
- try {\r
- mfun = Types.unifyFunction(requiredType, 1);\r
- } catch (UnificationException e) {\r
- context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");\r
- setType(Types.metaVar(Kinds.STAR));\r
- return this;\r
- }\r
- \r
- effect = mfun.effect;\r
- context.pushEffectUpperBound(location, mfun.effect);\r
- parameter.setType(mfun.parameterTypes[0]);\r
- value = value.checkType(context, mfun.returnType);\r
- context.popEffectUpperBound();\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression inferType(TypingContext context) {\r
- effect = Types.metaVar(Kinds.EFFECT);\r
- context.pushEffectUpperBound(location, effect);\r
- if(parameter.type == null)\r
- parameter.setType(Types.metaVar(Kinds.STAR));\r
- value = value.checkType(context, Types.metaVar(Kinds.STAR));\r
- context.popEffectUpperBound();\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- if(decorator.decorateSubstructure(this))\r
- value = value.decorate(decorator);\r
- return decorator.decorate(this);\r
- }\r
-\r
- @Override\r
- public boolean isEffectful() {\r
- return false;\r
- }\r
- \r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- value.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- @Override\r
- public void accept(ExpressionVisitor visitor) {\r
- visitor.visit(this);\r
- }\r
- \r
- public Expression getValue() {\r
- return value;\r
- }\r
- \r
- public Variable getParameter() {\r
- return parameter;\r
- }\r
-\r
- @Override\r
- public void forVariables(VariableProcedure procedure) {\r
- value.forVariables(procedure);\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 java.util.ArrayList;
+import java.util.Set;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+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.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.ILambda;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
+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;
+import org.simantics.scl.compiler.types.util.MultiFunction;
+
+public class ESimpleLambda extends Expression {
+ public Variable parameter;
+ public Expression value;
+ public Type effect = Types.NO_EFFECTS;
+
+ public ESimpleLambda(Variable parameter, Expression value) {
+ this.parameter = parameter;
+ this.value = value;
+ }
+
+ public ESimpleLambda(Type effect, Variable parameter, Expression value) {
+ this.parameter = parameter;
+ this.value = value;
+ this.effect = effect;
+ }
+
+ public ESimpleLambda(long loc, Variable parameter, Expression value) {
+ super(loc);
+ this.parameter = parameter;
+ this.value = value;
+ }
+
+ public ESimpleLambda(long loc, Variable parameter, Type effect, Expression value) {
+ super(loc);
+ this.parameter = parameter;
+ this.value = value;
+ this.effect = effect;
+ }
+
+ public Expression decomposeMatching() {
+ value = value.decomposeMatching();
+ return this;
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(Types.functionE(Types.canonical(parameter.type),
+ effect, value.getType()));
+ }
+
+ @Override
+ public IVal toVal(CompilationContext context, CodeWriter w) {
+ return lambdaToVal(context, w);
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ value = value.simplify(context);
+ return this;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ value = value.resolve(context);
+ return this;
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ Variable newParameter = parameter.copy();
+ context.varMap.put(parameter, new EVariable(newParameter));
+ ESimpleLambda result = new ESimpleLambda(getLocation(),
+ newParameter,
+ effect.replace(context.tvarMap),
+ value.replace(context));
+ // not absolutely needed, but maybe good for performance
+ context.varMap.remove(parameter);
+ return result;
+ }
+
+ public Type getLocalEffect() {
+ if(SCLCompilerConfiguration.DEBUG)
+ if(effect == null)
+ throw new InternalCompilerError();
+ return effect;
+ }
+
+ public void setEffect(Type effect) {
+ if(effect == null)
+ throw new InternalCompilerError();
+ this.effect = effect;
+ }
+
+ @Override
+ public IExpression toIExpression(ExpressionInterpretationContext context) {
+ // Find parameters of the whole function definition
+ ArrayList<Variable> parameters = new ArrayList<Variable>(2);
+ parameters.add(parameter);
+ Expression cur = value;
+ while(true) {
+ if(cur instanceof ESimpleLambda) {
+ ESimpleLambda lambda = (ESimpleLambda)cur;
+ parameters.add(lambda.parameter);
+ cur = lambda.value;
+ }
+ else if(cur instanceof ELambdaType) {
+ cur = ((ELambdaType)cur).value;
+ }
+ else
+ break;
+
+ }
+
+ // Free variables;
+ ExpressionInterpretationContext innerContext = context.createNewContext();
+ Set<Variable> freeVariables = cur.getFreeVariables();
+ for(Variable parameter : parameters)
+ freeVariables.remove(parameter);
+ int i=0;
+ int[] inheritedVariableIds = new int[freeVariables.size()];
+ for(Variable var : freeVariables) {
+ innerContext.push(var);
+ inheritedVariableIds[i++] = context.getVariableId(var);
+ }
+
+ // Parameters
+ for(Variable parameter : parameters)
+ innerContext.push(parameter);
+
+ // Construct lambda
+ IExpression body = cur.toIExpression(innerContext);
+ return new ILambda(inheritedVariableIds,
+ parameters.size(),
+ innerContext.getMaxVariableId(),
+ body);
+ }
+
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ MultiFunction mfun;
+ try {
+ mfun = Types.unifyFunction(requiredType, 1);
+ } catch (UnificationException e) {
+ context.getErrorLog().log(location, "Required type is <" + requiredType + "> which is incompatible with lambda.");
+ setType(Types.metaVar(Kinds.STAR));
+ return this;
+ }
+
+ context.pushEffectUpperBound(location, mfun.effect);
+ parameter.setType(mfun.parameterTypes[0]);
+ value = value.checkType(context, mfun.returnType);
+ effect = context.popEffectUpperBound();
+ return this;
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ effect = Types.metaVar(Kinds.EFFECT);
+ context.pushEffectUpperBound(location, effect);
+ if(parameter.type == null)
+ parameter.setType(Types.metaVar(Kinds.STAR));
+ value = value.checkType(context, Types.metaVar(Kinds.STAR));
+ context.popEffectUpperBound();
+ return this;
+ }
+
+ @Override
+ public boolean isEffectful() {
+ return false;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ value.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public Expression getValue() {
+ return value;
+ }
+
+ public Variable getParameter() {
+ return parameter;
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return 1 + value.getSyntacticFunctionArity();
+ }
+
+}