struct variable *ui_result(struct context *context, void *widget, int32_t w, int32_t h) { struct variable *widget2 = variable_new_void(context, widget); variable_push(context, widget2); variable_push(context, variable_new_int(context, w)); variable_push(context, variable_new_int(context, h)); return variable_new_src(context, 3); }
struct variable *sys_window(struct context *context) { struct variable *value = (struct variable*)stack_pop(context->operand_stack); struct variable *uictx = param_var(value, 1); struct variable *logic = param_var(value, 2); context->singleton->keepalive = true; // so that context_del isn't called when UI is active int32_t w=0, h=0; hal_window(context, uictx, &w, &h, logic); variable_push(context, variable_new_int(context, w)); variable_push(context, variable_new_int(context, h)); return variable_new_src(context, 2); }
// get the indexed item and push on operand stack void lookup(struct context *context, struct variable *indexable, struct variable *index, bool really) { if (!really && custom_method(context, RESERVED_GET, indexable, index, NULL)) { return; } struct variable *item=0; switch (index->type) { case VAR_INT: item = list_get_int(context, indexable, index->integer); break; case VAR_STR: if (indexable->map) item = (struct variable*)map_get(indexable->map, index->str); if (!item) item = builtin_method(context, indexable, index); if (!item) item = variable_new_nil(context); break; case VAR_NIL: item = variable_new_nil(context); break; default: vm_exit_message(context, "bad index type"); break; } // DEBUGPRINT(" found %s\n", variable_value_str(context, item)); variable_push(context, item); }
static void push_str(struct context *context, struct byte_array *program) { struct byte_array* str = serial_decode_string(program); VM_DEBUGPRINT("STR '%s'\n", byte_array_to_string(str)); struct variable* v = variable_new_str(context, str); variable_push(context, v); }
static void push_fnc(struct context *context, struct byte_array *program) { uint32_t num_closures = serial_decode_int(program); struct map *closures = NULL; for (int i=0; i<num_closures; i++) { struct byte_array *name = serial_decode_string(program); if (context->runtime) { if (!closures) closures = map_new(); struct variable *c = find_var(context, name); c = variable_copy(context, c); map_insert(closures, name, c); } } struct byte_array *body = serial_decode_string(program); DEBUGPRINT("FNC %u,%u\n", num_closures, body->length); //display_code(context, body); if (context->runtime) { struct variable *f = variable_new_fnc(context, body, closures); variable_push(context, f); } }
struct variable *sys_fileattr(struct context *context) { struct variable *args = (struct variable*)stack_pop(context->operand_stack); struct variable *path = param_var(args, 1); const char *path2 = byte_array_to_string(path->str); long siz = file_size(path2); long mod = file_timestamp(path2); struct variable *siz2 = variable_new_int(context, (int32_t)siz); struct variable *mod2 = variable_new_int(context, (int32_t)mod); variable_push(context, siz2); variable_push(context, mod2 ); struct variable *result = variable_new_src(context, 2); return result; }
static void push_bool(struct context *context, struct byte_array *program) { null_check(program); int32_t num = serial_decode_int(program); VM_DEBUGPRINT("BOOL %d\n", num); struct variable* var = variable_new_bool(context, num); variable_push(context, var); }
static void push_float(struct context *context, struct byte_array *program) { null_check(program); float num = serial_decode_float(program); VM_DEBUGPRINT("FLT %f\n", num); struct variable* var = variable_new_float(context, num); variable_push(context, var); }
static void push_var(struct context *context, struct byte_array *program) { struct byte_array* name = serial_decode_string(program); VM_DEBUGPRINT("VAR %s\n", byte_array_to_string(name)); struct variable *v = find_var(context, name); if (!v) DEBUGPRINT("variable %s not found\n", byte_array_to_string(name)); vm_assert(context, v, "variable %s not found", byte_array_to_string(name)); variable_push(context, v); }
// ascii to integer struct variable *sys_atoi(struct context *context) { struct variable *value = (struct variable*)stack_pop(context->operand_stack); char *str = (char*)((struct variable*)array_get(value->list.ordered, 1))->str->data; uint32_t offset = value->list.ordered->length > 2 ? ((struct variable*)array_get(value->list.ordered, 2))->integer : 0; int n=0, i=0; bool negative = false; if (str[offset] == '-') { negative = true; i++; }; while (isdigit(str[offset+i])) n = n*10 + str[offset + i++] - '0'; n *= negative ? -1 : 1; variable_push(context, variable_new_int(context, n)); variable_push(context, variable_new_int(context, i)); return variable_new_src(context, 2); }
struct variable *sys_open(struct context *context) { struct variable *args = (struct variable*)stack_pop(context->operand_stack); struct variable *path = param_var(args, 1); char *path2 = byte_array_to_string(path->str); bool result = hal_open(path2); struct variable *result2 = variable_new_bool(context, result); variable_push(context, result2); free(path2); return NULL; }
static void unary_op(struct context *context, enum Opcode op) { if (!context->runtime) VM_DEBUGPRINT("%s\n", NUM_TO_STRING(opcodes, op)); struct variable *v = (struct variable*)variable_pop(context); struct variable *result = NULL; switch (v->type) { case VAR_NIL: { switch (op) { case VM_NEG: result = variable_new_nil(context); break; case VM_NOT: result = variable_new_bool(context, true); break; default: vm_exit_message(context, "bad math operator"); break; } } break; case VAR_INT: { int32_t n = v->integer; switch (op) { case VM_NEG: result = variable_new_int(context, -n); break; case VM_NOT: result = variable_new_bool(context, !n); break; case VM_INV: result = variable_new_int(context, ~n); break; default: vm_exit_message(context, "bad math operator"); break; } } break; case VAR_FLT: { float n = v->floater; switch (op) { case VM_NEG: result = variable_new_float(context, -n); break; case VM_NOT: result = variable_new_bool(context, !n); break; default: vm_exit_message(context, "bad math operator"); break; } } break; default: if (op == VM_NOT) result = variable_new_bool(context, false); else vm_exit_message(context, "bad math type"); break; } variable_push(context, result); DEBUGPRINT("%s(%s) = %s\n", NUM_TO_STRING(opcodes, op), variable_value_str(context, v), variable_value_str(context, result)); }
static void push_map(struct context *context, struct byte_array *program) { int32_t num_items = serial_decode_int(program); DEBUGPRINT("MAP %d", num_items); if (!context->runtime) VM_DEBUGPRINT("\n"); struct map *map = map_new(); while (num_items--) { struct variable* value = variable_pop(context); struct variable* key = variable_pop(context); assert_message(key->type==VAR_STR, "non-string map index"); map_insert(map, key->str, value); } struct variable *v = variable_new_map(context, map); DEBUGPRINT(": %s\n", variable_value_str(context, v)); variable_push(context, v); }
void vm_call(struct context *context, struct variable *func, struct variable *arg, ...) { // add variables from vararg if (arg) { va_list argp; va_start(argp, arg); struct variable *s = (struct variable*)stack_peek(context->operand_stack, 0); if (s && s->type == VAR_SRC) s = (struct variable*)stack_pop(context->operand_stack); else s = variable_new_src(context, 0); for (; arg; arg = va_arg(argp, struct variable*)) array_add(s->list, arg); va_end(argp); variable_push(context, s); } vm_call_src(context, func); }
static void binary_op(struct context *context, enum Opcode op) { if (!context->runtime) VM_DEBUGPRINT("%s\n", NUM_TO_STRING(opcodes, op)); struct variable *u = variable_pop(context); struct variable *v = variable_pop(context); enum VarType ut = (enum VarType)u->type; enum VarType vt = (enum VarType)v->type; struct variable *w; if (ut == VAR_NIL || vt == VAR_NIL) { w = binary_op_nil(context, op, u, v); } else if ((op == VM_EQU) || (op == VM_NEQ)) { bool same = variable_compare(context, u, v) ^ (op == VM_NEQ); w = variable_new_bool(context, same); } else { bool floater = (ut == VAR_FLT && is_num(vt)) || (vt == VAR_FLT && is_num(ut)); bool inter = (ut==VAR_INT || ut==VAR_BOOL) && (vt==VAR_INT || vt==VAR_BOOL); if (floater) w = binary_op_float(context, op, u, v); else if (inter) w = binary_op_int(context, op, v, u); else if (vt == VAR_STR || ut == VAR_STR) w = binary_op_str(context, op, u, v); else if (vt == VAR_LST) w = binary_op_lst(context, op, u, v); else vm_exit_message(context, "unknown binary op"); } variable_push(context, w); DEBUGPRINT("%s(%s,%s) = %s\n", NUM_TO_STRING(opcodes, op), variable_value_str(context, v), variable_value_str(context, u), variable_value_str(context, w)); }
static void push_list(struct context *context, struct byte_array *program) { int32_t num_items = serial_decode_int(program); DEBUGPRINT("LST %d", num_items); if (!context->runtime) VM_DEBUGPRINT("\n"); struct array *items = array_new(); struct map *map = NULL; while (num_items--) { struct variable* v = variable_pop(context); if (v->type == VAR_MAP) { if (!map) map = map_new(context, NULL); map_update(map, v->map); // mapped values are stored in the map, not list } else array_insert(items, 0, v); } struct variable *list = variable_new_list(context, items); list->map = map; DEBUGPRINT(": %s\n", variable_value_str(context, list)); variable_push(context, list); }
static void push_nil(struct context *context) { struct variable* var = variable_new_nil(context); VM_DEBUGPRINT("NIL\n"); variable_push(context, var); }