// ---------------------------------------------------------------------------
// - Predicate.cpp                                                           -
// - afnix engine - predicate builtin functions implementation               -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  is  distributed in  the hope  that it will be useful, but -
// - without  any  warranty;  without  even   the   implied    warranty   of -
// - merchantability or fitness for a particular purpose.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2019 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Set.hpp"
#include "Byte.hpp"
#include "Real.hpp"
#include "Form.hpp"
#include "List.hpp"
#include "Enum.hpp"
#include "Item.hpp"
#include "Fifo.hpp"
#include "Heap.hpp"
#include "Tree.hpp"
#include "Queue.hpp"
#include "Regex.hpp"
#include "Plist.hpp"
#include "Lockf.hpp"
#include "Buffer.hpp"
#include "Combo.hpp"
#include "Loader.hpp"
#include "Thrset.hpp"
#include "Reader.hpp"
#include "Strvec.hpp"
#include "Vector.hpp"
#include "Bitset.hpp"
#include "Locale.hpp"
#include "Logger.hpp"
#include "Symbol.hpp"
#include "Numeral.hpp"
#include "Message.hpp"
#include "Options.hpp"
#include "Lexical.hpp"
#include "Condvar.hpp"
#include "Relatif.hpp"
#include "Builtin.hpp"
#include "Boolean.hpp"
#include "Promise.hpp"
#include "Closure.hpp"
#include "Counter.hpp"
#include "Resolver.hpp"
#include "Instance.hpp"
#include "Exception.hpp"
#include "Character.hpp"
#include "HashTable.hpp"
#include "Qualified.hpp"
#include "Librarian.hpp"
#include "AliasTable.hpp"
#include "PrintTable.hpp"
#include "BlockBuffer.hpp"

namespace afnix {

  // this procedure checks that we have one argument only and returns
  // the evaluated object
  static inline Object* get_obj (Runnable* robj, Nameset* nset, Cons* args,
				 const String& pname) {
    if ((args == nullptr) || (args->length () != 1))
      throw Exception ("argument-error", "illegal arguments with predicate",
		       pname);
    Object* car = args->getcar ();
    Object* obj = (car == nullptr) ? nullptr : car->eval (robj,nset);
    return obj;
  }

  // nilp: nilp predicate

  Object* builtin_nilp (Runnable* robj, Nameset* nset, Cons* args) {
    if (args == nullptr) return new Boolean (true);
    Object* obj = get_obj (robj, nset, args, "nil-p");
    bool result = (obj == nullptr) ? true : false;
    Object::cref (obj);
    return new Boolean (result);
  }

  // objp: object predicate

  Object* builtin_objp (Runnable* robj, Nameset* nset, Cons* args) {
    if (args == nullptr) return new Boolean (false);
    Object* obj = get_obj (robj, nset, args, "object-p");
    bool result = (obj == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // evlp: eval predicate

  Object* builtin_evlp (Runnable* robj, Nameset* nset, Cons* args) {
    try {
      Object* obj = get_obj (robj, nset, args, "eval-p");
      Object::cref (obj);
      return new Boolean (true);
    } catch (Exception&) {
      return new Boolean (false);
    }
  }
  
  // cblp: collectable predicate

  Object* builtin_cblp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "collectable-p");
    bool result = (dynamic_cast <Collectable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // srlp: serial predicate

  Object* builtin_srlp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "serial-p");
    bool result = (dynamic_cast <Serial*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // nblp: nameable predicate

  Object* builtin_nblp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "nameable-p");
    bool result = (dynamic_cast <Nameable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // symp: symbol predicate

  Object* builtin_symp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "symbol-p");
    bool result = (dynamic_cast <Symbol*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // lexp: lexical predicate

  Object* builtin_lexp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "lexical-p");
    bool result = (dynamic_cast <Lexical*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // setp: set predicate

  Object* builtin_setp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "set-p");
    bool result = (dynamic_cast <Set*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // clop: closure predicate

  Object* builtin_clop (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "closure-p");
    bool result = (dynamic_cast <Closure*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // quap: qualified predicate

  Object* builtin_qualp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "qualified-p");
    bool result = (dynamic_cast <Qualified*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // nump: number predicate

  Object* builtin_nump (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "number-p");
    bool result = (dynamic_cast <Number*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);

  }

  // intp: integer predicate

  Object* builtin_intp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "integer-p");
    bool result = (dynamic_cast <Integer*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // rltp: relatif predicate

  Object* builtin_rltp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "relatif-p");
    bool result = (dynamic_cast <Relatif*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // bytep: byte predicate

  Object* builtin_bytep (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "byte-p");
    bool result = (dynamic_cast <Byte*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // realp: real predicate

  Object* builtin_realp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "real-p");
    bool result = (dynamic_cast <Real*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // numrp: numeral predicate

  Object* builtin_numrp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "numeral-p");
    bool result = (dynamic_cast <Numeral*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // boolp: boolean predicate

  Object* builtin_boolp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "boolean-p");
    bool result = (dynamic_cast <Boolean*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // charp: character predicate

  Object* builtin_charp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "character-p");
    bool result = (dynamic_cast <Character*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // strp: string predicate

  Object* builtin_strp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "string-p");
    bool result = (dynamic_cast <String*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // litp: literal predicate

  Object* builtin_litp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "literal-p");
    bool result = (dynamic_cast <Literal*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // bufp: buffer predicate

  Object* builtin_bufp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "buffer-p");
    bool result = (dynamic_cast <Buffer*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
   
  // stvp: string vector predicate

  Object* builtin_stvp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "strvec-p");
    bool result = (dynamic_cast <Strvec*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // vecp: vector predicate

  Object* builtin_vecp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "vector-p");
    bool result = (dynamic_cast <Vector*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // consp: cons predicate

  Object* builtin_consp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "cons-p");
    bool result = (dynamic_cast <Cons*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // formp: form predicate

  Object* builtin_formp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "form-p");
    bool result = (dynamic_cast <Form*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // listp: list predicate

  Object* builtin_listp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "list-p");
    bool result = (dynamic_cast <List*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // cmbp: combo predicate

  Object* builtin_cmbp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "combo-p");
    bool result = (dynamic_cast <Combo*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }


  // nstp: nameset predicate

  Object* builtin_nstp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "nameset-p");
    bool result = (dynamic_cast <Nameset*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // prmp: promise predicate

  Object* builtin_prmp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "promise-p");
    bool result = (dynamic_cast <Promise*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // lbrnp: librarian predicate

  Object* builtin_lbrnp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "librarian-p");
    bool result = (dynamic_cast <Librarian*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // clsp: class predicate

  Object* builtin_clsp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "class-p");
    bool result = (dynamic_cast <Class*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // instp: instance predicate

  Object* builtin_instp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "instance-p");
    bool result = (dynamic_cast <Instance*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // ashp: hash table predicate

  Object* builtin_ashp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "hashtable-p");
    bool result = (dynamic_cast <HashTable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // thrp: thread predicate

  Object* builtin_thrp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "thread-p");
    bool result = (dynamic_cast <Thread*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // logp: logger predicate

  Object* builtin_logp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "logger-p");
    bool result = (dynamic_cast <Logger*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // bbufp: block buffer predicate

  Object* builtin_bbufp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "block-buffer-p");
    bool result = (dynamic_cast <BlockBuffer*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // hashp: hash table predicate

  Object* builtin_hashp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "hash-p");
    bool result = (dynamic_cast <HashTable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // fifop: fifo predicate

  Object* builtin_fifop (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "fifo-p");
    bool result = (dynamic_cast <Fifo*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // heapp: heap predicate

  Object* builtin_heapp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "heap-p");
    bool result = (dynamic_cast <Heap*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // treep: tree predicate

  Object* builtin_treep (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "tree-p");
    bool result = (dynamic_cast <Tree*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // enump: enum predicate

  Object* builtin_enump (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "enum-p");
    bool result = (dynamic_cast <Enum*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // itemp: item predicate

  Object* builtin_itemp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "enum-p");
    bool result = (dynamic_cast <Item*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // queuep: queue predicate

  Object* builtin_queuep (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "queue-p");
    bool result = (dynamic_cast <Queue*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // bitset predicate

  Object* builtin_bitsp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "bitset-p");
    bool result = (dynamic_cast <Bitset*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // condvar predicate

  Object* builtin_condp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "condvar-p");
    bool result = (dynamic_cast <Condvar*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // loader predicate

  Object* builtin_loadp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "loader-p");
    bool result = (dynamic_cast <Loader*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // resolver predicate

  Object* builtin_rslvp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "resolver-p");
    bool result = (dynamic_cast <Resolver*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // viewable predicate

  Object* builtin_viewp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "viewable-p");
    bool result = (dynamic_cast <Viewable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // locale predicate
  
  Object* builtin_localp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "locale-p");
    bool result = (dynamic_cast <Locale*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // regex predicate

  Object* builtin_regexp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "regex-p");
    bool result = (dynamic_cast <Regex*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // alias-table predicate

  Object* builtin_atblp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "alias-table-p");
    bool result = (dynamic_cast <AliasTable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // print-table predicate

  Object* builtin_ptblp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "print-table-p");
    bool result = (dynamic_cast <PrintTable*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // message predicate

  Object* builtin_mesgp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "message-p");
    bool result = (dynamic_cast <Message*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // property predicate

  Object* builtin_propp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "property-p");
    bool result = (dynamic_cast <Property*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // plist predicate

  Object* builtin_plistp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "plist-p");
    bool result = (dynamic_cast <Plist*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // counter predicate

  Object* builtin_cntrp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "counter-p");
    bool result = (dynamic_cast <Counter*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // thread set predicate

  Object* builtin_thrsp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "thrset-p");
    bool result = (dynamic_cast <Thrset*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // lexer predicate

  Object* builtin_lexerp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "lexer-p");
    bool result = (dynamic_cast <Lexer*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // style predicate

  Object* builtin_stylep (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "style-p");
    bool result = (dynamic_cast <Style*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // former predicate

  Object* builtin_formrp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "former-p");
    bool result = (dynamic_cast <Former*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
  
  // reader predicate
  
  Object* builtin_readrp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "reader-p");
    bool result = (dynamic_cast <Reader*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }

  // lock file predicate
  
  Object* builtin_lockfp (Runnable* robj, Nameset* nset, Cons* args) {
    Object* obj = get_obj (robj, nset, args, "lockf-p");
    bool result = (dynamic_cast <Lockf*> (obj) == nullptr) ? false : true;
    Object::cref (obj);
    return new Boolean (result);
  }
}
