/*
Copyright (C) 2005-2008, The Perl Foundation.
$Id: /mirror/trunk/languages/lua/src/pmc/luafunction.pmc 35875 2009-01-20T23:32:09.452436Z chromatic  $

=head1 NAME

pmc/luafunction.pmc - Lua Function

=head1 DESCRIPTION

C<LuaFunction> extends C<Parrot Sub> and C<LuaAny> to provide a class
with the behaviour of the Lua C<Function> type.

=head2 Overloaded Methods

=over 4

=cut

*/

#include "lua_private.h"


pmclass LuaFunction
    extends  Sub
    extends  LuaAny
    provides scalar
    provides sub
    dynpmc
    need_ext
    group    lua_group
    hll      lua
    maps     Sub {

/*

=item C<void init_pmc(PMC *sub)>

=cut

*/
    VTABLE void init_pmc(PMC *sub) {
        if (VTABLE_isa(INTERP, sub, const_string(INTERP, "Sub"))) {
            PMC_struct_val(SELF) = mem_allocate_zeroed_typed(Parrot_sub);
            PMC_pmc_val(SELF)    = NULL;
            PMC_metadata(SELF)   = NULL;
            PObj_custom_mark_destroy_SETALL(SELF);
            /* copy the sub struct */
            memcpy(PMC_sub(SELF), PMC_sub(sub), sizeof (Parrot_sub));
        }
        else
            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
                "not a Sub (%Ss)", SELF->vtable->whoami);
    }

/*

=item C<void mark()>

Marks the function as live.

=cut

*/
    VTABLE void mark() {
        SUPER();
        if (PMC_metadata(SELF))
            pobject_lives(INTERP, (PObj *)PMC_metadata(SELF));
    }

/*

=item C<STRING* name()>

Return the string "function".

=cut

*/
    VTABLE STRING* name() {
        return const_string(INTERP, "function");
    }

/*

=item C<PMC *clone()>

=cut

*/
    VTABLE PMC* clone() {
        PMC* ret = SUPER();
        PMC_metadata(ret) = PMC_metadata(SELF);
        return ret;
    }

/*

=item C<STRING* get_string()>

=cut

*/
    VTABLE STRING* get_string() {
        return Parrot_sprintf_c(INTERP, "function: %08X", SELF);
    }

/*

=item C<void set_pmc(PMC *value)>

=cut

*/
    VTABLE void set_pmc(PMC *value) {
        PMC_struct_val(SELF) = PMC_struct_val(value);
        PMC_metadata(SELF)   = PMC_metadata(value);
    }

/*

=back

=head2 non-Vtable Methods

=over 4

=item C<INTVAL is_equal(PMC *value)>

=cut

*/
    MULTI INTVAL is_equal(LuaFunction value) {
        return (PMC_sub(SELF))->start_offs == (PMC_sub(value))->start_offs
            && (PMC_sub(SELF))->seg        == (PMC_sub(value))->seg;
    }

    MULTI INTVAL is_equal(DEFAULT value) {
        return (INTVAL)0;
    }

/*

=back

=head2 Specific Methods

=over 4

=cut

*/
    METHOD STRING *get_name() {
        const Parrot_sub * const sub = PMC_sub(SELF);
        STRING *retval = string_copy(INTERP, sub->name);
        RETURN(STRING *retval);
    }

/*

=item C<PMC *getfenv()>

=cut

*/
    METHOD PMC* getfenv() {
        PMC *retval = PMC_metadata(SELF);

        if (!retval)
            retval = pmc_new(INTERP, dynpmc_LuaNil);

        RETURN(PMC *retval);
    }

/*

=item C<PMC* rawequal(PMC *value)>

=cut

*/
    METHOD PMC* rawequal(PMC *value) {
        PMC *retval = pmc_new(INTERP, dynpmc_LuaBoolean);

        if (PMC_type(SELF)             == PMC_type(value)
        && (PMC_sub(SELF))->start_offs == (PMC_sub(value))->start_offs
        && (PMC_sub(SELF))->seg        == (PMC_sub(value))->seg)
            VTABLE_set_integer_native(INTERP, retval, 1);
        else
            VTABLE_set_integer_native(INTERP, retval, 0);

        RETURN(PMC *retval);
    }

/*

=item C<void setfenv(PMC *env)>

=cut

*/
    METHOD void setfenv(PMC *env) {
        PMC_metadata(SELF) = env;
    }

}

/*

=back

=cut

*/

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */
