/* -*- mode: c++; indent-tabs-mode: nil -*- */
/*
  QoreNothingNode.h
  
  Qore Programming Language

  Copyright 2003 - 2013 David Nichols

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef _QORE_QORENOTHINGNODE_H

#define _QORE_QORENOTHINGNODE_H

#include <qore/AbstractQoreNode.h>

/** @file QoreNothingNode.h
    defines the QoreNothingNode class
*/

//! Qore's "NOTHING" parse tree/value type, not-referenced counted, not dynamically allocated
/** This class cannot be instantiated; there will only be one single QoreNothingNode object instantiated and used
    everywhere in the Qore library.  Use the nothing() function or simply &Nothing to acquire a pointer to an 
    object of this class.
    This value can be represented in Qore code as the keyword "NOTHING"
    @note Qore's "NULL" is not equal to "NOTHING"
    @note in C++ code, use the is_nothing() function to test an AbstractQoreNode* to see if it's "NOTHING" (because also a null pointer is equivalent to NOTHING)
    @see QoreNullNode
 */
class QoreNothingNode : public UniqueValueQoreNode {
protected:
   //! this function is never called for this type
   /** @see AbstractQoreNode::evalImpl()
    */
   using SimpleValueQoreNode::evalImpl;
   DLLLOCAL AbstractQoreNode *evalImpl(ExceptionSink *xsink) const;

public:
   DLLEXPORT QoreNothingNode();

   DLLEXPORT virtual ~QoreNothingNode();

   //! concatenate "<NOTHING>" to an existing QoreString
   /** used for %n and %N printf formatting
       @param str the string representation of the type will be concatenated to this QoreString reference
       @param foff for multi-line formatting offset, -1 = no line breaks
       @param xsink if an error occurs, the Qore-language exception information will be added here
       @return -1 for exception raised, 0 = OK
   */
   DLLEXPORT virtual int getAsString(QoreString &str, int foff, class ExceptionSink *xsink) const;

   //! returns a QoreString with the text: "<NOTHING>"
   /** used for %n and %N printf formatting
       @param del is always set to true for this implementation of the function, meaning that the returned QoreString pointer should be deleted
       @param foff for multi-line formatting offset, -1 = no line breaks (ignored by this version of the function)
       @param xsink ignored by this version of the function
       NOTE: Use the QoreNodeAsStringHelper class (defined in QoreStringNode.h) instead of using this function directly
       @see QoreNodeAsStringHelper
   */
   DLLEXPORT virtual QoreString *getAsString(bool &del, int foff, class ExceptionSink *xsink) const;

   //! tests for equality with possible type conversion (soft compare)
   /** since no type can be implicitly converted to NOTHING, this comparison is the same as is_equal_hard() for QoreNothingNode
       @param v the value to compare
       @param xsink ignored for this version of the function
   */
   DLLEXPORT virtual bool is_equal_soft(const AbstractQoreNode *v, ExceptionSink *xsink) const;

   //! tests for equality without type conversions (hard compare)
   /**
      @param v the value to compare
      @param xsink ignored for this version of the function
   */
   DLLEXPORT virtual bool is_equal_hard(const AbstractQoreNode *v, ExceptionSink *xsink) const;

   //! returns the type name as a c string
   DLLEXPORT virtual const char *getTypeName() const;

   //! returns the type information
   DLLLOCAL virtual AbstractQoreNode *parseInit(LocalVar *oflag, int pflag, int &lvids, const QoreTypeInfo *&typeInfo);

   //! returns the type name (useful in templates)
   DLLLOCAL static const char *getStaticTypeName() {
      return "nothing";
   }

   //! returns the type code (useful in templates)
   DLLLOCAL static qore_type_t getStaticTypeCode() {
      return NT_NOTHING;
   }
};

//! the global and unique NOTHING object in Qore
DLLEXPORT extern QoreNothingNode Nothing;

//! returns a pointer to Nothing
static inline QoreNothingNode *nothing() {
   return &Nothing;
}

#endif
