PmReturn_t seqiter_new(pPmObj_t pobj, pPmObj_t *r_pobj) { PmReturn_t retval; uint8_t *pchunk; pPmSeqIter_t psi; C_ASSERT(pobj != C_NULL); C_ASSERT(*r_pobj != C_NULL); /* Raise a TypeError if pobj is not a sequence */ if ((OBJ_GET_TYPE(pobj) != OBJ_TYPE_STR) && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_TUP) && (OBJ_GET_TYPE(pobj) != OBJ_TYPE_LST)) { PM_RAISE(retval, PM_RET_EX_TYPE); return retval; } /* Alloc a chunk for the sequence iterator obj */ retval = heap_getChunk(sizeof(PmSeqIter_t), &pchunk); PM_RETURN_IF_ERROR(retval); /* Set the sequence iterator's fields */ psi = (pPmSeqIter_t)pchunk; OBJ_SET_TYPE(psi, OBJ_TYPE_SQI); psi->si_sequence = pobj; psi->si_index = 0; *r_pobj = (pPmObj_t)psi; return retval; }
PmReturn_t mod_new(pPmObj_t pco, pPmObj_t *pmod) { PmReturn_t retval; uint8_t *pchunk; pPmObj_t pobj; /* If it's not a code obj, raise TypeError */ if (OBJ_GET_TYPE(pco) != OBJ_TYPE_COB) { PM_RAISE(retval, PM_RET_EX_TYPE); return retval; } /* Alloc and init func obj */ retval = heap_getChunk(sizeof(PmFunc_t), &pchunk); PM_RETURN_IF_ERROR(retval); *pmod = (pPmObj_t)pchunk; OBJ_SET_TYPE(*pmod, OBJ_TYPE_MOD); ((pPmFunc_t)*pmod)->f_co = (pPmCo_t)pco; /* Alloc and init attrs dict */ retval = dict_new(&pobj); ((pPmFunc_t)*pmod)->f_attrs = (pPmDict_t)pobj; /* A module's globals is the same as its attrs */ ((pPmFunc_t)*pmod)->f_globals = (pPmDict_t)pobj; return retval; }
PmReturn_t thread_new(pPmObj_t pframe, pPmObj_t *r_pobj) { PmReturn_t retval = PM_RET_OK; pPmThread_t pthread = C_NULL; C_ASSERT(pframe != C_NULL); /* If it's not a frame, raise TypeError */ if (OBJ_GET_TYPE(pframe) != OBJ_TYPE_FRM) { PM_RAISE(retval, PM_RET_EX_TYPE); return retval; } /* Allocate a thread */ retval = heap_getChunk(sizeof(PmThread_t), (uint8_t **)r_pobj); PM_RETURN_IF_ERROR(retval); /* Set type, frame and initialize status */ pthread = (pPmThread_t)*r_pobj; OBJ_SET_TYPE(pthread, OBJ_TYPE_THR); pthread->pframe = (pPmFrame_t)pframe; pthread->interpctrl = INTERP_CTRL_CONT; return retval; }
PmReturn_t class_method(pPmObj_t pinstance, pPmObj_t pfunc, pPmObj_t *r_pmeth) { PmReturn_t retval = PM_RET_OK; uint8_t *pchunk; pPmMethod_t pmeth; pPmObj_t pattrs; uint8_t objid; /* Allocate a method */ retval = heap_getChunk(sizeof(PmMethod_t), &pchunk); PM_RETURN_IF_ERROR(retval); OBJ_SET_TYPE(pchunk, OBJ_TYPE_MTH); /* Set method fields */ pmeth = (pPmMethod_t)pchunk; pmeth->m_instance = (pPmInstance_t)pinstance; pmeth->m_func = (pPmFunc_t)pfunc; pmeth->m_attrs = C_NULL; /* Create the attributes dict */ heap_gcPushTempRoot((pPmObj_t)pmeth, &objid); retval = dict_new(&pattrs); heap_gcPopTempRoot(objid); pmeth->m_attrs = (pPmDict_t)pattrs; *r_pmeth = (pPmObj_t)pmeth; return retval; }
/* Returns an instance of the class by reference */ PmReturn_t class_instantiate(pPmObj_t pclass, pPmObj_t *r_pobj) { PmReturn_t retval = PM_RET_OK; uint8_t *pchunk; pPmObj_t pobj; pPmObj_t pattrs; uint8_t objid; /* Allocate a class instance */ retval = heap_getChunk(sizeof(PmInstance_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_CLI); /* Set the instance's fields */ ((pPmInstance_t)pobj)->cli_class = (pPmClass_t)pclass; ((pPmInstance_t)pobj)->cli_attrs = C_NULL; /* Create the attributes dict */ heap_gcPushTempRoot(pobj, &objid); retval = dict_new(&pattrs); heap_gcPopTempRoot(objid); ((pPmInstance_t)pobj)->cli_attrs = (pPmDict_t)pattrs; /* TODO: Store pclass in __class__ attr */ *r_pobj = pobj; return retval; }
PmReturn_t class_new(pPmObj_t pattrs, pPmObj_t pbases, pPmObj_t pname, pPmObj_t *r_pclass) { PmReturn_t retval = PM_RET_OK; uint8_t *pchunk; pPmObj_t pobj; /* Ensure types */ if ((OBJ_GET_TYPE(pattrs) != OBJ_TYPE_DIC) || (OBJ_GET_TYPE(pbases) != OBJ_TYPE_TUP) || (OBJ_GET_TYPE(pname) != OBJ_TYPE_STR)) { PM_RAISE(retval, PM_RET_EX_TYPE); return retval; } /* Allocate a class obj */ retval = heap_getChunk(sizeof(PmClass_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_CLO); /* Class has no access to its CO */ ((pPmClass_t)pobj)->cl_attrs = (pPmDict_t)pattrs; ((pPmClass_t)pobj)->cl_bases = (pPmTuple_t)pbases; *r_pclass = pobj; return retval; }
PmReturn_t float_new(float f, pPmObj_t *r_pf) { PmReturn_t retval = PM_RET_OK; retval = heap_getChunk(sizeof(PmFloat_t), (uint8_t **)r_pf); PM_RETURN_IF_ERROR(retval); OBJ_SET_TYPE(*r_pf, OBJ_TYPE_FLT); ((pPmFloat_t) * r_pf)->val = f; return retval; }
PmReturn_t co_loadFromImg(PmMemSpace_t memspace, uint8_t const **paddr, pPmObj_t *r_pco) { PmReturn_t retval = PM_RET_OK; pPmObj_t pobj; pPmCo_t pco = C_NULL; uint8_t *pchunk; /* Store ptr to top of code img (less type byte) */ uint8_t const *pci = *paddr - 1; /* Get size of code img */ uint16_t size = mem_getWord(memspace, paddr); /* Allocate a code obj */ retval = heap_getChunk(sizeof(PmCo_t), &pchunk); PM_RETURN_IF_ERROR(retval); pco = (pPmCo_t)pchunk; /* Fill in the CO struct */ OBJ_SET_TYPE(pco, OBJ_TYPE_COB); pco->co_memspace = memspace; pco->co_codeimgaddr = pci; /* Load names (tuple obj) */ *paddr = pci + CI_NAMES_FIELD; retval = obj_loadFromImg(memspace, paddr, &pobj); PM_RETURN_IF_ERROR(retval); pco->co_names = (pPmTuple_t)pobj; /* Load consts (tuple obj) assume it follows names */ retval = obj_loadFromImg(memspace, paddr, &pobj); PM_RETURN_IF_ERROR(retval); pco->co_consts = (pPmTuple_t)pobj; /* Start of bcode always follows consts */ pco->co_codeaddr = *paddr; /* Set addr to point one past end of img */ *paddr = pci + size; *r_pco = (pPmObj_t)pco; return PM_RET_OK; }
PmReturn_t dict_new(pPmObj_t *r_pdict) { PmReturn_t retval = PM_RET_OK; pPmDict_t pdict = C_NULL; uint8_t *pchunk; /* Allocate a dict */ retval = heap_getChunk(sizeof(PmDict_t), &pchunk); PM_RETURN_IF_ERROR(retval); /* Init dict fields */ pdict = (pPmDict_t)pchunk; OBJ_SET_TYPE(pdict, OBJ_TYPE_DIC); pdict->length = 0; pdict->d_keys = C_NULL; pdict->d_vals = C_NULL; *r_pdict = (pPmObj_t)pchunk; return retval; }
PmReturn_t no_loadFromImg(PmMemSpace_t memspace, uint8_t const **paddr, pPmObj_t *r_pno) { PmReturn_t retval = PM_RET_OK; pPmNo_t pno = C_NULL; uint8_t *pchunk; /* Allocate a code obj */ retval = heap_getChunk(sizeof(PmNo_t), &pchunk); PM_RETURN_IF_ERROR(retval); pno = (pPmNo_t)pchunk; /* Fill in the NO struct */ OBJ_SET_TYPE(pno, OBJ_TYPE_NOB); pno->no_argcount = mem_getByte(memspace, paddr); /* Get index into native fxn table */ pno->no_funcindx = (int16_t)mem_getWord(memspace, paddr); *r_pno = (pPmObj_t)pno; return PM_RET_OK; }
PmReturn_t frame_new(pPmObj_t pfunc, pPmObj_t *r_pobj) { PmReturn_t retval = PM_RET_OK; int16_t fsize = 0; pPmCo_t pco = C_NULL; pPmFrame_t pframe = C_NULL; uint8_t *pchunk; /* Get fxn's code obj */ pco = ((pPmFunc_t)pfunc)->f_co; /* TypeError if passed func's CO is not a true COB */ if (OBJ_GET_TYPE(pco) != OBJ_TYPE_COB) { PM_RAISE(retval, PM_RET_EX_TYPE); return retval; } #ifdef HAVE_GENERATORS /* #207: Initializing a Generator using CALL_FUNC needs extra stack slot */ fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals + 2) * sizeof(pPmObj_t); #elif defined(HAVE_CLASSES) /* #230: Calling a class's __init__() takes two extra spaces on the stack */ fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals + 1) * sizeof(pPmObj_t); #else fsize = sizeof(PmFrame_t) + (pco->co_stacksize + pco->co_nlocals - 1) * sizeof(pPmObj_t); #endif /* HAVE_CLASSES */ #ifdef HAVE_CLOSURES /* #256: Add support for closures */ fsize = fsize + pco->co_nfreevars + ((pco->co_cellvars == C_NULL) ? 0 : pco->co_cellvars->length); #endif /* HAVE_CLOSURES */ /* Allocate a frame */ retval = heap_getChunk(fsize, &pchunk); PM_RETURN_IF_ERROR(retval); pframe = (pPmFrame_t)pchunk; /* Set frame fields */ OBJ_SET_TYPE(pframe, OBJ_TYPE_FRM); pframe->fo_back = C_NULL; pframe->fo_func = (pPmFunc_t)pfunc; pframe->fo_memspace = pco->co_memspace; /* Init instruction pointer and block stack */ pframe->fo_ip = pco->co_codeaddr; pframe->fo_blockstack = C_NULL; /* Get globals and attrs from the function object */ pframe->fo_globals = ((pPmFunc_t)pfunc)->f_globals; pframe->fo_attrs = ((pPmFunc_t)pfunc)->f_attrs; #ifndef HAVE_CLOSURES /* Empty stack points to one past locals */ pframe->fo_sp = &(pframe->fo_locals[pco->co_nlocals]); #else /* #256: Add support for closures */ pframe->fo_sp = &(pframe->fo_locals[pco->co_nlocals + pco->co_nfreevars + ((pco->co_cellvars == C_NULL) ? 0 : pco->co_cellvars->length)]); #endif /* HAVE_CLOSURES */ /* By default, this is a normal frame, not an import or __init__ one */ pframe->fo_isImport = 0; #ifdef HAVE_CLASSES pframe->fo_isInit = 0; #endif /* Clear the stack */ sli_memset((unsigned char *)&(pframe->fo_locals), (char const)0, (unsigned int)fsize - sizeof(PmFrame_t)); /* Return ptr to frame */ *r_pobj = (pPmObj_t)pframe; return retval; }
PmReturn_t global_init(void) { PmReturn_t retval; uint8_t *codestr = (uint8_t *)"code"; uint8_t *pchunk; pPmObj_t pobj; #ifdef HAVE_CLASSES uint8_t const *initstr = (uint8_t const *)"__init__"; #endif /* HAVE_CLASSES */ #ifdef HAVE_GENERATORS uint8_t const *genstr = (uint8_t const *)"Generator"; uint8_t const *nextstr = (uint8_t const *)"next"; #endif /* HAVE_GENERATORS */ #ifdef HAVE_ASSERT uint8_t const *exnstr = (uint8_t const *)"Exception"; #endif /* HAVE_ASSERT */ #ifdef HAVE_BYTEARRAY uint8_t const *pbastr = (uint8_t const *)"bytearray"; #endif /* HAVE_BYTEARRAY */ /* Clear the global struct */ sli_memset((uint8_t *)&gVmGlobal, '\0', sizeof(PmVmGlobal_t)); /* Set the PyMite release num (for debug and post mortem) */ gVmGlobal.errVmRelease = PM_RELEASE; /* Init zero */ retval = heap_getChunk(sizeof(PmInt_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_INT); ((pPmInt_t)pobj)->val = (int32_t)0; gVmGlobal.pzero = (pPmInt_t)pobj; /* Init one */ retval = heap_getChunk(sizeof(PmInt_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_INT); ((pPmInt_t)pobj)->val = (int32_t)1; gVmGlobal.pone = (pPmInt_t)pobj; /* Init negone */ retval = heap_getChunk(sizeof(PmInt_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_INT); ((pPmInt_t)pobj)->val = (int32_t)-1; gVmGlobal.pnegone = (pPmInt_t)pobj; /* Init False */ retval = heap_getChunk(sizeof(PmBoolean_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_BOOL); ((pPmBoolean_t) pobj)->val = (int32_t)C_FALSE; gVmGlobal.pfalse = (pPmInt_t)pobj; /* Init True */ retval = heap_getChunk(sizeof(PmBoolean_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_BOOL); ((pPmBoolean_t) pobj)->val = (int32_t)C_TRUE; gVmGlobal.ptrue = (pPmInt_t)pobj; /* Init None */ retval = heap_getChunk(sizeof(PmObj_t), &pchunk); PM_RETURN_IF_ERROR(retval); pobj = (pPmObj_t)pchunk; OBJ_SET_TYPE(pobj, OBJ_TYPE_NON); gVmGlobal.pnone = pobj; /* Init "code" string obj */ retval = string_new((uint8_t const **)&codestr, &pobj); PM_RETURN_IF_ERROR(retval); gVmGlobal.pcodeStr = (pPmString_t)pobj; #ifdef HAVE_CLASSES /* Init "__init__" string obj */ retval = string_new((uint8_t const **)&initstr, &pobj); PM_RETURN_IF_ERROR(retval); gVmGlobal.pinitStr = (pPmString_t)pobj; #endif /* HAVE_CLASSES */ #ifdef HAVE_GENERATORS /* Init "Generator" string obj */ retval = string_new((uint8_t const **)&genstr, &pobj); PM_RETURN_IF_ERROR(retval); gVmGlobal.pgenStr = (pPmString_t)pobj; /* Init "next" string obj */ retval = string_new((uint8_t const **)&nextstr, &pobj); PM_RETURN_IF_ERROR(retval); gVmGlobal.pnextStr = (pPmString_t)pobj; #endif /* HAVE_GENERATORS */ #ifdef HAVE_ASSERT /* Init "Exception" string obj */ retval = string_new((uint8_t const **)&exnstr, &pobj); PM_RETURN_IF_ERROR(retval); gVmGlobal.pexnStr = (pPmString_t)pobj; #endif /* HAVE_ASSERT */ #ifdef HAVE_BYTEARRAY /* Init "bytearray" string obj */ retval = string_new((uint8_t const **)&pbastr, &pobj); PM_RETURN_IF_ERROR(retval); gVmGlobal.pbaStr = (pPmString_t)pobj; #endif /* HAVE_BYTEARRAY */ /* Init empty builtins */ gVmGlobal.builtins = C_NULL; /* Init native frame */ OBJ_SET_SIZE(&gVmGlobal.nativeframe, sizeof(PmNativeFrame_t)); OBJ_SET_TYPE(&gVmGlobal.nativeframe, OBJ_TYPE_NFM); gVmGlobal.nativeframe.nf_func = C_NULL; gVmGlobal.nativeframe.nf_stack = C_NULL; gVmGlobal.nativeframe.nf_active = C_FALSE; gVmGlobal.nativeframe.nf_numlocals = 0; /* Create empty threadList */ retval = list_new(&pobj); gVmGlobal.threadList = (pPmList_t)pobj; /* Init the PmImgPaths with std image info */ gVmGlobal.imgPaths.memspace[0] = MEMSPACE_PROG; gVmGlobal.imgPaths.pimg[0] = (uint8_t *)&stdlib_img; gVmGlobal.imgPaths.pathcount = 1; #ifdef HAVE_PRINT gVmGlobal.needSoftSpace = C_FALSE; gVmGlobal.somethingPrinted = C_FALSE; #endif /* HAVE_PRINT */ return retval; }