static ChimpRef * _chimp_symtable_init (ChimpRef *self, ChimpRef *args) { ChimpRef *filename; ChimpRef *ast; if (!chimp_method_parse_args (args, "oo", &filename, &ast)) { return NULL; } CHIMP_ANY(self)->klass = chimp_symtable_class; CHIMP_SYMTABLE(self)->filename = filename; CHIMP_SYMTABLE(self)->ste = chimp_nil; CHIMP_SYMTABLE(self)->lookup = chimp_hash_new (); if (CHIMP_SYMTABLE(self)->lookup == NULL) { return NULL; } CHIMP_SYMTABLE(self)->stack = chimp_array_new (); if (CHIMP_SYMTABLE(self)->stack == NULL) { return NULL; } if (CHIMP_ANY_CLASS(ast) == chimp_ast_mod_class) { if (!chimp_symtable_visit_mod (self, ast)) return NULL; } else { CHIMP_BUG ("unknown top-level AST node type: %s", CHIMP_STR_DATA(CHIMP_CLASS(CHIMP_ANY_CLASS(ast))->name)); return NULL; } return self; }
static ChimpRef * _chimp_symtable_entry_init (ChimpRef *self, ChimpRef *args) { int64_t flags; ChimpRef *symtable; ChimpRef *scope; ChimpRef *parent; if (!chimp_method_parse_args ( args, "oooI", &symtable, &parent, &scope, &flags)) { return NULL; } CHIMP_SYMTABLE_ENTRY(self)->flags = flags; CHIMP_SYMTABLE_ENTRY(self)->symtable = symtable; CHIMP_SYMTABLE_ENTRY(self)->scope = scope; CHIMP_SYMTABLE_ENTRY(self)->parent = parent; CHIMP_SYMTABLE_ENTRY(self)->symbols = chimp_hash_new (); if (CHIMP_SYMTABLE_ENTRY(self)->symbols == NULL) { return NULL; } CHIMP_SYMTABLE_ENTRY(self)->children = chimp_array_new (); if (CHIMP_SYMTABLE_ENTRY(self)->children == NULL) { return NULL; } return self; }
static ChimpRef * parse_args (int argc, char **argv) { int i; ChimpRef *args; ChimpRef *argv_ = chimp_array_new (); for (i = 1; i < argc; i++) { ChimpRef *arg = chimp_str_new (argv[i], strlen(argv[i])); if (arg == NULL) { return NULL; } if (!chimp_array_push (argv_, arg)) { return NULL; } } args = chimp_array_new (); if (args == NULL) { return NULL; } if (!chimp_array_push (args, argv_)) { return NULL; } return args; }
static ChimpRef * _chimp_hash_items (ChimpRef *self, ChimpRef *args) { size_t i; ChimpRef *items = chimp_array_new (); for (i = 0; i < CHIMP_HASH(self)->size; i++) { ChimpRef *item = chimp_array_new_var ( CHIMP_HASH(self)->keys[i], CHIMP_HASH(self)->values[i], NULL); if (item == NULL) { return NULL; } if (!chimp_array_push (items, item)) { return NULL; } } return items; }
static ChimpRef * _chimp_unit_test(ChimpRef *self, ChimpRef *args) { fprintf (stdout, "."); // TODO: Size/argument validation on the incoming args ChimpRef *name = chimp_object_str (CHIMP_ARRAY_ITEM(args, 0)); ChimpRef *fn = CHIMP_ARRAY_ITEM(args, 1); if (test_runner == NULL) { test_runner = chimp_test_new(); } CHIMP_TEST(test_runner)->name = name; ChimpRef *fn_args = chimp_array_new(); chimp_array_push(fn_args, test_runner); chimp_object_call (fn, fn_args); CHIMP_TEST(test_runner)->passed++; return chimp_nil; }
static void * chimp_task_thread_func (void *arg) { /* NOTE: task->lock will be held by chimp_task_new at this point. */ /* this will prevent other threads fiddling before we're ready */ /* TODO better error handling */ ChimpTaskInternal *task = (ChimpTaskInternal *) arg; /* printf ("[%p] started\n", task); */ task->gc = chimp_gc_new ((void *)&task); if (task->gc == NULL) { return NULL; } chimp_task_init_per_thread_key_once (task); task->vm = chimp_vm_new (); if (task->vm == NULL) { return NULL; } task->flags |= CHIMP_TASK_FLAG_READY; pthread_cond_broadcast (&task->flags_cond); /* take an extra ref to keep the task around after the GC dies */ task->refs++; if (task->method != NULL) { ChimpRef *args; ChimpRef *taskobj = chimp_task_new_local (task); if (taskobj == NULL) { /* XXX we already have a lock, unref has its own locking code */ chimp_task_unref (task); return NULL; } task->self = taskobj; args = chimp_array_new (); CHIMP_TASK_UNLOCK(task); if (chimp_vm_invoke (task->vm, task->method, args) == NULL) { chimp_task_unref (task); return NULL; } } /************************************************************************ * * * Cleaning up the VM and GC is a-OK here because the task is finished. * * * * We can't kill the mutex nor free the internal task, because it might * * still be in use by other tasks. * * * * Bonus: this cleans up circular references & our 'self' ref. * * * ************************************************************************/ chimp_vm_delete (task->vm); task->vm = NULL; chimp_gc_delete (task->gc); task->gc = NULL; CHIMP_TASK_LOCK(task); if (task->inbox != NULL) { CHIMP_FREE (task->inbox); task->inbox = NULL; } task->inbox = NULL; /* XXX pretty much a copy/paste of chimp_task_unref without locking crap */ if (task->refs > 0) { task->refs--; if (task->refs == 0) { CHIMP_TASK_UNLOCK(task); chimp_task_cleanup (task); return NULL; } } task->flags |= CHIMP_TASK_FLAG_DONE; pthread_cond_broadcast (&task->flags_cond); CHIMP_TASK_UNLOCK(task); return NULL; }