/* ex: set ro ft=c:
 * !!!!!!!   DO NOT EDIT THIS FILE   !!!!!!!
 *
 * This file is generated automatically from './src/pmc/continuation.pmc'
 * by tools/build/pmc2c.pl.
 *
 * Any changes made here will be lost!
 *
 */

/* HEADERIZER HFILE: none */
/* HEADERIZER STOP */

#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "parrot/dynext.h"
#include "pmc_fixedintegerarray.h"
#include "pmc_continuation.h"
#include "pmc_default.h"
#include "continuation.str"
#include "pmc/pmc_continuation.h"
#include "pmc/pmc_context.h"
#line 1 "./src/pmc/continuation.pmc"
/*
Copyright (C) 2001-2008, Parrot Foundation.
$Id: continuation.pmc 42440 2009-11-12 09:49:10Z bacek $

=head1 NAME

src/pmc/continuation.pmc - Continuation PMC

=head1 DESCRIPTION

A C<Continuation> has a copy of the interpreter's context at the location where
the Continuation was constructed.  See the L<Glossary|docs/glossary.pod> for
more information.

=head2 Functions

=over 4

=cut

*/


#include "parrot/oplib/ops.h"
#include "pmc/pmc_sub.h"

/*

=back

=head2 Methods

=over 4

=cut

*/


/*
 * A Continuation (and RetContinuation, ExceptionHandler) has in its
 * context a pointer to the register frame, which contains active objects.
 * Additionally ct->current_cont has the continuation of the caller.
 */
#line 68 "./src/pmc/continuation.c"
static  PMC  * Parrot_Continuation_clone(PARROT_INTERP, PMC *pmc);
static  INTVAL  Parrot_Continuation_defined(PARROT_INTERP, PMC *pmc);
static  INTVAL  Parrot_Continuation_get_bool(PARROT_INTERP, PMC *pmc);
static  void  * Parrot_Continuation_get_pointer(PARROT_INTERP, PMC *pmc);
static  STRING  * Parrot_Continuation_get_string(PARROT_INTERP, PMC *pmc);
static  void  Parrot_Continuation_init(PARROT_INTERP, PMC *pmc);
static  void  Parrot_Continuation_init_pmc(PARROT_INTERP, PMC *pmc, PMC *values);
static  opcode_t  * Parrot_Continuation_invoke(PARROT_INTERP, PMC *pmc, void *next);
static  void  Parrot_Continuation_mark(PARROT_INTERP, PMC *pmc);
static  void  Parrot_Continuation_set_pmc(PARROT_INTERP, PMC *pmc, PMC *src);
static  void  Parrot_Continuation_set_pointer(PARROT_INTERP, PMC *pmc, void *value);
static  void Parrot_Continuation_nci_caller(PARROT_INTERP, PMC *pmc);
static  void Parrot_Continuation_nci_continuation(PARROT_INTERP, PMC *pmc);
void    Parrot_Continuation_class_init(PARROT_INTERP, int, int);
PARROT_EXPORT VTABLE* Parrot_Continuation_update_vtable(ARGMOD(VTABLE*));
PARROT_EXPORT VTABLE* Parrot_Continuation_get_vtable(PARROT_INTERP);
void    Parrot_Continuation_ro_class_init(PARROT_INTERP, int, int);
PARROT_EXPORT VTABLE* Parrot_Continuation_ro_update_vtable(ARGMOD(VTABLE*));
PARROT_EXPORT VTABLE* Parrot_Continuation_ro_get_vtable(PARROT_INTERP);
static  PMC  *
Parrot_Continuation_clone(PARROT_INTERP, PMC *pmc)
{
#line 146 "./src/pmc/continuation.pmc"

    /* Start to prepare for subclassable continuations */
    INTVAL type = pmc->vtable->base_type;
    PMC * ret = pmc_new_init(interp, type, pmc);
    return ret;
#line 97 "./src/pmc/continuation.c"
}
static  INTVAL 
Parrot_Continuation_defined(PARROT_INTERP, PMC *pmc)
{
#line 213 "./src/pmc/continuation.pmc"

    return PARROT_CONTINUATION(pmc)->address != NULL;
#line 105 "./src/pmc/continuation.c"
}
static  INTVAL 
Parrot_Continuation_get_bool(PARROT_INTERP, PMC *pmc)
{
#line 217 "./src/pmc/continuation.pmc"

    return PARROT_CONTINUATION(pmc)->address != NULL;
#line 113 "./src/pmc/continuation.c"
}
static  void  *
Parrot_Continuation_get_pointer(PARROT_INTERP, PMC *pmc)
{
#line 197 "./src/pmc/continuation.pmc"

    return PARROT_CONTINUATION(pmc)->address;
#line 121 "./src/pmc/continuation.c"
}
static  STRING  *
Parrot_Continuation_get_string(PARROT_INTERP, PMC *pmc)
{
#line 277 "./src/pmc/continuation.pmc"

    return Parrot_Context_infostr(interp, PARROT_CONTINUATION(pmc)->to_ctx);
#line 129 "./src/pmc/continuation.c"
}
static  void 
Parrot_Continuation_init(PARROT_INTERP, PMC *pmc)
{
#line 66 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const attrs = PARROT_CONTINUATION(pmc);

    attrs->to_ctx           = CURRENT_CONTEXT(interp);
    attrs->to_call_object   = Parrot_pcc_get_signature(interp, attrs->to_ctx);
    attrs->from_ctx         = CURRENT_CONTEXT(interp);
    attrs->runloop_id       = 0;
    attrs->seg              = interp->code;
    attrs->address          = NULL;

    PObj_custom_mark_SET(pmc);

    /* PANIC("don't do that"); */
    /*
     * Whenever we create a continuation, all return continuations
     * up the call chain may be reused due to invoking the
     * continuation. To avoid that all return continuations are
     * converted to true continuations.
     */
    invalidate_retc_context(interp, pmc);
#line 155 "./src/pmc/continuation.c"
}
static  void 
Parrot_Continuation_init_pmc(PARROT_INTERP, PMC *pmc, PMC *values)
{
#line 89 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const attrs  = PARROT_CONTINUATION(pmc);
    Parrot_Continuation_attributes * const theirs = PARROT_CONTINUATION(values);

    attrs->to_ctx           = theirs->to_ctx;
    attrs->to_call_object   = Parrot_pcc_get_signature(interp, attrs->to_ctx);
    attrs->from_ctx         = CURRENT_CONTEXT(interp);
    attrs->runloop_id       = 0;
    attrs->seg              = theirs->seg;
    attrs->address          = theirs->address;

    PObj_custom_mark_SET(pmc);

    /* PANIC("don't do that"); */
    /*
     * Whenever we create a continuation, all return continuations
     * up the call chain may be reused due to invoking the
     * continuation. To avoid that all return continuations are
     * converted to true continuations.
     */
    invalidate_retc_context(interp, pmc);
#line 182 "./src/pmc/continuation.c"
}
static  opcode_t  *
Parrot_Continuation_invoke(PARROT_INTERP, PMC *pmc, void *next)
{
#line 232 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(pmc);
    PMC      *from_ctx = CURRENT_CONTEXT(interp);
    PMC      *to_ctx   = cc->to_ctx;
    opcode_t *pc       = cc->address;
    PMC      *call_obj = cc->to_call_object;
    PMC      *from_obj = Parrot_pcc_get_signature(interp, from_ctx);
    UNUSED(next)

    Parrot_continuation_check(interp, pmc);
    Parrot_continuation_rewind_environment(interp, pmc);

    if (!PMC_IS_NULL(from_obj)) {
        STRING *string_sig = VTABLE_get_string(interp, from_obj);
        /* If there is no string - there is no args */
        if (string_sig) {
            PMC *raw_sig, *invalid_sig;
            Parrot_pcc_parse_signature_string(interp, string_sig, &raw_sig, &invalid_sig);

            /* Build results signature for continuation */
            if (*pc == PARROT_OP_get_results_pc)
                call_obj = Parrot_pcc_build_sig_object_returns_from_op(interp, call_obj,
                    Parrot_pcc_get_pmc_constant(interp, to_ctx, pc[1]), pc);

            Parrot_pcc_fill_returns_from_continuation(interp, call_obj, raw_sig, from_obj);
        }
    }

    /* switch segment */
    if (interp->code != cc->seg)
        Parrot_switch_to_cs(interp, cc->seg, 1);

    return pc;
#line 221 "./src/pmc/continuation.c"
}
static  void 
Parrot_Continuation_mark(PARROT_INTERP, PMC *pmc)
{
#line 124 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(pmc);

    /* If Continuation wasn't fully constructed yet */
    if (!cc)
        return;

    Parrot_gc_mark_PMC_alive(interp, cc->to_ctx);
    Parrot_gc_mark_PMC_alive(interp, cc->to_call_object);
    Parrot_gc_mark_PMC_alive(interp, cc->from_ctx);
#line 237 "./src/pmc/continuation.c"
}
static  void 
Parrot_Continuation_set_pmc(PARROT_INTERP, PMC *pmc, PMC *src)
{
#line 162 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const cc_self = PARROT_CONTINUATION(pmc);
    Parrot_Continuation_attributes * const cc_src  = PARROT_CONTINUATION(src);

    STRUCT_COPY(cc_self, cc_src);
#line 248 "./src/pmc/continuation.c"
}
static  void 
Parrot_Continuation_set_pointer(PARROT_INTERP, PMC *pmc, void *value)
{
#line 179 "./src/pmc/continuation.pmc"

    opcode_t                       * const pos = (opcode_t *)value;
    Parrot_Continuation_attributes * const cc  = PARROT_CONTINUATION(pmc);

    cc->address    = pos;
    cc->runloop_id = interp->current_runloop_id;
#line 260 "./src/pmc/continuation.c"
}
static  void
Parrot_Continuation_nci_caller(PARROT_INTERP, PMC *pmc)
{
#line 423 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    PMC * const _ctx         = CURRENT_CONTEXT(interp);
    PMC * const _ccont       = Parrot_pcc_get_continuation(interp, _ctx);
    PMC * const _call_object = Parrot_pcc_get_signature(interp, _ctx);

    Parrot_pcc_set_signature(interp, _ctx, NULL);

    { /* BEGIN PARMS SCOPE */
#line 273 "./src/pmc/continuation.pmc"
PMC* pmc;

#line 431 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
        Parrot_pcc_fill_params_from_c_args(interp, _call_object, "Pi",
            &pmc);
#line 435 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    { /* BEGIN PMETHOD BODY */
#line 291 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(pmc);
    PMC *caller = Parrot_pcc_get_sub(interp, cc->to_ctx);

    if (!caller)
        caller = PMCNULL;
    else {
        Parrot_Sub_attributes *sub;
        PMC_get_sub(interp, caller, sub);
        if (!sub->seg)
            caller = PMCNULL;
    }

    #line 260 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    {
    /*BEGIN RETURN PMC *caller */
#line 267 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    Parrot_pcc_fill_returns_from_c_args(interp, _call_object, "P",
            (PMC*)caller);
    return;
    /*END RETURN PMC *caller */
    }
#line 304 "./src/pmc/continuation.pmc"


#line 443 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"

    } /* END PMETHOD BODY */
    } /* END PARAMS SCOPE */
  no_return:
    return;
#line 313 "./src/pmc/continuation.c"
}
static  void
Parrot_Continuation_nci_continuation(PARROT_INTERP, PMC *pmc)
{
#line 423 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    PMC * const _ctx         = CURRENT_CONTEXT(interp);
    PMC * const _ccont       = Parrot_pcc_get_continuation(interp, _ctx);
    PMC * const _call_object = Parrot_pcc_get_signature(interp, _ctx);

    Parrot_pcc_set_signature(interp, _ctx, NULL);

    { /* BEGIN PARMS SCOPE */
#line 326 "./src/pmc/continuation.pmc"
PMC* pmc;

#line 431 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
        Parrot_pcc_fill_params_from_c_args(interp, _call_object, "Pi",
            &pmc);
#line 435 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    { /* BEGIN PMETHOD BODY */
#line 317 "./src/pmc/continuation.pmc"

    Parrot_Continuation_attributes * const cc = PARROT_CONTINUATION(pmc);
    PMC * const cont = Parrot_pcc_get_continuation(interp, cc->to_ctx);

    if (cont)
        #line 260 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    {
    /*BEGIN RETURN PMC *cont */
#line 267 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    Parrot_pcc_fill_returns_from_c_args(interp, _call_object, "P",
            (PMC*)cont);
    return;
    /*END RETURN PMC *cont */
    }
#line 322 "./src/pmc/continuation.pmc"


    #line 260 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    {
    /*BEGIN RETURN PMC *PMCNULL */
#line 267 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"
    Parrot_pcc_fill_returns_from_c_args(interp, _call_object, "P",
            (PMC*)PMCNULL);
    return;
    /*END RETURN PMC *PMCNULL */
    }
#line 324 "./src/pmc/continuation.pmc"

#line 443 "/Users/baest/programming/parrot/tools/build/../../lib/Parrot/Pmc2c/PCCMETHOD.pm"

    } /* END PMETHOD BODY */
    } /* END PARAMS SCOPE */
  no_return:
    return;
#line 369 "./src/pmc/continuation.c"
}
#include "pmc/pmc_default.h"

PARROT_EXPORT
VTABLE *Parrot_Continuation_update_vtable(VTABLE *vt) {
    vt->clone = Parrot_Continuation_clone;
    vt->defined = Parrot_Continuation_defined;
    vt->get_bool = Parrot_Continuation_get_bool;
    vt->get_pointer = Parrot_Continuation_get_pointer;
    vt->get_string = Parrot_Continuation_get_string;
    vt->init = Parrot_Continuation_init;
    vt->init_pmc = Parrot_Continuation_init_pmc;
    vt->invoke = Parrot_Continuation_invoke;
    vt->mark = Parrot_Continuation_mark;
    vt->set_pmc = Parrot_Continuation_set_pmc;
    vt->set_pointer = Parrot_Continuation_set_pointer;
    vt->attr_size = sizeof(Parrot_Continuation_attributes);

    return vt;
}


PARROT_EXPORT
VTABLE *Parrot_Continuation_ro_update_vtable(ARGMOD(VTABLE *vt)) {
    vt->clone = Parrot_Continuation_clone;
    vt->defined = Parrot_Continuation_defined;
    vt->get_bool = Parrot_Continuation_get_bool;
    vt->get_pointer = Parrot_Continuation_get_pointer;
    vt->get_string = Parrot_Continuation_get_string;
    vt->init = Parrot_Continuation_init;
    vt->init_pmc = Parrot_Continuation_init_pmc;
    vt->invoke = Parrot_Continuation_invoke;
    vt->mark = Parrot_Continuation_mark;
    vt->attr_size = sizeof(Parrot_Continuation_attributes);

    return vt;
}

PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
VTABLE* Parrot_Continuation_get_vtable(PARROT_INTERP) {
    VTABLE *vt;
    vt = Parrot_default_get_vtable(interp);
    Parrot_Continuation_update_vtable(vt);

    return vt;
}

PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
VTABLE* Parrot_Continuation_ro_get_vtable(PARROT_INTERP) {
    VTABLE *vt;
    vt = Parrot_default_ro_get_vtable(interp);
    Parrot_Continuation_ro_update_vtable(vt);

    return vt;
}

PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
PMC* Parrot_Continuation_get_mro(PARROT_INTERP, PMC* mro) {
    if (PMC_IS_NULL(mro)) {
        mro = pmc_new(interp, enum_class_ResizableStringArray);
    }

    VTABLE_unshift_string(interp, mro,
        string_make(interp, "Continuation", 12, NULL, 0));
    return mro;
}

PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
Hash* Parrot_Continuation_get_isa(PARROT_INTERP, Hash* isa) {
    if (isa == NULL) {
        isa = parrot_new_hash(interp);
    }

    parrot_hash_put(interp, isa, (void *)(CONST_STRING_GEN(interp, "Continuation")), PMCNULL);
    return isa;
}

void
Parrot_Continuation_class_init(PARROT_INTERP, int entry, int pass)
{
    static const char attr_defs [] =
        ":seg :address Fto_ctx Fto_call_object Ffrom_ctx :runloop_id :invoked ";
    if (pass == 0) {
        VTABLE * const vt  = Parrot_Continuation_get_vtable(interp);
        vt->base_type      = enum_class_Continuation;
        vt->flags          = 0|VTABLE_HAS_READONLY_FLAG;
        vt->attribute_defs = attr_defs;
        interp->vtables[entry] = vt;

        vt->whoami       = CONST_STRING_GEN(interp, "Continuation");
        vt->provides_str = CONST_STRING_GEN(interp, "scalar");
        vt->isa_hash     = NULL;
        {
            VTABLE                   *vt_ro;
            vt_ro                 = Parrot_Continuation_ro_get_vtable(interp);
            vt_ro->base_type      = enum_class_Continuation;
            vt_ro->flags          = 0|VTABLE_IS_READONLY_FLAG;

            vt_ro->attribute_defs = attr_defs;

            vt_ro->base_type           = entry;
            vt_ro->whoami              = vt->whoami;
            vt_ro->provides_str        = vt->provides_str;
            vt->ro_variant_vtable      = vt_ro;
            vt_ro->ro_variant_vtable = vt;
            vt_ro->isa_hash            = vt->isa_hash;
        }

    }
    else { /* pass */
        {
            VTABLE * const vt  = interp->vtables[entry];

            vt->mro = Parrot_Continuation_get_mro(interp, PMCNULL);

            if (vt->ro_variant_vtable)
                vt->ro_variant_vtable->mro = vt->mro;
        }

        /* set up MRO and _namespace */
        Parrot_create_mro(interp, entry);
        register_raw_nci_method_in_ns(interp, entry, F2DPTR(Parrot_Continuation_nci_caller), CONST_STRING_GEN(interp, "caller"));
        register_raw_nci_method_in_ns(interp, entry, F2DPTR(Parrot_Continuation_nci_continuation), CONST_STRING_GEN(interp, "continuation"));
        {
        }
    } /* pass */
} /* Parrot_Continuation_class_init */
#line 325 "./src/pmc/continuation.pmc"


/*

=back

=head1 HISTORY

Initial revision by sean 2002/08/04.

=cut

*/

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