package function.builtin; import function.*; import sexpression.*; import table.*; public class SET extends LispFunction { private ArgumentValidator argumentValidator; private ExecutionContext executionContext; public SET() { this.argumentValidator = new ArgumentValidator("SET"); this.argumentValidator.setExactNumberOfArguments(2); this.argumentValidator.setFirstArgumentExpectedType(Symbol.class); this.executionContext = ExecutionContext.getInstance(); } public SExpression call(Cons argumentList) { argumentValidator.validate(argumentList); Cons rest = (Cons) argumentList.getRest(); SExpression symbol = argumentList.getFirst(); SExpression value = rest.getFirst(); SymbolTable table = findScopeOfSymbol(symbol); table.put(symbol.toString(), value); return value; } private SymbolTable findScopeOfSymbol(SExpression symbol) { SymbolTable table = executionContext.getScope(); while (!isSymbolInTable(symbol, table) && !isGlobalTable(table)) table = table.getParent(); return table; } private boolean isSymbolInTable(SExpression symbol, SymbolTable table) { return table.contains(symbol.toString()); } private boolean isGlobalTable(SymbolTable table) { return table.getParent() == null; } }