package calculator.interpreter.ast.vars; import java.util.LinkedList; import calculator.interpreter.Cell; import calculator.interpreter.Environment; import calculator.interpreter.ast.ExpressionStatement; import calculator.interpreter.ast.Statement; /** * The letrec allows defining mutually recursive definitions. It is equivalent * to a sequence of unbounded let statements followed by assignment. */ public class LetRec extends Statement { /** definitions from letrec */ public final LinkedList<LetRecPart> definitions = new LinkedList<LetRecPart>(); /** true means that letrec parts has been already transformed */ private boolean converted = false; /** transformed statements */ private final LinkedList<Statement> statements = new LinkedList<Statement>(); @Override public Environment eval(Environment env, Cell result) { if (!converted) { for (LetRecPart p : definitions) { VarStatement s = new VarStatement(); s.location = p.location; Statement metadataSource = p.hasMetadata() ? p : this.hasMetadata() ? this : null; if (metadataSource != null) { s.annotations.addAll(metadataSource.annotations); s.documentation.addAll(metadataSource.documentation); } s.name = p.name; statements.add(s); } for (LetRecPart p : definitions) { ExpressionStatement s = new ExpressionStatement(); s.location = p.location; Assignment a = new Assignment(); a.location = p.location; a.first = p.name; a.second = p.value; s.value = a; statements.add(s); } converted = true; } for (Statement s : statements) { if (result != null) result.value = null; env = s.eval(env, result); } return env; } }