package org.simantics.scl.compiler.elaboration.expressions.list; 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.expressions.Expression; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.types.TMetaVar; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.UnificationException; import org.simantics.scl.compiler.types.kinds.Kinds; public class ListThen extends ListQualifier { public ListQualifier left; public Expression transformer; public Expression by; // optional TMetaVar cType; public ListThen(Expression transformer, Expression by) { this.transformer = transformer; this.by = by; } public void setLeft(ListQualifier inner) { this.left = inner; } @Override public void checkType(TypingContext context) { left.checkType(context); cType = Types.metaVar(Kinds.STAR); Type transformerType = Types.function(Types.list(cType), Types.list(cType)); if(by != null) { by = by.checkType(context, Types.metaVar(Kinds.STAR)); transformerType = Types.function(Types.function(cType, by.getType()), transformerType); } transformer = transformer.checkType(context, transformerType); if(!(Types.canonical(cType) instanceof TMetaVar)) { context.getErrorLog().log(location, "Transformation function must be generic on list elements."); } } @Override public CompiledQualifier compile(SimplificationContext context) { CompiledQualifier q = left.compile(context); try { Types.unify(cType, q.pattern.getType()); } catch (UnificationException e) { context.getErrorLog().log(location, "Transformation function must be generic on list elements."); } if(by == null) q.value = context.apply(transformer, q.value); else q.value = context.apply(transformer, context.lambda(q.pattern.copy(), by), q.value); return q; } @Override public void resolve(TranslationContext context) { transformer = transformer.resolve(context); left.resolve(context); if(by != null) by = by.resolve(context); } @Override public void setLocationDeep(long loc) { if(location == Locations.NO_LOCATION) { location = loc; left.setLocationDeep(loc); transformer.setLocationDeep(loc); if(by != null) by.setLocationDeep(loc); } } @Override public void accept(ListQualifierVisitor visitor) { visitor.visit(this); } @Override public ListQualifier accept(ListQualifierTransformer transformer) { return transformer.transform(this); } }