package org.simantics.scl.compiler.elaboration.expressions;
import java.util.ArrayList;
+import java.util.Set;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.precedence.Precedence;
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.expressions.visitors.CollectEffectsVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectFreeVariablesVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectRefsVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.CollectVarsVisitor;
import org.simantics.scl.compiler.elaboration.expressions.visitors.ForVariablesUsesVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.visitors.StandardExpressionVisitor;
import org.simantics.scl.compiler.elaboration.query.QAtom;
import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
import org.simantics.scl.compiler.internal.codegen.references.IVal;
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 {
try {
updateType();
} catch (MatchException e) {
- throw new InternalCompilerError(e);
+ throw new InternalCompilerError(location, e);
}
if(type == null)
- throw new InternalCompilerError(getClass().getSimpleName() +
+ throw new InternalCompilerError(location, getClass().getSimpleName() +
".updateType couldn't compute its type.");
}
return type;
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) {
+
+ /**
+ * 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) {
+ while(requiredType instanceof TFun) {
TFun fun = (TFun)requiredType;
if(fun.domain instanceof TPred) { // No need to canonicalize
ArrayList<Variable> constraints = new ArrayList<Variable>(2);
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);
- }
+ }
+ return checkBasicType(context, requiredType);
+ }
- public abstract void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs);
- public abstract void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars);
+ public final void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ accept(new CollectRefsVisitor(allRefs, refs));
+ }
- public void forVariableUses(VariableProcedure procedure) {
+ public final void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+ accept(new CollectVarsVisitor(allVars, vars));
+ }
+
+ public final void forVariableUses(VariableProcedure procedure) {
accept(new ForVariablesUsesVisitor(procedure));
}
return new ELambdaType(vars, this);
}
- public abstract void collectFreeVariables(THashSet<Variable> vars);
-
public Expression simplify(SimplificationContext context) {
System.out.println("#############################");
System.out.println(this);
public void getParameters(TranslationContext translationContext,
ArrayList<Expression> parameters) {
- throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not support getParameters.");
+ throw new InternalCompilerError(location, "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.");
+ throw new InternalCompilerError(location, "Already in a pattern.");
context.setInPattern(true);
Expression expression = checkType(context, requiredType);
context.setInPattern(false);
/**
* Used during simplification and in toIExpression
*/
- public THashSet<Variable> getFreeVariables() {
- THashSet<Variable> result = new THashSet<Variable>();
- collectFreeVariables(result);
- return result;
+ public Set<Variable> getFreeVariables() {
+ CollectFreeVariablesVisitor visitor = new CollectFreeVariablesVisitor();
+ accept(visitor);
+ return visitor.getFreeVariables();
}
public static Expression[] concat(Expression[] a, Expression[] b) {
}
public Expression replace(ReplaceContext context) {
- throw new InternalCompilerError(getClass().getSimpleName() + " does not support replace.");
+ throw new InternalCompilerError(location, getClass().getSimpleName() + " does not support replace.");
}
public static Expression[] replace(ReplaceContext context, Expression[] expressions) {
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()]));
+ CollectEffectsVisitor visitor = new CollectEffectsVisitor();
+ accept(visitor);
+ return visitor.getCombinedEffect();
}
public abstract void accept(ExpressionVisitor visitor);