Browse Source

ncd: NCDObject: Refactoring. Use just one kind of getvar/getobj callbacks. Change the state argument to callbacks to be an
NCDObject
poiter, and provide functions to retrieve state from that. Instead of a second state pointer (user2), use an integer
(data_int). Do not allow passing NULL getvar/getobj callbacks; instead, provide dummy callbacks. Move implementation to header
for better performance. Port everything to the new NCDObject interface.

ambrop7 13 years ago
parent
commit
abba37f455

+ 18 - 18
ncd/NCDModule.c

@@ -49,10 +49,10 @@
 #define PROCESS_STATE_TERMINATING 4
 #define PROCESS_STATE_TERMINATED 5
 
-static int object_func_getvar (NCDModuleInst *n, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
-static int object_func_getobj (NCDModuleInst *n, NCD_string_id_t name, NCDObject *out_object);
-static int process_args_object_func_getvar (NCDModuleProcess *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
-static int process_arg_object_func_getvar2 (NCDModuleProcess *o, void *n_ptr, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+static int object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+static int object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
+static int process_args_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+static int process_arg_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
 
 static void frontend_event (NCDModuleInst *n, int event)
 {
@@ -169,11 +169,9 @@ NCDObject NCDModuleInst_Object (NCDModuleInst *n)
     DebugObject_Access(&n->d_obj);
     ASSERT(n->m->base_type_id >= 0)
     
-    if (n->pass_mem_to_methods) {
-        return NCDObject_BuildMethodUser(n->m->base_type_id, n->mem, n, (NCDObject_func_getvar)object_func_getvar, (NCDObject_func_getobj)object_func_getobj);
-    } else {
-        return NCDObject_Build(n->m->base_type_id, n, (NCDObject_func_getvar)object_func_getvar, (NCDObject_func_getobj)object_func_getobj);
-    }
+    void *method_user = (n->pass_mem_to_methods ? n->mem : n);
+    
+    return NCDObject_BuildFull(n->m->base_type_id, n, 0, method_user, object_func_getvar, object_func_getobj);
 }
 
 void NCDModuleInst_Backend_PassMemToMethods (NCDModuleInst *n)
@@ -199,8 +197,9 @@ static int can_resolve (NCDModuleInst *n)
     }
 }
 
-static int object_func_getvar (NCDModuleInst *n, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
+static int object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
 {
+    NCDModuleInst *n = NCDObject_DataPtr(obj);
     DebugObject_Access(&n->d_obj);
     
     if ((!n->m->func_getvar && !n->m->func_getvar2) || !can_resolve(n)) {
@@ -220,8 +219,9 @@ static int object_func_getvar (NCDModuleInst *n, NCD_string_id_t name, NCDValMem
     return res;
 }
 
-static int object_func_getobj (NCDModuleInst *n, NCD_string_id_t name, NCDObject *out_object)
+static int object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    NCDModuleInst *n = NCDObject_DataPtr(obj);
     DebugObject_Access(&n->d_obj);
     
     if (!n->m->func_getobj || !can_resolve(n)) {
@@ -535,14 +535,14 @@ int NCDModuleProcess_Interp_GetSpecialObj (NCDModuleProcess *o, NCD_string_id_t
     
     if (!NCDVal_IsInvalid(o->args)) {
         if (name == NCD_STRING_ARGS) {
-            *out_object = NCDObject_Build(-1, o, (NCDObject_func_getvar)process_args_object_func_getvar, NULL);
+            *out_object = NCDObject_Build(-1, o, process_args_object_func_getvar, NCDObject_no_getobj);
             return 1;
         }
         
         if (name >= NCD_STRING_ARG0 && name <= NCD_STRING_ARG19) {
             int num = name - NCD_STRING_ARG0;
             if (num < NCDVal_ListCount(o->args)) {
-                *out_object = NCDObject_Build2(-1, o, (void *)((uintptr_t)(num + 1)), (NCDObject_func_getvar2)process_arg_object_func_getvar2, NULL);
+                *out_object = NCDObject_BuildFull(-1, o, num, NULL, process_arg_object_func_getvar, NCDObject_no_getobj);
                 return 1;
             }
         }
@@ -558,8 +558,9 @@ int NCDModuleProcess_Interp_GetSpecialObj (NCDModuleProcess *o, NCD_string_id_t
     return res;
 }
 
-static int process_args_object_func_getvar (NCDModuleProcess *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
+static int process_args_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
 {
+    NCDModuleProcess *o = NCDObject_DataPtr(obj);
     DebugObject_Access(&o->d_obj);
     process_assert_interp(o);
     ASSERT(!NCDVal_IsInvalid(o->args))
@@ -575,8 +576,9 @@ static int process_args_object_func_getvar (NCDModuleProcess *o, NCD_string_id_t
     return 1;
 }
 
-static int process_arg_object_func_getvar2 (NCDModuleProcess *o, void *n_ptr, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
+static int process_arg_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
 {
+    NCDModuleProcess *o = NCDObject_DataPtr(obj);
     DebugObject_Access(&o->d_obj);
     process_assert_interp(o);
     ASSERT(!NCDVal_IsInvalid(o->args))
@@ -585,9 +587,7 @@ static int process_arg_object_func_getvar2 (NCDModuleProcess *o, void *n_ptr, NC
         return 0;
     }
     
-    uintptr_t n = (uintptr_t)n_ptr - 1;
-    
-    *out_value = NCDVal_NewCopy(mem, NCDVal_ListGet(o->args, n));
+    *out_value = NCDVal_NewCopy(mem, NCDVal_ListGet(o->args, NCDObject_DataInt(obj)));
     if (NCDVal_IsInvalid(*out_value)) {
         BLog_LogToChannel(BLOG_CHANNEL_NCDModuleProcess, BLOG_ERROR, "NCDVal_NewCopy failed");
     }

+ 3 - 4
ncd/NCDModule.h

@@ -257,10 +257,9 @@ struct NCDModuleInst_new_params {
      * was called for the object on which the method is being called, in which case
      * this will directly point to the preallocated memory.
      * On the other hand, if this is a method on an internal object built using
-     * only {@link NCDObject_Build} or {@link NCDObject_Build2},
-     * {@link NCDObject_BuildMethodUser} or {@link NCDObject_BuildMethodUser2},
-     * this pointer will be whatever was passed as the "user" argument, for the
-     * former two functions, and as "method_user", for the latter two.
+     * only {@link NCDObject_Build} or {@link NCDObject_BuildFull},
+     * this pointer will be whatever was passed as the "data_ptr" argument, for the
+     * first function, and as "method_user", for the latter function.
      */
     void *method_user;
 };

+ 4 - 162
ncd/NCDObject.c

@@ -27,172 +27,14 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stddef.h>
-
-#include <ncd/static_strings.h>
-
 #include "NCDObject.h"
 
-NCDObject NCDObject_Build (NCD_string_id_t type, void *user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj)
-{
-    NCDObject obj;
-    obj.type = type;
-    obj.method_user = user;
-    obj.user = user;
-    obj.user2 = NULL;
-    obj.uv.func_getvar = func_getvar;
-    obj.uo.func_getobj = func_getobj;
-    
-    return obj;
-}
-
-NCDObject NCDObject_Build2 (NCD_string_id_t type, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2)
-{
-    ASSERT(user2)
-    
-    NCDObject obj;
-    obj.type = type;
-    obj.method_user = user;
-    obj.user = user;
-    obj.user2 = user2;
-    obj.uv.func_getvar2 = func_getvar2;
-    obj.uo.func_getobj2 = func_getobj2;
-    
-    return obj;
-}
-
-NCDObject NCDObject_BuildMethodUser (NCD_string_id_t type, void *method_user, void *user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj)
-{
-    NCDObject obj;
-    obj.type = type;
-    obj.method_user = method_user;
-    obj.user = user;
-    obj.user2 = NULL;
-    obj.uv.func_getvar = func_getvar;
-    obj.uo.func_getobj = func_getobj;
-    
-    return obj;
-}
-
-NCDObject NCDObject_BuildMethodUser2  (NCD_string_id_t type, void *method_user, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2)
-{
-    ASSERT(user2)
-    
-    NCDObject obj;
-    obj.type = type;
-    obj.method_user = method_user;
-    obj.user = user;
-    obj.user2 = user2;
-    obj.uv.func_getvar2 = func_getvar2;
-    obj.uo.func_getobj2 = func_getobj2;
-    
-    return obj;
-}
-
-NCD_string_id_t NCDObject_Type (NCDObject *o)
-{
-    return o->type;
-}
-
-void * NCDObject_MethodUser (NCDObject *o)
-{
-    ASSERT(o->type >= 0)
-    
-    return o->method_user;
-}
-
-int NCDObject_GetObj (NCDObject *o, NCD_string_id_t name, NCDObject *out_object)
-{
-    ASSERT(out_object)
-    
-    int res;
-    if (o->user2) {
-        res = (!o->uo.func_getobj2 ? 0 : o->uo.func_getobj2(o->user, o->user2, name, out_object));
-    } else {
-        res = (!o->uo.func_getobj ? 0 : o->uo.func_getobj(o->user, name, out_object));
-    }
-    
-    ASSERT(res == 0 || res == 1)
-    
-    return res;
-}
-
-int NCDObject_GetVar (NCDObject *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
-{
-    ASSERT(mem)
-    ASSERT(out_value)
-    
-    int res;
-    if (o->user2) {
-        res = (!o->uv.func_getvar2 ? 0 : o->uv.func_getvar2(o->user, o->user2, name, mem, out_value));
-    } else {
-        res = (!o->uv.func_getvar ? 0 : o->uv.func_getvar(o->user, name, mem, out_value));
-    }
-    
-    ASSERT(res == 0 || res == 1)
-    ASSERT(res == 0 || (NCDVal_Assert(*out_value), 1))
-    
-    return res;
-}
-
-static NCDObject dig_into_object (NCDObject object)
-{
-    NCDObject obj2;
-    while (NCDObject_GetObj(&object, NCD_STRING_EMPTY, &obj2)) {
-        object = obj2;
-    }
-    
-    return object;
-}
-
-int NCDObject_ResolveObjExprCompact (NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDObject *out_object)
+int NCDObject_no_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
 {
-    ASSERT(num_names == 0 || names)
-    ASSERT(num_names >= 0)
-    ASSERT(out_object)
-    
-    NCDObject object = dig_into_object(*o);
-    
-    while (num_names > 0) {
-        NCDObject obj2;
-        if (!NCDObject_GetObj(&object, *names, &obj2)) {
-            return 0;
-        }
-        
-        object = dig_into_object(obj2);
-        
-        names++;
-        num_names--;
-    }
-    
-    *out_object = object;
-    return 1;
+    return 0;
 }
 
-int NCDObject_ResolveVarExprCompact (NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value)
+int NCDObject_no_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
-    ASSERT(num_names == 0 || names)
-    ASSERT(num_names >= 0)
-    ASSERT(mem)
-    ASSERT(out_value)
-    
-    NCDObject object = dig_into_object(*o);
-    
-    while (num_names > 0) {
-        NCDObject obj2;
-        if (!NCDObject_GetObj(&object, *names, &obj2)) {
-            if (num_names == 1 && NCDObject_GetVar(&object, *names, mem, out_value)) {
-                return 1;
-            }
-            
-            return 0;
-        }
-        
-        object = dig_into_object(obj2);
-        
-        names++;
-        num_names--;
-    }
-    
-    return NCDObject_GetVar(&object, NCD_STRING_EMPTY, mem, out_value);
+    return 0;
 }

+ 310 - 24
ncd/NCDObject.h

@@ -30,41 +30,327 @@
 #ifndef BADVPN_NCDOBJECT_H
 #define BADVPN_NCDOBJECT_H
 
+#include <stddef.h>
+
 #include <misc/debug.h>
 #include <ncd/NCDVal.h>
 #include <ncd/NCDStringIndex.h>
+#include <ncd/static_strings.h>
 
+/**
+ * Represents an NCD object.
+ * Objects expose the following functionalities:
+ * - resolving variables by name,
+ * - resolving objects by name,
+ * - provide information for calling method-like statements.
+ * 
+ * The NCDObject structure must not be stored persistently; it is only
+ * valid at the time it was obtained, and any change of state in the
+ * execution of the NCD program may render the object invalid.
+ * However, the structure does not contain any resources, and can freely
+ * be passed around by value.
+ */
 typedef struct NCDObject_s NCDObject;
 
-typedef int (*NCDObject_func_getvar) (void *user, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
-typedef int (*NCDObject_func_getobj) (void *user, NCD_string_id_t name, NCDObject *out_object);
-typedef int (*NCDObject_func_getvar2) (void *user, void *user2, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
-typedef int (*NCDObject_func_getobj2) (void *user, void *user2, NCD_string_id_t name, NCDObject *out_object);
+/**
+ * Callback function for variable resolution requests.
+ * 
+ * @param obj const pointer to the NCDObject this is being called for.
+ *            {@link NCDObject_DataPtr} and {@link NCDObject_DataInt} can be
+ *            used to retrieve state information which was passed to
+ *            {@link NCDObject_Build} or {@link NCDObject_BuildFull}.
+ * @param name name of the variable being resolved, in form of an {@link NCDStringIndex}
+ *             string identifier
+ * @param mem pointer to the memory object where the resulting value should be
+ *            constructed
+ * @param out_value If the variable exists, *out_value should be set to the value
+ *                  reference to the result value. If the variable exists but there
+ *                  was an error constructing the value, should be set to an
+ *                  invalid value reference. Can be modified even if the variable
+ *                  does not exist.
+ * @return 1 if the variable exists, 0 if not
+ */
+typedef int (*NCDObject_func_getvar) (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+
+/**
+ * Callback function for object resolution requests.
+ * 
+ * @param obj const pointer to the NCDObject this is being called for.
+ *            {@link NCDObject_DataPtr} and {@link NCDObject_DataInt} can be
+ *            used to retrieve state information which was passed to
+ *            {@link NCDObject_Build} or {@link NCDObject_BuildFull}.
+ * @param name name of the object being resolved, in form of an {@link NCDStringIndex}
+ *             string identifier
+ * @param out_object If the object exists, *out_object should be set to the result
+ *                   object. Can be modified even if the object does not exist.
+ * @return 1 if the object exists, 0 if not
+ */
+typedef int (*NCDObject_func_getobj) (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 
 struct NCDObject_s {
     NCD_string_id_t type;
+    int data_int;
+    void *data_ptr;
     void *method_user;
-    void *user;
-    void *user2;
-    union {
-        NCDObject_func_getvar func_getvar;
-        NCDObject_func_getvar2 func_getvar2;
-    } uv;
-    union {
-        NCDObject_func_getobj func_getobj;
-        NCDObject_func_getobj2 func_getobj2;
-    } uo;
+    NCDObject_func_getvar func_getvar;
+    NCDObject_func_getobj func_getobj;
 };
 
-NCDObject NCDObject_Build (NCD_string_id_t type, void *user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
-NCDObject NCDObject_Build2 (NCD_string_id_t type, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2);
-NCDObject NCDObject_BuildMethodUser (NCD_string_id_t type, void *method_user, void *user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
-NCDObject NCDObject_BuildMethodUser2  (NCD_string_id_t type, void *method_user, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2);
-NCD_string_id_t NCDObject_Type (NCDObject *o);
-void * NCDObject_MethodUser (NCDObject *o);
-int NCDObject_GetObj (NCDObject *o, NCD_string_id_t name, NCDObject *out_object) WARN_UNUSED;
-int NCDObject_GetVar (NCDObject *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value) WARN_UNUSED;
-int NCDObject_ResolveObjExprCompact (NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDObject *out_object) WARN_UNUSED;
-int NCDObject_ResolveVarExprCompact (NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value) WARN_UNUSED;
+/**
+ * Basic object construction function.
+ * This is equivalent to calling {@link NCDObject_BuildFull} with data_int=0
+ * and method_user=data_ptr. See that function for detailed documentation.
+ */
+static NCDObject NCDObject_Build (NCD_string_id_t type, void *data_ptr, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
+
+/**
+ * Constructs an {@link NCDObject} structure.
+ * This is the full version where all supported parameters have to be provided.
+ * In most cases, {@link NCDObject_Build} will suffice.
+ * 
+ * @param type type of the object for the purpose of calling method-like statements
+ *             on the object, in form of an {@link NCDStringIndex} string identifier.
+ *             May be set to -1 if the object has no methods.
+ * @param data_ptr state-keeping pointer which can be restored from callbacks using
+ *                 {@link NCDObject_DataPtr}
+ * @param data_int state-keeping integer which can be restored from callbacks using
+ *                 {@link NCDObject_DataInt}
+ * @param method_user state-keeping pointer to be passed to new method-like statements
+ *                    created using this object. The value of this argument will be
+ *                    available as params->method_user within the {@link NCDModule_func_new2}
+ *                    module backend callback.
+ * @param func_getvar callback for resolving variables within the object. This must not
+ *                    be NULL; if the object exposes no variables, pass {@link NCDObject_no_getvar}.
+ * @param func_getobj callback for resolving objects within the object. This must not
+ *                    be NULL; if the object exposes no objects, pass {@link NCDObject_no_getobj}.
+ * @return an NCDObject structure encapsulating the information given
+ */
+static NCDObject NCDObject_BuildFull (NCD_string_id_t type, void *data_ptr, int data_int, void *method_user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
+
+/**
+ * Returns the 'type' attribute; see {@link NCDObject_BuildFull}.
+ */
+static NCD_string_id_t NCDObject_Type (const NCDObject *o);
+
+/**
+ * Returns the 'data_ptr' attribute; see {@link NCDObject_BuildFull}.
+ */
+static void * NCDObject_DataPtr (const NCDObject *o);
+
+/**
+ * Returns the 'data_int' attribute; see {@link NCDObject_BuildFull}.
+ */
+static int NCDObject_DataInt (const NCDObject *o);
+
+/**
+ * Returns the 'method_user' attribute; see {@link NCDObject_BuildFull}.
+ */
+static void * NCDObject_MethodUser (const NCDObject *o);
+
+/**
+ * Attempts to resolve a variable within the object.
+ * This just calls {@link NCDObject_func_getvar}, but also has some assertions to detect
+ * incorrect behavior of the callback.
+ */
+static int NCDObject_GetVar (const NCDObject *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value) WARN_UNUSED;
+
+/**
+ * Attempts to resolve an object within the object.
+ * This just calls {@link NCDObject_func_getobj}, but also has some assertions to detect
+ * incorrect behavior of the callback.
+ */
+static int NCDObject_GetObj (const NCDObject *o, NCD_string_id_t name, NCDObject *out_object) WARN_UNUSED;
+
+/**
+ * Resolves a variable expression starting with this object.
+ * A variable expression is usually represented in dotted form,
+ * e.g. object1.object2.variable (for a named variable) or object1.object2.object3
+ * (for an empty string variable). This function however receives the expression
+ * as an array of string identifiers.
+ * 
+ * Consult the implementation for exact semantics of variable expression resolution.
+ * 
+ * @param o object to start the resolution with
+ * @param names pointer to an array of names for the resolution. May be NULL if num_names is 0.
+ * @param num_names number in names in the array
+ * @param mem pointer to the memory object where the resulting value
+ *            should be constructed
+ * @param out_value If the variable exists, *out_value will be set to the value
+ *                  reference to the result value. If the variable exists but there
+ *                  was an error constructing the value, will be set to an
+ *                  invalid value reference. May be modified even if the variable
+ *                  does not exist.
+ * @return 1 if the variable exists, 0 if not
+ */
+static int NCDObject_ResolveVarExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value) WARN_UNUSED;
+
+/**
+ * Resolves an object expression starting with this object.
+ * An object expression is usually represented in dotted form,
+ * e.g. object1.object2.object3. This function however receives the expression
+ * as an array of string identifiers.
+ * 
+ * Consult the implementation for exact semantics of object expression resolution.
+ * 
+ * @param o object to start the resolution with
+ * @param names pointer to an array of names for the resolution. May be NULL if num_names is 0.
+ * @param num_names number in names in the array
+ * @param out_object If the object exists, *out_object will be set to the result
+ *                   object. May be modified even if the object does not exist.
+ * @return 1 if the object exists, 0 if not
+ */
+static int NCDObject_ResolveObjExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDObject *out_object) WARN_UNUSED;
+
+/**
+ * Returns 0. This can be used as a dummy variable resolution callback.
+ */
+int NCDObject_no_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+
+/**
+ * Returns 0. This can be used as a dummy object resolution callback.
+ */
+int NCDObject_no_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
+
+//
+
+NCDObject NCDObject_Build (NCD_string_id_t type, void *data_ptr, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj)
+{
+    ASSERT(type >= -1)
+    ASSERT(func_getvar)
+    ASSERT(func_getobj)
+    
+    NCDObject obj;
+    obj.type = type;
+    obj.data_int = 0;
+    obj.data_ptr = data_ptr;
+    obj.method_user = data_ptr;
+    obj.func_getvar = func_getvar;
+    obj.func_getobj = func_getobj;
+    
+    return obj;
+}
+
+NCDObject NCDObject_BuildFull (NCD_string_id_t type, void *data_ptr, int data_int, void *method_user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj)
+{
+    ASSERT(type >= -1)
+    ASSERT(func_getvar)
+    ASSERT(func_getobj)
+    
+    NCDObject obj;
+    obj.type = type;
+    obj.data_int = data_int;
+    obj.data_ptr = data_ptr;
+    obj.method_user = method_user;
+    obj.func_getvar = func_getvar;
+    obj.func_getobj = func_getobj;
+    
+    return obj;
+}
+
+NCD_string_id_t NCDObject_Type (const NCDObject *o)
+{
+    return o->type;
+}
+
+void * NCDObject_DataPtr (const NCDObject *o)
+{
+    return o->data_ptr;
+}
+
+int NCDObject_DataInt (const NCDObject *o)
+{
+    return o->data_int;
+}
+
+void * NCDObject_MethodUser (const NCDObject *o)
+{
+    return o->method_user;
+}
+
+int NCDObject_GetVar (const NCDObject *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
+{
+    ASSERT(name >= 0)
+    ASSERT(mem)
+    ASSERT(out_value)
+    
+    int res = o->func_getvar(o, name, mem, out_value);
+    
+    ASSERT(res == 0 || res == 1)
+    ASSERT(res == 0 || (NCDVal_Assert(*out_value), 1))
+    
+    return res;
+}
+
+int NCDObject_GetObj (const NCDObject *o, NCD_string_id_t name, NCDObject *out_object)
+{
+    ASSERT(name >= 0)
+    ASSERT(out_object)
+    
+    int res = o->func_getobj(o, name, out_object);
+    
+    ASSERT(res == 0 || res == 1)
+    
+    return res;
+}
+
+static NCDObject NCDObject__dig_into_object (NCDObject object)
+{
+    NCDObject obj2;
+    while (NCDObject_GetObj(&object, NCD_STRING_EMPTY, &obj2)) {
+        object = obj2;
+    }
+    
+    return object;
+}
+
+int NCDObject_ResolveVarExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value)
+{
+    ASSERT(num_names == 0 || names)
+    ASSERT(mem)
+    ASSERT(out_value)
+    
+    NCDObject object = NCDObject__dig_into_object(*o);
+    
+    while (num_names > 0) {
+        NCDObject obj2;
+        if (!NCDObject_GetObj(&object, *names, &obj2)) {
+            if (num_names == 1 && NCDObject_GetVar(&object, *names, mem, out_value)) {
+                return 1;
+            }
+            
+            return 0;
+        }
+        
+        object = NCDObject__dig_into_object(obj2);
+        
+        names++;
+        num_names--;
+    }
+    
+    return NCDObject_GetVar(&object, NCD_STRING_EMPTY, mem, out_value);
+}
+
+int NCDObject_ResolveObjExprCompact (const NCDObject *o, const NCD_string_id_t *names, size_t num_names, NCDObject *out_object)
+{
+    ASSERT(num_names == 0 || names)
+    ASSERT(out_object)
+    
+    NCDObject object = NCDObject__dig_into_object(*o);
+    
+    while (num_names > 0) {
+        NCDObject obj2;
+        if (!NCDObject_GetObj(&object, *names, &obj2)) {
+            return 0;
+        }
+        
+        object = NCDObject__dig_into_object(obj2);
+        
+        names++;
+        num_names--;
+    }
+    
+    *out_object = object;
+    return 1;
+}
 
 #endif

+ 10 - 6
ncd/modules/call.c

@@ -96,8 +96,8 @@ struct instance {
 };
 
 static void instance_free (struct instance *o);
-static int caller_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object);
-static int ref_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object);
+static int caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
+static int ref_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 
 enum {STRING_CALLER, STRING_REF};
 
@@ -147,12 +147,12 @@ static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_
     struct instance *o = UPPER_OBJECT(process, struct instance, process);
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, caller_obj_func_getobj);
         return 1;
     }
     
     if (name == strings[STRING_REF].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)ref_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, ref_obj_func_getobj);
         return 1;
     }
     
@@ -311,13 +311,17 @@ static int func_getobj (void *vo, NCD_string_id_t name, NCDObject *out_object)
     return NCDModuleProcess_GetObj(&o->process, name, out_object);
 }
 
-static int caller_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct instance *o = NCDObject_DataPtr(obj);
+    
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);
 }
 
-static int ref_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int ref_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct instance *o = NCDObject_DataPtr(obj);
+    
     if (!o->crh) {
         return 0;
     }

+ 5 - 3
ncd/modules/call2.c

@@ -66,7 +66,7 @@ struct instance {
 
 static void process_handler_event (NCDModuleProcess *process, int event);
 static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int caller_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object);
+static int caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 static void func_new_templ (void *vo, NCDModuleInst *i, NCDValRef template_name, NCDValRef args, int embed);
 static void instance_free (struct instance *o);
 
@@ -122,15 +122,17 @@ static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_
     }
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, caller_obj_func_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int caller_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct instance *o = NCDObject_DataPtr(obj);
+    
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);
 }
 

+ 20 - 15
ncd/modules/foreach.c

@@ -131,11 +131,11 @@ static void advance (struct instance *o);
 static void timer_handler (struct instance *o);
 static void element_process_handler_event (NCDModuleProcess *process, int event);
 static int element_process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int element_caller_object_func_getobj (struct element *e, NCD_string_id_t name, NCDObject *out_object);
-static int element_list_index_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
-static int element_list_elem_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
-static int element_map_key_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
-static int element_map_val_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
+static int element_caller_object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
+static int element_list_index_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
+static int element_list_elem_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
+static int element_map_key_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
+static int element_map_val_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
 static void instance_free (struct instance *o);
 
 enum {STRING_CALLER, STRING_INDEX, STRING_ELEM, STRING_KEY, STRING_VAL};
@@ -370,12 +370,12 @@ static int element_process_func_getspecialobj (NCDModuleProcess *process, NCD_st
             NCD_string_id_t elem_name = (o->name2 >= 0 ? o->name2 : o->name1);
             
             if (index_name >= 0 && name == index_name) {
-                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_list_index_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, element_list_index_object_func_getvar, NCDObject_no_getobj);
                 return 1;
             }
             
             if (name == elem_name) {
-                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_list_elem_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, element_list_elem_object_func_getvar, NCDObject_no_getobj);
                 return 1;
             }
         } break;
@@ -384,12 +384,12 @@ static int element_process_func_getspecialobj (NCDModuleProcess *process, NCD_st
             NCD_string_id_t val_name = o->name2;
             
             if (name == key_name) {
-                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_map_key_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, element_map_key_object_func_getvar, NCDObject_no_getobj);
                 return 1;
             }
             
             if (val_name >= 0 && name == val_name) {
-                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_map_val_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, element_map_val_object_func_getvar, NCDObject_no_getobj);
                 return 1;
             }
         } break;
@@ -400,15 +400,16 @@ static int element_process_func_getspecialobj (NCDModuleProcess *process, NCD_st
     }
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, e, NULL, (NCDObject_func_getobj)element_caller_object_func_getobj);
+        *out_object = NCDObject_Build(-1, e, NCDObject_no_getvar, element_caller_object_func_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int element_caller_object_func_getobj (struct element *e, NCD_string_id_t name, NCDObject *out_object)
+static int element_caller_object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct element *e = NCDObject_DataPtr(obj);
     struct instance *o = e->inst;
     ASSERT(e->state != ESTATE_FORGOTTEN)
     ASSERT(!NCDVal_IsInvalid(o->args))
@@ -416,8 +417,9 @@ static int element_caller_object_func_getobj (struct element *e, NCD_string_id_t
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);
 }
 
-static int element_list_index_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
+static int element_list_index_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
 {
+    struct element *e = NCDObject_DataPtr(obj);
     struct instance *o = e->inst;
     ASSERT(e->state != ESTATE_FORGOTTEN)
     ASSERT(o->type == NCDVAL_LIST)
@@ -433,8 +435,9 @@ static int element_list_index_object_func_getvar (struct element *e, NCD_string_
     return 1;
 }
 
-static int element_list_elem_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
+static int element_list_elem_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
 {
+    struct element *e = NCDObject_DataPtr(obj);
     struct instance *o = e->inst;
     ASSERT(e->state != ESTATE_FORGOTTEN)
     ASSERT(o->type == NCDVAL_LIST)
@@ -450,8 +453,9 @@ static int element_list_elem_object_func_getvar (struct element *e, NCD_string_i
     return 1;
 }
 
-static int element_map_key_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
+static int element_map_key_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
 {
+    struct element *e = NCDObject_DataPtr(obj);
     struct instance *o = e->inst;
     ASSERT(e->state != ESTATE_FORGOTTEN)
     ASSERT(o->type == NCDVAL_MAP)
@@ -467,8 +471,9 @@ static int element_map_key_object_func_getvar (struct element *e, NCD_string_id_
     return 1;
 }
 
-static int element_map_val_object_func_getvar (struct element *e, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
+static int element_map_val_object_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
 {
+    struct element *e = NCDObject_DataPtr(obj);
     struct instance *o = e->inst;
     ASSERT(e->state != ESTATE_FORGOTTEN)
     ASSERT(o->type == NCDVAL_MAP)

+ 4 - 3
ncd/modules/imperative.c

@@ -82,7 +82,7 @@ static void go_deinit (struct instance *o);
 static void init_process_handler_event (NCDModuleProcess *process, int event);
 static void deinit_process_handler_event (NCDModuleProcess *process, int event);
 static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int process_caller_object_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object);
+static int process_caller_object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 static void deinit_timer_handler (struct instance *o);
 static void instance_free (struct instance *o);
 
@@ -209,15 +209,16 @@ static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_
     ASSERT(o->state != STATE_UP)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)process_caller_object_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, process_caller_object_func_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int process_caller_object_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int process_caller_object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct instance *o = NCDObject_DataPtr(obj);
     ASSERT(o->state != STATE_UP)
     
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);

+ 4 - 3
ncd/modules/process_manager.c

@@ -96,7 +96,7 @@ static void process_free (struct process *p);
 static void process_retry_timer_handler (struct process *p);
 static void process_module_process_handler_event (NCDModuleProcess *process, int event);
 static int process_module_process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int process_module_process_caller_obj_func_getobj (struct process *p, NCD_string_id_t name, NCDObject *out_object);
+static int process_module_process_caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 static void process_stop (struct process *p);
 static int process_restart (struct process *p, NCDValRef template_name, NCDValRef args);
 static void process_try (struct process *p);
@@ -279,15 +279,16 @@ int process_module_process_func_getspecialobj (NCDModuleProcess *process, NCD_st
     ASSERT(p->have_module_process)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, p, NULL, (NCDObject_func_getobj)process_module_process_caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, p, NCDObject_no_getvar, process_module_process_caller_obj_func_getobj);
         return 1;
     }
     
     return 0;
 }
 
-int process_module_process_caller_obj_func_getobj (struct process *p, NCD_string_id_t name, NCDObject *out_object)
+int process_module_process_caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct process *p = NCDObject_DataPtr(obj);
     struct instance *o = p->manager;
     ASSERT(p->have_module_process)
     

+ 4 - 4
ncd/modules/socket.c

@@ -212,7 +212,7 @@ static void connection_send_handler_done (void *user, int data_len);
 static void connection_recv_handler_done (void *user, int data_len);
 static void connection_process_handler (struct NCDModuleProcess_s *process, int event);
 static int connection_process_func_getspecialobj (struct NCDModuleProcess_s *process, NCD_string_id_t name, NCDObject *out_object);
-static int connection_process_socket_obj_func_getvar (void *user, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+static int connection_process_socket_obj_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
 static void listen_listener_handler (void *user);
 
 static void connection_log (struct connection *o, int level, const char *fmt, ...)
@@ -478,16 +478,16 @@ static int connection_process_func_getspecialobj (struct NCDModuleProcess_s *pro
     ASSERT(o->type == CONNECTION_TYPE_LISTEN)
     
     if (name == strings[STRING_SOCKET].id) {
-        *out_object = NCDObject_Build(strings[STRING_SYS_SOCKET].id, o, connection_process_socket_obj_func_getvar, NULL);
+        *out_object = NCDObject_Build(strings[STRING_SYS_SOCKET].id, o, connection_process_socket_obj_func_getvar, NCDObject_no_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int connection_process_socket_obj_func_getvar (void *user, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
+static int connection_process_socket_obj_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value)
 {
-    struct connection *o = user;
+    struct connection *o = NCDObject_DataPtr(obj);
     ASSERT(o->type == CONNECTION_TYPE_LISTEN)
     
     if (name == strings[STRING_CLIENT_ADDR].id) {

+ 5 - 3
ncd/modules/spawn.c

@@ -87,7 +87,7 @@ struct join_instance {
 static void assert_dirty_state (struct instance *o);
 static void process_handler_event (NCDModuleProcess *process, int event);
 static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int caller_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object);
+static int caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 static void bring_joins_down (struct instance *o);
 static void continue_working (struct instance *o);
 static void continue_terminating (struct instance *o);
@@ -161,15 +161,17 @@ static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_
     struct instance *o = UPPER_OBJECT(process, struct instance, process);
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, caller_obj_func_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int caller_obj_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct instance *o = NCDObject_DataPtr(obj);
+    
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);
 }
 

+ 8 - 6
ncd/modules/sys_request_client.c

@@ -150,8 +150,8 @@ static void request_handler_reply (struct request_instance *o, NCDValMem reply_m
 static void request_handler_finished (struct request_instance *o, int is_error);
 static void request_process_handler_event (NCDModuleProcess *process, int event);
 static int request_process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int request_process_caller_obj_func_getobj (struct request_instance *o, NCD_string_id_t name, NCDObject *out_object);
-static int request_process_reply_obj_func_getvar (struct request_instance *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
+static int request_process_caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
+static int request_process_reply_obj_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out);
 static void request_gone (struct request_instance *o, int is_bad);
 static void request_terminate_process (struct request_instance *o);
 static void request_die (struct request_instance *o, int is_error);
@@ -323,27 +323,29 @@ static int request_process_func_getspecialobj (NCDModuleProcess *process, NCD_st
     ASSERT(o->pstate != RPSTATE_NONE)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)request_process_caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, request_process_caller_obj_func_getobj);
         return 1;
     }
     
     if (!o->process_is_finished && name == strings[STRING_REPLY].id) {
-        *out_object = NCDObject_Build(-1, o, (NCDObject_func_getvar)request_process_reply_obj_func_getvar, NULL);
+        *out_object = NCDObject_Build(-1, o, request_process_reply_obj_func_getvar, NCDObject_no_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int request_process_caller_obj_func_getobj (struct request_instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int request_process_caller_obj_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct request_instance *o = NCDObject_DataPtr(obj);
     ASSERT(o->pstate != RPSTATE_NONE)
     
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);
 }
 
-static int request_process_reply_obj_func_getvar (struct request_instance *o, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
+static int request_process_reply_obj_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
 {
+    struct request_instance *o = NCDObject_DataPtr(obj);
     ASSERT(o->pstate != RPSTATE_NONE)
     ASSERT(!o->process_is_finished)
     

+ 4 - 3
ncd/modules/sys_request_server.c

@@ -158,7 +158,7 @@ static void request_free (struct request *r);
 static struct request * find_request (struct connection *c, uint32_t request_id);
 static void request_process_handler_event (NCDModuleProcess *process, int event);
 static int request_process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int request_process_request_obj_func_getvar (struct request *r, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
+static int request_process_request_obj_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out_value);
 static void request_terminate (struct request *r);
 static struct reply * reply_init (struct connection *c, uint32_t request_id, NCDValRef reply_data);
 static void reply_start (struct reply *r, uint32_t type);
@@ -481,15 +481,16 @@ static int request_process_func_getspecialobj (NCDModuleProcess *process, NCD_st
     struct request *r = UPPER_OBJECT(process, struct request, process);
     
     if (name == strings[STRING_REQUEST].id) {
-        *out_object = NCDObject_Build(strings[STRING_SYS_REQUEST_SERVER_REQUEST].id, r, (NCDObject_func_getvar)request_process_request_obj_func_getvar, NULL);
+        *out_object = NCDObject_Build(strings[STRING_SYS_REQUEST_SERVER_REQUEST].id, r, request_process_request_obj_func_getvar, NCDObject_no_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int request_process_request_obj_func_getvar (struct request *r, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
+static int request_process_request_obj_func_getvar (const NCDObject *obj, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
 {
+    struct request *r = NCDObject_DataPtr(obj);
     struct instance *o = r->con->inst;
     
     if (name == strings[STRING_DATA].id) {

+ 5 - 4
ncd/modules/try.c

@@ -80,7 +80,7 @@ struct instance {
 
 static void process_handler_event (NCDModuleProcess *process, int event);
 static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_t name, NCDObject *out_object);
-static int process_caller_object_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object);
+static int process_caller_object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object);
 static void start_terminating (struct instance *o);
 static void instance_free (struct instance *o);
 
@@ -136,20 +136,21 @@ static int process_func_getspecialobj (NCDModuleProcess *process, NCD_string_id_
     ASSERT(o->state == STATE_INIT || o->state == STATE_DEINIT)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)process_caller_object_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NCDObject_no_getvar, process_caller_object_func_getobj);
         return 1;
     }
     
     if (name == strings[STRING_TRY].id) {
-        *out_object = NCDObject_Build(strings[STRING_TRY_TRY].id, o, NULL, NULL);
+        *out_object = NCDObject_Build(strings[STRING_TRY_TRY].id, o, NCDObject_no_getvar, NCDObject_no_getobj);
         return 1;
     }
     
     return 0;
 }
 
-static int process_caller_object_func_getobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
+static int process_caller_object_func_getobj (const NCDObject *obj, NCD_string_id_t name, NCDObject *out_object)
 {
+    struct instance *o = NCDObject_DataPtr(obj);
     ASSERT(o->state == STATE_INIT || o->state == STATE_DEINIT)
     
     return NCDModuleInst_Backend_GetObj(o->i, name, out_object);