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
def evaluate(exp, alst,dLst): if(exp.kind==-4): return exp if atom(exp) == 'T': if isInt(exp) == 'T': return exp elif eq(exp,dLst['T']) == 'T': return dLst['T'] elif eq(exp,dLst['NIL']) == 'T': return dLst['NIL'] elif getMapping(exp.getString(),alst,False).kind!=-4: return getMapping(exp.getString(),alst,True) else: errorObj = SExp.SExp(-4) errorObj.string = 'Unbound Variable' return errorObj elif atom(car(exp))=='T': if eq(car(exp),dLst['QUOTE']) == 'T': if cdr(exp).right.getString() == 'NIL': return car(cdr(exp)) else: errorObj = SExp.SExp(-4) errorObj.string = 'Too Many Args for QUOTE' return errorObj elif eq(car(exp),dLst['COND']) == 'T': return evconHelper(cdr(exp),alst,dLst) elif eq(car(exp),dLst['DEFUN']) == 'T': key = car(cdr(exp)) if cdr(cdr(cdr(cdr(exp)))).getString()!='NIL': errorObj = SExp.SExp(-4) errorObj.string = 'Invalid Defun syntax' return errorObj if isPrimitive(key.getString()) : errorObj = SExp.SExp(-4) errorObj.string = 'Cannot replace primitives' return errorObj temp = cdr(exp) val=cdr(temp) res = chkParams(car(val),[]) if res == 'T': tlst = getDefLst() splt = val.getString().replace('(', ' ( ').replace(')',' ) ').replace('.',' . ').split() if 'DEFUN' in splt: errorObj = SExp.SExp(-4) errorObj.string = 'Cannot Define function inside a UDF' return errorObj tlst[key.getString()]=val setDefLst(tlst) return key else: if res == -4: errorObj = SExp.SExp(-4) errorObj.string = 'Parameter Names Should Be Unique and non primitives' return errorObj return res else: return apply_function(car(exp),evlis(cdr(exp),alst,dLst),alst,dLst) else: errorObj = SExp.SExp(-4) errorObj.string = 'Invalid Eval Expression' return errorObj