package expressions; import java.util.Set; import java.util.TreeSet; import types.MonoType; import common.prettyprinter.PrettyStringBuilder; /** * Represents a lambda abstraction. * * @author Benedikt Meurer * @version $Id$ */ public final class Lambda extends Value { // // Attributes // /** * The identifier for the parameter. * * @see #getId() */ private String id; /** * The type of the parameter or <code>null</code>. * * @see #getTau() */ private MonoType tau; /** * The expression in the body. * * @see #getE() */ private Expression e; // // Constructors // /** * Convenience wrapper for {@link #Lambda(String, MonoType, Expression)} * passing <code>null</code> for <code>tau</code>. * * @param id the name of the parameter. * @param e the expression. * * @throws NullPointerException if <code>id</code> or <code>e</code> * is <code>null</code>. */ public Lambda(String id, Expression e) { this(id, null, e); } /** * Generates a new abstraction. * * @param id the name of the parameter. * @param tau the {@link types.MonoType} for the <code>id</code>, * or <code>null</code> if no type is known. * @param e the expression. * * @throws NullPointerException if <code>id</code> or <code>e</code> * is <code>null</code>. */ public Lambda(String id, MonoType tau, Expression e) { if (id == null) { throw new NullPointerException("id is null"); } if (e == null) { throw new NullPointerException("e is null"); } this.id = id; this.tau = tau; this.e = e; } // // Accessors // /** * @return Returns the id. */ public String getId() { return this.id; } /** * @return Returns the tau. */ public MonoType getTau() { return this.tau; } /** * @return Returns the e. */ public Expression getE() { return this.e; } // // Primitives // /** * Performs the substitution for <b>(LAMBDA)</b> expressions. * * @param id the identifier for the substitution. * @param e the expression to substitute. * * @return the new expression. */ @Override public Expression substitute(String id, Expression e) { if (this.id.equals(id)) { return this; } else { // determine the free identifiers for e Set<String> free = e.free(); // generate a new unique identifier String newId = this.id; while (free.contains(newId)) newId = newId + "'"; // perform the bound renaming Expression newE = this.e.substitute(this.id, new Identifier(newId)); // perform the substitution return new Lambda(newId, this.tau, newE.substitute(id, e)); } } /** * Returns the free identifiers minus the bound identifier. * @return the free identifiers minus the bound identifier. * @see expressions.Expression#free() */ @Override public Set<String> free() { Set<String> set = new TreeSet<String>(); set.addAll(this.e.free()); set.remove(this.id); return set; } /** * Returns the pretty string builder for abstractions. * @return the pretty string builder for abstractions. * @see expressions.Expression#toPrettyStringBuilder() */ @Override protected PrettyStringBuilder toPrettyStringBuilder() { PrettyStringBuilder builder = new PrettyStringBuilder(this, 0); builder.appendKeyword("\u03bb"); builder.appendText(this.id); if (this.tau != null) { builder.appendText(":"); builder.appendText(this.tau.toString()); } builder.appendText("."); builder.appendBuilder(this.e.toPrettyStringBuilder(), 0); return builder; } }