}
else if(annotation.id.text.equals("@inline")) {
try {
- int arity = defs.get(0).lhs.getFunctionDefinitionArity();
+ int arity = defs.get(0).lhs.getFunctionDefinitionPatternArity();
int phaseMask = 0xffffffff;
if(annotation.parameters.length > 0) {
phaseMask = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue());
Expression expression = value.getExpression();
+ int errorCountBeforeTypeChecking = compilationContext.errorLog.getErrorCount();
+ int functionArity = expression.getSyntacticFunctionArity();
+
try {
ArrayList<TVar> vars = new ArrayList<TVar>();
type = Types.removeForAll(type, vars);
overloaded.assertResolved(compilationContext.errorLog);
expression.getType().addPolarity(Polarity.POSITIVE);
context.solveSubsumptions(expression.getLocation());
+
+ if(compilationContext.errorLog.getErrorCount() != errorCountBeforeTypeChecking) {
+ int typeArity = Types.getArity(type);
+ if(typeArity != functionArity)
+ compilationContext.errorLog.log(value.definitionLocation, "Possible problem: type declaration has " + typeArity + " parameter types, but function definition has " + functionArity + " parameters.");
+ }
+
ArrayList<EVariable> demands = context.getConstraintDemand();
if(!demands.isEmpty() || !givenConstraints.isEmpty()) {
ReducedConstraints red =
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.errors.Locations;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.parsing.Symbol;\r
-import org.simantics.scl.compiler.types.Type;\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 Case extends Symbol {\r
- public Expression[] patterns;\r
- public Expression value;\r
- \r
- long lhs;\r
- \r
- public Case(Expression[] patterns, Expression value) {\r
- this.patterns = patterns;\r
- this.value = value;\r
- }\r
- \r
- public Case(Expression pattern, Expression value) {\r
- this(new Expression[] {pattern}, value);\r
- }\r
-\r
- public void setLhs(long lhs) {\r
- this.lhs = lhs;\r
- }\r
- \r
- public long getLhs() {\r
- return lhs;\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- value.collectRefs(allRefs, refs);\r
- }\r
-\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- value.collectVars(allVars, vars);\r
- }\r
-\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- value.collectFreeVariables(vars);\r
- for(int i=patterns.length-1;i>=0;--i)\r
- patterns[i].removeFreeVariables(vars);\r
- }\r
-\r
- public void resolve(TranslationContext context) {\r
- context.pushFrame();\r
- for(int i=0;i<patterns.length;++i)\r
- patterns[i] = patterns[i].resolveAsPattern(context);\r
- value = value.resolve(context);\r
- context.popFrame();\r
- }\r
-\r
- public void simplify(SimplificationContext context) {\r
- for(int i=0;i<patterns.length;++i)\r
- patterns[i] = patterns[i].simplify(context);\r
- value = value.simplify(context);\r
- }\r
-\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(Expression pattern : patterns)\r
- pattern.setLocationDeep(loc);\r
- value.setLocationDeep(loc);\r
- }\r
- }\r
-\r
- public Case replace(ReplaceContext context) {\r
- Expression[] newPatterns = new Expression[patterns.length]; \r
- for(int i=0;i<patterns.length;++i)\r
- newPatterns[i] = patterns[i].replaceInPattern(context);\r
- Expression newValue = value.replace(context);\r
- Case result = new Case(newPatterns, newValue);\r
- result.setLhs(lhs);\r
- return result;\r
- }\r
-\r
- public Expression[] getPatterns() {\r
- return patterns;\r
- }\r
-\r
- public void checkType(TypingContext context, Type[] parameterTypes,\r
- Type requiredType) {\r
- if(patterns.length != parameterTypes.length) {\r
- context.getErrorLog().log(location, "This case has different arity ("+patterns.length+\r
- ") than than the first case (+"+parameterTypes.length+"+).");\r
- return;\r
- }\r
- for(int i=0;i<patterns.length;++i)\r
- patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);\r
- value = value.checkType(context, requiredType);\r
- }\r
- \r
- public void checkIgnoredType(TypingContext context, Type[] parameterTypes) {\r
- if(patterns.length != parameterTypes.length) {\r
- context.getErrorLog().log(location, "This case has different arity ("+patterns.length+\r
- ") than than the first case (+"+parameterTypes.length+"+).");\r
- return;\r
- }\r
- for(int i=0;i<patterns.length;++i)\r
- patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);\r
- value = value.checkIgnoredType(context);\r
- }\r
- \r
- public void decorate(ExpressionDecorator decorator) {\r
- for(int i=0;i<patterns.length;++i)\r
- patterns[i] = patterns[i].decorate(decorator);\r
- value = value.decorate(decorator);\r
- }\r
-\r
- public void forVariables(VariableProcedure procedure) {\r
- value.forVariables(procedure);\r
- }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+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.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.types.Type;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class Case extends Symbol {
+ public Expression[] patterns;
+ public Expression value;
+
+ long lhs;
+
+ public Case(Expression[] patterns, Expression value) {
+ this.patterns = patterns;
+ this.value = value;
+ }
+
+ public Case(Expression pattern, Expression value) {
+ this(new Expression[] {pattern}, value);
+ }
+
+ public void setLhs(long lhs) {
+ this.lhs = lhs;
+ }
+
+ public long getLhs() {
+ return lhs;
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ value.collectRefs(allRefs, refs);
+ }
+
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ value.collectVars(allVars, vars);
+ }
+
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ value.collectFreeVariables(vars);
+ for(int i=patterns.length-1;i>=0;--i)
+ patterns[i].removeFreeVariables(vars);
+ }
+
+ public void resolve(TranslationContext context) {
+ context.pushFrame();
+ for(int i=0;i<patterns.length;++i)
+ patterns[i] = patterns[i].resolveAsPattern(context);
+ value = value.resolve(context);
+ context.popFrame();
+ }
+
+ public void simplify(SimplificationContext context) {
+ for(int i=0;i<patterns.length;++i)
+ patterns[i] = patterns[i].simplify(context);
+ value = value.simplify(context);
+ }
+
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(Expression pattern : patterns)
+ pattern.setLocationDeep(loc);
+ value.setLocationDeep(loc);
+ }
+ }
+
+ public Case replace(ReplaceContext context) {
+ Expression[] newPatterns = new Expression[patterns.length];
+ for(int i=0;i<patterns.length;++i)
+ newPatterns[i] = patterns[i].replaceInPattern(context);
+ Expression newValue = value.replace(context);
+ Case result = new Case(newPatterns, newValue);
+ result.setLhs(lhs);
+ return result;
+ }
+
+ public Expression[] getPatterns() {
+ return patterns;
+ }
+
+ public void checkType(TypingContext context, Type[] parameterTypes,
+ Type requiredType) {
+ if(patterns.length != parameterTypes.length) {
+ context.getErrorLog().log(location, "This case has different arity ("+patterns.length+
+ ") than than the first case (+"+parameterTypes.length+"+).");
+ return;
+ }
+ for(int i=0;i<patterns.length;++i)
+ patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);
+ value = value.checkType(context, requiredType);
+ }
+
+ public void checkIgnoredType(TypingContext context, Type[] parameterTypes) {
+ if(patterns.length != parameterTypes.length) {
+ context.getErrorLog().log(location, "This case has different arity ("+patterns.length+
+ ") than than the first case (+"+parameterTypes.length+"+).");
+ return;
+ }
+ for(int i=0;i<patterns.length;++i)
+ patterns[i] = patterns[i].checkTypeAsPattern(context, parameterTypes[i]);
+ value = value.checkIgnoredType(context);
+ }
+
+ public void decorate(ExpressionDecorator decorator) {
+ for(int i=0;i<patterns.length;++i)
+ patterns[i] = patterns[i].decorate(decorator);
+ value = value.decorate(decorator);
+ }
+
+ public void forVariables(VariableProcedure procedure) {
+ value.forVariables(procedure);
+ }
+}
}
@Override
- public int getFunctionDefinitionArity() throws NotPatternException {
- return expression.getFunctionDefinitionArity();
+ public int getFunctionDefinitionPatternArity() throws NotPatternException {
+ return expression.getFunctionDefinitionPatternArity();
}
@Override
expression = expression.checkIgnoredType(context);
return this;
}
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return expression.getSyntacticFunctionArity();
+ }
}
-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.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.environment.Environment;
+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.elaboration.utils.ExpressionDecorator;
+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;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EApply extends Expression {
+ public Expression function;
+ public Expression[] parameters;
+ 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;
+ }
+
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ function.collectRefs(allRefs, refs);
+ for(Expression parameter : parameters)
+ parameter.collectRefs(allRefs, refs);
+ }
+
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+ function.collectVars(allVars, vars);
+ for(Expression parameter : parameters)
+ parameter.collectVars(allVars, vars);
+ }
+
+ @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(Environment env, CodeWriter w) {
+ IVal functionVal = function.toVal(env, w);
+ IVal[] parameterVals = new IVal[parameters.length];
+ for(int i=0;i<parameters.length;++i)
+ parameterVals[i] = parameters[i].toVal(env, w);
+ Type type = getType();
+ effect = Types.simplifyFinalEffect(effect);
+ return w.applyWithEffect(location, effect, type, functionVal, parameterVals);
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ function.collectFreeVariables(vars);
+ for(Expression parameter : parameters)
+ parameter.collectFreeVariables(vars);
+ }
+
+ 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 void removeFreeVariables(THashSet<Variable> vars) {
+ function.removeFreeVariables(vars);
+ for(Expression parameter : parameters)
+ parameter.removeFreeVariables(vars);
+ }
+
+ @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) {
+ inferType(context, false);
+ return this;
+ }
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ inferType(context, true);
+ if(Types.canonical(getType()) != Types.UNIT)
+ return new ESimpleLet(location, null, this, new ELiteral(NoRepConstant.PUNIT));
+ return this;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ if(decorator.decorateSubstructure(this)) {
+ function = function.decorate(decorator);
+ for(int i=0;i<parameters.length;++i)
+ parameters[i] = parameters[i].decorate(decorator);
+ }
+ return decorator.decorate(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 collectEffects(THashSet<Type> effects) {
+ effects.add(effect);
+ function.collectEffects(effects);
+ for(Expression parameter : parameters)
+ parameter.collectEffects(effects);
+ }
+
+ @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 void forVariables(VariableProcedure procedure) {
+ function.forVariables(procedure);
+ for(Expression parameter : parameters)
+ parameter.forVariables(procedure);
+ }
+
+ @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;
+ }
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\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.common.precedence.Associativity;\r
-import org.simantics.scl.compiler.common.precedence.Precedence;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
-import org.simantics.scl.compiler.elaboration.modules.SCLValue;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-\r
-\r
-public class EBinary extends ASTExpression {\r
- public static final int NEGATION_LEVEL = 6;\r
- \r
- public Expression left;\r
- public ArrayList<EBinaryRightSide> rights = new ArrayList<EBinaryRightSide>();\r
- public EVar negation;\r
-\r
- public EBinary(Expression left, EVar negation) {\r
- this.left = left;\r
- this.negation = negation;\r
- }\r
-\r
- private EBinary(Expression left, EVar operator, Expression right) {\r
- this.left = left;\r
- rights.add(new EBinaryRightSide(operator, right));\r
- }\r
-\r
- public static EBinary create(Expression left, EVar operator, Expression right) {\r
- if(left instanceof EBinary) {\r
- EBinary left_ = (EBinary)left;\r
- left_.rights.add(new EBinaryRightSide(operator, right));\r
- return left_;\r
- }\r
- else\r
- return new EBinary(left, operator, right);\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- return parseOperators(context).resolve(context);\r
- }\r
- \r
- public Expression parseOperators(TranslationContext context) {\r
- ArrayList<Expression> output = new ArrayList<Expression>();\r
- ArrayList<Expression> ops = new ArrayList<Expression>();\r
- ArrayList<EVar> opAsts = new ArrayList<EVar>();\r
- \r
- EVar negation = this.negation;\r
- \r
- output.add(left);\r
- for(EBinaryRightSide right : rights) {\r
- // Read op\r
- Expression op = context.resolveExpression(right.operator.location, right.operator.name);\r
- if(op == null)\r
- return new EError(location);\r
- Precedence opPrec = op.getPrecedence();\r
- while(!ops.isEmpty()) {\r
- Expression oldOp = ops.get(ops.size()-1);\r
- Precedence oldOpPrecedence = oldOp.getPrecedence();\r
- \r
- if(oldOpPrecedence.level < opPrec.level)\r
- break;\r
- if(oldOpPrecedence.level == opPrec.level) {\r
- if(opPrec.associativity == Associativity.RIGHT)\r
- break;\r
- if(opPrec.associativity == Associativity.NONASSOC) {\r
- context.getErrorLog().log(right.operator.location, \r
- "Operator " + right.operator.name + " is not associative.");\r
- return new EError(location); \r
- }\r
- }\r
- \r
- // Pop op \r
- ops.remove(ops.size()-1);\r
- Expression r = output.remove(output.size()-1);\r
- Expression l = output.remove(output.size()-1);\r
- output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));\r
- }\r
- if(negation != null && ops.isEmpty()) {\r
- if(opPrec.level <= NEGATION_LEVEL) { \r
- SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
- if(neg == null) {\r
- context.getErrorLog().log(location, \r
- "Couldn't resolve variable neg.");\r
- return new EError(location);\r
- }\r
- output.set(0, unary(neg, negation, output.get(0)));\r
- negation = null;\r
- }\r
- }\r
- ops.add(op);\r
- opAsts.add(right.operator);\r
- \r
- // Read value\r
- output.add(right.right);\r
- }\r
- \r
- // Pop rest\r
- while(!ops.isEmpty()) { \r
- Expression oldOp = ops.remove(ops.size()-1);\r
- Expression r = output.remove(output.size()-1);\r
- Expression l = output.remove(output.size()-1);\r
- output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));\r
- }\r
- if(negation != null) {\r
- SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);\r
- if(neg == null) {\r
- context.getErrorLog().log(location, \r
- "Couldn't resolve variable neg.");\r
- return new EError(location);\r
- }\r
- output.set(0, unary(neg, negation, output.get(0)));\r
- }\r
- \r
- return output.get(0);\r
- \r
- //System.out.println("parseOperators: " + this);\r
- //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));\r
- }\r
-\r
- /*\r
- private Expression parse(TranslationContext context,\r
- Expression lhs, ListIterator<EBinaryRightSide> it, Precedence minPrec) {\r
- while(it.hasNext()) {\r
- EBinaryRightSide right = it.next();\r
- SCLValue op = context.resolveValue(right.operator.name);\r
- if(op == null) {\r
- context.getErrorLog().log(right.operator, \r
- "Couldn't resolve variable " + right.operator.name + ".");\r
- return lhs;\r
- }\r
- Precedence opPrec = op.getPrecedence();\r
- if(minPrec.level > opPrec.level)\r
- break;\r
- Expression rhs = right.right;\r
- while(it.hasNext()) {\r
- EVar var = it.next().operator;\r
- SCLValue nextOp = context.resolveValue(var.name);\r
- if(nextOp == null) {\r
- context.getErrorLog().log(var, \r
- "Couldn't resolve variable " + var.name + ".");\r
- return lhs;\r
- }\r
- it.previous();\r
- Precedence nextPrec = nextOp.getPrecedence();\r
- int precDiff = opPrec.level - nextPrec.level;\r
- if(precDiff == 0) {\r
- if(opPrec.associativity == Associativity.LEFT)\r
- break;\r
- else if(opPrec.associativity == Associativity.NONASSOC) {\r
- context.getErrorLog().log(it.next().operator, "Nonassociative operator.");\r
- return lhs;\r
- }\r
- }\r
- else if(precDiff > 0)\r
- break;\r
- rhs = parse(context, rhs, it, nextPrec);\r
- }\r
- lhs = binary(lhs, op, right.operator, rhs);\r
- } \r
- return lhs;\r
- }\r
- */\r
- private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) {\r
- return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs); \r
- }\r
- \r
- private Expression unary(SCLValue operator, EVar opAst, Expression expression) {\r
- EConstant op = new EConstant(opAst.location, operator);\r
- return new EApply(expression.location /*wrong*/, op, expression);\r
- }\r
- \r
- @Override\r
- public EVar getPatternHead() throws NotPatternException {\r
- if(rights.size() == 1)\r
- return rights.get(0).operator;\r
- else\r
- throw new NotPatternException(this);\r
- }\r
- \r
- @Override\r
- public LhsType getLhsType() throws NotPatternException {\r
- if(rights.size() == 1)\r
- return new FunctionDefinitionLhs(rights.get(0).operator.name);\r
- else\r
- throw new InternalCompilerError();\r
- }\r
- \r
- @Override\r
- public void getParameters(TranslationContext context,\r
- ArrayList<Expression> parameters) {\r
- parseOperators(context).getParameters(context, parameters);\r
- }\r
-\r
- public static Expression negate(EVar op, Expression expression) {\r
- if(expression instanceof EBinary) {\r
- ((EBinary)expression).negation = op;\r
- return expression;\r
- }\r
- /*else if(expression instanceof EIntegerLiteral) {\r
- EIntegerLiteral literal = (EIntegerLiteral)expression;\r
- literal.value = -literal.value;\r
- return expression;\r
- }*/\r
- else\r
- return new EBinary(expression, op);\r
- }\r
- \r
- @Override\r
- public int getFunctionDefinitionArity() throws NotPatternException {\r
- return 2;\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- left.setLocationDeep(loc);\r
- if(negation != null)\r
- negation.setLocationDeep(loc);\r
- for(EBinaryRightSide right : rights)\r
- right.setLocationDeep(loc);\r
- }\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 org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.common.precedence.Associativity;
+import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.errors.Locations;
+
+
+
+public class EBinary extends ASTExpression {
+ public static final int NEGATION_LEVEL = 6;
+
+ public Expression left;
+ public ArrayList<EBinaryRightSide> rights = new ArrayList<EBinaryRightSide>();
+ public EVar negation;
+
+ public EBinary(Expression left, EVar negation) {
+ this.left = left;
+ this.negation = negation;
+ }
+
+ private EBinary(Expression left, EVar operator, Expression right) {
+ this.left = left;
+ rights.add(new EBinaryRightSide(operator, right));
+ }
+
+ public static EBinary create(Expression left, EVar operator, Expression right) {
+ if(left instanceof EBinary) {
+ EBinary left_ = (EBinary)left;
+ left_.rights.add(new EBinaryRightSide(operator, right));
+ return left_;
+ }
+ else
+ return new EBinary(left, operator, right);
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ return parseOperators(context).resolve(context);
+ }
+
+ public Expression parseOperators(TranslationContext context) {
+ ArrayList<Expression> output = new ArrayList<Expression>();
+ ArrayList<Expression> ops = new ArrayList<Expression>();
+ ArrayList<EVar> opAsts = new ArrayList<EVar>();
+
+ EVar negation = this.negation;
+
+ output.add(left);
+ for(EBinaryRightSide right : rights) {
+ // Read op
+ Expression op = context.resolveExpression(right.operator.location, right.operator.name);
+ if(op == null)
+ return new EError(location);
+ Precedence opPrec = op.getPrecedence();
+ while(!ops.isEmpty()) {
+ Expression oldOp = ops.get(ops.size()-1);
+ Precedence oldOpPrecedence = oldOp.getPrecedence();
+
+ if(oldOpPrecedence.level < opPrec.level)
+ break;
+ if(oldOpPrecedence.level == opPrec.level) {
+ if(opPrec.associativity == Associativity.RIGHT)
+ break;
+ if(opPrec.associativity == Associativity.NONASSOC) {
+ context.getErrorLog().log(right.operator.location,
+ "Operator " + right.operator.name + " is not associative.");
+ return new EError(location);
+ }
+ }
+
+ // Pop op
+ ops.remove(ops.size()-1);
+ Expression r = output.remove(output.size()-1);
+ Expression l = output.remove(output.size()-1);
+ output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
+ }
+ if(negation != null && ops.isEmpty()) {
+ if(opPrec.level <= NEGATION_LEVEL) {
+ SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);
+ if(neg == null) {
+ context.getErrorLog().log(location,
+ "Couldn't resolve variable neg.");
+ return new EError(location);
+ }
+ output.set(0, unary(neg, negation, output.get(0)));
+ negation = null;
+ }
+ }
+ ops.add(op);
+ opAsts.add(right.operator);
+
+ // Read value
+ output.add(right.right);
+ }
+
+ // Pop rest
+ while(!ops.isEmpty()) {
+ Expression oldOp = ops.remove(ops.size()-1);
+ Expression r = output.remove(output.size()-1);
+ Expression l = output.remove(output.size()-1);
+ output.add(binary(l, oldOp, opAsts.remove(opAsts.size()-1), r));
+ }
+ if(negation != null) {
+ SCLValue neg = context.getEnvironment().getValue(Names.Prelude_neg);
+ if(neg == null) {
+ context.getErrorLog().log(location,
+ "Couldn't resolve variable neg.");
+ return new EError(location);
+ }
+ output.set(0, unary(neg, negation, output.get(0)));
+ }
+
+ return output.get(0);
+
+ //System.out.println("parseOperators: " + this);
+ //return parse(context, left, rights.listIterator(), new Precedence(-1, Associativity.NONASSOC));
+ }
+
+ /*
+ private Expression parse(TranslationContext context,
+ Expression lhs, ListIterator<EBinaryRightSide> it, Precedence minPrec) {
+ while(it.hasNext()) {
+ EBinaryRightSide right = it.next();
+ SCLValue op = context.resolveValue(right.operator.name);
+ if(op == null) {
+ context.getErrorLog().log(right.operator,
+ "Couldn't resolve variable " + right.operator.name + ".");
+ return lhs;
+ }
+ Precedence opPrec = op.getPrecedence();
+ if(minPrec.level > opPrec.level)
+ break;
+ Expression rhs = right.right;
+ while(it.hasNext()) {
+ EVar var = it.next().operator;
+ SCLValue nextOp = context.resolveValue(var.name);
+ if(nextOp == null) {
+ context.getErrorLog().log(var,
+ "Couldn't resolve variable " + var.name + ".");
+ return lhs;
+ }
+ it.previous();
+ Precedence nextPrec = nextOp.getPrecedence();
+ int precDiff = opPrec.level - nextPrec.level;
+ if(precDiff == 0) {
+ if(opPrec.associativity == Associativity.LEFT)
+ break;
+ else if(opPrec.associativity == Associativity.NONASSOC) {
+ context.getErrorLog().log(it.next().operator, "Nonassociative operator.");
+ return lhs;
+ }
+ }
+ else if(precDiff > 0)
+ break;
+ rhs = parse(context, rhs, it, nextPrec);
+ }
+ lhs = binary(lhs, op, right.operator, rhs);
+ }
+ return lhs;
+ }
+ */
+ private Expression binary(Expression lhs, Expression op, EVar opAst, Expression rhs) {
+ return new EApply(Locations.combine(lhs.location, rhs.location), op, lhs, rhs);
+ }
+
+ private Expression unary(SCLValue operator, EVar opAst, Expression expression) {
+ EConstant op = new EConstant(opAst.location, operator);
+ return new EApply(expression.location /*wrong*/, op, expression);
+ }
+
+ @Override
+ public EVar getPatternHead() throws NotPatternException {
+ if(rights.size() == 1)
+ return rights.get(0).operator;
+ else
+ throw new NotPatternException(this);
+ }
+
+ @Override
+ public LhsType getLhsType() throws NotPatternException {
+ if(rights.size() == 1)
+ return new FunctionDefinitionLhs(rights.get(0).operator.name);
+ else
+ throw new InternalCompilerError();
+ }
+
+ @Override
+ public void getParameters(TranslationContext context,
+ ArrayList<Expression> parameters) {
+ parseOperators(context).getParameters(context, parameters);
+ }
+
+ public static Expression negate(EVar op, Expression expression) {
+ if(expression instanceof EBinary) {
+ ((EBinary)expression).negation = op;
+ return expression;
+ }
+ /*else if(expression instanceof EIntegerLiteral) {
+ EIntegerLiteral literal = (EIntegerLiteral)expression;
+ literal.value = -literal.value;
+ return expression;
+ }*/
+ else
+ return new EBinary(expression, op);
+ }
+
+ @Override
+ public int getFunctionDefinitionPatternArity() throws NotPatternException {
+ return 2;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ left.setLocationDeep(loc);
+ if(negation != null)
+ negation.setLocationDeep(loc);
+ for(EBinaryRightSide right : rights)
+ right.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+}
return transformer.transform(this);
}
+ @Override
+ public int getSyntacticFunctionArity() {
+ if(monadic)
+ return 0;
+ Statement lastStatement = statements.getLast();
+ if(!(lastStatement instanceof GuardStatement))
+ return 0;
+ return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
+ }
}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.IConstant;\r
-import org.simantics.scl.compiler.internal.interpreted.IExpression;\r
-import org.simantics.scl.compiler.internal.interpreted.IIf;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\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.runtime.tuple.Tuple0;\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 EIf extends Expression {\r
- public Expression condition;\r
- public Expression then_;\r
- public Expression else_; // may be null\r
- \r
- public EIf(Expression condition, Expression then_, Expression else_) {\r
- this.condition = condition;\r
- this.then_ = then_;\r
- this.else_ = else_;\r
- }\r
-\r
- public EIf(long loc, Expression condition, Expression then_, Expression else_) {\r
- super(loc);\r
- this.condition = condition;\r
- this.then_ = then_;\r
- this.else_ = else_;\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- condition.collectRefs(allRefs, refs);\r
- then_.collectRefs(allRefs, refs);\r
- if(else_ != null)\r
- else_.collectRefs(allRefs, refs);\r
- }\r
-\r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- condition.collectVars(allVars, vars);\r
- then_.collectVars(allVars, vars);\r
- if(else_ != null)\r
- else_.collectVars(allVars, vars);\r
- }\r
-\r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(then_.getType());\r
- }\r
- \r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- IVal conditionVal = condition.toVal(env, w); \r
- CodeWriter joinPoint = w.createBlock(getType());\r
- CodeWriter thenBlock = w.createBlock();\r
- if(else_ != null) {\r
- CodeWriter elseBlock = w.createBlock(); \r
- w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());\r
- \r
- IVal elseVal = else_.toVal(env, elseBlock);\r
- elseBlock.jump(joinPoint.getContinuation(), elseVal);\r
- }\r
- else {\r
- w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());\r
- }\r
- IVal thenVal = then_.toVal(env, thenBlock);\r
- thenBlock.jump(joinPoint.getContinuation(), thenVal);\r
- w.continueAs(joinPoint);\r
- \r
- return w.getParameters()[0];\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- condition.collectFreeVariables(vars);\r
- then_.collectFreeVariables(vars);\r
- if(else_ != null)\r
- else_.collectFreeVariables(vars);\r
- }\r
-\r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- condition = condition.simplify(context);\r
- then_ = then_.simplify(context);\r
- if(else_ != null)\r
- else_ = else_.simplify(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- condition = condition.resolve(context);\r
- then_ = then_.resolve(context);\r
- if(else_ != null)\r
- else_ = else_.resolve(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- return new EIf(condition.replace(context), \r
- then_.replace(context), \r
- else_ == null ? null : else_.replace(context));\r
- }\r
- \r
- @Override\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- condition = condition.checkType(context, Types.BOOLEAN);\r
- then_ = then_.checkType(context, requiredType);\r
- if(else_ != null)\r
- else_ = else_.checkType(context, requiredType);\r
- else\r
- context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkIgnoredType(TypingContext context) {\r
- condition = condition.checkType(context, Types.BOOLEAN);\r
- then_ = then_.checkIgnoredType(context);\r
- if(else_ != null)\r
- else_ = else_.checkIgnoredType(context);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- condition = condition.decorate(decorator);\r
- then_ = then_.decorate(decorator);\r
- if(else_ != null)\r
- else_ = else_.decorate(decorator); \r
- return decorator.decorate(this);\r
- }\r
- \r
- @Override\r
- public boolean isEffectful() {\r
- return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());\r
- }\r
-\r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- condition.collectEffects(effects);\r
- then_.collectEffects(effects);\r
- if(else_ != null)\r
- else_.collectEffects(effects);\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- condition.setLocationDeep(loc);\r
- then_.setLocationDeep(loc);\r
- if(else_ != null)\r
- else_.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- @Override\r
- public void accept(ExpressionVisitor visitor) {\r
- visitor.visit(this);\r
- }\r
- \r
- @Override\r
- public IExpression toIExpression(ExpressionInterpretationContext target) {\r
- return new IIf(condition.toIExpression(target), then_.toIExpression(target), \r
- else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));\r
- }\r
-\r
- @Override\r
- public void forVariables(VariableProcedure procedure) {\r
- condition.forVariables(procedure);\r
- then_.forVariables(procedure);\r
- if(else_ != null)\r
- else_.forVariables(procedure);\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 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.environment.Environment;
+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.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IConstant;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.IIf;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+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.runtime.tuple.Tuple0;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EIf extends Expression {
+ public Expression condition;
+ public Expression then_;
+ public Expression else_; // may be null
+
+ public EIf(Expression condition, Expression then_, Expression else_) {
+ this.condition = condition;
+ this.then_ = then_;
+ this.else_ = else_;
+ }
+
+ public EIf(long loc, Expression condition, Expression then_, Expression else_) {
+ super(loc);
+ this.condition = condition;
+ this.then_ = then_;
+ this.else_ = else_;
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ condition.collectRefs(allRefs, refs);
+ then_.collectRefs(allRefs, refs);
+ if(else_ != null)
+ else_.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ condition.collectVars(allVars, vars);
+ then_.collectVars(allVars, vars);
+ if(else_ != null)
+ else_.collectVars(allVars, vars);
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(then_.getType());
+ }
+
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ IVal conditionVal = condition.toVal(env, w);
+ CodeWriter joinPoint = w.createBlock(getType());
+ CodeWriter thenBlock = w.createBlock();
+ if(else_ != null) {
+ CodeWriter elseBlock = w.createBlock();
+ w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
+
+ IVal elseVal = else_.toVal(env, elseBlock);
+ elseBlock.jump(joinPoint.getContinuation(), elseVal);
+ }
+ else {
+ w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
+ }
+ IVal thenVal = then_.toVal(env, thenBlock);
+ thenBlock.jump(joinPoint.getContinuation(), thenVal);
+ w.continueAs(joinPoint);
+
+ return w.getParameters()[0];
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ condition.collectFreeVariables(vars);
+ then_.collectFreeVariables(vars);
+ if(else_ != null)
+ else_.collectFreeVariables(vars);
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ condition = condition.simplify(context);
+ then_ = then_.simplify(context);
+ if(else_ != null)
+ else_ = else_.simplify(context);
+ return this;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ condition = condition.resolve(context);
+ then_ = then_.resolve(context);
+ if(else_ != null)
+ else_ = else_.resolve(context);
+ return this;
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ return new EIf(condition.replace(context),
+ then_.replace(context),
+ else_ == null ? null : else_.replace(context));
+ }
+
+ @Override
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ condition = condition.checkType(context, Types.BOOLEAN);
+ then_ = then_.checkType(context, requiredType);
+ if(else_ != null)
+ else_ = else_.checkType(context, requiredType);
+ else
+ context.getErrorLog().log(location, "Else branch is required because the return value of the if expression is used.");
+ return this;
+ }
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ condition = condition.checkType(context, Types.BOOLEAN);
+ then_ = then_.checkIgnoredType(context);
+ if(else_ != null)
+ else_ = else_.checkIgnoredType(context);
+ return this;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ condition = condition.decorate(decorator);
+ then_ = then_.decorate(decorator);
+ if(else_ != null)
+ else_ = else_.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public boolean isEffectful() {
+ return condition.isEffectful() || then_.isEffectful() || (else_ != null && else_.isEffectful());
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ condition.collectEffects(effects);
+ then_.collectEffects(effects);
+ if(else_ != null)
+ else_.collectEffects(effects);
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ condition.setLocationDeep(loc);
+ then_.setLocationDeep(loc);
+ if(else_ != null)
+ else_.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public IExpression toIExpression(ExpressionInterpretationContext target) {
+ return new IIf(condition.toIExpression(target), then_.toIExpression(target),
+ else_ != null ? else_.toIExpression(target) : new IConstant(Tuple0.INSTANCE));
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ condition.forVariables(procedure);
+ then_.forVariables(procedure);
+ if(else_ != null)
+ else_.forVariables(procedure);
+ }
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return Math.max(then_.getSyntacticFunctionArity(), else_.getSyntacticFunctionArity());
+ }
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.errors.Locations;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\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 ELambda extends SimplifiableExpression {\r
- public Case[] cases;\r
- Type effect = Types.NO_EFFECTS;\r
- \r
- public ELambda(Case[] cases) {\r
- this.cases = cases;\r
- }\r
- \r
- public ELambda(Case case_) {\r
- this(new Case[] {case_});\r
- }\r
-\r
- public ELambda(long loc, Case ... cases) {\r
- super(loc);\r
- this.cases = cases;\r
- }\r
- \r
- public ELambda(long loc, Expression pat, Expression exp) {\r
- this(loc, new Case(new Expression[] {pat}, exp));\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- for(Case case_ : cases)\r
- case_.collectRefs(allRefs, refs);\r
- }\r
- \r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- for(Case case_ : cases)\r
- case_.collectVars(allVars, vars);\r
- }\r
-\r
- public Expression decomposeMatching() {\r
- Expression[] patterns = cases[0].patterns;\r
- int arity = patterns.length;\r
- \r
- // Simple cases\r
- if(cases.length == 1 && \r
- !(cases[0].value instanceof GuardedExpressionGroup)) {\r
- boolean noMatchingNeeded = true;\r
- for(int i=0;i<arity;++i)\r
- if(!(patterns[i] instanceof EVariable)) {\r
- noMatchingNeeded = false;\r
- break;\r
- }\r
- if(noMatchingNeeded) {\r
- Expression decomposed = cases[0].value.decomposeMatching();\r
- Type effect = this.effect;\r
- for(int i=arity-1;i>=0;--i) {\r
- Variable var = ((EVariable)patterns[i]).getVariable(); \r
- decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);\r
- effect = Types.NO_EFFECTS;\r
- }\r
- return decomposed;\r
- }\r
- }\r
- \r
- // Complex case\r
- Variable[] vars = new Variable[arity];\r
- Expression[] scrutinee = new Expression[arity];\r
- for(int i=0;i<arity;++i) {\r
- vars[i] = new Variable("temp" + i);\r
- Type type = patterns[i].getType();\r
- vars[i].setType(type);\r
- scrutinee[i] = new EVariable(getLocation(), vars[i]);\r
- scrutinee[i].setType(type);\r
- }\r
- Expression decomposed = new EMatch(getLocation(), scrutinee, cases);\r
- Type curEffect = this.effect;\r
- for(int i=arity-1;i>=0;--i) { \r
- decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed); \r
- curEffect = Types.NO_EFFECTS; \r
- }\r
- return decomposed;\r
- }\r
- \r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));\r
- }\r
- \r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- return decomposeMatching().simplify(context);\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- for(Case case_ : cases)\r
- case_.collectFreeVariables(vars);\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- for(Case case_ : cases)\r
- case_.resolve(context);\r
- return this;\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(Case case_ : cases)\r
- case_.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- Case[] newCases = new Case[cases.length];\r
- for(int i=0;i<cases.length;++i)\r
- newCases[i] = cases[i].replace(context);\r
- return new ELambda(newCases);\r
- }\r
-\r
- public Case[] getCases() {\r
- return cases;\r
- }\r
- \r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- int arity = cases[0].patterns.length;\r
- MultiFunction mfun;\r
- try {\r
- mfun = Types.unifyFunction(requiredType, arity);\r
- } catch (UnificationException e) {\r
- int requiredArity = Types.getArity(requiredType);\r
- context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "\r
- + arity + " patterns have been given.");\r
- setType(Types.metaVar(Kinds.STAR));\r
- return this;\r
- }\r
- \r
- effect = mfun.effect;\r
- context.pushEffectUpperBound(location, mfun.effect);\r
- for(Case case_ : cases)\r
- case_.checkType(context, mfun.parameterTypes, mfun.returnType);\r
- context.popEffectUpperBound();\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression inferType(TypingContext context) {\r
- int arity = cases[0].patterns.length;\r
- effect = Types.metaVar(Kinds.EFFECT);\r
- context.pushEffectUpperBound(location, effect);\r
- Type[] parameterTypes = new Type[arity]; \r
- for(int i=0;i<parameterTypes.length;++i)\r
- parameterTypes[i] = Types.metaVar(Kinds.STAR);\r
- Type requiredType = Types.metaVar(Kinds.STAR);\r
- for(Case case_ : cases)\r
- case_.checkType(context, parameterTypes, requiredType);\r
- context.popEffectUpperBound();\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- if(decorator.decorateSubstructure(this))\r
- for(Case case_ : cases)\r
- case_.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
- for(Case case_ : cases) {\r
- for(Expression pattern : case_.patterns)\r
- pattern.collectEffects(effects);\r
- case_.value.collectEffects(effects);\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
- for(Case case_ : cases)\r
- case_.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 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.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;
+import org.simantics.scl.compiler.types.util.MultiFunction;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ELambda extends SimplifiableExpression {
+ public Case[] cases;
+ Type effect = Types.NO_EFFECTS;
+
+ public ELambda(Case[] cases) {
+ this.cases = cases;
+ }
+
+ public ELambda(Case case_) {
+ this(new Case[] {case_});
+ }
+
+ public ELambda(long loc, Case ... cases) {
+ super(loc);
+ this.cases = cases;
+ }
+
+ public ELambda(long loc, Expression pat, Expression exp) {
+ this(loc, new Case(new Expression[] {pat}, exp));
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ for(Case case_ : cases)
+ case_.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ for(Case case_ : cases)
+ case_.collectVars(allVars, vars);
+ }
+
+ public Expression decomposeMatching() {
+ Expression[] patterns = cases[0].patterns;
+ int arity = patterns.length;
+
+ // Simple cases
+ if(cases.length == 1 &&
+ !(cases[0].value instanceof GuardedExpressionGroup)) {
+ boolean noMatchingNeeded = true;
+ for(int i=0;i<arity;++i)
+ if(!(patterns[i] instanceof EVariable)) {
+ noMatchingNeeded = false;
+ break;
+ }
+ if(noMatchingNeeded) {
+ Expression decomposed = cases[0].value.decomposeMatching();
+ Type effect = this.effect;
+ for(int i=arity-1;i>=0;--i) {
+ Variable var = ((EVariable)patterns[i]).getVariable();
+ decomposed = new ESimpleLambda(getLocation(), var, effect, decomposed);
+ effect = Types.NO_EFFECTS;
+ }
+ return decomposed;
+ }
+ }
+
+ // Complex case
+ Variable[] vars = new Variable[arity];
+ Expression[] scrutinee = new Expression[arity];
+ for(int i=0;i<arity;++i) {
+ vars[i] = new Variable("temp" + i);
+ Type type = patterns[i].getType();
+ vars[i].setType(type);
+ scrutinee[i] = new EVariable(getLocation(), vars[i]);
+ scrutinee[i].setType(type);
+ }
+ Expression decomposed = new EMatch(getLocation(), scrutinee, cases);
+ Type curEffect = this.effect;
+ for(int i=arity-1;i>=0;--i) {
+ decomposed = new ESimpleLambda(getLocation(), vars[i], curEffect, decomposed);
+ curEffect = Types.NO_EFFECTS;
+ }
+ return decomposed;
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(Types.functionE(Types.getTypes(cases[0].patterns), effect, cases[0].value.getType()));
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ return decomposeMatching().simplify(context);
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ for(Case case_ : cases)
+ case_.collectFreeVariables(vars);
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ for(Case case_ : cases)
+ case_.resolve(context);
+ return this;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(Case case_ : cases)
+ case_.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ Case[] newCases = new Case[cases.length];
+ for(int i=0;i<cases.length;++i)
+ newCases[i] = cases[i].replace(context);
+ return new ELambda(newCases);
+ }
+
+ public Case[] getCases() {
+ return cases;
+ }
+
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ int arity = cases[0].patterns.length;
+ MultiFunction mfun;
+ try {
+ mfun = Types.unifyFunction(requiredType, arity);
+ } catch (UnificationException e) {
+ int requiredArity = Types.getArity(requiredType);
+ context.getErrorLog().log(cases[0].getLhs(), "Arity is " + requiredArity + " but "
+ + arity + " patterns have been given.");
+ setType(Types.metaVar(Kinds.STAR));
+ return this;
+ }
+
+ effect = mfun.effect;
+ context.pushEffectUpperBound(location, mfun.effect);
+ for(Case case_ : cases)
+ case_.checkType(context, mfun.parameterTypes, mfun.returnType);
+ context.popEffectUpperBound();
+ return this;
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ int arity = cases[0].patterns.length;
+ effect = Types.metaVar(Kinds.EFFECT);
+ context.pushEffectUpperBound(location, effect);
+ Type[] parameterTypes = new Type[arity];
+ for(int i=0;i<parameterTypes.length;++i)
+ parameterTypes[i] = Types.metaVar(Kinds.STAR);
+ Type requiredType = Types.metaVar(Kinds.STAR);
+ for(Case case_ : cases)
+ case_.checkType(context, parameterTypes, requiredType);
+ context.popEffectUpperBound();
+ return this;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ if(decorator.decorateSubstructure(this))
+ for(Case case_ : cases)
+ case_.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public boolean isEffectful() {
+ return false;
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ for(Case case_ : cases) {
+ for(Expression pattern : case_.patterns)
+ pattern.collectEffects(effects);
+ case_.value.collectEffects(effects);
+ }
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ for(Case case_ : cases)
+ case_.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ int result = 0;
+ for(Case case_ : cases)
+ result = Math.max(result, case_.patterns.length + case_.value.getSyntacticFunctionArity());
+ return result;
+ }
+
+}
-package org.simantics.scl.compiler.elaboration.expressions;\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.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.types.TVar;\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
-\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 ELambdaType extends Expression {\r
- public TVar[] parameters;\r
- public Expression value;\r
- \r
- public ELambdaType(TVar[] parameters, Expression value) {\r
- super(value.getLocation());\r
- this.parameters = parameters;\r
- this.value = value;\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
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(Types.forAll(parameters, 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
- }\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
- TVar[] newParameters = new TVar[parameters.length];\r
- for(int i=0;i<parameters.length;++i) {\r
- TVar var = Types.var(parameters[i].getKind());\r
- newParameters[i] = var;\r
- context.tvarMap.put(parameters[i], var);\r
- }\r
- \r
- ELambdaType result = new ELambdaType(newParameters, value.replace(context));\r
- for(int i=0;i<parameters.length;++i)\r
- context.tvarMap.remove(parameters[i]);\r
- return result;\r
- }\r
- \r
- @Override\r
- public IExpression toIExpression(ExpressionInterpretationContext target) {\r
- return value.toIExpression(target);\r
- }\r
- \r
- @Override\r
- public Expression inferType(TypingContext context) {\r
- throw new InternalCompilerError("Should not type check " + getClass().getSimpleName() + ".");\r
- }\r
- \r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- value = value.decorate(decorator);\r
- return decorator.decorate(this);\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
- @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 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.environment.Environment;
+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.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ELambdaType extends Expression {
+ public TVar[] parameters;
+ public Expression value;
+
+ public ELambdaType(TVar[] parameters, Expression value) {
+ super(value.getLocation());
+ this.parameters = parameters;
+ this.value = value;
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ value.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ value.collectVars(allVars, vars);
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(Types.forAll(parameters, value.getType()));
+ }
+
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ return lambdaToVal(env, w);
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ value.collectFreeVariables(vars);
+ }
+
+ @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) {
+ TVar[] newParameters = new TVar[parameters.length];
+ for(int i=0;i<parameters.length;++i) {
+ TVar var = Types.var(parameters[i].getKind());
+ newParameters[i] = var;
+ context.tvarMap.put(parameters[i], var);
+ }
+
+ ELambdaType result = new ELambdaType(newParameters, value.replace(context));
+ for(int i=0;i<parameters.length;++i)
+ context.tvarMap.remove(parameters[i]);
+ return result;
+ }
+
+ @Override
+ public IExpression toIExpression(ExpressionInterpretationContext target) {
+ return value.toIExpression(target);
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ throw new InternalCompilerError("Should not type check " + getClass().getSimpleName() + ".");
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ value = value.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ }
+
+ @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);
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ value.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return value.getSyntacticFunctionArity();
+ }
+
+}
-package org.simantics.scl.compiler.elaboration.expressions;\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.BoundVar;\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.codegen.writer.RecursiveDefinitionWriter;\r
-import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;\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 ELet extends Expression {\r
- public Assignment[] assignments;\r
- public Expression in;\r
- \r
- public ELet(long loc, Assignment[] assignments, Expression in) {\r
- super(loc);\r
- this.assignments = assignments;\r
- this.in = in;\r
- }\r
-\r
- @Override\r
- public void collectRefs(final TObjectIntHashMap<Object> allRefs, final TIntHashSet refs) {\r
- for(Assignment assign : assignments)\r
- assign.value.collectRefs(allRefs, refs);\r
- in.collectRefs(allRefs, refs);\r
- }\r
- \r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- for(Assignment assign : assignments)\r
- assign.value.collectVars(allVars, vars);\r
- in.collectVars(allVars, vars);\r
- }\r
- \r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(in.getType());\r
- }\r
- \r
- /**\r
- * Splits let \r
- */\r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- \r
- // Simplify assignments\r
- for(Assignment assignment : assignments) {\r
- assignment.value = assignment.value.simplify(context);\r
- }\r
- \r
- // Find strongly connected components\r
- final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(\r
- 2*assignments.length, 0.5f, -1);\r
-\r
- for(int i=0;i<assignments.length;++i)\r
- for(Variable var : assignments[i].pattern.getFreeVariables())\r
- allVars.put(var, i);\r
- final boolean isRecursive[] = new boolean[assignments.length];\r
- final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length)); \r
- new StronglyConnectedComponents(assignments.length) {\r
- @Override\r
- protected int[] findDependencies(int u) {\r
- TIntHashSet vars = new TIntHashSet();\r
- assignments[u].value.collectVars(allVars, vars);\r
- if(vars.contains(u))\r
- isRecursive[u] = true;\r
- return vars.toArray();\r
- }\r
-\r
- @Override\r
- protected void reportComponent(int[] component) {\r
- components.add(component);\r
- }\r
-\r
- }.findComponents();\r
-\r
- // Simplify in\r
- Expression result = in.simplify(context);\r
- \r
- // Handle each component\r
- for(int j=components.size()-1;j>=0;--j) {\r
- int[] component = components.get(j);\r
- boolean recursive = component.length > 1 || isRecursive[component[0]];\r
- if(recursive) {\r
- Assignment[] cAssignments = new Assignment[component.length];\r
- for(int i=0;i<component.length;++i)\r
- cAssignments[i] = assignments[component[i]];\r
- result = new ELet(location, cAssignments, result);\r
- }\r
- else {\r
- Assignment assignment = assignments[component[0]];\r
- Expression pattern = assignment.pattern;\r
- \r
- if(pattern instanceof EVariable) {\r
- EVariable pvar = (EVariable)pattern;\r
- result = new ESimpleLet(location, pvar.variable, assignment.value, result);\r
- }\r
- else {\r
- result = new EMatch(location, new Expression[] {assignment.value},\r
- new Case(new Expression[] {pattern}, result));\r
- }\r
- }\r
- }\r
- \r
- return result;\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- in.collectFreeVariables(vars);\r
- for(Assignment assign : assignments)\r
- assign.value.collectFreeVariables(vars);\r
- for(Assignment assign : assignments) \r
- assign.pattern.removeFreeVariables(vars);\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- throw new InternalCompilerError("ELet should be already resolved.");\r
- }\r
- \r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- Assignment[] newAssignments = new Assignment[assignments.length];\r
- for(int i=0;i<assignments.length;++i)\r
- newAssignments[i] = assignments[i].replace(context); \r
- Expression newIn = in.replace(context);\r
- return new ELet(getLocation(), newAssignments, newIn);\r
- }\r
- \r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- // Create bound variables\r
- BoundVar[] vars = new BoundVar[assignments.length];\r
- for(int i=0;i<assignments.length;++i) {\r
- Expression pattern = assignments[i].pattern;\r
- if(!(pattern instanceof EVariable))\r
- throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");\r
- vars[i] = new BoundVar(pattern.getType());\r
- ((EVariable)pattern).getVariable().setVal(vars[i]);\r
- }\r
- \r
- // Create values\r
- RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();\r
- long range = Locations.NO_LOCATION;\r
- for(Assignment assign2 : assignments) {\r
- range = Locations.combine(range, assign2.pattern.location);\r
- range = Locations.combine(range, assign2.value.location);\r
- }\r
- rdw.setLocation(range);\r
- for(int i=0;i<assignments.length;++i) {\r
- DecomposedExpression decomposed = \r
- DecomposedExpression.decompose(assignments[i].value);\r
- CodeWriter newW = rdw.createFunction(vars[i], \r
- decomposed.typeParameters,\r
- decomposed.effect,\r
- decomposed.returnType, \r
- decomposed.parameterTypes);\r
- IVal[] parameters = newW.getParameters();\r
- for(int j=0;j<parameters.length;++j)\r
- decomposed.parameters[j].setVal(parameters[j]);\r
- newW.return_(decomposed.body.toVal(env, newW));\r
- }\r
- return in.toVal(env, w);\r
- }\r
- \r
- private void checkAssignments(TypingContext context) {\r
- for(Assignment assign : assignments)\r
- assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));\r
- for(Assignment assign : assignments)\r
- assign.value = assign.value.checkType(context, assign.pattern.getType());\r
- }\r
- \r
- @Override\r
- public Expression inferType(TypingContext context) {\r
- checkAssignments(context);\r
- in = in.inferType(context);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- checkAssignments(context);\r
- in = in.checkType(context, requiredType);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkIgnoredType(TypingContext context) {\r
- checkAssignments(context);\r
- in = in.checkIgnoredType(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- in = in.decorate(decorator);\r
- for(Assignment assignment : assignments)\r
- assignment.decorate(decorator);\r
- return decorator.decorate(this);\r
- }\r
-\r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- for(Assignment assignment : assignments) {\r
- assignment.pattern.collectEffects(effects);\r
- assignment.value.collectEffects(effects);\r
- }\r
- in.collectEffects(effects);\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(Assignment assignment : assignments)\r
- assignment.setLocationDeep(loc);\r
- in.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
- for(Assignment assignment : assignments)\r
- assignment.forVariables(procedure);\r
- in.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 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.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.codegen.writer.RecursiveDefinitionWriter;
+import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
+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 ELet extends Expression {
+ public Assignment[] assignments;
+ public Expression in;
+
+ public ELet(long loc, Assignment[] assignments, Expression in) {
+ super(loc);
+ this.assignments = assignments;
+ this.in = in;
+ }
+
+ @Override
+ public void collectRefs(final TObjectIntHashMap<Object> allRefs, final TIntHashSet refs) {
+ for(Assignment assign : assignments)
+ assign.value.collectRefs(allRefs, refs);
+ in.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ for(Assignment assign : assignments)
+ assign.value.collectVars(allVars, vars);
+ in.collectVars(allVars, vars);
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(in.getType());
+ }
+
+ /**
+ * Splits let
+ */
+ @Override
+ public Expression simplify(SimplificationContext context) {
+
+ // Simplify assignments
+ for(Assignment assignment : assignments) {
+ assignment.value = assignment.value.simplify(context);
+ }
+
+ // Find strongly connected components
+ final TObjectIntHashMap<Variable> allVars = new TObjectIntHashMap<Variable>(
+ 2*assignments.length, 0.5f, -1);
+
+ for(int i=0;i<assignments.length;++i)
+ for(Variable var : assignments[i].pattern.getFreeVariables())
+ allVars.put(var, i);
+ final boolean isRecursive[] = new boolean[assignments.length];
+ final ArrayList<int[]> components = new ArrayList<int[]>(Math.max(10, assignments.length));
+ new StronglyConnectedComponents(assignments.length) {
+ @Override
+ protected int[] findDependencies(int u) {
+ TIntHashSet vars = new TIntHashSet();
+ assignments[u].value.collectVars(allVars, vars);
+ if(vars.contains(u))
+ isRecursive[u] = true;
+ return vars.toArray();
+ }
+
+ @Override
+ protected void reportComponent(int[] component) {
+ components.add(component);
+ }
+
+ }.findComponents();
+
+ // Simplify in
+ Expression result = in.simplify(context);
+
+ // Handle each component
+ for(int j=components.size()-1;j>=0;--j) {
+ int[] component = components.get(j);
+ boolean recursive = component.length > 1 || isRecursive[component[0]];
+ if(recursive) {
+ Assignment[] cAssignments = new Assignment[component.length];
+ for(int i=0;i<component.length;++i)
+ cAssignments[i] = assignments[component[i]];
+ result = new ELet(location, cAssignments, result);
+ }
+ else {
+ Assignment assignment = assignments[component[0]];
+ Expression pattern = assignment.pattern;
+
+ if(pattern instanceof EVariable) {
+ EVariable pvar = (EVariable)pattern;
+ result = new ESimpleLet(location, pvar.variable, assignment.value, result);
+ }
+ else {
+ result = new EMatch(location, new Expression[] {assignment.value},
+ new Case(new Expression[] {pattern}, result));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ in.collectFreeVariables(vars);
+ for(Assignment assign : assignments)
+ assign.value.collectFreeVariables(vars);
+ for(Assignment assign : assignments)
+ assign.pattern.removeFreeVariables(vars);
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ throw new InternalCompilerError("ELet should be already resolved.");
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ Assignment[] newAssignments = new Assignment[assignments.length];
+ for(int i=0;i<assignments.length;++i)
+ newAssignments[i] = assignments[i].replace(context);
+ Expression newIn = in.replace(context);
+ return new ELet(getLocation(), newAssignments, newIn);
+ }
+
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ // Create bound variables
+ BoundVar[] vars = new BoundVar[assignments.length];
+ for(int i=0;i<assignments.length;++i) {
+ Expression pattern = assignments[i].pattern;
+ if(!(pattern instanceof EVariable))
+ throw new InternalCompilerError("Cannot handle pattern targets in recursive assignments.");
+ vars[i] = new BoundVar(pattern.getType());
+ ((EVariable)pattern).getVariable().setVal(vars[i]);
+ }
+
+ // Create values
+ RecursiveDefinitionWriter rdw = w.createRecursiveDefinition();
+ long range = Locations.NO_LOCATION;
+ for(Assignment assign2 : assignments) {
+ range = Locations.combine(range, assign2.pattern.location);
+ range = Locations.combine(range, assign2.value.location);
+ }
+ rdw.setLocation(range);
+ for(int i=0;i<assignments.length;++i) {
+ DecomposedExpression decomposed =
+ DecomposedExpression.decompose(assignments[i].value);
+ CodeWriter newW = rdw.createFunction(vars[i],
+ decomposed.typeParameters,
+ decomposed.effect,
+ decomposed.returnType,
+ decomposed.parameterTypes);
+ IVal[] parameters = newW.getParameters();
+ for(int j=0;j<parameters.length;++j)
+ decomposed.parameters[j].setVal(parameters[j]);
+ newW.return_(decomposed.body.toVal(env, newW));
+ }
+ return in.toVal(env, w);
+ }
+
+ private void checkAssignments(TypingContext context) {
+ for(Assignment assign : assignments)
+ assign.pattern = assign.pattern.checkTypeAsPattern(context, Types.metaVar(Kinds.STAR));
+ for(Assignment assign : assignments)
+ assign.value = assign.value.checkType(context, assign.pattern.getType());
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ checkAssignments(context);
+ in = in.inferType(context);
+ return this;
+ }
+
+ @Override
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ checkAssignments(context);
+ in = in.checkType(context, requiredType);
+ return this;
+ }
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ checkAssignments(context);
+ in = in.checkIgnoredType(context);
+ return this;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ in = in.decorate(decorator);
+ for(Assignment assignment : assignments)
+ assignment.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ for(Assignment assignment : assignments) {
+ assignment.pattern.collectEffects(effects);
+ assignment.value.collectEffects(effects);
+ }
+ in.collectEffects(effects);
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(Assignment assignment : assignments)
+ assignment.setLocationDeep(loc);
+ in.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ for(Assignment assignment : assignments)
+ assignment.forVariables(procedure);
+ in.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return in.getSyntacticFunctionArity();
+ }
+
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\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.ssa.exits.Throw;\r
-import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;\r
-import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;\r
-import org.simantics.scl.compiler.internal.elaboration.matching.Row;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\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 EMatch extends Expression {\r
-\r
- public Expression[] scrutinee;\r
- public Case[] cases;\r
- \r
- public EMatch(Expression[] scrutinee, Case ... cases) {\r
- this.scrutinee = scrutinee;\r
- this.cases = cases;\r
- }\r
- \r
- public EMatch(Expression scrutinee, Case ... cases) {\r
- this(new Expression[] {scrutinee}, cases);\r
- }\r
-\r
- public EMatch(long loc, Expression[] scrutinee, Case ... cases) {\r
- super(loc);\r
- this.scrutinee = scrutinee;\r
- this.cases = cases;\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- for(Expression s : scrutinee)\r
- s.collectRefs(allRefs, refs);\r
- for(Case case_ : cases)\r
- case_.collectRefs(allRefs, refs);\r
- }\r
- \r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- for(Expression s : scrutinee)\r
- s.collectVars(allVars, vars);\r
- for(Case case_ : cases)\r
- case_.collectVars(allVars, vars);\r
- }\r
- \r
- @Override\r
- protected void updateType() {\r
- setType(cases[0].value.getType());\r
- }\r
-\r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- ArrayList<Row> rows = new ArrayList<Row>(cases.length);\r
- for(Case case_ : cases)\r
- rows.add(new Row(case_.patterns, case_.value));\r
- \r
- IVal[] scrutineeVals = new IVal[scrutinee.length];\r
- for(int i=0;i<scrutinee.length;++i)\r
- scrutineeVals[i] = scrutinee[i].toVal(env, w);\r
- \r
- CodeWriter joinPoint = w.createBlock(getType());\r
- CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function\r
- PatternMatchingCompiler.split(w, env, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);\r
- failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());\r
- w.continueAs(joinPoint);\r
- return w.getParameters()[0];\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- for(Expression s : scrutinee)\r
- s.collectFreeVariables(vars);\r
- for(Case case_ : cases)\r
- case_.collectFreeVariables(vars);\r
- }\r
- \r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- for(int i=0;i<scrutinee.length;++i)\r
- scrutinee[i] = scrutinee[i].simplify(context);\r
- for(Case case_ : cases)\r
- case_.simplify(context); \r
- if(cases.length == 1 && scrutinee.length == 1) {\r
- Case case_ = cases[0];\r
- Expression pattern = case_.patterns[0];\r
- if(case_.patterns[0] instanceof EVariable\r
- && !(case_.value instanceof GuardedExpressionGroup)) {\r
- Variable var = ((EVariable)pattern).variable;\r
- return new ESimpleLet(var, scrutinee[0], case_.value);\r
- }\r
- }\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- for(int i=0;i<scrutinee.length;++i)\r
- scrutinee[i] = scrutinee[i].resolve(context);\r
- for(Case case_ : cases)\r
- case_.resolve(context);\r
- return this;\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(Case case_ : cases)\r
- case_.setLocationDeep(loc);\r
- for(Expression e : scrutinee)\r
- e.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- Expression[] newScrutinee = new Expression[scrutinee.length];\r
- for(int i=0;i<scrutinee.length;++i)\r
- newScrutinee[i] = scrutinee[i].replace(context);\r
- Case[] newCases = new Case[cases.length];\r
- for(int i=0;i<cases.length;++i)\r
- newCases[i] = cases[i].replace(context);\r
- return new EMatch(getLocation(), newScrutinee, newCases);\r
- }\r
- \r
- @Override\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- Type[] scrutineeTypes = new Type[scrutinee.length];\r
- for(int i=0;i<scrutinee.length;++i) {\r
- scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));\r
- scrutineeTypes[i] = scrutinee[i].getType();\r
- }\r
- for(Case case_ : cases)\r
- case_.checkType(context, scrutineeTypes, requiredType);\r
- setType(requiredType);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkIgnoredType(TypingContext context) {\r
- Type[] scrutineeTypes = new Type[scrutinee.length];\r
- for(int i=0;i<scrutinee.length;++i) {\r
- scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));\r
- scrutineeTypes[i] = scrutinee[i].getType();\r
- }\r
- for(Case case_ : cases)\r
- case_.checkIgnoredType(context, scrutineeTypes);\r
- setType(Types.UNIT);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- for(int i=0;i<scrutinee.length;++i)\r
- scrutinee[i] = scrutinee[i].decorate(decorator);\r
- for(Case case_ : cases)\r
- case_.decorate(decorator);\r
- return decorator.decorate(this);\r
- }\r
-\r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- for(Expression s : scrutinee)\r
- s.collectEffects(effects);\r
- for(Case case_ : cases) {\r
- for(Expression pattern : case_.patterns)\r
- pattern.collectEffects(effects);\r
- case_.value.collectEffects(effects);\r
- }\r
- }\r
- \r
- @Override\r
- public void accept(ExpressionVisitor visitor) {\r
- visitor.visit(this);\r
- }\r
- \r
- public Expression[] getScrutinee() {\r
- return scrutinee;\r
- }\r
- \r
- public Case[] getCases() {\r
- return cases;\r
- }\r
-\r
- @Override\r
- public void forVariables(VariableProcedure procedure) {\r
- for(Expression s : scrutinee)\r
- s.forVariables(procedure);\r
- for(Case case_ : cases)\r
- case_.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 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.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.matching.PatternMatchingCompiler;
+import org.simantics.scl.compiler.internal.elaboration.matching.Row;
+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.kinds.Kinds;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EMatch extends Expression {
+
+ public Expression[] scrutinee;
+ public Case[] cases;
+
+ public EMatch(Expression[] scrutinee, Case ... cases) {
+ this.scrutinee = scrutinee;
+ this.cases = cases;
+ }
+
+ public EMatch(Expression scrutinee, Case ... cases) {
+ this(new Expression[] {scrutinee}, cases);
+ }
+
+ public EMatch(long loc, Expression[] scrutinee, Case ... cases) {
+ super(loc);
+ this.scrutinee = scrutinee;
+ this.cases = cases;
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ for(Expression s : scrutinee)
+ s.collectRefs(allRefs, refs);
+ for(Case case_ : cases)
+ case_.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ for(Expression s : scrutinee)
+ s.collectVars(allVars, vars);
+ for(Case case_ : cases)
+ case_.collectVars(allVars, vars);
+ }
+
+ @Override
+ protected void updateType() {
+ setType(cases[0].value.getType());
+ }
+
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ ArrayList<Row> rows = new ArrayList<Row>(cases.length);
+ for(Case case_ : cases)
+ rows.add(new Row(case_.patterns, case_.value));
+
+ IVal[] scrutineeVals = new IVal[scrutinee.length];
+ for(int i=0;i<scrutinee.length;++i)
+ scrutineeVals[i] = scrutinee[i].toVal(env, w);
+
+ CodeWriter joinPoint = w.createBlock(getType());
+ CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function
+ PatternMatchingCompiler.split(w, env, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);
+ failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
+ w.continueAs(joinPoint);
+ return w.getParameters()[0];
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ for(Expression s : scrutinee)
+ s.collectFreeVariables(vars);
+ for(Case case_ : cases)
+ case_.collectFreeVariables(vars);
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ for(int i=0;i<scrutinee.length;++i)
+ scrutinee[i] = scrutinee[i].simplify(context);
+ for(Case case_ : cases)
+ case_.simplify(context);
+ if(cases.length == 1 && scrutinee.length == 1) {
+ Case case_ = cases[0];
+ Expression pattern = case_.patterns[0];
+ if(case_.patterns[0] instanceof EVariable
+ && !(case_.value instanceof GuardedExpressionGroup)) {
+ Variable var = ((EVariable)pattern).variable;
+ return new ESimpleLet(var, scrutinee[0], case_.value);
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ for(int i=0;i<scrutinee.length;++i)
+ scrutinee[i] = scrutinee[i].resolve(context);
+ for(Case case_ : cases)
+ case_.resolve(context);
+ return this;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(Case case_ : cases)
+ case_.setLocationDeep(loc);
+ for(Expression e : scrutinee)
+ e.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ Expression[] newScrutinee = new Expression[scrutinee.length];
+ for(int i=0;i<scrutinee.length;++i)
+ newScrutinee[i] = scrutinee[i].replace(context);
+ Case[] newCases = new Case[cases.length];
+ for(int i=0;i<cases.length;++i)
+ newCases[i] = cases[i].replace(context);
+ return new EMatch(getLocation(), newScrutinee, newCases);
+ }
+
+ @Override
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ Type[] scrutineeTypes = new Type[scrutinee.length];
+ for(int i=0;i<scrutinee.length;++i) {
+ scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));
+ scrutineeTypes[i] = scrutinee[i].getType();
+ }
+ for(Case case_ : cases)
+ case_.checkType(context, scrutineeTypes, requiredType);
+ setType(requiredType);
+ return this;
+ }
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ Type[] scrutineeTypes = new Type[scrutinee.length];
+ for(int i=0;i<scrutinee.length;++i) {
+ scrutinee[i] = scrutinee[i].checkType(context, Types.metaVar(Kinds.STAR));
+ scrutineeTypes[i] = scrutinee[i].getType();
+ }
+ for(Case case_ : cases)
+ case_.checkIgnoredType(context, scrutineeTypes);
+ setType(Types.UNIT);
+ return this;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ for(int i=0;i<scrutinee.length;++i)
+ scrutinee[i] = scrutinee[i].decorate(decorator);
+ for(Case case_ : cases)
+ case_.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ for(Expression s : scrutinee)
+ s.collectEffects(effects);
+ for(Case case_ : cases) {
+ for(Expression pattern : case_.patterns)
+ pattern.collectEffects(effects);
+ case_.value.collectEffects(effects);
+ }
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public Expression[] getScrutinee() {
+ return scrutinee;
+ }
+
+ public Case[] getCases() {
+ return cases;
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ for(Expression s : scrutinee)
+ s.forVariables(procedure);
+ for(Case case_ : cases)
+ case_.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ int result = 0;
+ for(Case case_ : cases)
+ result = Math.max(result, case_.value.getSyntacticFunctionArity());
+ return result;
+ }
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectObjectProcedure;\r
-\r
-public class EPreLet extends ASTExpression {\r
-\r
- List<LetStatement> assignments;\r
- Expression in;\r
- \r
- public EPreLet(List<LetStatement> assignments, Expression in) {\r
- this.assignments = assignments;\r
- this.in = in;\r
- }\r
- \r
- @Override\r
- public Expression resolve(final TranslationContext context) {\r
- context.pushFrame();\r
- THashMap<String, ArrayList<LetStatement>> functionDefinitions =\r
- new THashMap<String, ArrayList<LetStatement>>();\r
- ArrayList<LetStatement> otherDefinitions = new ArrayList<LetStatement>();\r
- final THashMap<String, Variable> localVars = new THashMap<String, Variable>();\r
- try {\r
- for(LetStatement assign : assignments) {\r
- LhsType lhsType = assign.pattern.getLhsType();\r
- if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) {\r
- String name = ((FunctionDefinitionLhs)lhsType).functionName;\r
- ArrayList<LetStatement> group = functionDefinitions.get(name);\r
- if(group == null) {\r
- group = new ArrayList<LetStatement>(2);\r
- functionDefinitions.put(name, group);\r
- }\r
- group.add(assign);\r
- localVars.put(name, context.newVariable(name));\r
- }\r
- else {\r
- otherDefinitions.add(assign);\r
- assign.pattern = assign.pattern.resolveAsPattern(context);\r
- }\r
- }\r
- } catch (NotPatternException e) {\r
- context.getErrorLog().log(e.getExpression().location, "Not a pattern.");\r
- return new EError();\r
- }\r
- \r
- final ArrayList<Assignment> as = new ArrayList<Assignment>(functionDefinitions.size() + otherDefinitions.size());\r
- functionDefinitions.forEachEntry(new TObjectObjectProcedure<String, ArrayList<LetStatement>>() {\r
- @Override\r
- public boolean execute(String name, ArrayList<LetStatement> cases) {\r
- as.add(new Assignment(\r
- new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)), \r
- context.translateCases(cases)));\r
- return true;\r
- }\r
- });\r
- for(LetStatement stat : otherDefinitions)\r
- as.add(new Assignment(\r
- stat.pattern /* already resolved above */, \r
- stat.value.resolve(context)));\r
- Expression inExpr = in.resolve(context);\r
- context.popFrame();\r
- \r
- ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr);\r
- /*System.out.println("-----------------------------------------");\r
- System.out.println(this);\r
- System.out.println("-----------------------------------------");\r
- System.out.println(result);\r
- System.out.println("-----------------------------------------");*/\r
- return result;\r
- }\r
-\r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(LetStatement assignment : assignments)\r
- assignment.setLocationDeep(loc);\r
- in.setLocationDeep(loc);\r
- }\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.List;
+
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.errors.Locations;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+
+public class EPreLet extends ASTExpression {
+
+ List<LetStatement> assignments;
+ Expression in;
+
+ public EPreLet(List<LetStatement> assignments, Expression in) {
+ this.assignments = assignments;
+ this.in = in;
+ }
+
+ @Override
+ public Expression resolve(final TranslationContext context) {
+ context.pushFrame();
+ THashMap<String, ArrayList<LetStatement>> functionDefinitions =
+ new THashMap<String, ArrayList<LetStatement>>();
+ ArrayList<LetStatement> otherDefinitions = new ArrayList<LetStatement>();
+ final THashMap<String, Variable> localVars = new THashMap<String, Variable>();
+ try {
+ for(LetStatement assign : assignments) {
+ LhsType lhsType = assign.pattern.getLhsType();
+ if(!(assign.pattern instanceof EVar) && lhsType instanceof FunctionDefinitionLhs) {
+ String name = ((FunctionDefinitionLhs)lhsType).functionName;
+ ArrayList<LetStatement> group = functionDefinitions.get(name);
+ if(group == null) {
+ group = new ArrayList<LetStatement>(2);
+ functionDefinitions.put(name, group);
+ }
+ group.add(assign);
+ localVars.put(name, context.newVariable(name));
+ }
+ else {
+ otherDefinitions.add(assign);
+ assign.pattern = assign.pattern.resolveAsPattern(context);
+ }
+ }
+ } catch (NotPatternException e) {
+ context.getErrorLog().log(e.getExpression().location, "Not a pattern.");
+ return new EError();
+ }
+
+ final ArrayList<Assignment> as = new ArrayList<Assignment>(functionDefinitions.size() + otherDefinitions.size());
+ functionDefinitions.forEachEntry(new TObjectObjectProcedure<String, ArrayList<LetStatement>>() {
+ @Override
+ public boolean execute(String name, ArrayList<LetStatement> cases) {
+ as.add(new Assignment(
+ new EVariable(cases.size()==1 ? cases.get(0).pattern.location : location, localVars.get(name)),
+ context.translateCases(cases)));
+ return true;
+ }
+ });
+ for(LetStatement stat : otherDefinitions)
+ as.add(new Assignment(
+ stat.pattern /* already resolved above */,
+ stat.value.resolve(context)));
+ Expression inExpr = in.resolve(context);
+ context.popFrame();
+
+ ELet result = new ELet(location, as.toArray(new Assignment[as.size()]), inExpr);
+ /*System.out.println("-----------------------------------------");
+ System.out.println(this);
+ System.out.println("-----------------------------------------");
+ System.out.println(result);
+ System.out.println("-----------------------------------------");*/
+ return result;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(LetStatement assignment : assignments)
+ assignment.setLocationDeep(loc);
+ in.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return in.getSyntacticFunctionArity();
+ }
+
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;\r
-import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;\r
-import org.simantics.scl.compiler.elaboration.relations.LocalRelation;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-\r
-public class EPreRuleset extends ASTExpression {\r
-\r
- RuleStatement[] statements;\r
- Expression in;\r
- \r
- public EPreRuleset(RuleStatement[] statements, Expression in) {\r
- this.statements = statements;\r
- this.in = in;\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- THashMap<String, LocalRelation> relations = new THashMap<String, LocalRelation>(); \r
- DatalogRule[] rules = new DatalogRule[statements.length];\r
- context.pushRelationFrame();\r
- try {\r
- for(int i=0;i<statements.length;++i) {\r
- RuleStatement statement = statements[i];\r
- Expression head = statement.head;\r
- if(!(head instanceof EApply)) {\r
- context.getErrorLog().log(head.location, "Invalid rule head.");\r
- return new EError();\r
- }\r
- EApply apply = (EApply)head;\r
- if(!(apply.function instanceof EVar)) {\r
- context.getErrorLog().log(head.location, "Invalid relation in rule head.");\r
- return new EError();\r
- }\r
- String relationName = ((EVar)apply.function).name;\r
- LocalRelation relation = relations.get(relationName);\r
- if(relation == null) {\r
- relation = new LocalRelation(relationName, apply.parameters.length);\r
- relations.put(relationName, relation);\r
- context.newRelation(relationName, relation);\r
- }\r
- else if(apply.parameters.length != relation.getArity()) {\r
- context.getErrorLog().log(apply.location, "Different rules have different relation arity.");\r
- return new EError();\r
- }\r
- rules[i] = new DatalogRule(relation, apply.parameters, statement.body);\r
- }\r
- for(DatalogRule rule : rules) {\r
- context.pushExistentialFrame();\r
- for(int i=0;i<rule.headParameters.length;++i)\r
- rule.headParameters[i] = rule.headParameters[i].resolve(context);\r
- rule.body = rule.body.resolve(context);\r
- rule.variables = context.popExistentialFrame();\r
- }\r
- return new ERuleset(\r
- relations.values().toArray(new LocalRelation[relations.size()]),\r
- rules,\r
- in.resolve(context));\r
- } finally {\r
- context.popRelationFrame();\r
- }\r
- }\r
-\r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(RuleStatement statement : statements)\r
- statement.setLocationDeep(loc);\r
- in.setLocationDeep(loc);\r
- }\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 org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;
+import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
+import org.simantics.scl.compiler.elaboration.relations.LocalRelation;
+import org.simantics.scl.compiler.errors.Locations;
+
+import gnu.trove.map.hash.THashMap;
+
+public class EPreRuleset extends ASTExpression {
+
+ RuleStatement[] statements;
+ Expression in;
+
+ public EPreRuleset(RuleStatement[] statements, Expression in) {
+ this.statements = statements;
+ this.in = in;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ THashMap<String, LocalRelation> relations = new THashMap<String, LocalRelation>();
+ DatalogRule[] rules = new DatalogRule[statements.length];
+ context.pushRelationFrame();
+ try {
+ for(int i=0;i<statements.length;++i) {
+ RuleStatement statement = statements[i];
+ Expression head = statement.head;
+ if(!(head instanceof EApply)) {
+ context.getErrorLog().log(head.location, "Invalid rule head.");
+ return new EError();
+ }
+ EApply apply = (EApply)head;
+ if(!(apply.function instanceof EVar)) {
+ context.getErrorLog().log(head.location, "Invalid relation in rule head.");
+ return new EError();
+ }
+ String relationName = ((EVar)apply.function).name;
+ LocalRelation relation = relations.get(relationName);
+ if(relation == null) {
+ relation = new LocalRelation(relationName, apply.parameters.length);
+ relations.put(relationName, relation);
+ context.newRelation(relationName, relation);
+ }
+ else if(apply.parameters.length != relation.getArity()) {
+ context.getErrorLog().log(apply.location, "Different rules have different relation arity.");
+ return new EError();
+ }
+ rules[i] = new DatalogRule(relation, apply.parameters, statement.body);
+ }
+ for(DatalogRule rule : rules) {
+ context.pushExistentialFrame();
+ for(int i=0;i<rule.headParameters.length;++i)
+ rule.headParameters[i] = rule.headParameters[i].resolve(context);
+ rule.body = rule.body.resolve(context);
+ rule.variables = context.popExistentialFrame();
+ }
+ return new ERuleset(
+ relations.values().toArray(new LocalRelation[relations.size()]),
+ rules,
+ in.resolve(context));
+ } finally {
+ context.popRelationFrame();
+ }
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(RuleStatement statement : statements)
+ statement.setLocationDeep(loc);
+ in.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return in.getSyntacticFunctionArity();
+ }
+
+}
-package org.simantics.scl.compiler.elaboration.expressions;\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
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\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 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.environment.Environment;
+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.elaboration.utils.ExpressionDecorator;
+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;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+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 void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ value.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ value.collectVars(allVars, vars);
+ }
+
+ 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(Environment env, CodeWriter w) {
+ return lambdaToVal(env, w);
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ value.collectFreeVariables(vars);
+ vars.remove(parameter);
+ }
+
+ @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();
+ THashSet<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;
+ }
+
+ effect = mfun.effect;
+ context.pushEffectUpperBound(location, mfun.effect);
+ parameter.setType(mfun.parameterTypes[0]);
+ value = value.checkType(context, mfun.returnType);
+ 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 Expression decorate(ExpressionDecorator decorator) {
+ if(decorator.decorateSubstructure(this))
+ value = value.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public boolean isEffectful() {
+ return false;
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ }
+
+ @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 void forVariables(VariableProcedure procedure) {
+ value.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return 1 + value.getSyntacticFunctionArity();
+ }
+
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.ILet;\r
-import org.simantics.scl.compiler.internal.interpreted.ISeq;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\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 ESimpleLet extends Expression {\r
- Variable variable; // may be null\r
- Expression value;\r
- Expression in;\r
- \r
- public ESimpleLet(Variable variable, Expression value, Expression in) {\r
- if(value == null)\r
- throw new NullPointerException();\r
- if(in == null)\r
- throw new NullPointerException();\r
- this.variable = variable;\r
- this.value = value;\r
- this.in = in;\r
- }\r
-\r
- public ESimpleLet(long loc, Variable variable, Expression value, Expression in) {\r
- super(loc);\r
- if(value == null)\r
- throw new NullPointerException();\r
- if(in == null)\r
- throw new NullPointerException();\r
- this.variable = variable;\r
- this.value = value;\r
- this.in = in;\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- value.collectRefs(allRefs, refs);\r
- in.collectRefs(allRefs, refs);\r
- }\r
- \r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- value.collectVars(allVars, vars);\r
- in.collectVars(allVars, vars);\r
- }\r
-\r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(in.getType());\r
- }\r
- \r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- IVal valueVal = value.toVal(env, w);\r
- if(variable != null)\r
- variable.setVal(valueVal);\r
- return in.toVal(env, w);\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- value.collectFreeVariables(vars);\r
- in.collectFreeVariables(vars);\r
- vars.remove(variable);\r
- }\r
-\r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- value = value.simplify(context);\r
- if(value instanceof EConstant || value instanceof ELiteral) {\r
- context.addInlinedVariable(variable, value);\r
- return in.simplify(context);\r
- }\r
- in = in.simplify(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- value = value.resolve(context);\r
- in = in.resolve(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- if(variable == null)\r
- return new ESimpleLet(location,\r
- null, \r
- value.replace(context), \r
- in.replace(context));\r
- else {\r
- Variable newVariable = variable.copy();\r
- context.varMap.put(variable, new EVariable(newVariable));\r
- ESimpleLet result = new ESimpleLet(location, newVariable, \r
- value.replace(context), \r
- in.replace(context));\r
- context.varMap.remove(variable);\r
- return result;\r
- }\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- value.setLocationDeep(loc);\r
- in.setLocationDeep(loc);\r
- }\r
- }\r
-\r
- @Override\r
- public IExpression toIExpression(ExpressionInterpretationContext context) {\r
- if(variable == null) {\r
- IExpression valueI = value.toIExpression(context);\r
- IExpression inI = in.toIExpression(context);\r
- return new ISeq(valueI, inI);\r
- }\r
- else {\r
- IExpression valueI = value.toIExpression(context);\r
- int variableId = context.push(variable);\r
- IExpression inI = in.toIExpression(context);\r
- context.pop(variable);\r
- return new ILet(variableId, valueI, inI);\r
- }\r
- }\r
-\r
- private void checkBinding(TypingContext context) {\r
- if(variable == null)\r
- value = value.checkIgnoredType(context);\r
- else if(variable.getType() == null) {\r
- value = value.inferType(context);\r
- variable.setType(value.getType());\r
- }\r
- else\r
- value = value.checkType(context, variable.type);\r
- /*else {\r
- if(variable.getType() == null)\r
- variable.setType(Types.metaVar(Kinds.STAR));\r
- value = value.checkType(context, variable.type);\r
- }*/\r
- }\r
- \r
- @Override\r
- public Expression inferType(TypingContext context) {\r
- checkBinding(context);\r
- in = in.inferType(context);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- checkBinding(context);\r
- in = in.checkType(context, requiredType);\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkIgnoredType(TypingContext context) {\r
- checkBinding(context);\r
- in = in.checkIgnoredType(context);\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- value = value.decorate(decorator);\r
- in = in.decorate(decorator);\r
- return decorator.decorate(this);\r
- }\r
-\r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- value.collectEffects(effects);\r
- in.collectEffects(effects);\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 getVariable() {\r
- return variable;\r
- }\r
- \r
- public Expression getIn() {\r
- return in;\r
- }\r
-\r
- @Override\r
- public void forVariables(VariableProcedure procedure) {\r
- value.forVariables(procedure);\r
- in.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 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.environment.Environment;
+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.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.interpreted.ILet;
+import org.simantics.scl.compiler.internal.interpreted.ISeq;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ESimpleLet extends Expression {
+ Variable variable; // may be null
+ Expression value;
+ Expression in;
+
+ public ESimpleLet(Variable variable, Expression value, Expression in) {
+ if(value == null)
+ throw new NullPointerException();
+ if(in == null)
+ throw new NullPointerException();
+ this.variable = variable;
+ this.value = value;
+ this.in = in;
+ }
+
+ public ESimpleLet(long loc, Variable variable, Expression value, Expression in) {
+ super(loc);
+ if(value == null)
+ throw new NullPointerException();
+ if(in == null)
+ throw new NullPointerException();
+ this.variable = variable;
+ this.value = value;
+ this.in = in;
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ value.collectRefs(allRefs, refs);
+ in.collectRefs(allRefs, refs);
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ value.collectVars(allVars, vars);
+ in.collectVars(allVars, vars);
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(in.getType());
+ }
+
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ IVal valueVal = value.toVal(env, w);
+ if(variable != null)
+ variable.setVal(valueVal);
+ return in.toVal(env, w);
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ value.collectFreeVariables(vars);
+ in.collectFreeVariables(vars);
+ vars.remove(variable);
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ value = value.simplify(context);
+ if(value instanceof EConstant || value instanceof ELiteral) {
+ context.addInlinedVariable(variable, value);
+ return in.simplify(context);
+ }
+ in = in.simplify(context);
+ return this;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ value = value.resolve(context);
+ in = in.resolve(context);
+ return this;
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ if(variable == null)
+ return new ESimpleLet(location,
+ null,
+ value.replace(context),
+ in.replace(context));
+ else {
+ Variable newVariable = variable.copy();
+ context.varMap.put(variable, new EVariable(newVariable));
+ ESimpleLet result = new ESimpleLet(location, newVariable,
+ value.replace(context),
+ in.replace(context));
+ context.varMap.remove(variable);
+ return result;
+ }
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ value.setLocationDeep(loc);
+ in.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public IExpression toIExpression(ExpressionInterpretationContext context) {
+ if(variable == null) {
+ IExpression valueI = value.toIExpression(context);
+ IExpression inI = in.toIExpression(context);
+ return new ISeq(valueI, inI);
+ }
+ else {
+ IExpression valueI = value.toIExpression(context);
+ int variableId = context.push(variable);
+ IExpression inI = in.toIExpression(context);
+ context.pop(variable);
+ return new ILet(variableId, valueI, inI);
+ }
+ }
+
+ private void checkBinding(TypingContext context) {
+ if(variable == null)
+ value = value.checkIgnoredType(context);
+ else if(variable.getType() == null) {
+ value = value.inferType(context);
+ variable.setType(value.getType());
+ }
+ else
+ value = value.checkType(context, variable.type);
+ /*else {
+ if(variable.getType() == null)
+ variable.setType(Types.metaVar(Kinds.STAR));
+ value = value.checkType(context, variable.type);
+ }*/
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ checkBinding(context);
+ in = in.inferType(context);
+ return this;
+ }
+
+ @Override
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ checkBinding(context);
+ in = in.checkType(context, requiredType);
+ return this;
+ }
+
+ @Override
+ public Expression checkIgnoredType(TypingContext context) {
+ checkBinding(context);
+ in = in.checkIgnoredType(context);
+ return this;
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ value = value.decorate(decorator);
+ in = in.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ value.collectEffects(effects);
+ in.collectEffects(effects);
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ public Expression getValue() {
+ return value;
+ }
+
+ public Variable getVariable() {
+ return variable;
+ }
+
+ public Expression getIn() {
+ return in;
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ value.forVariables(procedure);
+ in.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return in.getSyntacticFunctionArity();
+ }
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.errors.NotPatternException;\r
-import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;\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.errors.Locations;\r
-\r
-public class EVar extends ASTExpression {\r
- public final String name;\r
-\r
- public EVar(long location, String name) {\r
- this.location = location;\r
- this.name = name;\r
- }\r
- \r
- public EVar(String name) {\r
- this(Locations.NO_LOCATION, name);\r
- }\r
- \r
- @Override\r
- public EVar getPatternHead() {\r
- return this;\r
- }\r
- \r
- @Override\r
- public LhsType getLhsType() throws NotPatternException {\r
- if(TranslationContext.isConstructorName(name))\r
- return new PatternMatchingLhs();\r
- else\r
- return new FunctionDefinitionLhs(name);\r
- }\r
- \r
- @Override\r
- protected void collectVariableNames(PatternMatchingLhs lhsType)\r
- throws NotPatternException {\r
- if(!TranslationContext.isConstructorName(name))\r
- lhsType.variableNames.add(name);\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- return context.resolveExpression(location, name);\r
- }\r
- \r
- @Override\r
- public void getParameters(TranslationContext translationContext,\r
- ArrayList<Expression> parameters) {\r
- }\r
- \r
- @Override\r
- public Expression resolveAsPattern(TranslationContext context) {\r
- return context.resolvePattern(this);\r
- }\r
- \r
- @Override\r
- public int getFunctionDefinitionArity() throws NotPatternException {\r
- if(TranslationContext.isConstructorName(name))\r
- throw new NotPatternException(this);\r
- else\r
- return 0;\r
- }\r
- \r
- @Override\r
- public boolean isConstructorApplication() {\r
- return TranslationContext.isConstructorName(name);\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION)\r
- location = loc;\r
- }\r
- \r
- @Override\r
- public Expression accept(ExpressionTransformer transformer) {\r
- return transformer.transform(this);\r
- }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
+import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;
+import org.simantics.scl.compiler.errors.Locations;
+
+public class EVar extends ASTExpression {
+ public final String name;
+
+ public EVar(long location, String name) {
+ this.location = location;
+ this.name = name;
+ }
+
+ public EVar(String name) {
+ this(Locations.NO_LOCATION, name);
+ }
+
+ @Override
+ public EVar getPatternHead() {
+ return this;
+ }
+
+ @Override
+ public LhsType getLhsType() throws NotPatternException {
+ if(TranslationContext.isConstructorName(name))
+ return new PatternMatchingLhs();
+ else
+ return new FunctionDefinitionLhs(name);
+ }
+
+ @Override
+ protected void collectVariableNames(PatternMatchingLhs lhsType)
+ throws NotPatternException {
+ if(!TranslationContext.isConstructorName(name))
+ lhsType.variableNames.add(name);
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ return context.resolveExpression(location, name);
+ }
+
+ @Override
+ public void getParameters(TranslationContext translationContext,
+ ArrayList<Expression> parameters) {
+ }
+
+ @Override
+ public Expression resolveAsPattern(TranslationContext context) {
+ return context.resolvePattern(this);
+ }
+
+ @Override
+ public int getFunctionDefinitionPatternArity() throws NotPatternException {
+ if(TranslationContext.isConstructorName(name))
+ throw new NotPatternException(this);
+ else
+ return 0;
+ }
+
+ @Override
+ public boolean isConstructorApplication() {
+ return TranslationContext.isConstructorName(name);
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION)
+ location = loc;
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.common.precedence.Precedence;\r
-import org.simantics.scl.compiler.constants.NoRepConstant;\r
-import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;\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.expressions.printing.ExpressionToStringVisitor;\r
-import org.simantics.scl.compiler.elaboration.query.QAtom;\r
-import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
-import org.simantics.scl.compiler.environment.Environment;\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.decomposed.DecomposedExpression;\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.parsing.Symbol;\r
-import org.simantics.scl.compiler.top.ExpressionInterpretationContext;\r
-import org.simantics.scl.compiler.types.TForAll;\r
-import org.simantics.scl.compiler.types.TFun;\r
-import org.simantics.scl.compiler.types.TPred;\r
-import org.simantics.scl.compiler.types.TVar;\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
-import org.simantics.scl.compiler.types.util.Typed;\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 abstract class Expression extends Symbol implements Typed {\r
- public static final Expression[] EMPTY_ARRAY = new Expression[0];\r
- \r
- transient\r
- private Type type;\r
- \r
- public Expression() {\r
- }\r
- \r
- public Expression(long loc) {\r
- this.location = loc;\r
- }\r
- \r
- @Override\r
- public Type getType() {\r
- if(type == null) {\r
- try {\r
- updateType();\r
- } catch (MatchException e) {\r
- throw new InternalCompilerError(e);\r
- }\r
- if(type == null)\r
- throw new InternalCompilerError(getClass().getSimpleName() + \r
- ".updateType couldn't compute its type.");\r
- }\r
- return type;\r
- }\r
-\r
- public void setType(Type type) {\r
- if(type == null)\r
- throw new NullPointerException();\r
- this.type = type;\r
- }\r
- \r
- /**\r
- * Infers the type of the expression without any context. Adds type\r
- * applications and lambdas if needed. \r
- */\r
- public Expression inferType(TypingContext context) {\r
- return checkBasicType(context, Types.metaVar(Kinds.STAR));\r
- }\r
-\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- return context.subsume(inferType(context), requiredType);\r
- }\r
- \r
- protected Expression applyPUnit(EnvironmentalContext context) {\r
- Type type = Types.canonical(getType());\r
- if(type instanceof TFun) {\r
- TFun fun = (TFun)type;\r
- if(fun.getCanonicalDomain() == Types.PUNIT) {\r
- EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT));\r
- result.effect = fun.getCanonicalEffect();\r
- return result;\r
- }\r
- }\r
- return this;\r
- }\r
-\r
- public Expression checkIgnoredType(TypingContext context) {\r
- Expression expression = inferType(context);\r
- if(Types.canonical(expression.getType()) != Types.UNIT)\r
- expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT));\r
- return expression;\r
- }\r
- \r
- /**\r
- * Checks the type of the expression against the given type. Adds type\r
- * applications and lambdas if needed.\r
- */\r
- public final Expression checkType(TypingContext context, Type requiredType) {\r
- //System.out.println("checkType: " + this + " :: " + requiredType);\r
- if(!context.isInPattern()) {\r
- requiredType = Types.canonical(requiredType);\r
- if(requiredType instanceof TForAll) {\r
- TForAll forAll = (TForAll)requiredType;\r
- TVar var = forAll.var;\r
- TVar newVar = Types.var(var.getKind());\r
- requiredType = Types.canonical(forAll.type).replace(var, newVar);\r
- return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType));\r
- }\r
- while(requiredType instanceof TFun) {\r
- TFun fun = (TFun)requiredType;\r
- if(fun.domain instanceof TPred) { // No need to canonicalize\r
- ArrayList<Variable> constraints = new ArrayList<Variable>(2);\r
- while(true) {\r
- constraints.add(new Variable("constraint", fun.domain));\r
- requiredType = Types.canonical(fun.range);\r
- if(!(requiredType instanceof TFun))\r
- break;\r
- fun = (TFun)requiredType;\r
- if(!(fun.domain instanceof TPred))\r
- break;\r
- }\r
- context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()]));\r
- Expression expression = checkType(context, requiredType);\r
- context.popConstraintFrame();\r
- for(int i=constraints.size()-1;i>=0;--i)\r
- expression = new ESimpleLambda(constraints.get(i), expression);\r
- return expression;\r
- }\r
- else if(fun.domain == Types.PUNIT) {\r
- context.pushEffectUpperBound(location, fun.effect);\r
- Expression expr = checkType(context, fun.range);\r
- context.popEffectUpperBound(); \r
- \r
- // Wrap\r
- Variable var = new Variable("punit", Types.PUNIT);\r
- return new ESimpleLambda(location, var, fun.effect, expr);\r
- }\r
- else\r
- break;\r
- }\r
- }\r
- return checkBasicType(context, requiredType); \r
- }\r
-\r
- public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);\r
- public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);\r
- public abstract void forVariables(VariableProcedure procedure);\r
- \r
- public Expression decomposeMatching() {\r
- return this;\r
- }\r
-\r
- public String toString() {\r
- StringBuilder b = new StringBuilder();\r
- ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
- accept(visitor);\r
- return b.toString();\r
- }\r
-\r
- protected abstract void updateType() throws MatchException;\r
- \r
- public static class TypeValidationException extends Exception {\r
- private static final long serialVersionUID = 3181298127162041248L; \r
- \r
- long loc;\r
-\r
- public TypeValidationException(long loc) {\r
- this.loc = loc;\r
- }\r
- \r
- public long getLoc() {\r
- return loc;\r
- }\r
-\r
- public TypeValidationException(long loc, Throwable cause) {\r
- super(cause);\r
- this.loc = loc;\r
- }\r
- }\r
- \r
- public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException {\r
- if(!Types.equals(a, b))\r
- throw new TypeValidationException(loc);\r
- }\r
-\r
- public abstract IVal toVal(Environment env, CodeWriter w);\r
- \r
- public Expression closure(TVar ... vars) {\r
- if(vars.length == 0)\r
- return this;\r
- return new ELambdaType(vars, this);\r
- }\r
- \r
- public abstract void collectFreeVariables(THashSet<Variable> vars);\r
- \r
- public Expression simplify(SimplificationContext context) {\r
- System.out.println("#############################");\r
- System.out.println(this);\r
- throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method.");\r
- }\r
-\r
- public abstract Expression resolve(TranslationContext context);\r
- \r
- /**\r
- * Returns head of the pattern.\r
- */\r
- public EVar getPatternHead() throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
- \r
- public LhsType getLhsType() throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
-\r
- protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
-\r
- public void getParameters(TranslationContext translationContext,\r
- ArrayList<Expression> parameters) {\r
- throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters."); \r
- }\r
-\r
- public Expression resolveAsPattern(TranslationContext context) {\r
- context.getErrorLog().log(location, "Pattern was expected here.");\r
- return new EError();\r
- }\r
-\r
- public void removeFreeVariables(THashSet<Variable> vars) {\r
- throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern.");\r
- }\r
- \r
- public Expression checkTypeAsPattern(TypingContext context, Type requiredType) {\r
- if(context.isInPattern())\r
- throw new InternalCompilerError("Already in a pattern.");\r
- context.setInPattern(true);\r
- Expression expression = checkType(context, requiredType);\r
- context.setInPattern(false);\r
- return expression;\r
- }\r
-\r
- public THashSet<Variable> getFreeVariables() {\r
- THashSet<Variable> result = new THashSet<Variable>();\r
- collectFreeVariables(result);\r
- return result;\r
- } \r
-\r
- public static Expression[] concat(Expression[] a, Expression[] b) {\r
- if(a.length == 0)\r
- return b;\r
- if(b.length == 0)\r
- return a;\r
- Expression[] result = new Expression[a.length + b.length];\r
- for(int i=0;i<a.length;++i)\r
- result[i] = a[i];\r
- for(int i=0;i<b.length;++i)\r
- result[i+a.length] = b[i];\r
- return result;\r
- }\r
-\r
- public Expression replace(ReplaceContext context) {\r
- throw new InternalCompilerError(getClass().getSimpleName() + " does not support replace.");\r
- }\r
- \r
- public static Expression[] replace(ReplaceContext context, Expression[] expressions) {\r
- Expression[] result = new Expression[expressions.length];\r
- for(int i=0;i<expressions.length;++i)\r
- result[i] = expressions[i].replace(context);\r
- return result;\r
- }\r
- \r
- public Expression copy() {\r
- return replace(new ReplaceContext(null));\r
- }\r
- \r
- public Expression copy(TypingContext typingContext) {\r
- return replace(new ReplaceContext(typingContext));\r
- }\r
-\r
- public abstract void setLocationDeep(long loc);\r
-\r
- public Expression replaceInPattern(ReplaceContext context) {\r
- context.inPattern = true;\r
- Expression result = replace(context);\r
- context.inPattern = false;\r
- return result;\r
- }\r
-\r
- public int getFunctionDefinitionArity() throws NotPatternException {\r
- throw new NotPatternException(this);\r
- }\r
- \r
- public IVal lambdaToVal(Environment env, CodeWriter w) {\r
- DecomposedExpression decomposed = DecomposedExpression.decompose(this);\r
- CodeWriter newW = w.createFunction(decomposed.typeParameters, decomposed.effect, decomposed.returnType, decomposed.parameterTypes);\r
- IVal[] parameters = newW.getParameters();\r
- IVal functionVal = newW.getFunction().getTarget();\r
- for(int i=0;i<parameters.length;++i)\r
- decomposed.parameters[i].setVal(parameters[i]);\r
- newW.return_(decomposed.body.toVal(env, newW));\r
- return functionVal;\r
- }\r
- \r
- public IExpression toIExpression(ExpressionInterpretationContext context) {\r
- throw new UnsupportedOperationException();\r
- }\r
- \r
- public static IExpression[] toIExpressions(ExpressionInterpretationContext target, Expression[] expressions) {\r
- IExpression[] result = new IExpression[expressions.length];\r
- for(int i=0;i<expressions.length;++i)\r
- result[i] = expressions[i].toIExpression(target);\r
- return result;\r
- }\r
- \r
- public Expression applyType(Type type) {\r
- return new EApplyType(location, this, type);\r
- }\r
- \r
- public abstract Expression decorate(ExpressionDecorator decorator);\r
-\r
- public boolean isEffectful() {\r
- return true;\r
- }\r
-\r
- public boolean isFunctionPattern() {\r
- return false;\r
- }\r
-\r
- public boolean isConstructorApplication() {\r
- return false;\r
- }\r
- \r
- public abstract void collectEffects(THashSet<Type> effects);\r
- \r
- public Type getEffect() {\r
- THashSet<Type> effects = new THashSet<Type>();\r
- collectEffects(effects);\r
- return Types.union(effects.toArray(new Type[effects.size()]));\r
- }\r
- \r
- public abstract void accept(ExpressionVisitor visitor);\r
- \r
- public void collectRelationRefs(\r
- final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {\r
- accept(new StandardExpressionVisitor() {\r
- @Override\r
- public void visit(QAtom query) {\r
- int id = allRefs.get(query.relation);\r
- if(id >= 0)\r
- refs.add(id);\r
- }\r
- });\r
- }\r
-\r
- public boolean isFunctionDefinitionLhs() {\r
- return false;\r
- }\r
-\r
- public Precedence getPrecedence() {\r
- return Precedence.DEFAULT;\r
- }\r
-\r
- public boolean isPattern(int arity) {\r
- return false;\r
- }\r
- \r
- public abstract Expression accept(ExpressionTransformer transformer);\r
-\r
- // TODO implement for all expressions\r
- public boolean equalsExpression(Expression expression) {\r
- return false;\r
- }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.constants.NoRepConstant;
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
+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.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.query.QAtom;
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.decomposed.DecomposedExpression;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.TForAll;
+import org.simantics.scl.compiler.types.TFun;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+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 org.simantics.scl.compiler.types.util.Typed;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public abstract class Expression extends Symbol implements Typed {
+ public static final Expression[] EMPTY_ARRAY = new Expression[0];
+
+ transient
+ private Type type;
+
+ public Expression() {
+ }
+
+ public Expression(long loc) {
+ this.location = loc;
+ }
+
+ @Override
+ public Type getType() {
+ if(type == null) {
+ try {
+ updateType();
+ } catch (MatchException e) {
+ throw new InternalCompilerError(e);
+ }
+ if(type == null)
+ throw new InternalCompilerError(getClass().getSimpleName() +
+ ".updateType couldn't compute its type.");
+ }
+ return type;
+ }
+
+ public void setType(Type type) {
+ if(type == null)
+ throw new NullPointerException();
+ this.type = type;
+ }
+
+ /**
+ * Infers the type of the expression without any context. Adds type
+ * applications and lambdas if needed.
+ */
+ public Expression inferType(TypingContext context) {
+ return checkBasicType(context, Types.metaVar(Kinds.STAR));
+ }
+
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ return context.subsume(inferType(context), requiredType);
+ }
+
+ protected Expression applyPUnit(EnvironmentalContext context) {
+ Type type = Types.canonical(getType());
+ if(type instanceof TFun) {
+ TFun fun = (TFun)type;
+ if(fun.getCanonicalDomain() == Types.PUNIT) {
+ EApply result = new EApply(location, this, new ELiteral(NoRepConstant.PUNIT));
+ result.effect = fun.getCanonicalEffect();
+ return result;
+ }
+ }
+ return this;
+ }
+
+ public Expression checkIgnoredType(TypingContext context) {
+ Expression expression = inferType(context);
+ if(Types.canonical(expression.getType()) != Types.UNIT)
+ expression = new ESimpleLet(location, null, expression, new ELiteral(NoRepConstant.PUNIT));
+ return expression;
+ }
+
+ /**
+ * Checks the type of the expression against the given type. Adds type
+ * applications and lambdas if needed.
+ */
+ public final Expression checkType(TypingContext context, Type requiredType) {
+ //System.out.println("checkType: " + this + " :: " + requiredType);
+ if(!context.isInPattern()) {
+ requiredType = Types.canonical(requiredType);
+ if(requiredType instanceof TForAll) {
+ TForAll forAll = (TForAll)requiredType;
+ TVar var = forAll.var;
+ TVar newVar = Types.var(var.getKind());
+ requiredType = Types.canonical(forAll.type).replace(var, newVar);
+ return new ELambdaType(new TVar[] {newVar}, checkType(context, requiredType));
+ }
+ while(requiredType instanceof TFun) {
+ TFun fun = (TFun)requiredType;
+ if(fun.domain instanceof TPred) { // No need to canonicalize
+ ArrayList<Variable> constraints = new ArrayList<Variable>(2);
+ while(true) {
+ constraints.add(new Variable("constraint", fun.domain));
+ requiredType = Types.canonical(fun.range);
+ if(!(requiredType instanceof TFun))
+ break;
+ fun = (TFun)requiredType;
+ if(!(fun.domain instanceof TPred))
+ break;
+ }
+ context.pushConstraintFrame(constraints.toArray(new Variable[constraints.size()]));
+ Expression expression = checkType(context, requiredType);
+ context.popConstraintFrame();
+ for(int i=constraints.size()-1;i>=0;--i)
+ expression = new ESimpleLambda(constraints.get(i), expression);
+ return expression;
+ }
+ else if(fun.domain == Types.PUNIT) {
+ context.pushEffectUpperBound(location, fun.effect);
+ Expression expr = checkType(context, fun.range);
+ context.popEffectUpperBound();
+
+ // Wrap
+ Variable var = new Variable("punit", Types.PUNIT);
+ return new ESimpleLambda(location, var, fun.effect, expr);
+ }
+ else
+ break;
+ }
+ }
+ return checkBasicType(context, requiredType);
+ }
+
+ public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);
+ public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);
+ public abstract void forVariables(VariableProcedure procedure);
+
+ public Expression decomposeMatching() {
+ return this;
+ }
+
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
+ accept(visitor);
+ return b.toString();
+ }
+
+ protected abstract void updateType() throws MatchException;
+
+ public static class TypeValidationException extends Exception {
+ private static final long serialVersionUID = 3181298127162041248L;
+
+ long loc;
+
+ public TypeValidationException(long loc) {
+ this.loc = loc;
+ }
+
+ public long getLoc() {
+ return loc;
+ }
+
+ public TypeValidationException(long loc, Throwable cause) {
+ super(cause);
+ this.loc = loc;
+ }
+ }
+
+ public static void assertEquals(long loc, Type a, Type b) throws TypeValidationException {
+ if(!Types.equals(a, b))
+ throw new TypeValidationException(loc);
+ }
+
+ public abstract IVal toVal(Environment env, CodeWriter w);
+
+ public Expression closure(TVar ... vars) {
+ if(vars.length == 0)
+ return this;
+ return new ELambdaType(vars, this);
+ }
+
+ public abstract void collectFreeVariables(THashSet<Variable> vars);
+
+ public Expression simplify(SimplificationContext context) {
+ System.out.println("#############################");
+ System.out.println(this);
+ throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support simplify method.");
+ }
+
+ public abstract Expression resolve(TranslationContext context);
+
+ /**
+ * Returns head of the pattern.
+ */
+ public EVar getPatternHead() throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ public LhsType getLhsType() throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ protected void collectVariableNames(PatternMatchingLhs lhsType) throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ public void getParameters(TranslationContext translationContext,
+ ArrayList<Expression> parameters) {
+ throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters.");
+ }
+
+ public Expression resolveAsPattern(TranslationContext context) {
+ context.getErrorLog().log(location, "Pattern was expected here.");
+ return new EError();
+ }
+
+ public void removeFreeVariables(THashSet<Variable> vars) {
+ throw new InternalCompilerError(getClass().getSimpleName() + " is not a pattern.");
+ }
+
+ public Expression checkTypeAsPattern(TypingContext context, Type requiredType) {
+ if(context.isInPattern())
+ throw new InternalCompilerError("Already in a pattern.");
+ context.setInPattern(true);
+ Expression expression = checkType(context, requiredType);
+ context.setInPattern(false);
+ return expression;
+ }
+
+ public THashSet<Variable> getFreeVariables() {
+ THashSet<Variable> result = new THashSet<Variable>();
+ collectFreeVariables(result);
+ return result;
+ }
+
+ public static Expression[] concat(Expression[] a, Expression[] b) {
+ if(a.length == 0)
+ return b;
+ if(b.length == 0)
+ return a;
+ Expression[] result = new Expression[a.length + b.length];
+ for(int i=0;i<a.length;++i)
+ result[i] = a[i];
+ for(int i=0;i<b.length;++i)
+ result[i+a.length] = b[i];
+ return result;
+ }
+
+ public Expression replace(ReplaceContext context) {
+ throw new InternalCompilerError(getClass().getSimpleName() + " does not support replace.");
+ }
+
+ public static Expression[] replace(ReplaceContext context, Expression[] expressions) {
+ Expression[] result = new Expression[expressions.length];
+ for(int i=0;i<expressions.length;++i)
+ result[i] = expressions[i].replace(context);
+ return result;
+ }
+
+ public Expression copy() {
+ return replace(new ReplaceContext(null));
+ }
+
+ public Expression copy(TypingContext typingContext) {
+ return replace(new ReplaceContext(typingContext));
+ }
+
+ public abstract void setLocationDeep(long loc);
+
+ public Expression replaceInPattern(ReplaceContext context) {
+ context.inPattern = true;
+ Expression result = replace(context);
+ context.inPattern = false;
+ return result;
+ }
+
+ public int getFunctionDefinitionPatternArity() throws NotPatternException {
+ throw new NotPatternException(this);
+ }
+
+ public IVal lambdaToVal(Environment env, CodeWriter w) {
+ DecomposedExpression decomposed = DecomposedExpression.decompose(this);
+ CodeWriter newW = w.createFunction(decomposed.typeParameters, decomposed.effect, decomposed.returnType, decomposed.parameterTypes);
+ IVal[] parameters = newW.getParameters();
+ IVal functionVal = newW.getFunction().getTarget();
+ for(int i=0;i<parameters.length;++i)
+ decomposed.parameters[i].setVal(parameters[i]);
+ newW.return_(decomposed.body.toVal(env, newW));
+ return functionVal;
+ }
+
+ public IExpression toIExpression(ExpressionInterpretationContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static IExpression[] toIExpressions(ExpressionInterpretationContext target, Expression[] expressions) {
+ IExpression[] result = new IExpression[expressions.length];
+ for(int i=0;i<expressions.length;++i)
+ result[i] = expressions[i].toIExpression(target);
+ return result;
+ }
+
+ public Expression applyType(Type type) {
+ return new EApplyType(location, this, type);
+ }
+
+ public abstract Expression decorate(ExpressionDecorator decorator);
+
+ public boolean isEffectful() {
+ return true;
+ }
+
+ public boolean isFunctionPattern() {
+ return false;
+ }
+
+ public boolean isConstructorApplication() {
+ return false;
+ }
+
+ public abstract void collectEffects(THashSet<Type> effects);
+
+ public Type getEffect() {
+ THashSet<Type> effects = new THashSet<Type>();
+ collectEffects(effects);
+ return Types.union(effects.toArray(new Type[effects.size()]));
+ }
+
+ public abstract void accept(ExpressionVisitor visitor);
+
+ public void collectRelationRefs(
+ final TObjectIntHashMap<SCLRelation> allRefs, final TIntHashSet refs) {
+ accept(new StandardExpressionVisitor() {
+ @Override
+ public void visit(QAtom query) {
+ int id = allRefs.get(query.relation);
+ if(id >= 0)
+ refs.add(id);
+ }
+ });
+ }
+
+ public boolean isFunctionDefinitionLhs() {
+ return false;
+ }
+
+ public Precedence getPrecedence() {
+ return Precedence.DEFAULT;
+ }
+
+ public boolean isPattern(int arity) {
+ return false;
+ }
+
+ public abstract Expression accept(ExpressionTransformer transformer);
+
+ // TODO implement for all expressions
+ public boolean equalsExpression(Expression expression) {
+ return false;
+ }
+
+ /**
+ * This method returns a lower bound for the function arity of the value this expression defines.
+ * The lower bound is calculated purely looking the syntax of the expression, not the
+ * types of the constants and variables the expression refers to.
+ */
+ public int getSyntacticFunctionArity() {
+ return 0;
+ }
+}
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\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.continuations.ICont;\r
-import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;\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.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\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 GuardedExpressionGroup extends Expression {\r
- public GuardedExpression[] expressions;\r
-\r
- public GuardedExpressionGroup(GuardedExpression[] expressions) {\r
- this.expressions = expressions;\r
- }\r
-\r
- @Override\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs,\r
- TIntHashSet refs) {\r
- for(GuardedExpression expression : expressions) {\r
- for(Expression guard : expression.guards)\r
- guard.collectRefs(allRefs, refs);\r
- expression.value.collectRefs(allRefs, refs);\r
- }\r
- }\r
-\r
- @Override\r
- public void collectVars(TObjectIntHashMap<Variable> allVars,\r
- TIntHashSet vars) {\r
- for(GuardedExpression expression : expressions) {\r
- for(Expression guard : expression.guards)\r
- guard.collectVars(allVars, vars);\r
- expression.value.collectVars(allVars, vars);\r
- }\r
- }\r
-\r
- @Override\r
- protected void updateType() throws MatchException {\r
- setType(expressions[0].value.getType());\r
- }\r
-\r
- @Override\r
- public IVal toVal(Environment env, CodeWriter w) {\r
- CodeWriter success = w.createBlock(getType());\r
- IVal result = success.getParameters()[0];\r
- CodeWriter failure = w.createBlock();\r
- compile(env, w, success.getContinuation(), failure.getContinuation());\r
- w.continueAs(success);\r
- failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());\r
- return result;\r
- //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");\r
- }\r
-\r
- @Override\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- for(GuardedExpression expression : expressions) {\r
- for(Expression guard : expression.guards)\r
- guard.collectFreeVariables(vars);\r
- expression.value.collectFreeVariables(vars);\r
- }\r
- }\r
-\r
- @Override\r
- public Expression simplify(SimplificationContext context) {\r
- for(GuardedExpression expression : expressions) {\r
- for(int i=0;i<expression.guards.length;++i)\r
- expression.guards[i] = expression.guards[i].simplify(context);\r
- expression.value = expression.value.simplify(context);\r
- }\r
- return this;\r
- }\r
-\r
- @Override\r
- public Expression resolve(TranslationContext context) {\r
- for(GuardedExpression expression : expressions) {\r
- for(int i=0;i<expression.guards.length;++i)\r
- expression.guards[i] = expression.guards[i].resolve(context);\r
- expression.value = expression.value.resolve(context);\r
- }\r
- return this;\r
- }\r
- \r
- @Override\r
- public Expression checkBasicType(TypingContext context, Type requiredType) {\r
- for(GuardedExpression expression : expressions) {\r
- for(int i=0;i<expression.guards.length;++i)\r
- expression.guards[i] = expression.guards[i].checkType(context, Types.BOOLEAN);\r
- expression.value = expression.value.checkType(context, requiredType);\r
- }\r
- return this;\r
- }\r
- \r
- public void compile(Environment env, CodeWriter firstWriter, ICont success,\r
- ICont lastFailure) {\r
- // Create all code blocks\r
- CodeWriter[] writers = new CodeWriter[expressions.length]; \r
- ICont[] failures = new ICont[expressions.length];\r
- writers[0] = firstWriter;\r
- failures[expressions.length-1] = lastFailure;\r
- for(int i=1;i<expressions.length;++i) {\r
- CodeWriter writer = firstWriter.createBlock();\r
- writers[i] = writer;\r
- failures[i-1] = writer.getContinuation();\r
- }\r
- \r
- // Compile\r
- for(int i=0;i<expressions.length;++i) {\r
- CodeWriter w = writers[i];\r
- ICont failure = failures[i];\r
- \r
- for(Expression guard : expressions[i].guards) {\r
- CodeWriter nextW = w.createBlock();\r
- w.if_(guard.toVal(env, w), nextW.getContinuation(), failure);\r
- w = nextW;\r
- }\r
- \r
- w.jump(success, expressions[i].value.toVal(env, w));\r
- }\r
- }\r
- \r
- @Override\r
- public Expression replace(ReplaceContext context) {\r
- GuardedExpression[] newExpressions = new GuardedExpression[expressions.length];\r
- for(int i=0;i<expressions.length;++i)\r
- newExpressions[i] = expressions[i].replace(context);\r
- return new GuardedExpressionGroup(newExpressions); \r
- }\r
-\r
- @Override\r
- public Expression decorate(ExpressionDecorator decorator) {\r
- for(GuardedExpression expression : expressions)\r
- expression.decorate(decorator);\r
- return decorator.decorate(this);\r
- }\r
-\r
- @Override\r
- public void collectEffects(THashSet<Type> effects) {\r
- for(GuardedExpression ge : expressions) {\r
- for(Expression guard : ge.guards)\r
- guard.collectEffects(effects);\r
- ge.value.collectEffects(effects);\r
- }\r
- }\r
- \r
- @Override\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- location = loc;\r
- for(GuardedExpression expression : expressions)\r
- expression.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
- for(GuardedExpression expression : expressions)\r
- expression.forVariables(procedure);\r
- }\r
-\r
- @Override\r
- public Expression accept(ExpressionTransformer transformer) {\r
- return transformer.transform(this);\r
- }\r
-}\r
+package org.simantics.scl.compiler.elaboration.expressions;
+
+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.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+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 gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class GuardedExpressionGroup extends Expression {
+ public GuardedExpression[] expressions;
+
+ public GuardedExpressionGroup(GuardedExpression[] expressions) {
+ this.expressions = expressions;
+ }
+
+ @Override
+ public void collectRefs(TObjectIntHashMap<Object> allRefs,
+ TIntHashSet refs) {
+ for(GuardedExpression expression : expressions) {
+ for(Expression guard : expression.guards)
+ guard.collectRefs(allRefs, refs);
+ expression.value.collectRefs(allRefs, refs);
+ }
+ }
+
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars,
+ TIntHashSet vars) {
+ for(GuardedExpression expression : expressions) {
+ for(Expression guard : expression.guards)
+ guard.collectVars(allVars, vars);
+ expression.value.collectVars(allVars, vars);
+ }
+ }
+
+ @Override
+ protected void updateType() throws MatchException {
+ setType(expressions[0].value.getType());
+ }
+
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ CodeWriter success = w.createBlock(getType());
+ IVal result = success.getParameters()[0];
+ CodeWriter failure = w.createBlock();
+ compile(env, w, success.getContinuation(), failure.getContinuation());
+ w.continueAs(success);
+ failure.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
+ return result;
+ //throw new InternalCompilerError("GuardedExpressionGroup should be handled in match compilation.");
+ }
+
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ for(GuardedExpression expression : expressions) {
+ for(Expression guard : expression.guards)
+ guard.collectFreeVariables(vars);
+ expression.value.collectFreeVariables(vars);
+ }
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ for(GuardedExpression expression : expressions) {
+ for(int i=0;i<expression.guards.length;++i)
+ expression.guards[i] = expression.guards[i].simplify(context);
+ expression.value = expression.value.simplify(context);
+ }
+ return this;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ for(GuardedExpression expression : expressions) {
+ for(int i=0;i<expression.guards.length;++i)
+ expression.guards[i] = expression.guards[i].resolve(context);
+ expression.value = expression.value.resolve(context);
+ }
+ return this;
+ }
+
+ @Override
+ public Expression checkBasicType(TypingContext context, Type requiredType) {
+ for(GuardedExpression expression : expressions) {
+ for(int i=0;i<expression.guards.length;++i)
+ expression.guards[i] = expression.guards[i].checkType(context, Types.BOOLEAN);
+ expression.value = expression.value.checkType(context, requiredType);
+ }
+ return this;
+ }
+
+ public void compile(Environment env, CodeWriter firstWriter, ICont success,
+ ICont lastFailure) {
+ // Create all code blocks
+ CodeWriter[] writers = new CodeWriter[expressions.length];
+ ICont[] failures = new ICont[expressions.length];
+ writers[0] = firstWriter;
+ failures[expressions.length-1] = lastFailure;
+ for(int i=1;i<expressions.length;++i) {
+ CodeWriter writer = firstWriter.createBlock();
+ writers[i] = writer;
+ failures[i-1] = writer.getContinuation();
+ }
+
+ // Compile
+ for(int i=0;i<expressions.length;++i) {
+ CodeWriter w = writers[i];
+ ICont failure = failures[i];
+
+ for(Expression guard : expressions[i].guards) {
+ CodeWriter nextW = w.createBlock();
+ w.if_(guard.toVal(env, w), nextW.getContinuation(), failure);
+ w = nextW;
+ }
+
+ w.jump(success, expressions[i].value.toVal(env, w));
+ }
+ }
+
+ @Override
+ public Expression replace(ReplaceContext context) {
+ GuardedExpression[] newExpressions = new GuardedExpression[expressions.length];
+ for(int i=0;i<expressions.length;++i)
+ newExpressions[i] = expressions[i].replace(context);
+ return new GuardedExpressionGroup(newExpressions);
+ }
+
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ for(GuardedExpression expression : expressions)
+ expression.decorate(decorator);
+ return decorator.decorate(this);
+ }
+
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ for(GuardedExpression ge : expressions) {
+ for(Expression guard : ge.guards)
+ guard.collectEffects(effects);
+ ge.value.collectEffects(effects);
+ }
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ for(GuardedExpression expression : expressions)
+ expression.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ for(GuardedExpression expression : expressions)
+ expression.forVariables(procedure);
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public int getSyntacticFunctionArity() {
+ return expressions[0].value.getSyntacticFunctionArity();
+ }
+}
public String toString() {
return getErrorsAsString();
}
+
+ public int getErrorCount() {
+ return errors.size();
+ }
}
-\r
-data Foo a = Foo a\r
-\r
-f :: Foo a -> a\r
-f = \Foo a -> a \r
-\r
-main = "Not to be executed"\r
---\r
-5:6-5:11: Arity is 1 but 2 patterns have been given.
\ No newline at end of file
+data Foo a = Foo a
+
+f :: Foo a -> a
+f = \Foo a -> a
+
+main = "Not to be executed"
+--
+3:1-3:2: Possible problem: type declaration has 1 parameter types, but function definition has 2 parameters.
+4:6-4:11: Arity is 1 but 2 patterns have been given.
+--
+import "Prelude"
+
+f :: Integer -> Integer -> <Proc> Integer
+f x = do
+ print x
+ x
+
+main = "Not to be executed"
+--
+3:1-3:2: Possible problem: type declaration has 2 parameter types, but function definition has 1 parameters.
+5:5-5:12: No side-effects allowed here.
+6:5-6:6: Expected <Integer -> <Proc> Integer> got <Integer>.
\ No newline at end of file