Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

391 lines (281 sloc) 7.847 kb
/*
Copyright (C) 2005-2009, Parrot Foundation.
$Id$
=head1 Lua Userdata
=head2 Description
C<LuaUserdata> extends C<LuaAny> to provide a class with the behaviour of
the Lua C<Userdata> type.
=head3 Overloaded Methods
=over 4
=cut
*/
#include "lua_private.h"
#define u_val(pmc) (PARROT_LUAUSERDATA(pmc))->val
#define u_env(pmc) (PARROT_LUAUSERDATA(pmc))->env
#define u_mt(pmc) (PARROT_LUAUSERDATA(pmc))->mt
PMC *
_LuaUserdata_get_metatable(PARROT_INTERP, PMC *obj) {
return u_mt(obj);
}
static PMC* getcurrenv(PARROT_INTERP) {
PMC *sub_ctx = Parrot_pcc_get_caller_ctx(interp, CURRENT_CONTEXT(interp));
while (1) {
PMC *cont;
PMC *current_sub = Parrot_pcc_get_sub(interp, sub_ctx);
if (!PMC_IS_NULL(current_sub)
&& PMC_type(current_sub) == dynpmc_LuaFunction) {
PMC * const env = _LuaFunction_get_environment(interp, current_sub);
if (!PMC_IS_NULL(env))
return env;
}
cont = Parrot_pcc_get_continuation(interp, sub_ctx);
if (PMC_IS_NULL(cont))
break;
if (sub_ctx == PMC_cont(cont)->to_ctx)
break;
sub_ctx = PMC_cont(cont)->to_ctx;
if (PMC_IS_NULL(sub_ctx))
break;
}
return NULL;
}
pmclass LuaUserdata
extends LuaAny
provides scalar
auto_attrs
dynpmc
group lua_group
hll lua {
ATTR PMC *val;
ATTR PMC *env;
ATTR PMC *mt;
/*
=item C<void init()>
Initializes the userdata.
=cut
*/
VTABLE void init() {
u_val(SELF) = PMCNULL;
u_env(SELF) = getcurrenv(INTERP);
u_mt(SELF) = PMCNULL;
PObj_custom_mark_destroy_SETALL(SELF);
}
/*
=item C<void mark()>
Marks the userdata as live.
=cut
*/
VTABLE void mark() {
if (!PMC_IS_NULL(u_val(SELF)))
Parrot_gc_mark_PMC_alive(INTERP, u_val(SELF));
if (!PMC_IS_NULL(u_env(SELF)))
Parrot_gc_mark_PMC_alive(INTERP, u_env(SELF));
if (!PMC_IS_NULL(u_mt(SELF)))
Parrot_gc_mark_PMC_alive(INTERP, u_mt(SELF));
}
/*
=item C<void destroy()>
Call finalizer and free the userdata.
=cut
*/
VTABLE void destroy() {
#if 0
PMC * const meth = _LuaAny_find_meth(INTERP, SELF, "__gc");
if (!PMC_IS_NULL(meth))
Parrot_ext_call(INTERP, meth, "Pi->", SELF);
#endif
}
/*
=item C<STRING* get_string()>
=cut
*/
VTABLE STRING* get_string() {
return Parrot_sprintf_c(INTERP, "userdata: %08X", SELF);
}
/*
=item C<STRING* name()>
Return the string "userdata".
=cut
*/
VTABLE STRING* name() {
return Parrot_str_new_constant(INTERP, "userdata");
}
/*
=item C<PMC* clone()>
=cut
*/
VTABLE PMC* clone() {
return SELF;
}
/*
=item C<void set_pmc(PMC *value)>
=cut
*/
VTABLE void set_pmc(PMC *value) {
if (PMC_type(SELF) == PMC_type(value))
memcpy(PMC_data(SELF), PMC_data(value),
sizeof (Parrot_LuaUserdata_attributes));
else
Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INVALID_OPERATION,
"Can't assign a non-LuaUserdata type to a LuaUserdata");
}
/*
=item C<PMC* get_attr_str(STRING* key)>
=cut
*/
VTABLE PMC* get_attr_str(STRING *key) {
return u_val(SELF);
}
/*
=item C<void set_attr_str(STRING *key, PMC *value)>
=cut
*/
VTABLE void set_attr_str(STRING *key, PMC *value) {
u_val(SELF) = value;
}
/*
=back
=head3 non-Vtable Methods
=over 4
=item C<INTVAL is_equal(PMC *value)>
The C<==> operation. Compares reference (not in depth).
=cut
*/
MULTI INTVAL is_equal(LuaUserdata value) {
PMC * const meth = _LuaAny_find_meth(INTERP, SELF, "__eq");
if (!PMC_IS_NULL(meth)) {
PMC * retval = PMCNULL;
Parrot_ext_call(INTERP, meth, "PiP->P", SELF, value, &retval);
if (PMC_IS_NULL(retval))
return (INTVAL)0;
return VTABLE_get_bool(INTERP, retval);
}
return (SELF == value) ? (INTVAL)1 : (INTVAL)0;
}
MULTI INTVAL is_equal(DEFAULT value) {
return (INTVAL)0;
}
/*
=item C<INTVAL cmp(PMC *value)>
=cut
*/
MULTI INTVAL cmp(LuaUserdata value) {
#if 0
PMC * const meth = _LuaAny_find_meth(INTERP, SELF, "__cmp");
if (!PMC_IS_NULL(meth)) {
PMC * retval = PMCNULL;
Parrot_ext_call(INTERP, meth, "PiP->P", SELF, value, &retval);
if (!PMC_IS_NULL(retval))
return (INTVAL)VTABLE_get_number(INTERP, retval);
}
#else
PMC * const _lt = _LuaAny_find_meth(INTERP, SELF, "__lt");
if (!PMC_IS_NULL(_lt)) {
INTVAL r;
PMC * retval = PMCNULL;
Parrot_ext_call(INTERP, _lt, "PiP->P", SELF, value, &retval);
r = PMC_IS_NULL(retval)
? (INTVAL)0
: VTABLE_get_bool(INTERP, retval);
if (r)
return (INTVAL)-1;
else {
PMC * const _le = _LuaAny_find_meth(INTERP, SELF, "__le");
if (!PMC_IS_NULL(_le)) {
retval = PMCNULL;
Parrot_ext_call(INTERP, _le, "PiP->P", SELF, value, &retval);
r = PMC_IS_NULL(retval)
? (INTVAL)0
: VTABLE_get_bool(INTERP, retval);
if (r)
return (INTVAL)0;
else
return (INTVAL)1;
}
else {
retval = PMCNULL;
Parrot_ext_call(INTERP, _lt, "PiP->P", SELF, value, &retval);
r = PMC_IS_NULL(retval)
? (INTVAL)0
: VTABLE_get_bool(INTERP, retval);
if (r)
return (INTVAL)1;
else
return (INTVAL)0;
}
}
}
#endif
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
"attempt to compare two userdata values");
}
MULTI INTVAL cmp(DEFAULT value) {
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ILL_INHERIT,
"attempt to compare userdata with %Ss",
VTABLE_name(INTERP, value));
}
/*
=back
=head3 Specific Methods
=over 4
=item C<PMC *getfenv()>
=cut
*/
METHOD PMC* getfenv() {
PMC *retval = u_env(SELF);
if (PMC_IS_NULL(retval))
retval = Parrot_pmc_new(INTERP, dynpmc_LuaNil);
RETURN(PMC *retval);
}
/*
=item C<PMC *get_metatable()>
=cut
*/
METHOD PMC* get_metatable() {
PMC *retval = _LuaUserdata_get_metatable(INTERP, SELF);
if (PMC_IS_NULL(retval))
retval = Parrot_pmc_new(INTERP, dynpmc_LuaNil);
RETURN(PMC *retval);
}
/*
=item C<PMC* rawequal(PMC *value)>
=cut
*/
METHOD PMC* rawequal(PMC *value) {
const INTVAL b = (PMC_type(SELF) == PMC_type(value)
&& u_val(SELF) == u_val(value)
&& u_env(SELF) == u_env(value))
? 1 : 0;
PMC * const retval = Parrot_pmc_new(INTERP, dynpmc_LuaBoolean);
VTABLE_set_integer_native(INTERP, retval, b);
RETURN(PMC *retval);
}
/*
=item C<void setfenv(PMC *env)>
=cut
*/
METHOD void setfenv(PMC *env) {
u_env(SELF) = env;
}
/*
=item C<void set_metatable(PMC *meta)>
=cut
*/
METHOD void set_metatable(PMC *meta) {
if (dynpmc_LuaNil == PMC_type(meta))
u_mt(SELF) = PMCNULL;
else
u_mt(SELF) = meta;
}
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
Jump to Line
Something went wrong with that request. Please try again.