/* # This file is Copyright 2003, 2006, 2007, 2009, 2010 Dean Hall. # # This file is part of the PyMite VM. # The PyMite VM is free software: you can redistribute it and/or modify # it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2. # # The PyMite VM is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # A copy of the GNU GENERAL PUBLIC LICENSE Version 2 # is seen in the file COPYING in this directory. */ #ifndef __FRAME_H__ #define __FRAME_H__ /** * \file * \brief VM Frame * * VM frame header. */ /** * The maximum number of local variables a native function can have. * This defines the length of the locals array in the native frame struct. */ #define NATIVE_MAX_NUM_LOCALS 8 /** * Block Type * * Numerical values to put in the 'b_type' field of the tPmBlockType struct. */ typedef enum PmBlockType_e { /** Invalid block type */ B_INVALID = 0, /** Loop type */ B_LOOP, /** Try type */ B_TRY } PmBlockType_t, *pPmBlockType_t; /** * Block * * Extra info for loops and trys (others?) * Frames use linked list of blocks to handle * nested loops and try-catch blocks. */ typedef struct PmBlock_s { /** Obligatory obj descriptor */ PmObjDesc_t od; /** Ptr to backup stack ptr */ pPmObj_t *b_sp; /** Handler fxn obj */ uint8_t const *b_handler; /** Block type */ PmBlockType_t b_type:8; /** Next block in stack */ struct PmBlock_s *next; } PmBlock_t, *pPmBlock_t; /** * Frame * * A struct that holds the execution frame of a function, including the stack, * local vars and pointer to the code object. * * This struct doesn't declare the stack. * frame_new() is responsible for allocating the extra memory * at the tail of fo_locals[] to hold both the locals and stack. */ typedef struct PmFrame_s { /** Obligatory obj descriptor */ PmObjDesc_t od; /** Ptr to previous frame obj */ struct PmFrame_s *fo_back; /** Ptr to fxn obj */ pPmFunc_t fo_func; /** Mem space where func's CO comes from */ PmMemSpace_t fo_memspace:8; /** Instrxn ptr (pts into memspace) */ uint8_t const *fo_ip; /** Linked list of blocks */ pPmBlock_t fo_blockstack; /** Local attributes dict (non-fast locals) */ pPmDict_t fo_attrs; /** Global attributes dict (pts to root frame's globals */ pPmDict_t fo_globals; /** Points to next empty slot in fo_locals (1 past TOS) */ pPmObj_t *fo_sp; /** Frame can be an import-frame that handles RETURN differently */ uint8_t fo_isImport:1; #ifdef HAVE_CLASSES /** Flag to indicate class initailzer frame; handle RETURN differently */ uint8_t fo_isInit:1; #endif /* HAVE_CLASSES */ /** Array of local vars and stack (space appended at alloc) */ pPmObj_t fo_locals[1]; /* WARNING: Do not put new fields below fo_locals */ } PmFrame_t, *pPmFrame_t; /** * Native Frame * * A struct that holds the execution frame of a native function, * including the args and single stack slot, and pointer to the code object. * * This struct doesn't need an OD because it is only used statically in the * globals struct. There's only one native frame, the global one. * This happens because a native function is a leaf node * in the call tree (a native func can't call python funcs). */ typedef struct PmNativeFrame_s { /** Object descriptor */ PmObjDesc_t od; /** Ptr to previous frame obj */ struct PmFrame_s *nf_back; /** Ptr to fxn obj */ pPmFunc_t nf_func; /** Single stack slot */ pPmObj_t nf_stack; /** Boolean to indicate if the native frame is active */ uint8_t nf_active; /** Number of args passed to the native function */ uint8_t nf_numlocals; /** Local vars */ pPmObj_t nf_locals[NATIVE_MAX_NUM_LOCALS]; } PmNativeFrame_t, *pPmNativeFrame_t; /** * Allocate space for a new frame, fill its fields * with respect to the given function object. * Return pointer to the new frame. * * @param pfunc ptr to Function object. * @param r_pobj Return value; the new frame. * @return Return status. */ PmReturn_t frame_new(pPmObj_t pfunc, pPmObj_t *r_pobj); #endif /* __FRAME_H__ */