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;
}
}