/* amber_string.pmc
 *  Copyright: same as Parrot.
 *  Overview:
 *     The Amber_STRING PMC, which implementes the Amber kernel class STRING
 */

#include "parrot/parrot.h"

static INTVAL class_CHARACTER;

pmclass Amber_STRING extends String extends Amber_DEFAULT does string dynpmc group amber_kernel hll Amber maps String {

    void class_init() {
        if (pass) {
            /* Record the type-id of PMC Amber_CHARACTER */
            class_CHARACTER = Parrot_PMC_typenum(INTERP, "Amber_CHARACTER");
        }
    }

/* non-vtable methods follow */

    METHOD PMC* boolean() {
        PMC* result = pmc_new(
            INTERP, Parrot_get_ctx_HLL_type(INTERP, enum_class_Boolean)
        );
        VTABLE_set_bool(INTERP, result, PMC_int_val(SELF));
        return result;
    }

    METHOD PMC* count() {
        PMC* result = pmc_new(
            INTERP, Parrot_get_ctx_HLL_type(INTERP, enum_class_Integer)
        );
        VTABLE_set_integer_native(
            INTERP, result, string_compute_strlen(INTERP, PMC_str_val(SELF))
        );
        return result;
    }

    METHOD PMC* classname() {
        PMC* result = pmc_new(
            INTERP, Parrot_get_ctx_HLL_type(INTERP, enum_class_String)
        );
        VTABLE_set_string_native(
            INTERP, result, string_from_const_cstring(INTERP, "STRING", 6)
        );
        return result;
    }

    METHOD PMC* first() {
        /* XXX reject if count = 0 */
        PMC* result = pmc_new(INTERP, class_CHARACTER);
        VTABLE_set_integer_native(INTERP, result, string_ord(
            INTERP, PMC_str_val(SELF), (INTVAL) 0
        ));
        return result;
    }

    METHOD PMC* integer() {  /* XXX OVERFLOW */
        PMC* result = pmc_new(
            INTERP, Parrot_get_ctx_HLL_type(INTERP, enum_class_Integer)
        );
        VTABLE_set_integer_native(
            INTERP, result, string_to_int(INTERP, PMC_str_val(SELF))
        );
        return result;
    }

    METHOD PMC* item(PMC* index) {
        /* XXX reject out-of-range values (0, or > count, or < -count) */
        PMC* result;
        INTVAL adjusted_index = VTABLE_get_integer(INTERP, index);
        if (adjusted_index > 0) adjusted_index = adjusted_index - 1;
        result = pmc_new(INTERP, class_CHARACTER);
        VTABLE_set_integer_native(INTERP, result, string_ord(
            INTERP, PMC_str_val(SELF), adjusted_index
        ));
        return result;
    }

    METHOD PMC* last() {
        /* XXX reject if count = 0 */
        PMC* result = pmc_new(INTERP, class_CHARACTER);
        VTABLE_set_integer_native(INTERP, result, string_ord(
            INTERP, PMC_str_val(SELF), string_compute_strlen(
                INTERP, PMC_str_val(SELF)
            ) - 1
        ));
        return result;
    }

}

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