package table; import function.LispFunction; import sexpression.Cons; import sexpression.SExpression; import java.util.Stack; import static sexpression.Nil.NIL; public class ExecutionContext { private static ExecutionContext uniqueInstance = new ExecutionContext(); public static ExecutionContext getInstance() { return uniqueInstance; } private SymbolTable scope; private Stack functionCalls; private boolean recur; private ExecutionContext() { clearContext(); } public void clearContext() { this.scope = new SymbolTable(); this.functionCalls = new Stack<>(); this.clearRecur(); } public SymbolTable getScope() { return scope; } public void setScope(SymbolTable scope) { this.scope = scope; } public void restoreGlobalScope() { while (!scope.isGlobal()) scope = scope.getParent(); } public SExpression lookupSymbolValue(String symbolName) { for (SymbolTable t = scope; t != null; t = t.getParent()) if (t.contains(symbolName)) return t.get(symbolName); return null; } public Cons toList() { Cons symbols = NIL; for (SymbolTable t = scope; t != null; t = t.getParent()) symbols = new Cons(t.toList(), symbols); return symbols; } public void pushFunctionCall(LispFunction function) { functionCalls.push(new LispFunctionRecurInfo(function)); } public void popFunctionCall() { functionCalls.pop(); } public boolean isInFunctionCall() { return !functionCalls.empty(); } public LispFunction getCurrentFunction() { return functionCalls.peek().getLispFunction(); } public boolean isRecur() { return recur; } public void setRecur() { recur = true; } public void clearRecur() { recur = false; } public boolean isRecurInitializing() { return functionCalls.peek().isRecurInitializing(); } public void setRecurInitializing() { functionCalls.peek().setRecurInitializing(); } public void clearRecurInitializing() { functionCalls.peek().clearRecurInitializing(); } public static class LispFunctionRecurInfo { private LispFunction lispFunction; private boolean recurInitializing; public LispFunctionRecurInfo(LispFunction lispFunction) { this.lispFunction = lispFunction; this.clearRecurInitializing(); } public boolean isRecurInitializing() { return recurInitializing; } public void setRecurInitializing() { this.recurInitializing = true; } public void clearRecurInitializing() { this.recurInitializing = false; } public LispFunction getLispFunction() { return lispFunction; } } }