-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.names.Name;\r
-import org.simantics.scl.compiler.constants.NoRepConstant;\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.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;\r
-import org.simantics.scl.compiler.elaboration.java.ListConstructor;\r
-import org.simantics.scl.compiler.elaboration.macros.MacroRule;\r
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;\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.IApply;\r
-import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.IListLiteral;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.types.Skeletons;\r
-import org.simantics.scl.compiler.types.TFun;\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
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class EApply extends Expression {\r
- public Expression function;\r
- public Expression[] parameters;\r
- Type effect = Types.NO_EFFECTS;\r
- \r
- public EApply(Expression function, Expression ... parameters) {\r
- this.function = function;\r
- this.parameters = parameters;\r
- }\r
- \r
- public EApply(Expression function, Expression parameter) {\r
- this(function, new Expression[] {parameter});\r
- }\r
-\r
- public EApply(long loc, Expression function, Expression ... parameters) {\r
- super(loc);\r
- this.function = function;\r
- this.parameters = parameters;\r
- }\r
- \r
- public EApply(long loc, Type effect, Expression function, Expression ... parameters) {\r
- super(loc);\r
- this.effect = effect;\r
- this.function = function;\r
- this.parameters = parameters;\r
- }\r
- \r
- public void set(Expression function, Expression[] parameters) {\r
- this.function = function;\r
- this.parameters = parameters;\r
- }\r
-\r
- public Expression getFunction() {\r
- return function;\r
- }\r
- \r
- public Expression[] getParameters() {\r
- return parameters;\r
- }\r
- \r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- function.collectRefs(allRefs, refs);\r
- for(Expression parameter : parameters)\r
- parameter.collectRefs(allRefs, refs);\r
- }\r
- \r
- public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
- function.collectVars(allVars, vars);\r
- for(Expression parameter : parameters)\r
- parameter.collectVars(allVars, vars);\r
- }\r
- \r
- @Override\r
- protected void updateType() throws MatchException {\r
- MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);\r
- /*for(int i=0;i<parameters.length;++i)\r
- if(!Types.equals(parameters[i].getType(), mfun.parameterTypes[i]))\r
- throw new MatchException();*/\r
- effect = mfun.effect;\r
- setType(mfun.returnType);\r
- }\r
-\r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- IVal functionVal = function.toVal(env, w);\r
- IVal[] parameterVals = new IVal[parameters.length];\r
- for(int i=0;i<parameters.length;++i)\r
- parameterVals[i] = parameters[i].toVal(env, w);\r
- Type type = getType();\r
- effect = Types.simplifyFinalEffect(effect);\r
- return w.applyWithEffect(location, effect, type, functionVal, parameterVals);\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- function.collectFreeVariables(vars);\r
- for(Expression parameter : parameters)\r
- parameter.collectFreeVariables(vars);\r
- }\r
- \r
- private void combineApplications() {\r
- if(function instanceof EApply) {\r
- EApply apply = (EApply)function;\r
- if(Types.canonical(apply.effect) == Types.NO_EFFECTS) {\r
- function = apply.function;\r
- parameters = Expression.concat(apply.parameters, parameters); \r
- } \r
- }\r
- }\r
-\r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- function = function.simplify(context);\r
- for(int i=0;i<parameters.length;++i)\r
- parameters[i] = parameters[i].simplify(context);\r
- combineApplications();\r
- \r
- // Try to apply macro rule\r
- if(function instanceof EConstant) {\r
- EConstant constant = (EConstant)function;\r
- MacroRule rule = constant.value.getMacroRule();\r
- if(rule != null) {\r
- Expression simplified = rule.apply(context, constant.typeParameters, this);\r
- if(simplified != null)\r
- // There may be more to simplify after macro application\r
- // However this may cause performance problems (O(n^2) algorithm in pathologic cases)\r
- return simplified.simplify(context);\r
- }\r
- }\r
- \r
- return this;\r
- }\r
- \r
- @Override\r
- public EVar getPatternHead() throws NotPatternException {\r
- return function.getPatternHead();\r
- }\r
-\r
- @Override\r
- public LhsType getLhsType() throws NotPatternException {\r
- LhsType lhsType = function.getLhsType();\r
- if(lhsType instanceof PatternMatchingLhs)\r
- for(Expression parameter : parameters)\r
- parameter.collectVariableNames((PatternMatchingLhs)lhsType);\r
- return lhsType;\r
- }\r
- \r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- function = function.resolve(context);\r
- for(int i=0;i<parameters.length;++i)\r
- parameters[i] = parameters[i].resolve(context);\r
- //combineApplications();\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression resolveAsPattern(TranslationContext context) {\r
- function = function.resolveAsPattern(context);\r
- for(int i=0;i<parameters.length;++i)\r
- parameters[i] = parameters[i].resolveAsPattern(context);\r
- combineApplications();\r
- if(!(function instanceof EConstant || function instanceof EError)) {\r
- context.getErrorLog().log(location, "Only constants can be applied in patterns.");\r
- return new EError();\r
- }\r
- return this;\r
- }\r
- \r
- @Override\r
- public void getParameters(TranslationContext context,\r
- ArrayList<Expression> parameters) {\r
- function.getParameters(context, parameters);\r
- for(Expression parameter : this.parameters)\r
- parameters.add(parameter);\r
- }\r
- \r
- @Override\r
- public void removeFreeVariables(THashSet<Variable> vars) {\r
- function.removeFreeVariables(vars);\r
- for(Expression parameter : parameters)\r
- parameter.removeFreeVariables(vars);\r
- }\r
-\r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- return new EApply(\r
- getLocation(), \r
- effect.replace(context.tvarMap),\r
- function.replace(context),\r
- replace(context, parameters));\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- function.setLocationDeep(loc);\r
- for(Expression parameter : parameters)\r
- parameter.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- @Override\r
- public int getFunctionDefinitionArity() throws NotPatternException {\r
- return function.getFunctionDefinitionArity() + parameters.length;\r
- }\r
- \r
- @Override\r
- public IExpression toIExpression(ExpressionInterpretationContext target) {\r
- IExpression[] parametersI = toIExpressions(target, parameters);\r
- \r
- Expression function = this.function;\r
- while(function instanceof EApplyType)\r
- function = ((EApplyType)function).expression;\r
- \r
- // Special cases\r
- if(function instanceof EConstant) {\r
- SCLValue functionValue = ((EConstant)function).value;\r
- Name name = functionValue.getName();\r
- if(name.module.equals("Builtin")) {\r
- IVal val = functionValue.getValue();\r
- if(val instanceof ListConstructor) {\r
- if(((ListConstructor)val).arity == parametersI.length)\r
- return new IListLiteral(parametersI);\r
- }\r
- }\r
- }\r
- //System.out.println("--> " + function + " " + function.getClass().getSimpleName());\r
- \r
- // The basic case\r
- return new IApply(function.toIExpression(target), parametersI);\r
- }\r
- \r
- private void inferType(TypingContext context, boolean ignoreResult) {\r
- function = function.inferType(context);\r
- function = context.instantiate(function);\r
- MultiFunction mfun;\r
- try {\r
- mfun = Types.unifyFunction(function.getType(), parameters.length);\r
- } catch (UnificationException e) {\r
- int arity = Types.getArity(function.getType());\r
- if(arity == 0)\r
- context.getErrorLog().log(location, "Application of non-function.");\r
- else\r
- context.getErrorLog().log(location, "Function of arity " + arity + \r
- " is applied with " + parameters.length + " parameters.");\r
- setType(Types.metaVar(Kinds.STAR));\r
- for(int i=0;i<parameters.length;++i)\r
- parameters[i] = parameters[i].inferType(context);\r
- return;\r
- }\r
- if((ignoreResult && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun &&\r
- Types.canonical(mfun.effect) == Types.NO_EFFECTS) ||\r
- (context.isInPattern() && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun)) {\r
- context.getErrorLog().log(location, "The function is applied with too few parameters.");\r
- }\r
- \r
- // Check parameter types\r
- for(int i=0;i<parameters.length;++i)\r
- parameters[i] = parameters[i].checkType(context, mfun.parameterTypes[i]);\r
-\r
- effect = mfun.effect;\r
- \r
- context.declareEffect(location, mfun.effect);\r
- setType(mfun.returnType);\r
- }\r
- \r
- @Override\r
- public Expression inferType(TypingContext context) {\r
- inferType(context, false);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkIgnoredType(TypingContext context) {\r
- inferType(context, true);\r
- if(Types.canonical(getType()) != Types.UNIT)\r
- return new ESimpleLet(location, null, this, new ELiteral(NoRepConstant.PUNIT));\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- if(decorator.decorateSubstructure(this)) {\r
- function = function.decorate(decorator);\r
- for(int i=0;i<parameters.length;++i)\r
- parameters[i] = parameters[i].decorate(decorator);\r
- }\r
- return decorator.decorate(this);\r
- }\r
- \r
- public Type getLocalEffect() {\r
- return effect;\r
- }\r
- \r
- public Expression toANormalForm(Expression root) {\r
- Expression expression = root;\r
- for(int i=parameters.length-1;i>=0;--i) {\r
- Expression parameter = parameters[i];\r
- if(parameter.isEffectful()) {\r
- Variable var = new Variable("aNormalTemp" + i, parameter.getType());\r
- expression = new ESimpleLet(var, parameter, expression);\r
- parameters[i] = new EVariable(var);\r
- }\r
- }\r
- if(function.isEffectful()) {\r
- Variable var = new Variable("aNormalTempF", function.getType());\r
- expression = new ESimpleLet(var, function, expression);\r
- function = new EVariable(var);\r
- }\r
- return expression;\r
- }\r
- \r
- @Override\r
- public boolean isEffectful() {\r
- if(effect != Types.NO_EFFECTS)\r
- return true; \r
- for(Expression parameter : parameters)\r
- if(parameter.isEffectful())\r
- return true;\r
- if(function.isEffectful())\r
- return true;\r
- return false;\r
- }\r
- \r
- @Override\r
- public boolean isFunctionPattern() {\r
- return !isConstructorApplication();\r
- }\r
- \r
- @Override\r
- public boolean isConstructorApplication() {\r
- return function.isConstructorApplication();\r
- }\r
-\r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- effects.add(effect);\r
- function.collectEffects(effects);\r
- for(Expression parameter : parameters)\r
- parameter.collectEffects(effects);\r
- }\r
-\r
- @Override\r
- public void accept(ExpressionVisitor visitor) {\r
- visitor.visit(this);\r
- }\r
- \r
- @Override\r
- public boolean isFunctionDefinitionLhs() {\r
- try {\r
- EVar patternHead = function.getPatternHead();\r
- return !Character.isUpperCase(patternHead.name.charAt(0));\r
- } catch(NotPatternException e) {\r
- return false;\r
- }\r
- }\r
-\r
- @Override\r
- public void forVariables(VariableProcedure procedure) {\r
- function.forVariables(procedure);\r
- for(Expression parameter : parameters)\r
- parameter.forVariables(procedure);\r
- }\r
- \r
- @Override\r
- public boolean isPattern(int arity) {\r
- if(!function.isPattern(arity+parameters.length))\r
- return false;\r
- for(Expression parameter : parameters)\r
- if(!parameter.isPattern(0))\r
- return false;\r
- return true;\r
- }\r
-\r
- @Override\r
- public Expression accept(ExpressionTransformer transformer) {\r
- return transformer.transform(this);\r
- }\r
- \r
- @Override\r
- public boolean equalsExpression(Expression expression) {\r
- if(expression.getClass() != getClass())\r
- return false;\r
- EApply other = (EApply)expression;\r
- if(parameters.length != other.parameters.length)\r
- return false;\r
- if(!function.equalsExpression(other.function))\r
- return false;\r
- for(int i=0;i<parameters.length;++i)\r
- if(!parameters[i].equalsExpression(other.parameters[i]))\r
- return false;\r
- return true;\r
- }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.constants.NoRepConstant;
+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.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;
+import org.simantics.scl.compiler.elaboration.java.ListConstructor;
+import org.simantics.scl.compiler.elaboration.macros.MacroRule;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+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.IApply;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.IListLiteral;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.Skeletons;
+import org.simantics.scl.compiler.types.TFun;
+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 EApply extends Expression {
+ public Expression function;
+ public Expression[] parameters;
+ public Type effect = Types.NO_EFFECTS;
+
+ public EApply(Expression function, Expression ... parameters) {
+ this.function = function;
+ this.parameters = parameters;
+ }
+
+ public EApply(Expression function, Expression parameter) {
+ this(function, new Expression[] {parameter});
+ }
+
+ public EApply(long loc, Expression function, Expression ... parameters) {
+ super(loc);
+ this.function = function;
+ this.parameters = parameters;
+ }
+
+ public EApply(long loc, Type effect, Expression function, Expression ... parameters) {
+ super(loc);
+ this.effect = effect;
+ this.function = function;
+ this.parameters = parameters;
+ }
+
+ public void set(Expression function, Expression[] parameters) {
+ this.function = function;
+ this.parameters = parameters;
+ }
+
+ public Expression getFunction() {
+ return function;
+ }
+
+ public Expression[] getParameters() {
+ return parameters;
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
+ /*for(int i=0;i<parameters.length;++i)
+ if(!Types.equals(parameters[i].getType(), mfun.parameterTypes[i]))
+ throw new MatchException();*/
+ effect = mfun.effect;
+ setType(mfun.returnType);
+ }
+
+ @Override
+ public IVal toVal(CompilationContext context, CodeWriter w) {
+ IVal functionVal = function.toVal(context, w);
+ IVal[] parameterVals = new IVal[parameters.length];
+ for(int i=0;i<parameters.length;++i)
+ parameterVals[i] = parameters[i].toVal(context, w);
+ Type type = getType();
+ effect = Types.simplifyFinalEffect(effect);
+ return w.applyWithEffect(location, effect, type, functionVal, parameterVals);
+ }
+
+ private void combineApplications() {
+ if(function instanceof EApply) {
+ EApply apply = (EApply)function;
+ if(Types.canonical(apply.effect) == Types.NO_EFFECTS) {
+ function = apply.function;
+ parameters = Expression.concat(apply.parameters, parameters);
+ }
+ }
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ function = function.simplify(context);
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].simplify(context);
+ combineApplications();
+
+ // Try to apply macro rule
+ if(function instanceof EConstant) {
+ EConstant constant = (EConstant)function;
+ MacroRule rule = constant.value.getMacroRule();
+ if(rule != null) {
+ Expression simplified = rule.apply(context, constant.typeParameters, this);
+ if(simplified != null)
+ // There may be more to simplify after macro application
+ // However this may cause performance problems (O(n^2) algorithm in pathologic cases)
+ return simplified.simplify(context);
+ }
+ }
+
+ return this;
+ }
+
+ @Override
+ public EVar getPatternHead() throws NotPatternException {
+ return function.getPatternHead();
+ }
+
+ @Override
+ public LhsType getLhsType() throws NotPatternException {
+ LhsType lhsType = function.getLhsType();
+ if(lhsType instanceof PatternMatchingLhs)
+ for(Expression parameter : parameters)
+ parameter.collectVariableNames((PatternMatchingLhs)lhsType);
+ return lhsType;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ function = function.resolve(context);
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].resolve(context);
+ //combineApplications();
+ return this;
+ }
+
+ @Override
+ public Expression resolveAsPattern(TranslationContext context) {
+ function = function.resolveAsPattern(context);
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].resolveAsPattern(context);
+ combineApplications();
+ if(!(function instanceof EConstant || function instanceof EError)) {
+ context.getErrorLog().log(location, "Only constants can be applied in patterns.");
+ return new EError();
+ }
+ return this;
+ }
+
+ @Override
+ public void getParameters(TranslationContext context,
+ ArrayList<Expression> parameters) {
+ function.getParameters(context, parameters);
+ for(Expression parameter : this.parameters)
+ parameters.add(parameter);
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ return new EApply(
+ getLocation(),
+ effect.replace(context.tvarMap),
+ function.replace(context),
+ replace(context, parameters));
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ function.setLocationDeep(loc);
+ for(Expression parameter : parameters)
+ parameter.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public int getFunctionDefinitionPatternArity() throws NotPatternException {
+ return function.getFunctionDefinitionPatternArity() + parameters.length;
+ }
+
+ @Override
+ public IExpression toIExpression(ExpressionInterpretationContext target) {
+ IExpression[] parametersI = toIExpressions(target, parameters);
+
+ Expression function = this.function;
+ while(function instanceof EApplyType)
+ function = ((EApplyType)function).expression;
+
+ // Special cases
+ if(function instanceof EConstant) {
+ SCLValue functionValue = ((EConstant)function).value;
+ Name name = functionValue.getName();
+ if(name.module.equals("Builtin")) {
+ IVal val = functionValue.getValue();
+ if(val instanceof ListConstructor) {
+ if(((ListConstructor)val).arity == parametersI.length)
+ return new IListLiteral(parametersI);
+ }
+ }
+ }
+ //System.out.println("--> " + function + " " + function.getClass().getSimpleName());
+
+ // The basic case
+ return new IApply(function.toIExpression(target), parametersI);
+ }
+
+ private void inferType(TypingContext context, boolean ignoreResult) {
+ function = function.inferType(context);
+ function = context.instantiate(function);
+ MultiFunction mfun;
+ try {
+ mfun = Types.unifyFunction(function.getType(), parameters.length);
+ } catch (UnificationException e) {
+ int arity = Types.getArity(function.getType());
+ if(arity == 0)
+ context.getErrorLog().log(location, "Application of non-function.");
+ else
+ context.getErrorLog().log(location, "Function of arity " + arity +
+ " is applied with " + parameters.length + " parameters.");
+ setType(Types.metaVar(Kinds.STAR));
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].inferType(context);
+ return;
+ }
+ if((ignoreResult && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun &&
+ Types.canonical(mfun.effect) == Types.NO_EFFECTS) ||
+ (context.isInPattern() && Skeletons.canonicalSkeleton(mfun.returnType) instanceof TFun)) {
+ context.getErrorLog().log(location, "The function is applied with too few parameters.");
+ }
+
+ // Check parameter types
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].checkType(context, mfun.parameterTypes[i]);
+
+ effect = mfun.effect;
+
+ context.declareEffect(location, mfun.effect);
+ setType(mfun.returnType);
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ if(parameters.length == 2 && function instanceof EConstant && ((EConstant)function).value.getName() == Names.Prelude_dollar)
+ return new EApply(location, parameters[0], parameters[1]).inferType(context);
+ inferType(context, false);
+ return this;
+ }
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ if(parameters.length == 2 && function instanceof EConstant && ((EConstant)function).value.getName() == Names.Prelude_dollar)
+ return new EApply(location, parameters[0], parameters[1]).checkIgnoredType(context);
+ inferType(context, true);
+ if(Types.canonical(getType()) != Types.UNIT)
+ return new ESimpleLet(location, null, this, new ELiteral(NoRepConstant.PUNIT));
+ return this;
+ }
+
+ public Type getLocalEffect() {
+ return effect;
+ }
+
+ public Expression toANormalForm(Expression root) {
+ Expression expression = root;
+ for(int i=parameters.length-1;i>=0;--i) {
+ Expression parameter = parameters[i];
+ if(parameter.isEffectful()) {
+ Variable var = new Variable("aNormalTemp" + i, parameter.getType());
+ expression = new ESimpleLet(var, parameter, expression);
+ parameters[i] = new EVariable(var);
+ }
+ }
+ if(function.isEffectful()) {
+ Variable var = new Variable("aNormalTempF", function.getType());
+ expression = new ESimpleLet(var, function, expression);
+ function = new EVariable(var);
+ }
+ return expression;
+ }
+
+ @Override
+ public boolean isEffectful() {
+ if(effect != Types.NO_EFFECTS)
+ return true;
+ for(Expression parameter : parameters)
+ if(parameter.isEffectful())
+ return true;
+ if(function.isEffectful())
+ return true;
+ return false;
+ }
+
+ @Override
+ public boolean isFunctionPattern() {
+ return !isConstructorApplication();
+ }
+
+ @Override
+ public boolean isConstructorApplication() {
+ return function.isConstructorApplication();
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public boolean isFunctionDefinitionLhs() {
+ try {
+ EVar patternHead = function.getPatternHead();
+ return !Character.isUpperCase(patternHead.name.charAt(0));
+ } catch(NotPatternException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isPattern(int arity) {
+ if(!function.isPattern(arity+parameters.length))
+ return false;
+ for(Expression parameter : parameters)
+ if(!parameter.isPattern(0))
+ return false;
+ return true;
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public boolean equalsExpression(Expression expression) {
+ if(expression.getClass() != getClass())
+ return false;
+ EApply other = (EApply)expression;
+ if(parameters.length != other.parameters.length)
+ return false;
+ if(!function.equalsExpression(other.function))
+ return false;
+ for(int i=0;i<parameters.length;++i)
+ if(!parameters[i].equalsExpression(other.parameters[i]))
+ return false;
+ return true;
+ }
+}