package org.simantics.scl.compiler.elaboration.macros; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.ELambda; import org.simantics.scl.compiler.elaboration.expressions.ELambdaType; import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.types.TVar; import org.simantics.scl.compiler.types.Type; import gnu.trove.map.hash.THashMap; /** * This is a macro rule that replaces an application with * the definition of the function. * @author Hannu Niemistö */ public class StandardMacroRule implements MacroRule { Expression baseExpression; int arity; public StandardMacroRule() { } public void setBaseExpression(Expression baseExpression) { this.baseExpression = baseExpression; Expression cur = baseExpression; while(true) { if(cur instanceof ELambdaType) { cur = ((ELambdaType)cur).value; } else if(cur instanceof ELambda) { ELambda lambda = (ELambda)cur; arity += lambda.getCases()[0].getPatterns().length; break; } else if(cur instanceof ESimpleLambda) { ESimpleLambda lambda = (ESimpleLambda)cur; cur = lambda.value; ++arity; } else break; } } @Override public Expression apply(SimplificationContext context, Type[] typeParameters, EApply apply) { if(apply.getParameters().length < arity) return null; THashMap tvarMap = new THashMap(); THashMap varMap = new THashMap(); Expression baseExpr = baseExpression; /*System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); TypeUnparsingContext tuc = new TypeUnparsingContext(); System.out.println("initial1 = " + baseExpr.toString(tuc)); */ { int typeParameterId = 0; while(typeParameterId < typeParameters.length) { ELambdaType lambda = (ELambdaType)baseExpr; for(TVar var : lambda.parameters) tvarMap.put(var, typeParameters[typeParameterId++]); baseExpr = lambda.value; } } for(Expression parameter : apply.getParameters()) { if(baseExpr instanceof ELambda) baseExpr = ((ELambda)baseExpr).decomposeMatching(); ESimpleLambda lambda = (ESimpleLambda)baseExpr; varMap.put(lambda.parameter, parameter); baseExpr = lambda.value; } /* System.out.println("initial2 = " + baseExpr.toString(tuc)); System.out.print("tvarMap={"); boolean first = true; for(Map.Entry entry : tvarMap.entrySet()) { if(first) first = false; else System.out.print(", "); System.out.print(entry.getKey().toString(tuc)); System.out.print(" = "); System.out.print(entry.getValue().toString(tuc)); } System.out.println("}"); System.out.println("varMap = " + varMap); */ baseExpr = baseExpr.replace(new ReplaceContext(tvarMap, varMap, null)); //System.out.println("final = " + baseExpr.toString(tuc)); return baseExpr; } }