Bladeren bron

ncd: NCDObject: store object type as a string identifier instead of char pointer

ambrop7 13 jaren geleden
bovenliggende
commit
7e29861b10

+ 2 - 2
ncd/NCDInterpProcess.c

@@ -361,13 +361,13 @@ const struct NCDModule * NCDInterpProcess_StatementGetSimpleModule (NCDInterpPro
     return o->stmts[i].binding.simple_module;
 }
 
-const struct NCDModule * NCDInterpProcess_StatementGetMethodModule (NCDInterpProcess *o, int i, const char *obj_type, NCDMethodIndex *method_index)
+const struct NCDModule * NCDInterpProcess_StatementGetMethodModule (NCDInterpProcess *o, int i, NCD_string_id_t obj_type, NCDMethodIndex *method_index)
 {
     DebugObject_Access(&o->d_obj);
     ASSERT(i >= 0)
     ASSERT(i < o->num_stmts)
     ASSERT(o->stmts[i].objnames)
-    ASSERT(obj_type)
+    ASSERT(obj_type >= 0)
     ASSERT(method_index)
     
     return NCDMethodIndex_GetMethodModule(method_index, obj_type, o->stmts[i].binding.method_name_id);

+ 1 - 1
ncd/NCDInterpProcess.h

@@ -86,7 +86,7 @@ int NCDInterpProcess_FindStatement (NCDInterpProcess *o, int from_index, NCD_str
 const char * NCDInterpProcess_StatementCmdName (NCDInterpProcess *o, int i);
 void NCDInterpProcess_StatementObjNames (NCDInterpProcess *o, int i, const NCD_string_id_t **out_objnames, size_t *out_num_objnames);
 const struct NCDModule * NCDInterpProcess_StatementGetSimpleModule (NCDInterpProcess *o, int i);
-const struct NCDModule * NCDInterpProcess_StatementGetMethodModule (NCDInterpProcess *o, int i, const char *obj_type, NCDMethodIndex *method_index);
+const struct NCDModule * NCDInterpProcess_StatementGetMethodModule (NCDInterpProcess *o, int i, NCD_string_id_t obj_type, NCDMethodIndex *method_index);
 int NCDInterpProcess_CopyStatementArgs (NCDInterpProcess *o, int i, NCDValMem *out_valmem, NCDValRef *out_val, NCDValReplaceProg *out_prog) WARN_UNUSED;
 void NCDInterpProcess_StatementBumpAllocSize (NCDInterpProcess *o, int i, int alloc_size);
 int NCDInterpProcess_PreallocSize (NCDInterpProcess *o);

+ 17 - 19
ncd/NCDMethodIndex.c

@@ -95,7 +95,7 @@ static int add_method_name (NCDMethodIndex *o, const char *method_name, int *out
     }
     
     struct NCDMethodIndex__entry *entry = &o->entries[o->num_entries];
-    entry->obj_type = NULL;
+    entry->obj_type = -1;
     entry->next = -1;
     
     struct NCDMethodIndex__method_name *name_entry = &o->names[o->num_names];
@@ -123,8 +123,12 @@ fail0:
     return 0;
 }
 
-int NCDMethodIndex_Init (NCDMethodIndex *o)
+int NCDMethodIndex_Init (NCDMethodIndex *o, NCDStringIndex *string_index)
 {
+    ASSERT(string_index)
+    
+    o->string_index = string_index;
+    
     if (!NamesArray_Init(o, NCDMETHODINDEX_NUM_EXPECTED_METHOD_NAMES)) {
         BLog(BLOG_ERROR, "NamesArray_Init failed");
         goto fail0;
@@ -159,10 +163,6 @@ void NCDMethodIndex_Free (NCDMethodIndex *o)
         free(o->names[i].method_name);
     }
     
-    for (int i = 0; i < o->num_entries; i++) {
-        free(o->entries[i].obj_type);
-    }
-    
     NCDMethodIndex__Hash_Free(&o->hash);
     EntriesArray_Free(o);
     NamesArray_Free(o);
@@ -174,6 +174,12 @@ int NCDMethodIndex_AddMethod (NCDMethodIndex *o, const char *obj_type, const cha
     ASSERT(method_name)
     ASSERT(module)
     
+    NCD_string_id_t obj_type_id = NCDStringIndex_Get(o->string_index, obj_type);
+    if (obj_type_id < 0) {
+        BLog(BLOG_ERROR, "NCDStringIndex_Get failed");
+        goto fail0;
+    }
+    
     int first_entry_idx;
     
     if (!find_method_name(o, method_name, &first_entry_idx)) {
@@ -187,11 +193,7 @@ int NCDMethodIndex_AddMethod (NCDMethodIndex *o, const char *obj_type, const cha
         
         struct NCDMethodIndex__entry *entry = &o->entries[entry_idx];
         
-        if (!(entry->obj_type = b_strdup(obj_type))) {
-            BLog(BLOG_ERROR, "b_strdup failed");
-            goto fail0;
-        }
-        
+        entry->obj_type = obj_type_id;
         entry->module = module;
     } else {
         ASSERT(first_entry_idx >= 0)
@@ -204,11 +206,7 @@ int NCDMethodIndex_AddMethod (NCDMethodIndex *o, const char *obj_type, const cha
         
         struct NCDMethodIndex__entry *entry = &o->entries[o->num_entries];
         
-        if (!(entry->obj_type = b_strdup(obj_type))) {
-            BLog(BLOG_ERROR, "b_strdup failed");
-            goto fail0;
-        }
-        
+        entry->obj_type = obj_type_id;
         entry->module = module;
         
         entry->next = o->entries[first_entry_idx].next;
@@ -241,16 +239,16 @@ int NCDMethodIndex_GetMethodNameId (NCDMethodIndex *o, const char *method_name)
     return first_entry_idx;
 }
 
-const struct NCDModule * NCDMethodIndex_GetMethodModule (NCDMethodIndex *o, const char *obj_type, int method_name_id)
+const struct NCDModule * NCDMethodIndex_GetMethodModule (NCDMethodIndex *o, NCD_string_id_t obj_type, int method_name_id)
 {
-    ASSERT(obj_type)
+    ASSERT(obj_type >= 0)
     ASSERT(method_name_id >= 0)
     ASSERT(method_name_id < o->num_entries)
     
     do {
         struct NCDMethodIndex__entry *entry = &o->entries[method_name_id];
         
-        if (entry->obj_type && !strcmp(entry->obj_type, obj_type)) {
+        if (entry->obj_type == obj_type) {
             ASSERT(entry->module)
             return entry->module;
         }

+ 7 - 5
ncd/NCDMethodIndex.h

@@ -33,6 +33,7 @@
 #include <misc/debug.h>
 #include <structure/CHash.h>
 #include <ncd/NCDModule.h>
+#include <ncd/NCDStringIndex.h>
 
 #define NCDMETHODINDEX_NUM_EXPECTED_METHOD_NAMES 64
 #define NCDMETHODINDEX_NUM_EXPECTED_ENTRIES 64
@@ -44,7 +45,7 @@ struct NCDMethodIndex__method_name {
 };
 
 struct NCDMethodIndex__entry {
-    char *obj_type;
+    NCD_string_id_t obj_type;
     const struct NCDModule *module;
     int next;
 };
@@ -72,6 +73,7 @@ typedef struct {
     int num_names;
     int num_entries;
     NCDMethodIndex__Hash hash;
+    NCDStringIndex *string_index;
 } NCDMethodIndex;
 
 /**
@@ -79,7 +81,7 @@ typedef struct {
  * 
  * @return 1 on success, 0 on failure
  */
-int NCDMethodIndex_Init (NCDMethodIndex *o) WARN_UNUSED;
+int NCDMethodIndex_Init (NCDMethodIndex *o, NCDStringIndex *string_index) WARN_UNUSED;
 
 /**
  * Frees the method index.
@@ -114,12 +116,12 @@ int NCDMethodIndex_GetMethodNameId (NCDMethodIndex *o, const char *method_name);
  * Looks up the module corresponding to a method. The method name is passed as an
  * identifier obtained from \link NCDMethodIndex_GetMethodNameId.
  * 
- * @param obj_type object type of method, e.g. "cat" in "cat::meow".
- *                 Must not be NULL.
+ * @param obj_type object type of method, e.g. "cat" in "cat::meow", as a string
+ *                 identifier via {@link NCDStringIndex}
  * @param method_name_id method name identifier. Must have been previously returned
  *                       by a successfull call of \link NCDMethodIndex_GetMethodNameId.
  * @return module pointer, or NULL if no such method exists
  */
-const struct NCDModule * NCDMethodIndex_GetMethodModule (NCDMethodIndex *o, const char *obj_type, int method_name_id);
+const struct NCDModule * NCDMethodIndex_GetMethodModule (NCDMethodIndex *o, NCD_string_id_t obj_type, int method_name_id);
 
 #endif

+ 5 - 5
ncd/NCDModule.c

@@ -71,6 +71,7 @@ void NCDModuleInst_Init (NCDModuleInst *n, const struct NCDModule *m, void *mem,
     ASSERT(m)
     ASSERT(m->func_new2)
     ASSERT(m->alloc_size >= 0)
+    ASSERT(m->base_type_id >= 0)
     ASSERT(!!mem == m->alloc_size > 0)
     ASSERT(NCDVal_IsList(args))
     ASSERT(params)
@@ -145,10 +146,9 @@ void NCDModuleInst_Clean (NCDModuleInst *n)
 NCDObject NCDModuleInst_Object (NCDModuleInst *n)
 {
     DebugObject_Access(&n->d_obj);
+    ASSERT(n->m->base_type_id >= 0)
     
-    const char *type = (n->m->base_type ? n->m->base_type : n->m->type);
-    
-    return NCDObject_Build(type, n, (NCDObject_func_getvar)object_func_getvar, (NCDObject_func_getobj)object_func_getobj);
+    return NCDObject_Build(n->m->base_type_id, n, (NCDObject_func_getvar)object_func_getvar, (NCDObject_func_getobj)object_func_getobj);
 }
 
 static int can_resolve (NCDModuleInst *n)
@@ -489,13 +489,13 @@ int NCDModuleProcess_Interp_GetSpecialObj (NCDModuleProcess *o, NCD_string_id_t
     
     if (!NCDVal_IsInvalid(o->args)) {
         if (name == NCD_STRING_ARGS) {
-            *out_object = NCDObject_Build(NULL, o, (NCDObject_func_getvar)process_args_object_func_getvar, NULL);
+            *out_object = NCDObject_Build(-1, o, (NCDObject_func_getvar)process_args_object_func_getvar, NULL);
             return 1;
         }
         
         if (name >= NCD_STRING_ARG0 && name <= NCD_STRING_ARG19) {
             int num = name - NCD_STRING_ARG0;
-            *out_object = NCDObject_Build2(NULL, o, (void *)((uintptr_t)(num + 1)), (NCDObject_func_getvar2)process_arg_object_func_getvar2, NULL);
+            *out_object = NCDObject_Build2(-1, o, (void *)((uintptr_t)(num + 1)), (NCDObject_func_getvar2)process_arg_object_func_getvar2, NULL);
             return 1;
         }
     }

+ 7 - 0
ncd/NCDModule.h

@@ -828,6 +828,13 @@ struct NCDModule {
      * {@link NCDModuleInst_Backend_SetUser}).
      */
     int alloc_size;
+    
+    /**
+     * The string identifier of this module's base_type (or type if base_type is
+     * not specified) according to {@link NCDStringIndex}. This is initialized
+     * by the interpreter on startup and should not be set by the module.
+     */
+    NCD_string_id_t base_type_id;
 };
 
 /**

+ 3 - 3
ncd/NCDObject.c

@@ -33,7 +33,7 @@
 
 #include "NCDObject.h"
 
-NCDObject NCDObject_Build (const char *type, void *user, 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 obj;
     obj.type = type;
@@ -45,7 +45,7 @@ NCDObject NCDObject_Build (const char *type, void *user, NCDObject_func_getvar f
     return obj;
 }
 
-NCDObject NCDObject_Build2 (const char *type, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2)
+NCDObject NCDObject_Build2 (NCD_string_id_t type, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2)
 {
     ASSERT(user2)
     
@@ -59,7 +59,7 @@ NCDObject NCDObject_Build2 (const char *type, void *user, void *user2, NCDObject
     return obj;
 }
 
-const char * NCDObject_Type (NCDObject *o)
+NCD_string_id_t NCDObject_Type (NCDObject *o)
 {
     return o->type;
 }

+ 4 - 4
ncd/NCDObject.h

@@ -42,7 +42,7 @@ typedef int (*NCDObject_func_getvar2) (void *user, void *user2, NCD_string_id_t
 typedef int (*NCDObject_func_getobj2) (void *user, void *user2, NCD_string_id_t name, NCDObject *out_object);
 
 struct NCDObject_s {
-    const char *type;
+    NCD_string_id_t type;
     void *user;
     void *user2;
     union {
@@ -55,9 +55,9 @@ struct NCDObject_s {
     } uo;
 };
 
-NCDObject NCDObject_Build (const char *type, void *user, NCDObject_func_getvar func_getvar, NCDObject_func_getobj func_getobj);
-NCDObject NCDObject_Build2 (const char *type, void *user, void *user2, NCDObject_func_getvar2 func_getvar2, NCDObject_func_getobj2 func_getobj2);
-const char * NCDObject_Type (NCDObject *o);
+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);
+NCD_string_id_t NCDObject_Type (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;

+ 2 - 2
ncd/modules/call.c

@@ -143,12 +143,12 @@ static void process_handler_event (struct instance *o, int event)
 static int process_func_getspecialobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
 {
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
         return 1;
     }
     
     if (name == strings[STRING_REF].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)ref_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)ref_obj_func_getobj);
         return 1;
     }
     

+ 1 - 1
ncd/modules/call2.c

@@ -115,7 +115,7 @@ static int process_func_getspecialobj (struct instance *o, NCD_string_id_t name,
     }
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
         return 1;
     }
     

+ 5 - 5
ncd/modules/foreach.c

@@ -366,12 +366,12 @@ static int element_process_func_getspecialobj (struct element *e, NCD_string_id_
             NCD_string_id_t elem_name = (o->name2 >= 0 ? o->name2 : o->name1);
             
             if (index_name >= 0 && name == index_name) {
-                *out_object = NCDObject_Build(NULL, e, (NCDObject_func_getvar)element_list_index_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_list_index_object_func_getvar, NULL);
                 return 1;
             }
             
             if (name == elem_name) {
-                *out_object = NCDObject_Build(NULL, e, (NCDObject_func_getvar)element_list_elem_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_list_elem_object_func_getvar, NULL);
                 return 1;
             }
         } break;
@@ -380,12 +380,12 @@ static int element_process_func_getspecialobj (struct element *e, NCD_string_id_
             NCD_string_id_t val_name = o->name2;
             
             if (name == key_name) {
-                *out_object = NCDObject_Build(NULL, e, (NCDObject_func_getvar)element_map_key_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_map_key_object_func_getvar, NULL);
                 return 1;
             }
             
             if (val_name >= 0 && name == val_name) {
-                *out_object = NCDObject_Build(NULL, e, (NCDObject_func_getvar)element_map_val_object_func_getvar, NULL);
+                *out_object = NCDObject_Build(-1, e, (NCDObject_func_getvar)element_map_val_object_func_getvar, NULL);
                 return 1;
             }
         } break;
@@ -396,7 +396,7 @@ static int element_process_func_getspecialobj (struct element *e, NCD_string_id_
     }
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, e, NULL, (NCDObject_func_getobj)element_caller_object_func_getobj);
+        *out_object = NCDObject_Build(-1, e, NULL, (NCDObject_func_getobj)element_caller_object_func_getobj);
         return 1;
     }
     

+ 1 - 1
ncd/modules/imperative.c

@@ -203,7 +203,7 @@ static int process_func_getspecialobj (struct instance *o, NCD_string_id_t name,
     ASSERT(o->state != STATE_UP)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)process_caller_object_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)process_caller_object_func_getobj);
         return 1;
     }
     

+ 1 - 1
ncd/modules/process_manager.c

@@ -273,7 +273,7 @@ int process_module_process_func_getspecialobj (struct process *p, NCD_string_id_
     ASSERT(p->have_module_process)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, p, NULL, (NCDObject_func_getobj)process_module_process_caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, p, NULL, (NCDObject_func_getobj)process_module_process_caller_obj_func_getobj);
         return 1;
     }
     

+ 1 - 1
ncd/modules/spawn.c

@@ -158,7 +158,7 @@ static void process_handler_event (struct instance *o, int event)
 static int process_func_getspecialobj (struct instance *o, NCD_string_id_t name, NCDObject *out_object)
 {
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)caller_obj_func_getobj);
         return 1;
     }
     

+ 2 - 2
ncd/modules/sys_request_client.c

@@ -323,12 +323,12 @@ static int request_process_func_getspecialobj (struct request_instance *o, NCD_s
     ASSERT(o->pstate != RPSTATE_NONE)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)request_process_caller_obj_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)request_process_caller_obj_func_getobj);
         return 1;
     }
     
     if (!o->process_is_finished && name == strings[STRING_REPLY].id) {
-        *out_object = NCDObject_Build(NULL, o, (NCDObject_func_getvar)request_process_reply_obj_func_getvar, NULL);
+        *out_object = NCDObject_Build(-1, o, (NCDObject_func_getvar)request_process_reply_obj_func_getvar, NULL);
         return 1;
     }
     

+ 5 - 3
ncd/modules/sys_request_server.c

@@ -171,10 +171,12 @@ static void reply_send_qflow_if_handler_done (struct reply *r);
 static int init_listen (struct instance *o, NCDValRef listen_addr_arg);
 static void instance_free (struct instance *o);
 
-enum {STRING_REQUEST, STRING_DATA, STRING_CLIENT_ADDR_TYPE, STRING_CLIENT_ADDR};
+enum {STRING_REQUEST, STRING_DATA, STRING_CLIENT_ADDR_TYPE, STRING_CLIENT_ADDR,
+      STRING_SYS_REQUEST_SERVER_REQUEST};
 
 static struct NCD_string_request strings[] = {
-    {"_request"}, {"data"}, {"client_addr_type"}, {"client_addr"}, {NULL}
+    {"_request"}, {"data"}, {"client_addr_type"}, {"client_addr"},
+    {"sys.request_server.request"}, {NULL}
 };
 
 static void listener_handler (struct instance *o)
@@ -481,7 +483,7 @@ static void request_process_handler_event (struct request *r, int event)
 static int request_process_func_getspecialobj (struct request *r, NCD_string_id_t name, NCDObject *out_object)
 {
     if (name == strings[STRING_REQUEST].id) {
-        *out_object = NCDObject_Build("sys.request_server.request", r, (NCDObject_func_getvar)request_process_request_obj_func_getvar, NULL);
+        *out_object = NCDObject_Build(strings[STRING_SYS_REQUEST_SERVER_REQUEST].id, r, (NCDObject_func_getvar)request_process_request_obj_func_getvar, NULL);
         return 1;
     }
     

+ 4 - 4
ncd/modules/try.c

@@ -83,10 +83,10 @@ static int process_caller_object_func_getobj (struct instance *o, NCD_string_id_
 static void start_terminating (struct instance *o);
 static void instance_free (struct instance *o);
 
-enum {STRING_CALLER, STRING_TRY};
+enum {STRING_CALLER, STRING_TRY, STRING_TRY_TRY};
 
 static struct NCD_string_request strings[] = {
-    {"_caller"}, {"_try"}, {NULL}
+    {"_caller"}, {"_try"}, {"try.try"}, {NULL}
 };
 
 static void process_handler_event (struct instance *o, int event)
@@ -132,12 +132,12 @@ static int process_func_getspecialobj (struct instance *o, NCD_string_id_t name,
     ASSERT(o->state == STATE_INIT || o->state == STATE_DEINIT)
     
     if (name == strings[STRING_CALLER].id) {
-        *out_object = NCDObject_Build(NULL, o, NULL, (NCDObject_func_getobj)process_caller_object_func_getobj);
+        *out_object = NCDObject_Build(-1, o, NULL, (NCDObject_func_getobj)process_caller_object_func_getobj);
         return 1;
     }
     
     if (name == strings[STRING_TRY].id) {
-        *out_object = NCDObject_Build("try.try", o, NULL, NULL);
+        *out_object = NCDObject_Build(strings[STRING_TRY_TRY].id, o, NULL, NULL);
         return 1;
     }
     

+ 26 - 5
ncd/ncd.c

@@ -165,6 +165,7 @@ static int parse_arguments (int argc, char *argv[]);
 static void signal_handler (void *unused);
 static void start_terminate (int exit_code);
 static char * implode_id_strings (const NCD_string_id_t *names, size_t num_names, char del);
+static int alloc_base_type_strings (const struct NCDModuleGroup *g);
 static int process_new (NCDInterpProcess *iprocess, NCDModuleProcess *module_process);
 static void process_free (struct process *p, NCDModuleProcess **out_mp);
 static int process_state (struct process *p);
@@ -300,7 +301,7 @@ int main (int argc, char **argv)
     }
     
     // init method index
-    if (!NCDMethodIndex_Init(&method_index)) {
+    if (!NCDMethodIndex_Init(&method_index, &string_index)) {
         BLog(BLOG_ERROR, "NCDMethodIndex_Init failed");
         goto fail1b;
     }
@@ -311,12 +312,15 @@ int main (int argc, char **argv)
         goto fail1c;
     }
     
-    // add module groups to index
+    // add module groups to index and allocate string id's for base_type's
     for (const struct NCDModuleGroup **g = ncd_modules; *g; g++) {
         if (!NCDModuleIndex_AddGroup(&mindex, *g, &method_index)) {
             BLog(BLOG_ERROR, "NCDModuleIndex_AddGroup failed");
             goto fail2;
         }
+        if (!alloc_base_type_strings(*g)) {
+            goto fail2;
+        }
     }
     
     // setup signal handler
@@ -717,6 +721,22 @@ fail0:
     return NULL;
 }
 
+int alloc_base_type_strings (const struct NCDModuleGroup *g)
+{
+    for (struct NCDModule *m = g->modules; m->type; m++) {
+        const char *type = (m->base_type ? m->base_type : m->type);
+        ASSERT(type)
+        
+        m->base_type_id = NCDStringIndex_Get(&string_index, type);
+        if (m->base_type_id < 0) {
+            BLog(BLOG_ERROR, "NCDStringIndex_Get failed");
+            return 0;
+        }
+    }
+    
+    return 1;
+}
+
 int process_new (NCDInterpProcess *iprocess, NCDModuleProcess *module_process)
 {
     ASSERT(iprocess)
@@ -1112,8 +1132,8 @@ void process_advance (struct process *p)
         object_ptr = &object;
         
         // get object type
-        const char *object_type = NCDObject_Type(&object);
-        if (!object_type) {
+        NCD_string_id_t object_type = NCDObject_Type(&object);
+        if (object_type < 0) {
             statement_log(ps, BLOG_ERROR, "cannot call method on object with no type");
             goto fail0;
         }
@@ -1122,7 +1142,8 @@ void process_advance (struct process *p)
         module = NCDInterpProcess_StatementGetMethodModule(p->iprocess, p->ap, object_type, &method_index);
         
         if (!module) {
-            statement_log(ps, BLOG_ERROR, "unknown method statement: %s::%s", object_type, NCDInterpProcess_StatementCmdName(p->iprocess, p->ap));
+            const char *type_str = NCDStringIndex_Value(&string_index, object_type);
+            statement_log(ps, BLOG_ERROR, "unknown method statement: %s::%s", type_str, NCDInterpProcess_StatementCmdName(p->iprocess, p->ap));
             goto fail0;
         }
     }