Page MenuHomePhorge

objects.h
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

objects.h

#ifndef SV_OBJECTS_H
#define SV_OBJECTS_H
#include "utf8.h"
#include "property.h"
#include "descriptors.h"
#include "silver/engine.h"
#include "modules/symbol.h"
static inline void sv_op_define_method(
sv_vm_t *vm, ant_t *js,
sv_func_t *func, uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
uint8_t flags = sv_get_u8(ip + 5);
sv_atom_t *a = &func->atoms[atom_idx];
ant_value_t fn = vm->stack[--vm->sp];
ant_value_t obj = vm->stack[vm->sp - 1];
ant_value_t desc_obj = js_as_obj(obj);
bool is_getter = (flags & 1) != 0;
bool is_setter = (flags & 2) != 0;
if (is_getter) {
js_set_getter_desc(js, desc_obj, a->str, a->len, fn, JS_DESC_E | JS_DESC_C);
return;
}
if (is_setter) {
js_set_setter_desc(js, desc_obj, a->str, a->len, fn, JS_DESC_E | JS_DESC_C);
return;
}
ant_value_t key = js_mkstr(js, a->str, a->len);
mkprop(js, obj, key, fn, 0);
}
static inline void sv_op_define_method_comp(
sv_vm_t *vm, ant_t *js,
uint8_t *ip
) {
uint8_t flags = sv_get_u8(ip + 1);
ant_value_t fn = vm->stack[--vm->sp];
ant_value_t key = vm->stack[--vm->sp];
ant_value_t obj = vm->stack[vm->sp - 1];
ant_value_t desc_obj = js_as_obj(obj);
bool is_getter = (flags & 1) != 0;
bool is_setter = (flags & 2) != 0;
if (vtype(key) == T_SYMBOL) {
if (is_getter) { js_set_sym_getter_desc(js, desc_obj, key, fn, JS_DESC_E | JS_DESC_C); return; }
if (is_setter) { js_set_sym_setter_desc(js, desc_obj, key, fn, JS_DESC_E | JS_DESC_C); return; }
js_set_sym(js, obj, key, fn);
return;
}
ant_value_t key_str = sv_key_to_propstr(js, key);
if ((is_getter || is_setter) && vtype(key_str) == T_STR) {
ant_offset_t klen = 0;
ant_offset_t koff = vstr(js, key_str, &klen);
const char *kptr = (const char *)(uintptr_t)(koff);
if (is_getter) js_set_getter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C);
else js_set_setter_desc(js, desc_obj, kptr, klen, fn, JS_DESC_E | JS_DESC_C);
return;
}
if (vtype(key_str) == T_STR) {
ant_offset_t klen = 0;
ant_offset_t koff = vstr(js, key_str, &klen);
const char *kptr = (const char *)(uintptr_t)(koff);
js_define_own_prop(js, obj, kptr, (size_t)klen, fn);
} else mkprop(js, obj, key_str, fn, 0);
}
static inline void sv_op_set_name(
sv_vm_t *vm, ant_t *js,
sv_func_t *func, uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
sv_atom_t *a = &func->atoms[atom_idx];
ant_value_t fn = vm->stack[vm->sp - 1];
ant_value_t name = js_mkstr(js, a->str, a->len);
setprop_cstr(js, fn, "name", 4, name);
}
static inline void sv_op_set_name_comp(sv_vm_t *vm, ant_t *js) {
ant_value_t key = vm->stack[vm->sp - 1];
ant_value_t fn = vm->stack[vm->sp - 2];
ant_value_t name = coerce_to_str(js, key);
setprop_cstr(js, fn, "name", 4, name);
}
static inline void sv_op_set_proto(sv_vm_t *vm, ant_t *js) {
ant_value_t proto = vm->stack[--vm->sp];
ant_value_t obj = vm->stack[vm->sp - 1];
uint8_t pt = vtype(proto);
if (pt == T_OBJ || pt == T_NULL || pt == T_FUNC || pt == T_ARR) js_set_proto_wb(js, obj, proto);
}
static inline void sv_op_set_home_obj(sv_vm_t *vm, ant_t *js) {
ant_value_t home = vm->stack[vm->sp - 1];
ant_value_t fn = vm->stack[vm->sp - 2];
sv_closure_t *c = js_func_closure(fn);
c->super_val = home;
c->call_flags |= SV_CALL_HAS_SUPER;
}
static inline void sv_op_append(sv_vm_t *vm, ant_t *js) {
ant_value_t val = vm->stack[--vm->sp];
ant_value_t arr = vm->stack[vm->sp - 2];
js_arr_push(js, arr, val);
}
static inline void sv_op_copy_data_props(
sv_vm_t *vm, ant_t *js,
uint8_t *ip
) {
if (vm->sp < 2) return;
ant_value_t src = vm->stack[vm->sp - 1];
ant_value_t dst = vm->stack[vm->sp - 2];
if (!is_object_type(src) || !is_object_type(dst)) return;
ant_iter_t iter = js_prop_iter_begin(js, src);
ant_object_t *source_ptr = js_obj_ptr(js_as_obj(src));
ant_iter_key_t key = {0};
ant_value_t val = js_mkundef();
while (js_prop_iter_next_key(&iter, &key, NULL)) {
if (!js_is_own_enumerable_prop(js, src, source_ptr, &key)) continue;
if (key.is_symbol) {
ant_value_t prop_key = mkval(T_SYMBOL, key.sym_off);
val = js_get_sym(js, src, prop_key);
js_setprop(js, dst, prop_key, val);
} else {
val = js_get(js, src, key.str);
js_setprop(js, dst, js_mkstr(js, key.str, key.key_len), val);
}
}
js_prop_iter_end(&iter);
}
static inline ant_value_t sv_op_spread(sv_vm_t *vm, ant_t *js) {
if (vm->sp < 2)
return js_mkerr(js, "invalid spread state");
ant_value_t iterable = vm->stack[--vm->sp];
ant_value_t arr = vm->stack[vm->sp - 1];
if (vtype(arr) != T_ARR)
return js_mkerr(js, "spread target is not an array");
if (vtype(iterable) == T_ARR) {
ant_offset_t len = js_arr_len(js, iterable);
for (ant_offset_t i = 0; i < len; i++)
js_arr_push(js, arr, js_arr_get(js, iterable, i));
return tov(0);
}
if (vtype(iterable) == T_STR) {
if (str_is_heap_rope(iterable) || str_is_heap_builder(iterable)) {
iterable = str_materialize(js, iterable);
if (is_err(iterable)) return iterable;
}
ant_offset_t slen = str_len_fast(js, iterable);
for (ant_offset_t i = 0; i < slen; ) {
ant_offset_t off = vstr(js, iterable, NULL);
utf8proc_int32_t cp;
ant_offset_t cb_len = (ant_offset_t)utf8_next(
(const utf8proc_uint8_t *)(uintptr_t)(off + i),
(utf8proc_ssize_t)(slen - i), &cp
);
js_arr_push(js, arr, js_mkstr(js, (const void *)(uintptr_t)(off + i), cb_len));
i += cb_len;
}
return tov(0);
}
ant_value_t iter_fn = js_get_sym(js, iterable, get_iterator_sym());
uint8_t ft = vtype(iter_fn);
if (ft != T_FUNC && ft != T_CFUNC)
return js_mkerr(js, "not iterable");
ant_value_t iterator = sv_vm_call(vm, js, iter_fn, iterable, NULL, 0, NULL, false);
if (is_err(iterator)) return iterator;
if (!is_object_type(iterator))
return js_mkerr(js, "not iterable");
ant_value_t status = tov(0);
for (;;) {
ant_value_t next_method = js_getprop_fallback(js, iterator, "next");
ft = vtype(next_method);
if (ft != T_FUNC && ft != T_CFUNC) {
status = js_mkerr(js, "iterator.next is not a function");
break;
}
ant_value_t result = sv_vm_call(vm, js, next_method, iterator, NULL, 0, NULL, false);
if (is_err(result)) {
status = result;
break;
}
if (!is_object_type(result)) {
status = js_mkerr_typed(js, JS_ERR_TYPE, "Iterator result is not an object");
break;
}
ant_value_t done = js_getprop_fallback(js, result, "done");
if (js_truthy(js, done))
break;
ant_value_t value = js_getprop_fallback(js, result, "value");
js_arr_push(js, arr, value);
}
return status;
}
static inline void sv_op_define_class(
sv_vm_t *vm, ant_t *js,
sv_func_t *func, uint8_t *ip
) {
uint32_t atom_idx = sv_get_u32(ip + 1);
uint8_t cls_flags = sv_get_u8(ip + 5);
uint32_t source_start = sv_get_u32(ip + 6);
uint32_t source_end = sv_get_u32(ip + 10);
bool has_name = (cls_flags & 1) && (int)atom_idx < func->atom_count;
sv_atom_t *a = has_name ? &func->atoms[atom_idx] : NULL;
ant_value_t ctor = vm->stack[vm->sp - 1];
ant_value_t parent = vm->stack[vm->sp - 2];
uint8_t pt = vtype(parent);
bool parent_is_object = is_object_type(parent);
bool parent_is_callable = (pt == T_FUNC || pt == T_CFUNC);
if (vtype(ctor) == T_UNDEF) {
ant_value_t ctor_obj = mkobj(js, 0);
ctor = js_obj_to_func_ex(ctor_obj, SV_CALL_IS_DEFAULT_CTOR);
ant_value_t func_proto = js_get_slot(js->global, SLOT_FUNC_PROTO);
if (vtype(func_proto) == T_FUNC)
js_set_proto_init(ctor_obj, func_proto);
}
ant_value_t proto = mkobj(js, 0);
if (pt == T_NULL) {
js_set_proto_init(proto, js_mknull());
ant_value_t func_proto = js_get_slot(js->global, SLOT_FUNC_PROTO);
if (vtype(func_proto) == T_FUNC) js_set_proto_wb(js, ctor, func_proto);
} else if (parent_is_object) {
ant_value_t parent_proto = js_getprop_fallback(js, parent, "prototype");
if (is_object_type(parent_proto)) js_set_proto_init(proto, parent_proto);
js_set_proto_wb(js, ctor, parent);
} else {
ant_value_t object_ctor = js_getprop_fallback(js, js->global, "Object");
if (vtype(object_ctor) == T_FUNC) {
ant_value_t object_proto = js_getprop_fallback(js, object_ctor, "prototype");
if (is_object_type(object_proto)) js_set_proto_init(proto, object_proto);
}
}
if (parent_is_callable) {
if (vtype(ctor) == T_FUNC) {
sv_closure_t *c = js_func_closure(ctor);
c->super_val = parent;
c->call_flags |= SV_CALL_HAS_SUPER;
}
}
if (vtype(ctor) == T_FUNC) js_mark_constructor(js_func_obj(ctor), true);
if (
vtype(ctor) == T_FUNC && func->source &&
source_end > source_start && source_end <= (uint32_t)func->source_len
) {
js_set_slot(ctor, SLOT_CODE, mkval(T_NTARG, (uintptr_t)(func->source + source_start)));
js_set_slot(ctor, SLOT_CODE_LEN, tov((double)(source_end - source_start)));
}
setprop_interned(js, proto, "constructor", 11, ctor);
ant_value_t ctor_obj = (vtype(ctor) == T_FUNC) ? js_func_obj(ctor) : ctor;
js_mkprop_fast(js, ctor_obj, "prototype", 9, proto);
if (a && a->len > 0)
setprop_cstr(js, ctor, "name", 4, js_mkstr(js, a->str, a->len));
vm->stack[vm->sp - 2] = ctor;
vm->stack[vm->sp - 1] = proto;
}
static inline void sv_op_define_class_comp(
sv_vm_t *vm, ant_t *js,
sv_func_t *func, uint8_t *ip
) {
ant_value_t name = vm->stack[vm->sp - 1];
vm->sp--;
sv_op_define_class(vm, js, func, ip);
vm->stack[vm->sp++] = name;
}
static inline void sv_op_add_brand(sv_vm_t *vm) {
vm->sp -= 2;
}
#endif

File Metadata

Mime Type
text/x-c
Expires
Fri, May 1, 6:23 PM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
541328
Default Alt Text
objects.h (9 KB)

Event Timeline