static void exec_get_attr(YogEnv* env, YogVal self, ID name) { SAVE_ARG(env, self); YogVal klass = YUNDEF; YogVal attr = YUNDEF; PUSH_LOCALS2(env, klass, attr); klass = YogVal_get_class(env, self); attr = YogClass_get_attr(env, klass, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, self, klass); YogScriptFrame_push_stack(env, env->frame, attr); RETURN_VOID(env); } attr = YogObj_get_attr(env, self, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, YNIL, self); YogScriptFrame_push_stack(env, env->frame, attr); RETURN_VOID(env); } YogError_raise_AttributeError(env, "%C object has no attribute \"%I\"", self, name); /* NOTREACHED */ RETURN_VOID(env); }
// Error.prototype.toString() js_val * error_proto_to_string(js_val *instance, js_args *args, eval_state *state) { if (!IS_OBJ(instance)) fh_error(state, E_TYPE, "Error.prototype.toString called on a non-object"); js_val *name_prop = fh_get_proto(instance, "name"); js_val *msg_prop = fh_get_proto(instance, "message"); js_val *name = IS_UNDEF(name_prop) ? JSSTR("Error") : TO_STR(name_prop); js_val *msg = IS_UNDEF(msg_prop) ? JSSTR("") : TO_STR(msg_prop); if (strlen(name->string.ptr) == 0) return msg; if (strlen(msg->string.ptr) == 0) return name; return JSSTR(fh_str_concat(fh_str_concat(name->string.ptr, ": "), msg->string.ptr)); }
static YogVal property(YogEnv* env, YogVal self, YogVal pkg, YogVal args, YogVal kw, YogVal block) { SAVE_ARGS5(env, self, pkg, args, kw, block); YogVal getter = YUNDEF; YogVal setter = YUNDEF; YogVal prop = YUNDEF; PUSH_LOCALS3(env, getter, setter, prop); YogCArg params[] = { { "getter", &getter }, { "|", NULL }, { "setter", &setter }, { NULL, NULL } }; YogGetArgs_parse_args(env, "property", params, args, kw); if (IS_UNDEF(setter)) { setter = YNIL; } prop = YogProperty_new(env); YogGC_UPDATE_PTR(env, PTR_AS(YogProperty, prop), getter, getter); YogGC_UPDATE_PTR(env, PTR_AS(YogProperty, prop), setter, setter); RETURN(env, prop); }
static void set_assigned_local(YogEnv* env, YogVal tbl, YogVal name, YogVal val) { if (IS_UNDEF(val)) { return; } YogDict_set(env, tbl, name, val); }
YogVal YogClass_get_attr_and_defining_class(YogEnv* env, YogVal self, ID name, YogVal* defining_class) { YogVal klass = self; YogVal attr = YUNDEF; while (IS_UNDEF(attr) && IS_PTR(klass)) { *defining_class = klass; attr = YogObj_get_attr(env, klass, name); klass = PTR_AS(YogClass, klass)->super; } return attr; }
// [new] Error(message) js_val * error_new(js_val *instance, js_args *args, eval_state *state) { js_val *err = JSOBJ(); js_val *msg = ARG(args, 0); fh_set_class(err, "Error"); if (!IS_UNDEF(msg)) fh_set(err, "message", TO_STR(msg)); err->proto = fh_try_get_proto("Error"); return err; }
static YogVal call_get_attr(YogEnv* env, YogVal self, ID name) { SAVE_ARG(env, self); YogVal klass = YUNDEF; YogVal attr = YUNDEF; PUSH_LOCALS2(env, klass, attr); klass = YogVal_get_class(env, self); attr = YogClass_get_attr(env, klass, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, self, klass); RETURN(env, attr); } attr = YogObj_get_attr(env, self, name); if (!IS_UNDEF(attr)) { attr = YogVal_get_descr(env, attr, YNIL, self); RETURN(env, attr); } RETURN(env, YUNDEF); }
METHOD_RESULT get_normal_type_instace_attribute(VALUE obj, VALUE attr, VALUE *result) { VALUE ut; HASH_OBJECT_ENTRY *e; size_t n; ut = NORMAL_TYPE_INSTANCE_TYPE(obj); e = get_hash_key(NGS_TYPE_FIELDS(ut), attr); if(!e) { return METHOD_EXCEPTION; } n = GET_INT(e->val); if(n >= OBJ_LEN(NORMAL_TYPE_INSTANCE_FIELDS(obj))) { return METHOD_EXCEPTION; } *result = ARRAY_ITEMS(NORMAL_TYPE_INSTANCE_FIELDS(obj))[n]; if(IS_UNDEF(*result)) { return METHOD_EXCEPTION; } return METHOD_OK; }
static YogVal repr_as_str(YogEnv* env, YogVal obj) { if (IS_PTR(obj) && (BASIC_OBJ_TYPE(obj) == TYPE_STRING)) { return obj; } YogHandle* h = VAL2HDL(env, obj); #define METHOD_NAME "to_s" YogVal s = YogEval_call_method0(env, obj, METHOD_NAME); YOG_ASSERT(env, !IS_UNDEF(s), "%s returned undef", METHOD_NAME); if (IS_PTR(s) && (BASIC_OBJ_TYPE(s) == TYPE_STRING)) { return s; } const char* fmt = "%C#%s() returned non-string (%C)"; YogError_raise_TypeError(env, fmt, HDL2VAL(h), METHOD_NAME, s); #undef METHOD_NAME /* NOTREACHED */ return YUNDEF; }
static void _dump(VALUE v, int level) { char **symbols; void *symbols_buffer[1]; VALUE *ptr; size_t i; HASH_OBJECT_ENTRY *e; HASH_OBJECT_ENTRY **buckets; if(IS_NULL(v)) { printf("%*s* null\n", level << 1, ""); goto exit; } if(IS_TRUE(v)) { printf("%*s* true\n", level << 1, ""); goto exit; } if(IS_FALSE(v)) { printf("%*s* false\n", level << 1, ""); goto exit; } if(IS_UNDEF(v)) { printf("%*s* undef\n", level << 1, ""); goto exit; } if(IS_KWARGS_MARKER(v)){ printf("%*s* kwargs marker\n", level << 1, ""); goto exit; } if(IS_INT(v)) { printf("%*s* int %" VALUE_NUM_FMT "\n", level << 1, "", GET_INT(v)); goto exit; } if(IS_REAL(v)) { printf("%*s* real %g\n", level << 1, "", REAL_OBJECT_VAL(v)); goto exit; } if(IS_STRING(v)) { // TODO: properly handle // 1. non-printable characters // 2. zero character printf("%*s* string(len=%zu) %.*s\n", level << 1, "", OBJ_LEN(v), (int) OBJ_LEN(v), (char *)OBJ_DATA_PTR(v)); goto exit; } if(IS_NATIVE_METHOD(v)) { symbols_buffer[0] = OBJ_DATA_PTR(v); symbols = backtrace_symbols(symbols_buffer, 1); printf("%*s* native method %s at %p req_params=%d\n", level << 1, "", symbols[0], OBJ_DATA_PTR(v), NATIVE_METHOD_OBJ_N_REQ_PAR(v)); for(i=0; i<NATIVE_METHOD_OBJ_N_REQ_PAR(v); i++) { printf("%*s* required parameter %zu\n", (level+1) << 1, "", i+1); _dump(NATIVE_METHOD_OBJ_PARAMS(v)[i*2+0], level+2); _dump(NATIVE_METHOD_OBJ_PARAMS(v)[i*2+1], level+2); } goto exit; } if(IS_CLOSURE(v)) { printf("%*s* closure name=%s ip=%zu locals_including_params=%d req_params=%d opt_params=%d n_uplevels=%d params_flags=%d\n", level << 1, "", IS_NULL(CLOSURE_OBJ_NAME(v)) ? "(none)" : obj_to_cstring(CLOSURE_OBJ_NAME(v)), CLOSURE_OBJ_IP(v), CLOSURE_OBJ_N_LOCALS(v), CLOSURE_OBJ_N_REQ_PAR(v), CLOSURE_OBJ_N_OPT_PAR(v), CLOSURE_OBJ_N_UPLEVELS(v), CLOSURE_OBJ_PARAMS_FLAGS(v) ); for(i=0; i<CLOSURE_OBJ_N_REQ_PAR(v); i++) { printf("%*s* required parameter %zu (name and type follow)\n", (level+1) << 1, "", i+1); _dump(CLOSURE_OBJ_PARAMS(v)[i*2+0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[i*2+1], level+2); } for(i=0; i<CLOSURE_OBJ_N_OPT_PAR(v); i++) { printf("%*s* optional parameter %zu (name, type and default value follow)\n", (level+1) << 1, "", i+1); _dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 1], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[CLOSURE_OBJ_N_REQ_PAR(v)*2 + i*3 + 2], level+2); } i = CLOSURE_OBJ_N_REQ_PAR(v)*2 + CLOSURE_OBJ_N_OPT_PAR(v)*3; if(CLOSURE_OBJ_PARAMS_FLAGS(v) & PARAMS_FLAG_ARR_SPLAT) { printf("%*s* array splat parameter\n", (level+1) << 1, ""); _dump(CLOSURE_OBJ_PARAMS(v)[i+0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[i+1], level+2); i+=3; } if(CLOSURE_OBJ_PARAMS_FLAGS(v) & PARAMS_FLAG_HASH_SPLAT) { printf("%*s* hash splat parameter\n", (level+1) << 1, ""); _dump(CLOSURE_OBJ_PARAMS(v)[i+0], level+2); _dump(CLOSURE_OBJ_PARAMS(v)[i+1], level+2); i+=3; } goto exit; } if(IS_ARRAY(v)) { printf("%*s* array of length %zu\n", level << 1, "", OBJ_LEN(v)); for(i=0, ptr=(VALUE *)OBJ_DATA_PTR(v); i<OBJ_LEN(v); i++, ptr++) { _dump(*ptr, level+1); } goto exit; } if(IS_HASH(v)) { printf("%*s* hash with total of %zu items in %zu buckets at %p\n", level << 1, "", OBJ_LEN(v), HASH_BUCKETS_N(v), OBJ_DATA_PTR(v)); buckets = OBJ_DATA_PTR(v); for(i=0; i<HASH_BUCKETS_N(v); i++) { if(!buckets[i]) { continue; } printf("%*s* bucket # %zu\n", (level+1) << 1, "", i); for(e=buckets[i]; e; e=e->bucket_next) { printf("%*s* item at %p with hash() of %u insertion_order_prev=%p insertion_order_next=%p \n", (level+2) << 1, "", (void *)e, e->hash, (void *)e->insertion_order_prev, (void *)e->insertion_order_next); printf("%*s* key\n", (level+3) << 1, ""); _dump(e->key, level+4); printf("%*s* value\n", (level+3) << 1, ""); _dump(e->val, level+4); } } goto exit; } if(IS_NGS_TYPE(v)) { printf("%*s* type (name and optionally constructors and parents follow) id=%" PRIdPTR " ptr=%p\n", level << 1, "", NGS_TYPE_ID(v), IS_NORMAL_TYPE(v) ? v.ptr : 0); _dump(NGS_TYPE_NAME(v), level + 1); if(level < 3) { _dump(NGS_TYPE_FIELDS(v), level + 1); _dump(NGS_TYPE_CONSTRUCTORS(v), level + 1); _dump(NGS_TYPE_PARENTS(v), level + 1); } goto exit; } if(IS_CLIB(v)) { printf("%*s* C library (name follows) ptr=%p\n", level << 1, "", OBJ_DATA_PTR(v)); _dump(CLIB_OBJECT_NAME(v), level + 1); goto exit; } if(IS_CSYM(v)) { printf("%*s* C symbol (name and libraray follow) ptr=%p\n", level << 1, "", OBJ_DATA_PTR(v)); _dump(CSYM_OBJECT_NAME(v), level + 1); _dump(CSYM_OBJECT_LIB(v), level + 1); goto exit; } if(IS_NORMAL_TYPE_CONSTRUCTOR(v)) { printf("%*s* user type constructor (type optionally follows)\n", level << 1, ""); if(level < 3) { _dump(OBJ_DATA(v), level + 1); } goto exit; } if(IS_NORMAL_TYPE_INSTANCE(v)) { printf("%*s* user type instance (type and fields optionally follow)\n", level << 1, ""); // level < 4 so that uncaught exception ImplNotFound could display the type of the arguments if(level < 4) { _dump(NORMAL_TYPE_INSTANCE_TYPE(v), level + 1); _dump(NORMAL_TYPE_INSTANCE_FIELDS(v), level + 1); } goto exit; } printf("%*s* (dump not implemented for the object at %p)\n", level << 1, "", OBJ_DATA_PTR(v)); exit: return; }