/*
Copyright (C) 2005-2006, The Perl Foundation.
$Id: luanil.pmc 17096 2007-02-20 20:20:48Z paultcochrane $

=head1 NAME

pmc/luanil.pmc - Lua Nil

=head1 DESCRIPTION

C<LuaNil> extends C<LuaAny> to provide a class with the behaviour of
the Lua C<Nil> type.

=for rational

LuaNil is no longer a singleton;
this would be a problem, as all uninitialized values in Lua are LuaNil.
If some value is assigned, the LuaNil should morph into the correct type,
and so a new PMC is constructed anyway. Therefore, we may as well create
a new PMC right away. Also, creating a new PMC from a singleton class is
troublesome (if not possible?).

=head2 Methods

=over 4

=cut

*/

#include "parrot/parrot.h"

static STRING *string_representation;
STRING *lua_metatable;
INTVAL dynpmc_LuaBoolean;
INTVAL dynpmc_LuaClosure;
INTVAL dynpmc_LuaFunction;
INTVAL dynpmc_LuaNil;
INTVAL dynpmc_LuaNumber;
INTVAL dynpmc_LuaString;
INTVAL dynpmc_LuaTable;

pmclass LuaNil
    extends LuaAny
    does scalar
    dynpmc
    group lua_group
    hll Lua {

/*
* Class initialization. Caches constant strings that will be used later.
*/
    void class_init() {
        if (pass) {
            string_representation = const_string(INTERP, "nil");
            dynpmc_LuaBoolean = pmc_type(INTERP,
              const_string(INTERP, "LuaBoolean"));
            dynpmc_LuaClosure = pmc_type(INTERP,
              const_string(INTERP, "LuaClosure"));
            dynpmc_LuaFunction = pmc_type(INTERP,
              const_string(INTERP, "LuaFunction"));
            dynpmc_LuaNil = pmc_type(INTERP,
              const_string(INTERP, "LuaNil"));
            dynpmc_LuaNumber = pmc_type(INTERP,
              const_string(INTERP, "LuaNumber"));
            dynpmc_LuaString = pmc_type(INTERP,
              const_string(INTERP, "LuaString"));
            dynpmc_LuaTable = pmc_type(INTERP,
              const_string(INTERP, "LuaTable"));
            lua_metatable = const_string(INTERP, "__metatable");
        }
    }

/*

=item C<PMC* new_from_string(STRING *rep, INTVAL flags)>

Allow :

    .const .LuaNil nil = "dummy"

=cut

*/
    PMC* new_from_string (STRING *rep, INTVAL flags) {
        INTVAL type;
        PMC *res;

        type = SELF->vtable->base_type;
        if (flags & PObj_constant_FLAG)
            res = constant_pmc_new(INTERP, type);
        else
            res = pmc_new(INTERP, type);

        return res;
    }

/*

=item C<void morph(INTVAL type)>

Morphs the scalar to the specified type.

=cut

*/
    void morph (INTVAL type) {
        if (SELF->vtable->base_type == type)
            return;
        pmc_reuse(INTERP, SELF, type, 0);
    }

/*

=item C<STRING* name()>

Return the string "nil".

=cut

*/
    STRING* name () {
        return string_representation;
    }

/*

=item C<PMC *clone()>

Creates and returns a clone of the scalar.

=cut

*/
    PMC* clone () {
        PMC* dest = pmc_new(INTERP, SELF->vtable->base_type);
        memcpy(&PMC_union(dest), &PMC_union(SELF), sizeof(UnionVal));
        return dest;
    }

/*

=item C<STRING* get_string ()>

Return the string "nil".

=cut

*/
    STRING* get_string () {
        return string_representation;
    }

/*

=item C<INTVAL get_bool()>

Return always C<false>.

=cut

*/
    INTVAL get_bool () {
        return (INTVAL)0;
    }

/*

=item C<INTVAL defined()>

"nil" in Lua is always undefined.

=cut

*/
    INTVAL defined() {
        return (INTVAL)0;
    }

/*

=back

=head2 non-Vtable Methods

=over 4

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

=cut

*/
    INTVAL is_equal (PMC* value) {
MMD_LuaNil: {
            return (INTVAL)1;
        }
MMD_DEFAULT: {
            return (INTVAL)0;
        }
    }

/*

=back

=head2 Specific Methods

=over 4

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

=cut

*/
    METHOD PMC* rawequal (PMC* value) {
        PMC *retval;

        retval = pmc_new(INTERP, dynpmc_LuaBoolean);
        if (SELF->vtable->base_type == value->vtable->base_type)
            PMC_int_val(retval) = 1;
        else
            PMC_int_val(retval) = 0;
        return retval;
    }

}

/*

=back

=head1 AUTHORS

Original code by Klaas-Jan Stol.

=cut

*/

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