package org.simantics.scl.compiler.elaboration.expressions; import java.util.ArrayList; import org.simantics.scl.compiler.common.names.Name; import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.constants.NoRepConstant; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.elaboration.errors.NotPatternException; import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType; import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs; import org.simantics.scl.compiler.elaboration.java.ListConstructor; import org.simantics.scl.compiler.elaboration.macros.MacroRule; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.codegen.references.IVal; import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; import org.simantics.scl.compiler.internal.interpreted.IApply; import org.simantics.scl.compiler.internal.interpreted.IExpression; import org.simantics.scl.compiler.internal.interpreted.IListLiteral; import org.simantics.scl.compiler.top.ExpressionInterpretationContext; import org.simantics.scl.compiler.types.Skeletons; import org.simantics.scl.compiler.types.TFun; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; import org.simantics.scl.compiler.types.exceptions.UnificationException; import org.simantics.scl.compiler.types.kinds.Kinds; import org.simantics.scl.compiler.types.util.MultiFunction; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.TIntHashSet; public class EApply extends Expression { public Expression function; public Expression[] parameters; public Type effect = Types.NO_EFFECTS; public EApply(Expression function, Expression ... parameters) { this.function = function; this.parameters = parameters; } public EApply(Expression function, Expression parameter) { this(function, new Expression[] {parameter}); } public EApply(long loc, Expression function, Expression ... parameters) { super(loc); this.function = function; this.parameters = parameters; } public EApply(long loc, Type effect, Expression function, Expression ... parameters) { super(loc); this.effect = effect; this.function = function; this.parameters = parameters; } public void set(Expression function, Expression[] parameters) { this.function = function; this.parameters = parameters; } public Expression getFunction() { return function; } public Expression[] getParameters() { return parameters; } public void collectVars(TObjectIntHashMap 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) { function.getParameters(context, parameters); for(Expression parameter : this.parameters) parameters.add(parameter); } @Override public Expression replace(ReplaceContext context) { return new EApply( getLocation(), effect.replace(context.tvarMap), function.replace(context), replace(context, parameters)); } @Override public void setLocationDeep(long loc) { if(location == Locations.NO_LOCATION) { location = loc; function.setLocationDeep(loc); for(Expression parameter : parameters) parameter.setLocationDeep(loc); } } @Override public int getFunctionDefinitionPatternArity() throws NotPatternException { return function.getFunctionDefinitionPatternArity() + parameters.length; } @Override public IExpression toIExpression(ExpressionInterpretationContext target) { IExpression[] parametersI = toIExpressions(target, parameters); Expression function = this.function; while(function instanceof EApplyType) function = ((EApplyType)function).expression; // Special cases if(function instanceof EConstant) { SCLValue functionValue = ((EConstant)function).value; Name name = functionValue.getName(); if(name.module.equals("Builtin")) { IVal val = functionValue.getValue(); if(val instanceof ListConstructor) { if(((ListConstructor)val).arity == parametersI.length) return new IListLiteral(parametersI); } } } //System.out.println("--> " + function + " " + function.getClass().getSimpleName()); // The basic case return new IApply(function.toIExpression(target), parametersI); } private void inferType(TypingContext context, boolean ignoreResult) { function = function.inferType(context); function = context.instantiate(function); MultiFunction mfun; try { mfun = Types.unifyFunction(function.getType(), parameters.length); } catch (UnificationException e) { int arity = Types.getArity(function.getType()); if(arity == 0) context.getErrorLog().log(location, "Application of non-function."); else context.getErrorLog().log(location, "Function of arity " + arity + " is applied with " + parameters.length + " parameters."); setType(Types.metaVar(Kinds.STAR)); for(int i=0;i=0;--i) { Expression parameter = parameters[i]; if(parameter.isEffectful()) { Variable var = new Variable("aNormalTemp" + i, parameter.getType()); expression = new ESimpleLet(var, parameter, expression); parameters[i] = new EVariable(var); } } if(function.isEffectful()) { Variable var = new Variable("aNormalTempF", function.getType()); expression = new ESimpleLet(var, function, expression); function = new EVariable(var); } return expression; } @Override public boolean isEffectful() { if(effect != Types.NO_EFFECTS) return true; for(Expression parameter : parameters) if(parameter.isEffectful()) return true; if(function.isEffectful()) return true; return false; } @Override public boolean isFunctionPattern() { return !isConstructorApplication(); } @Override public boolean isConstructorApplication() { return function.isConstructorApplication(); } @Override public void accept(ExpressionVisitor visitor) { visitor.visit(this); } @Override public boolean isFunctionDefinitionLhs() { try { EVar patternHead = function.getPatternHead(); return !Character.isUpperCase(patternHead.name.charAt(0)); } catch(NotPatternException e) { return false; } } @Override public boolean isPattern(int arity) { if(!function.isPattern(arity+parameters.length)) return false; for(Expression parameter : parameters) if(!parameter.isPattern(0)) return false; return true; } @Override public Expression accept(ExpressionTransformer transformer) { return transformer.transform(this); } @Override public boolean equalsExpression(Expression expression) { if(expression.getClass() != getClass()) return false; EApply other = (EApply)expression; if(parameters.length != other.parameters.length) return false; if(!function.equalsExpression(other.function)) return false; for(int i=0;i