def chkParams(lst,buff):
    if lst.kind == -4:
        return lst
    if lst.getString() == 'NIL':
        return 'T'
    obj = car(lst)
   
    if(obj.getString() not in buff and not isPrimitive(obj.getString())):
        buff.append(obj.getString())
        return chkParams(cdr(lst), buff)
    else:
        return -4
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