def evlis (lst, alst,dLst): if lst.kind==-4: return lst if isNull(lst) == 'T': return dLst['NIL'] else: return cons(evaluate(car(lst),alst,dLst),evlis(cdr(lst),alst,dLst))
def apply_function(f,x,alst,dLst): if x.kind==3 and (x.left.getString()=='NIL' and x.right.getString()=='NIL'): x=dLst['NIL'] if f.kind==-4: return f if x.kind == -4: return x if atom(f) == 'T' : if eq(f,dLst['CAR']) == 'T' : return car(car(x)) elif eq(f,dLst['CDR']) == 'T' : return cdr(car(x)) elif eq(f,dLst['CONS']) == 'T' : if(cdr(cdr(x)).getString()!='NIL'): errorObj = SExp.SExp(-4) errorObj.string = 'CONS takes only two atomic arguments' return errorObj return cons(car(x),car(cdr(x))) elif eq(f,dLst['ATOM']) == 'T' : if(cdr(x).getString()=='NIL'): return dLst[atom(car(x))] return dLst[atom(x)] elif eq(f,dLst['INT']) == 'T' : if(cdr(x).getString()=='NIL'): return dLst[isInt(car(x))] return dLst[atom(x)] elif eq(f,dLst['NULL']) == 'T' : return dLst[isNull(x)] elif eq(f,dLst['PLUS']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'PLUS takes only two integer arguments' return errorObj obj=plus(car(x),car(cdr(x))) if(obj.kind==-4): return obj if(obj.value not in dLst.keys()): dLst[obj.value]=obj setDict(dLst) return obj elif eq(f,dLst['MINUS']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'MINUS takes only two integer arguments' return errorObj obj=minus(car(x),car(cdr(x))) if(obj.value not in dLst.keys()): dLst[obj.value]=obj setDict(dLst) return obj elif eq(f,dLst['TIMES']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'TIMES takes only two integer arguments' return errorObj obj=times(car(x),car(cdr(x))) if(obj.value not in dLst.keys()): dLst[obj.value]=obj setDict(dLst) return obj elif eq(f,dLst['QUOTIENT']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'QUOTIENT takes only two integer arguments' return errorObj obj=divide(car(x),car(cdr(x))) if(obj.value not in dLst.keys()): dLst[obj.value]=obj setDict(dLst) return obj elif eq(f,dLst['REMAINDER']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'REMAINDER takes only two integer arguments' return errorObj obj=mod(car(x),car(cdr(x))) if(obj.value not in dLst.keys()): dLst[obj.value]=obj setDict(dLst) return obj elif eq(f,dLst['LESS']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'LESS takes only two integer arguments' return errorObj return dLst[lt(car(x),car(cdr(x)))] elif eq(f,dLst['GREATER']) == 'T' : if(cdr(cdr(x)).getString()!='NIL' or car(x).kind!=1 or car(cdr(x)).kind!=1): errorObj = SExp.SExp(-4) errorObj.string = 'GREATER takes only two integer arguments' return errorObj return dLst[gt(car(x),car(cdr(x)))] elif eq(f,dLst['EQ']) == 'T' : if(cdr(cdr(x)).getString()!='NIL'): errorObj = SExp.SExp(-4) errorObj.string = 'EQ takes only two atomic arguments' return errorObj res=eq(car(x),car(cdr(x))) if res == 'T' or res=='NIL': return dLst[res] else: return res else: try: tlst = getDefLst() if f.getString() not in tlst.keys(): errorObj = SExp.SExp(-4) errorObj.string = 'Undefined function:'+f.getString() return errorObj fundef = tlst[f.getString()] setDefun(True) return evaluate(car(cdr(fundef)),addpairs(car(fundef),x,alst,dLst),dLst) except: errorObj = SExp.SExp(-4) errorObj.string = 'Improper input for function or function execution did not complete' return errorObj