Qore Programming Language
1.12.2
|
All data value in Qore (and, in fact, all elements of Qore parse trees) are descended from AbstractQoreNode.
The following are the basic data types in Qore, implemented as C++ classes descended from AbstractQoreNode, and their type codes, accessed via AbstractQoreNode::getType():
Additionally, the following classes are exposed in the library:
The fastest way to directly access data of a specific type is to use the non-virtual function AbstractQoreNode::getType() and then to do a reinterpret_cast to the appropriate type as follows:
This is faster than using dynamic_cast<> as follows (which is also a perfectly legal method for getting a pointer/testing the data type as well, just a little slower due to the dynamic_cast<>):
The QoreBigIntNode (NT_INT), QoreFloatNode (NT_FLOAT), QoreStringNode (NT_STRING), DateTimeNode (NT_DATE), and BinaryNode (NT_BINARY) classes are reference counted and can only be dynamically allocated.
They are all descendents of SimpleQoreNode, meaning that dereferencing their objects cannot cause a Qore-language exception to be thrown (hence all support the SimpleQoreNode::deref() function), therefore the SimpleRefHolder class can be used to manage temporary references to objects of these types.
For example:
QoreBoolNode (NT_BOOLEAN), QoreNullNode (NT_NULL), and QoreNothingNode (NT_NOTHING, but also equivalent to a 0 pointer, see the note below) are special classes in that they may not be directly instantiated with the new operator. They are all represented by single non-reference-counted objects managed directly by the Qore library. Each of these classes represents a type that has only one value, therefore as a memory and performance optimization, reference counting is disabled for their objects. Actually in the case of QoreBoolNode the subclasses QoreBoolTrueNode and QoreBoolFalseNode have actual instantiations.
For the QoreBoolNode class, you can use these objects by referring to the global True
and False
objects, or by calling get_bool_node() as follows in the example function:
Or, some even simpler functions:
Similarly, for QoreNullNode there is the global Null object or the inline function null() that returns a pointer to this object. The inline function is_null() can be used to test for a Qore SQL Null value.
QoreNothingNode has the gobal Nothing object and the inline function nothing() that returns a pointer to it as well.
NOTHING
, therefore the inline function is_nothing() should always be used to test for NOTHING
. Therefore the following code is incorrect:The code should look like this instead:
The QoreHashNode (NT_HASH), QoreListNode (NT_LIST), and QoreObject (NT_OBJECT) classes define container types in Qore. QoreObject objects in particular could throw an exception when dereferenced (if the object goes out of scope and its destructor is run, the destructor could throw an exception). Because container types can hold any type, when they are deferenced it could cause a QoreObject to go out of scope, and therefore the possibility that a Qore-language exception could be thrown must be taken into consideration. Therefore, to dereference these objects a pointer to an ExceptionSink object must be passed to AbstractQoreNode::deref().
The ReferenceHolder class can be used to manage temporary reference counts as follows:
QoreObject objects have node type NT_OBJECT as returned by AbstractQoreNode::getType().
QoreObject is special in that the implementation for objects in Qore mirrors that of Java, in that objects are pased by reference when used as function or method arguments, unlike other types. However, like Java, the reference to the object is passed, and not the variable, so, while an object passed as an argument to a function can be modified by that function (modifications are made to the original object), in order to write a swap method, for example, you would need to pass the variables by reference (or the lvalue expression by reference, as the case may be) to the swap function. Unlike Java, Qore does support passing arguments by reference.
Handling lvalue references is more complicated, as access to global variables and object member references must be made under the appropriate thread locks. However the ReferenceHelper class makes access to lvalue references much easier and takes care of all the locking and access to the lvalue expression. With the ReferenceHelper class you can get the type of the lvalue expression's value, get a pointer to a node with a reference count of 1 for in-place modification, or assign a new value to the lvalue.
Here is an example of the use of ReferenceHelper: