resolve confusion between null, none, void, and undefined

This commit is contained in:
David Rose 2009-07-08 22:31:48 +00:00
parent 06005cc440
commit 095c719f9d
16 changed files with 105 additions and 106 deletions

View File

@ -30,13 +30,14 @@
p3dInstanceManager.h p3dInstanceManager.I \
p3dIntObject.h \
p3dMultifileReader.h p3dMultifileReader.I \
p3dNoneObject.h p3dNullObject.h \
p3dNoneObject.h \
p3dObject.h p3dObject.I \
p3dPackage.h p3dPackage.I \
p3dPythonObject.h \
p3dSession.h p3dSession.I \
p3dSplashWindow.h p3dSplashWindow.I \
p3dStringObject.h \
p3dObject.h p3dObject.I \
p3dUndefinedObject.h \
p3dWinSplashWindow.h p3dWinSplashWindow.I \
p3dWindowParams.h p3dWindowParams.I
@ -52,13 +53,14 @@
p3dInstanceManager.cxx \
p3dIntObject.cxx \
p3dMultifileReader.cxx \
p3dNoneObject.cxx p3dNullObject.cxx \
p3dNoneObject.cxx \
p3dObject.cxx \
p3dPackage.cxx \
p3dPythonObject.cxx \
p3dSession.cxx \
p3dSplashWindow.cxx \
p3dStringObject.cxx \
p3dObject.cxx \
p3dUndefinedObject.cxx \
p3dWinSplashWindow.cxx \
p3dWindowParams.cxx

View File

@ -42,7 +42,7 @@ P3D_instance_finish_func *P3D_instance_finish;
P3D_instance_setup_window_func *P3D_instance_setup_window;
P3D_make_class_definition_func *P3D_make_class_definition;
P3D_new_null_object_func *P3D_new_null_object;
P3D_new_undefined_object_func *P3D_new_undefined_object;
P3D_new_none_object_func *P3D_new_none_object;
P3D_new_bool_object_func *P3D_new_bool_object;
P3D_new_int_object_func *P3D_new_int_object;
@ -166,7 +166,7 @@ load_plugin(const string &p3d_plugin_filename) {
P3D_instance_setup_window = (P3D_instance_setup_window_func *)get_func(module, "P3D_instance_setup_window");
P3D_make_class_definition = (P3D_make_class_definition_func *)get_func(module, "P3D_make_class_definition");
P3D_new_null_object = (P3D_new_null_object_func *)get_func(module, "P3D_new_null_object");
P3D_new_undefined_object = (P3D_new_undefined_object_func *)get_func(module, "P3D_new_undefined_object");
P3D_new_none_object = (P3D_new_none_object_func *)get_func(module, "P3D_new_none_object");
P3D_new_bool_object = (P3D_new_bool_object_func *)get_func(module, "P3D_new_bool_object");
P3D_new_int_object = (P3D_new_int_object_func *)get_func(module, "P3D_new_int_object");
@ -191,7 +191,7 @@ load_plugin(const string &p3d_plugin_filename) {
P3D_instance_setup_window == NULL ||
P3D_make_class_definition == NULL ||
P3D_new_null_object == NULL ||
P3D_new_undefined_object == NULL ||
P3D_new_none_object == NULL ||
P3D_new_bool_object == NULL ||
P3D_new_int_object == NULL ||
@ -215,7 +215,7 @@ load_plugin(const string &p3d_plugin_filename) {
<< "\nP3D_instance_setup_window = " << P3D_instance_setup_window
<< "\nP3D_make_class_definition = " << P3D_make_class_definition
<< "\nP3D_new_null_object = " << P3D_new_null_object
<< "\nP3D_new_undefined_object = " << P3D_new_undefined_object
<< "\nP3D_new_none_object = " << P3D_new_none_object
<< "\nP3D_new_bool_object = " << P3D_new_bool_object
<< "\nP3D_new_int_object = " << P3D_new_int_object
@ -294,7 +294,7 @@ unload_dso() {
P3D_instance_setup_window = NULL;
P3D_make_class_definition = NULL;
P3D_new_null_object = NULL;
P3D_new_undefined_object = NULL;
P3D_new_none_object = NULL;
P3D_new_bool_object = NULL;
P3D_new_int_object = NULL;

View File

@ -28,7 +28,7 @@ extern P3D_instance_finish_func *P3D_instance_finish;
extern P3D_instance_setup_window_func *P3D_instance_setup_window;
extern P3D_make_class_definition_func *P3D_make_class_definition;
extern P3D_new_null_object_func *P3D_new_null_object;
extern P3D_new_undefined_object_func *P3D_new_undefined_object;
extern P3D_new_none_object_func *P3D_new_none_object;
extern P3D_new_bool_object_func *P3D_new_bool_object;
extern P3D_new_int_object_func *P3D_new_int_object;

View File

@ -20,7 +20,7 @@
#include "p3dSplashWindow.h"
#include "p3dWinSplashWindow.h"
#include "p3dObject.h"
#include "p3dNullObject.h"
#include "p3dUndefinedObject.h"
#include <sstream>
#include <algorithm>
@ -195,7 +195,7 @@ get_panda_script_object() const {
}
if (result == NULL) {
result = new P3DNullObject;
result = new P3DUndefinedObject;
}
return result;

View File

@ -21,7 +21,7 @@
////////////////////////////////////////////////////////////////////
// Class : P3DNoneObject
// Description : An object type that contains no value, similar to
// Python's None type, or JavaScript's void type.
// Python's None type, or JavaScript's null type.
////////////////////////////////////////////////////////////////////
class P3DNoneObject : public P3DObject {
public:

View File

@ -126,16 +126,16 @@ run_python() {
}
Py_DECREF(app_runner_class);
// Get the NullObject class.
_null_object_class = PyObject_GetAttrString(runp3d, "NullObject");
if (_null_object_class == NULL) {
// Get the UndefinedObject class.
_undefined_object_class = PyObject_GetAttrString(runp3d, "UndefinedObject");
if (_undefined_object_class == NULL) {
PyErr_Print();
return false;
}
// And the "Null" instance.
_null = PyObject_GetAttrString(runp3d, "Null");
if (_null == NULL) {
// And the "Undefined" instance.
_undefined = PyObject_GetAttrString(runp3d, "Undefined");
if (_undefined == NULL) {
PyErr_Print();
return false;
}
@ -564,9 +564,10 @@ py_request_func(PyObject *args) {
if (xvalue != NULL) {
value = xml_to_pyobj(xvalue);
} else {
// An absence of a <value> element means a NULL pointer.
value = _null;
Py_INCREF(value);
// An absence of a <value> element is an exception. We will
// return NULL from this function, but first set the error
// condition.
PyErr_SetString(PyExc_EnvironmentError, "Error on script call");
}
delete doc;
@ -937,9 +938,9 @@ pyobj_to_xml(PyObject *value) {
xvalue->SetAttribute("value", str);
}
} else if (PyObject_IsInstance(value, _null_object_class)) {
// This is a NullObject, our equivalent to a NULL pointer.
xvalue->SetAttribute("type", "null");
} else if (PyObject_IsInstance(value, _undefined_object_class)) {
// This is an UndefinedObject.
xvalue->SetAttribute("type", "undefined");
} else if (PyObject_IsInstance(value, _browser_object_class)) {
// This is a BrowserObject, a reference to an object that actually
@ -1007,9 +1008,9 @@ xml_to_pyobj(TiXmlElement *xvalue) {
return PyString_FromStringAndSize(value->data(), value->length());
}
} else if (strcmp(type, "null") == 0) {
Py_INCREF(_null);
return _null;
} else if (strcmp(type, "undefined") == 0) {
Py_INCREF(_undefined);
return _undefined;
} else if (strcmp(type, "browser") == 0) {
int object_id;

View File

@ -110,8 +110,8 @@ private:
char **_py_argv;
PyObject *_runner;
PyObject *_null_object_class;
PyObject *_null;
PyObject *_undefined_object_class;
PyObject *_undefined;
PyObject *_browser_object_class;
PyObject *_taskMgr;

View File

@ -16,7 +16,7 @@
#include "p3dInstance.h"
#include "p3dInstanceManager.h"
#include "p3d_plugin_config.h"
#include "p3dNullObject.h"
#include "p3dUndefinedObject.h"
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "p3dIntObject.h"
@ -321,8 +321,8 @@ command_and_response(TiXmlDocument *command) {
P3D_object *P3DSession::
xml_to_p3dobj(const TiXmlElement *xvalue) {
const char *type = xvalue->Attribute("type");
if (strcmp(type, "null") == 0) {
return new P3DNullObject;
if (strcmp(type, "undefined") == 0) {
return new P3DUndefinedObject;
} else if (strcmp(type, "none") == 0) {
return new P3DNoneObject;
@ -383,8 +383,8 @@ p3dobj_to_xml(const P3D_object *obj) {
TiXmlElement *xvalue = new TiXmlElement("value");
switch (P3D_OBJECT_GET_TYPE(obj)) {
case P3D_OT_null:
xvalue->SetAttribute("type", "null");
case P3D_OT_undefined:
xvalue->SetAttribute("type", "undefined");
break;
case P3D_OT_none:

View File

@ -1,4 +1,4 @@
// Filename: p3dNullObject.cxx
// Filename: p3dUndefinedObject.cxx
// Created by: drose (07Jul09)
//
////////////////////////////////////////////////////////////////////
@ -12,45 +12,45 @@
//
////////////////////////////////////////////////////////////////////
#include "p3dNullObject.h"
#include "p3dUndefinedObject.h"
////////////////////////////////////////////////////////////////////
// Function: P3DNullObject::Constructor
// Function: P3DUndefinedObject::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
P3DNullObject::
P3DNullObject() {
P3DUndefinedObject::
P3DUndefinedObject() {
}
////////////////////////////////////////////////////////////////////
// Function: P3DNullObject::get_type
// Function: P3DUndefinedObject::get_type
// Access: Public, Virtual
// Description: Returns the fundamental type of this kind of object.
////////////////////////////////////////////////////////////////////
P3D_object_type P3DNullObject::
P3D_object_type P3DUndefinedObject::
get_type() const {
return P3D_OT_null;
return P3D_OT_undefined;
}
////////////////////////////////////////////////////////////////////
// Function: P3DNullObject::get_bool
// Function: P3DUndefinedObject::get_bool
// Access: Public, Virtual
// Description: Returns the object value coerced to a boolean, if
// possible.
////////////////////////////////////////////////////////////////////
bool P3DNullObject::
bool P3DUndefinedObject::
get_bool() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: P3DNullObject::make_string
// Function: P3DUndefinedObject::make_string
// Access: Public, Virtual
// Description: Fills the indicated C++ string object with the value
// of this object coerced to a string.
////////////////////////////////////////////////////////////////////
void P3DNullObject::
void P3DUndefinedObject::
make_string(string &value) const {
value = "Null";
value = "Undefined";
}

View File

@ -1,4 +1,4 @@
// Filename: p3dNullObject.h
// Filename: p3dUndefinedObject.h
// Created by: drose (07Jul09)
//
////////////////////////////////////////////////////////////////////
@ -12,22 +12,21 @@
//
////////////////////////////////////////////////////////////////////
#ifndef P3DNULLOBJECT_H
#define P3DNULLOBJECT_H
#ifndef P3DUNDEFINEDOBJECT_H
#define P3DUNDEFINEDOBJECT_H
#include "p3d_plugin_common.h"
#include "p3dObject.h"
////////////////////////////////////////////////////////////////////
// Class : P3DNullObject
// Description : An object type that represents a NULL pointer.
// Python doesn't have such a concept, but C and
// JavaScript do, and it is sometimes an important
// return value.
// Class : P3DUndefinedObject
// Description : An object type that represents an undefined value.
// Python doesn't have such a concept, but JavaScript
// does, and it is sometimes an important return value.
////////////////////////////////////////////////////////////////////
class P3DNullObject : public P3DObject {
class P3DUndefinedObject : public P3DObject {
public:
P3DNullObject();
P3DUndefinedObject();
public:
virtual P3D_object_type get_type() const;

View File

@ -16,7 +16,7 @@
#include "p3dInstanceManager.h"
#include "p3dInstance.h"
#include "p3dWindowParams.h"
#include "p3dNullObject.h"
#include "p3dUndefinedObject.h"
#include "p3dNoneObject.h"
#include "p3dBoolObject.h"
#include "p3dIntObject.h"
@ -134,11 +134,11 @@ P3D_make_class_definition() {
}
P3D_object *
P3D_new_null_object() {
P3D_new_undefined_object() {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock);
P3D_object *result = new P3DNullObject();
P3D_object *result = new P3DUndefinedObject();
RELEASE_LOCK(_api_lock);
return result;

View File

@ -294,7 +294,7 @@ typedef struct _P3D_object P3D_object;
/* A list of fundamental object types. */
typedef enum {
P3D_OT_null,
P3D_OT_undefined,
P3D_OT_none,
P3D_OT_bool,
P3D_OT_int,
@ -461,16 +461,16 @@ struct _P3D_object {
typedef P3D_class_definition *
P3D_make_class_definition_func();
/* Allocates a new P3D_object of type null. This value has no
particular value and corresponds a NULL pointer in C or JavaScript.
It has no Python equivalent (but we map it to an explicit Null
instance in runp3d.py). */
/* Allocates a new P3D_object of type "undefined". This corresponds
to the undefined or void type on JavaScript. It is similar to
Python's None, but has a subtly different shade of meaning; we map
it to an explicit Undefined instance in runp3d.py. */
typedef P3D_object *
P3D_new_null_object_func();
P3D_new_undefined_object_func();
/* Allocates a new P3D_object of type none. This value has no
particular value and corresponds to Python's None type or C's void
type. */
particular value and corresponds to Python's None type or
JavaScript's null type. */
typedef P3D_object *
P3D_new_none_object_func();
@ -752,7 +752,7 @@ EXPCL_P3D_PLUGIN P3D_instance_finish_func P3D_instance_finish;
EXPCL_P3D_PLUGIN P3D_instance_setup_window_func P3D_instance_setup_window;
EXPCL_P3D_PLUGIN P3D_make_class_definition_func P3D_make_class_definition;
EXPCL_P3D_PLUGIN P3D_new_null_object_func P3D_new_null_object;
EXPCL_P3D_PLUGIN P3D_new_undefined_object_func P3D_new_undefined_object;
EXPCL_P3D_PLUGIN P3D_new_none_object_func P3D_new_none_object;
EXPCL_P3D_PLUGIN P3D_new_bool_object_func P3D_new_bool_object;
EXPCL_P3D_PLUGIN P3D_new_int_object_func P3D_new_int_object;

View File

@ -9,13 +9,13 @@
#include "p3dInstanceManager.cxx"
#include "p3dIntObject.cxx"
#include "p3dMultifileReader.cxx"
#include "p3dPythonObject.cxx"
#include "p3dNoneObject.cxx"
#include "p3dNullObject.cxx"
#include "p3dObject.cxx"
#include "p3dPackage.cxx"
#include "p3dPythonObject.cxx"
#include "p3dSession.cxx"
#include "p3dSplashWindow.cxx"
#include "p3dStringObject.cxx"
#include "p3dUndefinedObject.cxx"
#include "p3dWinSplashWindow.cxx"
#include "p3dWindowParams.cxx"

View File

@ -157,17 +157,11 @@ set_property(const string &property, P3D_object *value) {
bool result;
if (value != NULL) {
// Set the property.
if (P3D_OBJECT_GET_TYPE(value) != P3D_OT_null) {
NPVariant npvalue;
_instance->p3dobj_to_variant(&npvalue, value);
result = browser->setproperty(_instance->get_npp_instance(), _npobj,
property_name, &npvalue);
browser->releasevariantvalue(&npvalue);
} else {
// Actually, delete the property after all.
result = browser->removeproperty(_instance->get_npp_instance(), _npobj,
property_name);
}
NPVariant npvalue;
_instance->p3dobj_to_variant(&npvalue, value);
result = browser->setproperty(_instance->get_npp_instance(), _npobj,
property_name, &npvalue);
browser->releasevariantvalue(&npvalue);
P3D_OBJECT_FINISH(value);
} else {

View File

@ -500,12 +500,12 @@ get_panda_script_object() {
void PPInstance::
p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
switch (P3D_OBJECT_GET_TYPE(object)) {
case P3D_OT_null:
NULL_TO_NPVARIANT(*result);
case P3D_OT_undefined:
VOID_TO_NPVARIANT(*result);
break;
case P3D_OT_none:
VOID_TO_NPVARIANT(*result);
NULL_TO_NPVARIANT(*result);
break;
case P3D_OT_bool:
@ -548,9 +548,9 @@ p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
////////////////////////////////////////////////////////////////////
P3D_object *PPInstance::
variant_to_p3dobj(const NPVariant *variant) {
if (NPVARIANT_IS_NULL(*variant)) {
return P3D_new_null_object();
} else if (NPVARIANT_IS_VOID(*variant)) {
if (NPVARIANT_IS_VOID(*variant)) {
return P3D_new_undefined_object();
} else if (NPVARIANT_IS_NULL(*variant)) {
return P3D_new_none_object();
} else if (NPVARIANT_IS_BOOLEAN(*variant)) {
return P3D_new_bool_object(NPVARIANT_TO_BOOLEAN(*variant));

View File

@ -59,9 +59,9 @@ class AppRunner(DirectObject):
self.windowOpened = False
self.windowPrc = None
# Store this Null instance where the application can easily
# Store this Undefined instance where the application can easily
# get to it.
self.Null = Null
self.Undefined = Undefined
# This is per session.
self.nextScriptId = 0
@ -413,15 +413,20 @@ class AppRunner(DirectObject):
return (osFilename, tokens)
class NullObject:
class UndefinedObject:
""" This is a special object that is returned by the browser to
represent a NULL pointer, typically the return value for a failed
operation. It has no attributes. """
pass
operation. It has no attributes, similar to None. """
def __nonzero__(self):
return False
def __str__(self):
return "Undefined"
# In fact, we normally always return this precise instance of the
# NullObject.
Null = NullObject()
# UndefinedObject.
Undefined = UndefinedObject()
class BrowserObject:
""" This class provides the Python wrapper around some object that
@ -475,10 +480,6 @@ class BrowserObject:
# Call it as a plain function.
result = self.__runner.scriptRequest('call', self, value = args)
if result is Null:
# Could not call the method.
raise TypeError
return result
def __getattr__(self, name):
@ -486,9 +487,10 @@ class BrowserObject:
into the appropriate calls to query the actual browser object
under the hood. """
value = self.__runner.scriptRequest('get_property', self,
propertyName = name)
if value is Null:
try:
value = self.__runner.scriptRequest('get_property', self,
propertyName = name)
except EnvironmentError:
# Failed to retrieve the attribute.
raise AttributeError(name)
@ -528,9 +530,10 @@ class BrowserObject:
under the hood. Following the JavaScript convention, we treat
obj['attr'] almost the same as obj.attr. """
value = self.__runner.scriptRequest('get_property', self,
propertyName = str(key))
if value is Null:
try:
value = self.__runner.scriptRequest('get_property', self,
propertyName = str(key))
except EnvironmentError:
# Failed to retrieve the property. We return IndexError
# for numeric keys so we can properly support Python's
# iterators, but we return KeyError for string keys to