void js_builtin_core (JSVirtualMachine *vm) { int i; JSNode *n; /* Properties. */ n = &vm->globals[js_vm_intern (vm, "NaN")]; n->type = JS_NAN; n = &vm->globals[js_vm_intern (vm, "Infinity")]; JS_MAKE_POSITIVE_INFINITY (n); /* Global methods. */ for (i = 0; global_methods[i].name; i++) { JSBuiltinInfo *info; info = js_vm_builtin_info_create (vm); info->global_method_proc = global_methods[i].method; n = &vm->globals[js_vm_intern (vm, global_methods[i].name)]; js_vm_builtin_create (vm, n, info, NULL); } }
static void js_core_globals (JSInterpPtr interp) { JSNode *n; JSBuiltinInfo *info; JSVirtualMachine *vm = interp->vm; /* Command `error'. */ info = js_vm_builtin_info_create (vm); info->global_method_proc = error_global_method; n = &interp->vm->globals[js_vm_intern (interp->vm, "error")]; js_vm_builtin_create (interp->vm, n, info, interp); if (!interp->options.no_compiler) { /* Command `eval'. */ info = js_vm_builtin_info_create (vm); info->global_method_proc = eval_global_method; n = &interp->vm->globals[js_vm_intern (interp->vm, "eval")]; js_vm_builtin_create (interp->vm, n, info, interp); } /* Command `load'. */ info = js_vm_builtin_info_create (vm); info->global_method_proc = load_global_method; n = &interp->vm->globals[js_vm_intern (interp->vm, "load")]; js_vm_builtin_create (interp->vm, n, info, interp); }
void js_builtin_Number (JSVirtualMachine *vm) { NumberCtx *ctx; JSNode *n; JSBuiltinInfo *info; ctx = js_calloc (vm, 1, sizeof (*ctx)); ctx->s_MAX_VALUE = js_vm_intern (vm, "MAX_VALUE"); ctx->s_MIN_VALUE = js_vm_intern (vm, "MIN_VALUE"); ctx->s_NaN = js_vm_intern (vm, "NaN"); ctx->s_NEGATIVE_INFINITY = js_vm_intern (vm, "NEGATIVE_INFINITY"); ctx->s_POSITIVE_INFINITY = js_vm_intern (vm, "POSITIVE_INFINITY"); info = js_vm_builtin_info_create (vm); vm->prim[JS_INTEGER] = info; vm->prim[JS_FLOAT] = info; vm->prim[JS_NAN] = info; info->method_proc = method; info->property_proc = property; info->obj_context = ctx; info->obj_context_delete = js_free; /* Define it. */ n = &vm->globals[js_vm_intern (vm, "Number")]; js_vm_builtin_create (vm, n, info, NULL); }
int js_create_global_method (JSInterpPtr interp, char *name, JSGlobalMethodProc proc, void *context, JSFreeProc context_free_proc) { JSNode *n = &interp->vm->globals[js_vm_intern (interp->vm, name)]; JSVirtualMachine *vm = interp->vm; int result = 1; /* Need one toplevel here. */ { JSErrorHandlerFrame handler; /* We must create the toplevel ourself. */ memset (&handler, 0, sizeof (handler)); handler.next = vm->error_handler; vm->error_handler = &handler; if (setjmp (vm->error_handler->error_jmp)) /* An error occurred. */ result = 0; else { JSBuiltinInfo *info; JSGlobalMethodContext *ctx; /* Context. */ ctx = js_calloc (vm, 1, sizeof (*ctx)); ctx->proc = proc; ctx->context = context; ctx->free_proc = context_free_proc; ctx->interp = interp; /* Info. */ info = js_vm_builtin_info_create (vm); info->global_method_proc = js_global_method_stub; /* Create the builtin. */ js_vm_builtin_create (interp->vm, n, info, ctx); } /* Pop the error handler. */ vm->error_handler = vm->error_handler->next; } return result; }
void js_builtin_Function (JSVirtualMachine *vm) { JSNode *n; JSBuiltinInfo *info; info = js_vm_builtin_info_create (vm); vm->prim[JS_FUNC] = info; info->method_proc = method; info->property_proc = property; /* Define it. */ n = &vm->globals[js_vm_intern (vm, "Function")]; js_vm_builtin_create (vm, n, info, NULL); }
void init_builtin_digitalio(JSVirtualMachine *vm) { JSBuiltinInfo *info; JSNode *n; unsigned char i; struct { char *name; JSBuiltinGlobalMethod method; } global_methods[] = { {"pinMode", pinMode_global_method}, {"digitalWrite", digitalWrite_global_method}, {"digitalRead", digitalRead_global_method}, {NULL, NULL} }; for (i = 0; global_methods[i].name; i++) { info = js_vm_builtin_info_create(vm); info->global_method_proc = global_methods[i].method; n = &vm->globals[js_vm_intern(vm, global_methods[i].name)]; js_vm_builtin_create(vm, n, info, NULL); } }
int js_vm_switch0_exec (JSVirtualMachine *vm, JSByteCode *bc, JSSymtabEntry *symtab, unsigned int num_symtab_entries, unsigned int consts_offset, unsigned int anonymous_function_offset, /*unsigned char *debug_info, unsigned int debug_info_len,*/ JSNode *object, JSNode *func, unsigned int argc, JSNode *argv) { int i; unsigned int ui; Function *global_f = NULL; Function *f; unsigned char *code = NULL; char buf[512]; if (bc) { /* Executing byte-code. */ /* Find the code section. */ for (i = 0; i < bc->num_sects; i++) if (bc->sects[i].type == JS_BCST_CODE) code = bc->sects[i].data; assert (code != NULL); /* Enter all functions to the known functions of the VM. */ for (i = 0; i < num_symtab_entries; i++) { /* Need one function. */ f = js_vm_alloc_destroyable (vm, sizeof (*f)); f->destroy = function_destroy; f->name = js_strdup (vm, symtab[i].name); f->length = symtab[i + 1].offset - symtab[i].offset + 1; f->code = js_malloc (vm, f->length); memcpy (f->code, code + symtab[i].offset, f->length - 1); f->code[f->length - 1] = 1; /* op `done' */ /* Link the code to our environment. */ link_code (vm, f->code, f->length, consts_offset); if (strcmp (symtab[i].name, JS_GLOBAL_NAME) == 0) global_f = f; else { int is_anonymous = 0; /* Check for the anonymous function. */ if (symtab[i].name[0] == '.' && symtab[i].name[1] == 'F' && symtab[i].name[2] == ':') is_anonymous = 1; if (vm->verbose > 3) { sprintf_P (buf, vmswt0_string_0, symtab[i].name, symtab[i].offset, symtab[i + 1].offset - symtab[i].offset); if (is_anonymous) sprintf_P (buf + strlen (buf), vmswt0_string_1, anonymous_function_offset); strcat (buf, JS_HOST_LINE_BREAK); //js_iostream_write (vm->s_stderr, buf, strlen (buf)); } if (is_anonymous) { sprintf (buf, ".F:%u", (unsigned int) atoi (symtab[i].name + 3) + anonymous_function_offset); ui = js_vm_intern (vm, buf); } else ui = js_vm_intern (vm, symtab[i].name); vm->globals[ui].type = JS_FUNC; vm->globals[ui].u.vfunction = js_vm_make_function (vm, f); } } } else { /* Applying arguments to function. */ if (func->type != JS_FUNC) { sprintf_P (vm->error, vmswt0_string_2); return 0; } if (vm->verbose > 1) { sprintf_P (buf, vmswt0_string_3, JS_HOST_LINE_BREAK); //js_iostream_write (vm->s_stderr, buf, strlen (buf)); } f = func->u.vfunction->implementation; execute_code (vm, object, f, argc, argv); } if (global_f) { if (vm->verbose > 1) { sprintf_P (buf, vmswt0_string_4, global_f->name, JS_HOST_LINE_BREAK); //js_iostream_write (vm->s_stderr, buf, strlen (buf)); } /* Execute. */ execute_code (vm, NULL, global_f, 0, NULL); } return 1; }
void js_ext_curses (JSInterpPtr interp) { CursesCtx *ctx; JSBuiltinInfo *info; JSNode *n; JSVirtualMachine *vm = interp->vm; /* Class context. */ ctx = js_calloc (vm, 1, sizeof (*ctx)); ctx->s_addstr = js_vm_intern (vm, "addstr"); ctx->s_attron = js_vm_intern (vm, "attron"); ctx->s_attroff = js_vm_intern (vm, "attroff"); ctx->s_beep = js_vm_intern (vm, "beep"); ctx->s_cbreak = js_vm_intern (vm, "cbreak"); ctx->s_clear = js_vm_intern (vm, "clear"); ctx->s_clrtobot = js_vm_intern (vm, "clrtobot"); ctx->s_clrtoeol = js_vm_intern (vm, "clrtoeol"); ctx->s_echo = js_vm_intern (vm, "echo"); ctx->s_endwin = js_vm_intern (vm, "endwin"); ctx->s_getch = js_vm_intern (vm, "getch"); ctx->s_initscr = js_vm_intern (vm, "initscr"); ctx->s_keypad = js_vm_intern (vm, "keypad"); ctx->s_move = js_vm_intern (vm, "move"); ctx->s_mvaddstr = js_vm_intern (vm, "mvaddstr"); ctx->s_mvaddsubstr = js_vm_intern (vm, "mvaddsubstr"); ctx->s_mvgetch = js_vm_intern (vm, "mvgetch"); ctx->s_nocbreak = js_vm_intern (vm, "nocbreak"); ctx->s_noecho = js_vm_intern (vm, "noecho"); ctx->s_refresh = js_vm_intern (vm, "refresh"); ctx->s_standend = js_vm_intern (vm, "standend"); ctx->s_standout = js_vm_intern (vm, "standout"); ctx->s_LINES = js_vm_intern (vm, "LINES"); ctx->s_COLS = js_vm_intern (vm, "COLS"); /* Object information. */ info = js_vm_builtin_info_create (vm); info->method_proc = method; info->property_proc = property; info->obj_context = ctx; info->obj_context_delete = js_free; /* Define it. */ n = &vm->globals[js_vm_intern (vm, "Curses")]; js_vm_builtin_create (vm, n, info, NULL); }
void js_get_var (JSInterpPtr interp, char *name, JSType *value) { JSNode *n = &interp->vm->globals[js_vm_intern (interp->vm, name)]; JS_COPY ((JSNode *) value, n); }
int js_vm_call_method(JSVirtualMachine * vm, JSNode * object, const char *method_name, unsigned int argc, JSNode * argv) { int result = 1; JSNode *saved_sp; JSErrorHandlerFrame *handler, *saved_handler; JSSymbol symbol; /* Initialize error handler. */ saved_sp = vm->sp; saved_handler = vm->error_handler; handler = js_calloc(NULL, 1, sizeof(*handler)); if (handler == NULL) { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "VM: out of memory"); #endif return 0; } handler->next = vm->error_handler; vm->error_handler = handler; if (setjmp(vm->error_handler->error_jmp)) { /* An error occurred. */ if(vm->error_handler->thrown.type == JS_INTEGER) { result = vm->error_handler->thrown.u.vinteger; } else { result = 0; } } else { /* Intern the method name. */ symbol = js_vm_intern(vm, method_name); /* Clear error message and old exec result. */ #ifdef JS_RUNTIME_WARNING vm->error[0] = '\0'; #endif vm->exec_result.type = JS_UNDEFINED; /* What kind of object was called? */ if (object->type == JS_BUILTIN) { if (object->u.vbuiltin->info->method_proc) { if ((*object->u.vbuiltin->info->method_proc) (vm, object->u. vbuiltin-> info, object->u. vbuiltin-> instance_context, symbol, &vm->exec_result, argv) == JS_PROPERTY_UNKNOWN) { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "call_method: unknown method"); #endif result = 0; } } else { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "illegal builtin object for call_method"); #endif result = 0; } } else if (object->type == JS_OBJECT) { JSNode method; /* Fetch the method's implementation. */ if (js_vm_object_load_property(vm, object->u.vobject, symbol, &method) == JS_PROPERTY_FOUND) { /* The property has been defined in the object. */ if (method.type != JS_FUNC) { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "call_method: unknown method"); #endif result = 0; } else { JS_PROFILING_ON(); result = (*vm->dispatch_execute) (vm, NULL, NULL, 0, 0, 0, #ifdef JS_RUNTIME_DEBUG NULL, 0, #endif object, &method, argc, argv); } } else /* Let the built-in Object handle this. */ goto to_builtin_please; } else if (vm->prim[object->type]) { /* The primitive language types. */ to_builtin_please: if ((*vm->prim[object->type]->method_proc) (vm, vm->prim[object-> type], object, symbol, &vm->exec_result, argv) == JS_PROPERTY_UNKNOWN) { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "call_method: unknown method"); #endif result = 0; } } else { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "illegal object for call_method"); #endif result = 0; } } JS_PROFILING_OFF(); /* Pop all error handler frames from the handler chain. */ for (; vm->error_handler != saved_handler; vm->error_handler = handler) { handler = vm->error_handler->next; js_free(vm->error_handler); } /* Restore virtual machine's idea about the stack top. */ vm->sp = saved_sp; return result; }
JSVirtualMachine *js_vm_create( unsigned int stack_size #ifdef JS_RUNTIME_WARNING , unsigned int verbose #endif #ifdef JS_RUNTIME_DEBUG , int stacktrace_on_error #endif #ifdef JS_IOSTREAM , JSIOStream * s_stdin, JSIOStream * s_stdout, JSIOStream * s_stderr #endif ) { JSVirtualMachine *vm; vm = js_calloc(NULL, 1, sizeof(*vm)); if (vm == NULL) return NULL; #ifdef JS_RUNTIME_WARNING vm->verbose = verbose; vm->warn_undef = 1; #endif #ifdef JS_RUNTIME_DEBUG vm->stacktrace_on_error = stacktrace_on_error; #endif /* Set the system streams. */ #ifdef JS_IOSTREAM vm->s_stdin = s_stdin; vm->s_stdout = s_stdout; vm->s_stderr = s_stderr; #endif /* Resolve the dispatch method. */ vm->dispatch_execute = js_vm_switch0_exec; #ifdef JS_RUNTIME_DEBUG vm->dispatch_func_name = js_vm_switch0_func_name; vm->dispatch_debug_position = js_vm_switch0_debug_position; #endif vm->stack_size = stack_size; vm->stack = js_malloc(NULL, vm->stack_size * sizeof(*vm->stack)); if (vm->stack == NULL) { js_free(vm); return NULL; } /* Set the initial stack pointer. */ vm->sp = vm->stack + vm->stack_size - 1; vm->gc.trigger = GC_TRIGGER; /* We need a toplevel here. */ { JSErrorHandlerFrame handler; int result = 1; memset(&handler, 0, sizeof(handler)); handler.next = vm->error_handler; vm->error_handler = &handler; if (setjmp(vm->error_handler->error_jmp)) /* An error occurred. */ result = 0; else { /* Intern some commonly used symbols. */ vm->syms.s___proto__ = js_vm_intern(vm, "__proto__"); vm->syms.s_prototype = js_vm_intern(vm, "prototype"); vm->syms.s_toSource = js_vm_intern(vm, "toSource"); vm->syms.s_toString = js_vm_intern(vm, "toString"); vm->syms.s_valueOf = js_vm_intern(vm, "valueOf"); /* Intern system built-in objects. */ intern_builtins(vm); } /* Pop the error handler. */ vm->error_handler = vm->error_handler->next; if (result == 0) { /* Argh, the initialization failed. */ js_vm_destroy(vm); return NULL; } } return vm; }
int js_vm_apply(JSVirtualMachine * vm, char *func_name, JSNode * func, unsigned int argc, JSNode * argv) { int result = 1; JSNode *saved_sp; JSErrorHandlerFrame *handler, *saved_handler; /* Initialize error handler. */ saved_sp = vm->sp; saved_handler = vm->error_handler; handler = js_calloc(NULL, 1, sizeof(*handler)); if (handler == NULL) { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "VM: out of memory"); #endif return 0; } handler->next = vm->error_handler; vm->error_handler = handler; if (setjmp(vm->error_handler->error_jmp)) { /* An error occurred. */ if(vm->error_handler->thrown.type == JS_INTEGER) { result = vm->error_handler->thrown.u.vinteger; } else { result = 0; } } else { /* Clear error message and old exec result. */ #ifdef JS_RUNTIME_WARNING vm->error[0] = '\0'; #endif vm->exec_result.type = JS_UNDEFINED; if (func_name) /* Lookup the function. */ func = &vm->globals[js_vm_intern(vm, func_name)]; /* Check what kind of function should be called. */ if (func->type == JS_FUNC) { JS_PROFILING_ON(); /* Call function. */ result = (*vm->dispatch_execute) (vm, NULL, NULL, 0, 0, 0, #ifdef JS_RUNTIME_DEBUG NULL, 0, #endif NULL, func, argc, argv); } else if (func->type == JS_BUILTIN && func->u.vbuiltin->info->global_method_proc != NULL) { (*func->u.vbuiltin->info->global_method_proc) (vm, func->u. vbuiltin->info, func->u. vbuiltin-> instance_context, &vm->exec_result, argv); } else { #ifdef JS_RUNTIME_WARNING if (func_name) sprintf(vm->error, "undefined function `%s' in apply", func_name); else sprintf(vm->error, "undefiend function in apply"); #endif result = 0; } } JS_PROFILING_OFF(); /* Pop all error handler frames from the handler chain. */ for (; vm->error_handler != saved_handler; vm->error_handler = handler) { handler = vm->error_handler->next; js_free(vm->error_handler); } /* Restore virtual machine's idea about the stack top. */ vm->sp = saved_sp; return result; }
int js_vm_execute(JSVirtualMachine * vm, JSByteCode * bc) { int i, sect; unsigned int ui; unsigned char *cp; unsigned int consts_offset; char buf[256]; JSSymtabEntry *symtab = NULL; unsigned int num_symtab_entries = 0; unsigned int code_len = 0; JSNode *saved_sp; JSErrorHandlerFrame *handler, *saved_handler; int result = 1; #ifdef JS_RUNTIME_DEBUG unsigned char *debug_info; unsigned int debug_info_len; #endif unsigned int anonymous_function_offset; /* We need a toplevel over the whole function. */ saved_sp = vm->sp; saved_handler = vm->error_handler; handler = js_calloc(NULL, 1, sizeof(*handler)); if (handler == NULL) { #ifdef JS_RUNTIME_WARNING sprintf(vm->error, "VM: out of memory"); #endif return 0; } handler->next = vm->error_handler; vm->error_handler = handler; if (setjmp(vm->error_handler->error_jmp)) { /* Ok, we had an error down there somewhere. */ if(vm->error_handler->thrown.type == JS_INTEGER) { result = vm->error_handler->thrown.u.vinteger; } else { result = 0; } } else { /* The main stuffs for the execute. */ /* Process constants. */ consts_offset = vm->num_consts; anonymous_function_offset = vm->anonymous_function_next_id; for (sect = 0; sect < bc->num_sects; sect++) if (bc->sects[sect].type == JS_BCST_CONSTANTS) { cp = bc->sects[sect].data; for (ui = 0; ui < bc->sects[sect].length;) { JSNode *c; /* Check that we still have space for this constant. */ if (vm->num_consts >= vm->consts_alloc) { // CHANGE alloc times to 16 vm->consts = js_realloc(vm, vm->consts, (vm->consts_alloc + 16) * sizeof(JSNode)); vm->consts_alloc += 16; } c = &vm->consts[vm->num_consts++]; /* Process this constant. */ c->type = (JSNodeType) cp[ui++]; switch (c->type) { case JS_NULL: break; case JS_BOOLEAN: c->u.vboolean = cp[ui++]; break; case JS_STRING: c->u.vstring = js_vm_alloc(vm, sizeof(*c->u.vstring)); c->u.vstring->staticp = 1; c->u.vstring->prototype = NULL; JS_BC_READ_INT32(cp + ui, c->u.vstring->len); ui += 4; c->u.vstring->data = js_malloc(vm, c->u.vstring->len + 1); memcpy(c->u.vstring->data, cp + ui, c->u.vstring->len); c->u.vstring->data[c->u.vstring->len] = '\0'; ui += c->u.vstring->len; break; case JS_INTEGER: JS_BC_READ_INT32(cp + ui, c->u.vinteger); ui += 4; break; case JS_FLOAT: memcpy(&c->u.vfloat, cp + ui, sizeof(JSFloat)); ui += sizeof(JSFloat); break; case JS_SYMBOL: for (i = 0; cp[ui]; ui++, i++) buf[i] = cp[ui]; buf[i] = '\0'; /* Eat the trailing '\0' from the data. */ ui++; if (buf[0] == '.' && buf[1] == 'F' && buf[2] == ':') //sprintf(buf + 3, "%u", vm->anonymous_function_next_id++); vm->anonymous_function_next_id++; /* Intern symbol. */ c->u.vsymbol = js_vm_intern(vm, buf); break; #if 0 case JS_BUILTIN: /* Regular expression. */ { unsigned char flags; unsigned int length; flags = cp[ui++]; JS_BC_READ_INT32 (cp + ui, length); ui += 4; js_builtin_RegExp_new (vm, cp + ui, length, flags, 1, NULL, c); ui += length; } break; #endif case JS_NAN: /* Nothing here. */ break; default: case JS_IPTR: #ifdef JS_RUNTIME_WARNING sprintf(buf, "js_vm_execute(): unknown constant type %d%s", c->type, JS_HOST_LINE_BREAK); #ifdef JS_IOSTREAM js_iostream_write(vm->s_stderr, buf, strlen(buf)); js_iostream_flush(vm->s_stderr); #else fwrite(buf, strlen(buf), 1, stderr); #endif #endif abort(); break; } } /* All done with the constants. */ break; } /* Check how long the code section is. */ for (sect = 0; sect < bc->num_sects; sect++) if (bc->sects[sect].type == JS_BCST_CODE) { code_len = bc->sects[sect].length; break; } /* Process symbol table. */ for (sect = 0; sect < bc->num_sects; sect++) if (bc->sects[sect].type == JS_BCST_SYMTAB) { JSSymtabEntry *se; char buf[257]; cp = bc->sects[sect].data; /* The number of symbols. */ JS_BC_READ_INT32(cp, num_symtab_entries); symtab = js_calloc(vm, num_symtab_entries + 1, sizeof(*symtab)); /* Make the terminator by hand. */ symtab[num_symtab_entries].offset = code_len; /* Enter symbols. */ se = symtab; for (ui = 4; ui < bc->sects[sect].length; se++) { for (i = 0; cp[ui]; ui++, i++) buf[i] = cp[ui]; buf[i] = '\0'; se->name = js_strdup(vm, buf); ui++; JS_BC_READ_INT32(cp + ui, se->offset); ui += 4; } break; } /* Check if we have debugging information. */ #ifdef JS_RUNTIME_DEBUG debug_info = NULL; debug_info_len = 0; for (sect = 0; sect < bc->num_sects; sect++) if (bc->sects[sect].type == JS_BCST_DEBUG) { debug_info = bc->sects[sect].data; debug_info_len = bc->sects[sect].length; } #endif /* Clear error message and old exec result. */ #ifdef JS_RUNTIME_WARNING vm->error[0] = '\0'; #endif vm->exec_result.type = JS_UNDEFINED; JS_PROFILING_ON(); /* Execute. */ result = (*vm->dispatch_execute) (vm, bc, symtab, num_symtab_entries, consts_offset, anonymous_function_offset, #ifdef JS_RUNTIME_DEBUG debug_info, debug_info_len, #endif NULL, NULL, 0, NULL); } JS_PROFILING_OFF(); if (symtab) { for (ui = 0; ui < num_symtab_entries; ui++) js_free(symtab[ui].name); js_free(symtab); } /* Pop all error handler frames from the handler chain. */ for (; vm->error_handler != saved_handler; vm->error_handler = handler) { handler = vm->error_handler->next; js_free(vm->error_handler); } /* Restore virtual machine's idea about the stack top. */ vm->sp = saved_sp; return result; }
int js_vm_switch_exec (JSVirtualMachine *vm, JSByteCode *bc, JSSymtabEntry *symtab, unsigned int num_symtab_entries, unsigned int consts_offset, unsigned char *debug_info, unsigned int debug_info_len, char *func_name, JSNode *func, unsigned int argc, JSNode *argv) { int i; unsigned int ui; Function *global_f = NULL; Function *f; unsigned char *code = NULL; if (bc) { /* Executing byte-code. */ /* Find the code section. */ for (i = 0; i < bc->num_sects; i++) if (bc->sects[i].type == JS_BCST_CODE) code = bc->sects[i].data; assert (code != NULL); /* Enter all functions to the known functions of the VM. */ for (i = 0; i < num_symtab_entries; i++) { /* Link the code to our environment. */ f = link_code (vm, code + symtab[i].offset, symtab[i + 1].offset - symtab[i].offset, consts_offset); f->name = js_strdup (vm, symtab[i].name); if (strcmp (symtab[i].name, JS_GLOBAL_NAME) == 0) global_f = f; else { if (vm->verbose > 3) printf ("VM: link: %s(): start=%d, length=%d\n", symtab[i].name, symtab[i].offset, symtab[i + 1].offset - symtab[i].offset); ui = js_vm_intern (vm, symtab[i].name); vm->globals[ui].type = JS_FUNC; vm->globals[ui].u.vfunction = js_vm_make_function (vm, f); } } } else { JSNode *n; /* Applying arguments to function. */ if (func_name) { /* Lookup function. */ JSSymbol sym; sym = js_vm_intern (vm, func_name); n = &vm->globals[sym]; if (n->type != JS_FUNC) { sprintf (vm->error, "undefined function `%s' in apply", func_name); return 0; } if (vm->verbose > 1) printf ("VM: calling %s()\n", func_name); } else { /* Use the function the caller gave us. */ n = func; if (n->type != JS_FUNC) { sprintf (vm->error, "illegal function in apply"); return 0; } if (vm->verbose > 1) printf ("VM: calling function\n"); } f = n->u.vfunction->implementation; execute_code (vm, f, argc, argv); } if (global_f) { if (vm->verbose > 1) printf ("VM: exec: %s\n", global_f->name); /* Execute. */ execute_code (vm, global_f, 0, NULL); } return 1; }
void js_builtin_Array (JSVirtualMachine *vm) { ArrayCtx *ctx; JSNode *n; JSBuiltinInfo *info; ctx = js_calloc (vm, 1, sizeof (*ctx)); ctx->s_concat = js_vm_intern (vm, "concat"); ctx->s_join = js_vm_intern (vm, "join"); ctx->s_pop = js_vm_intern (vm, "pop"); ctx->s_push = js_vm_intern (vm, "push"); ctx->s_reverse = js_vm_intern (vm, "reverse"); ctx->s_shift = js_vm_intern (vm, "shift"); ctx->s_slice = js_vm_intern (vm, "slice"); ctx->s_splice = js_vm_intern (vm, "splice"); ctx->s_sort = js_vm_intern (vm, "sort"); ctx->s_unshift = js_vm_intern (vm, "unshift"); ctx->s_length = js_vm_intern (vm, "length"); info = js_vm_builtin_info_create (vm); vm->prim[JS_ARRAY] = info; info->method_proc = method; info->property_proc = property; info->new_proc = new_proc; info->obj_context = ctx; info->obj_context_delete = js_free; /* Define it. */ n = &vm->globals[js_vm_intern (vm, "Array")]; js_vm_builtin_create (vm, n, info, NULL); }