/* Eval.pmc
 *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
 *  CVS Info
 *     $Id: eval.pmc,v 1.21 2003/10/24 21:33:25 dan Exp $
 *  Overview:
 *     These are the vtable functions for evaluating a code segment
 *  Data Structure and Algorithms:
 *  History:
 *     Initial version by leo 2003/01/16
 *  Notes:
 *  References:
 */

#include "parrot/parrot.h"
#include "parrot/runops_cores.h"
#include "parrot/interp_guts.h"
#include "parrot/packfile.h"

pmclass Eval extends Closure {

    void destroy () {
	/* TODO
	 * when this PMC gets out of scope
	 * it should destroy the attached PackFile
	 */
    }

    void* invoke (void* next) {
	struct PackFile_ByteCode *old_cs;
	struct PackFile *eval_pf = (struct PackFile *)
	    SUPER(next);	/* invoke on Sub returns the address */
#if EXEC_CAPABLE
	extern int Parrot_exec_run;
	if (Interp_core_TEST(interpreter, PARROT_EXEC_CORE)) {
	    Parrot_exec_run = 2;
	}
#endif

	/* switch to code segment */
	old_cs = Parrot_switch_to_cs(interpreter, eval_pf->cur_cs);
	if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) {
	    PIO_eprintf(interpreter, "*** invoking %s\n",
		    eval_pf->cur_cs->base.name);
	}
	runops_int(interpreter, 0);
	if (Interp_flags_TEST(interpreter, PARROT_TRACE_FLAG)) {
	    PIO_eprintf(interpreter, "*** back from %s\n",
		    eval_pf->cur_cs->base.name);
	}
	/* restore ctx */
	interpreter->ctx.pad_stack =
	    ((struct Parrot_Sub*) PMC_sub(SELF))->ctx.pad_stack;
	/* if code jumped to different code segment, branch_cs
	 * is setting the resum_flag to 2, so that the
	 * runloop was left
	 */
	if (interpreter->resume_flag & 2) {
	    interpreter->resume_flag = 1;
	    next = 0;
	}
	else
	    (void)Parrot_switch_to_cs(interpreter, old_cs);
	return next;
    }

    INTVAL get_integer_keyed (PMC* key) {
	opcode_t *code =  ((struct PackFile *)SELF->cache.struct_val)->byte_code;
/*	int i = 0;
	for (i=0; i < 16; i++) {
  	  printf("At %p there is an %i\n", code+i, *(code+i));
	}*/
        return (INTVAL) code;
    }

    STRING* get_string () {
	size_t size;
	opcode_t *packed;

	struct PackFile *pf = (struct PackFile *) SELF->cache.struct_val;
	STRING *s;

	size = PackFile_pack_size(pf) * sizeof(opcode_t);
	packed = (opcode_t*) mem_sys_allocate(size);
	PackFile_pack(pf, packed);
	s = string_make(interpreter, packed, size, NULL,0,NULL);
	mem_sys_free(packed);
	return s;
    }
}
