package expressions; import java.util.Set; import java.util.TreeSet; import common.prettyprinter.PrettyStringBuilder; import expressions.annotation.SyntacticSugar; /** * Represents the <code>let rec</code> expression, which is * syntactic sugar for <b>(LET)</b> and <b>(REC)</b>. * * The expression * <pre>let rec id = e1 in e2</pre> * is equal to * <pre>let id = rec id.e1 in e2</pre> * * @author Benedikt Meurer * @version $Id$ */ @SyntacticSugar public final class LetRec extends Let { // // Constructor // /** * Generates a new let rec expression. * * @param id the name of the identifier. * @param e1 the first expression. * @param e2 the second expression. */ public LetRec(String id, Expression e1, Expression e2) { super(id, e1, e2); } // // Primitives // /** * Performs the substitution on let rec expressions. * * @param id the identifier for the substitution. * @param e the expression to substitute. * * @return the new expression. * * @see expressions.Expression#substitute(java.lang.String, expressions.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 newE1 = this.e1.substitute(this.id, new Identifier(newId)); // perform the substitution return new LetRec(newId, newE1.substitute(id, e), this.e2.substitute(id, e)); } } /** * Returns the free identifiers of * the subexpressions. * * @return the free identifiers. * * @see expressions.Expression#free() */ @Override public Set<String> free() { Set<String> set = new TreeSet<String>(); set.addAll(this.e2.free()); set.addAll(this.e1.free()); set.remove(this.id); return set; } /** * Translates the syntactic sugar for the <b>(LET-REC)</b> * and its subexpressions to the core syntax. * * @return the new expression in the core syntax. * * @see expressions.Expression#translateSyntacticSugar() */ @Override public Expression translateSyntacticSugar() { return new Let(this.id, new Recursion(this.id, this.e1), this.e2); } /** * Returns the pretty string builder for let rec expressions. * @return the pretty string builder for let rec expressions. * @see expressions.Expression#toPrettyStringBuilder() */ @Override protected PrettyStringBuilder toPrettyStringBuilder() { PrettyStringBuilder builder = new PrettyStringBuilder(this, 0); builder.appendKeyword("let"); builder.appendText(" "); builder.appendKeyword("rec"); builder.appendText(" " + this.id + " = "); builder.appendBuilder(this.e1.toPrettyStringBuilder(), 0); builder.appendBreak(); builder.appendText(" "); builder.appendKeyword("in"); builder.appendText(" "); builder.appendBuilder(this.e2.toPrettyStringBuilder(), 0); return builder; } }