MOO
Moo Language
 
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130  131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919                                                                           9209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266/*
 * $Id$
 *
    Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved.
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
    1. Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
 
    THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#ifndef _MOO_H_
#define _MOO_H_
 
#include "moo-cmn.h"
#include "moo-rbt.h"
 
/* TODO: move this macro out to the build files.... */
#define MOO_INCLUDE_COMPILER
 
/* define this to allow an pointer(OOP) object to have trailing bytes 
 * this is used to embed bytes codes into the back of a compile method
 * object instead of putting in in a separate byte array. */
#define MOO_USE_METHOD_TRAILER
 
/* ========================================================================== */
 
/**
 * The moo_errnum_t type defines the error codes.
 */
enum moo_errnum_t
{
	MOO_ENOERR,   /**< no error */
	MOO_EGENERIC, /**< generic error */
 
	MOO_ENOIMPL,  /**< not implemented */
	MOO_ESYSERR,  /**< system error */
	MOO_EINTERN,  /**< internal error */
	MOO_ESYSMEM,  /**< insufficient system memory */
	MOO_EOOMEM,   /**< insufficient object memory */
	MOO_ETYPE,    /**< invalid class/type */
 
	MOO_EINVAL,   /**< invalid parameter or data */
	MOO_ENOENT,   /**< data not found */
	MOO_EEXIST,   /**< existing/duplicate data */
	MOO_EBUSY, 
	MOO_EACCES,
	MOO_EPERM,
	MOO_ENOTDIR,
	MOO_EINTR,
	MOO_EPIPE,
	MOO_EAGAIN,
	MOO_EBADHND,
 
	MOO_EXXXXX1,  /**< **** not used ****/
	MOO_EMSGRCV,  /**< mesasge receiver error */
	MOO_EMSGSND,  /**< message sending error. even doesNotUnderstand: is not found */
	MOO_ENUMARGS, /**< wrong number of arguments */
	MOO_ERANGE,   /**< range error. overflow and underflow */
	MOO_EBCFULL,  /**< byte-code full */
	MOO_EDFULL,   /**< dictionary full */
	MOO_EPFULL,   /**< processor full */
	MOO_ESEMFLOOD,/**< too many semaphores */
	MOO_EXXXXX2,  /**< **** not used ***** */
	MOO_EDIVBY0,  /**< divide by zero */
	MOO_EIOERR,   /**< I/O error */
	MOO_EECERR,   /**< encoding conversion error */
	MOO_EBUFFULL, /**< buffer full */
 
#if defined(MOO_INCLUDE_COMPILER)
	MOO_ESYNERR  /** < syntax error */
#endif
};
typedef enum moo_errnum_t moo_errnum_t;
 
enum moo_option_t
{
	MOO_TRAIT,
	MOO_LOG_MASK,
	MOO_LOG_MAXCAPA,
	MOO_SYMTAB_SIZE,  /* default system table size */
	MOO_SYSDIC_SIZE,  /* default system dictionary size */
	MOO_PROCSTK_SIZE, /* default process stack size */
	MOO_MOD_INCTX
};
typedef enum moo_option_t moo_option_t;
 
/* [NOTE] ensure that it is a power of 2 */
#define MOO_LOG_CAPA_ALIGN 512
 
enum moo_option_dflval_t
{
	MOO_DFL_LOG_MAXCAPA = MOO_LOG_CAPA_ALIGN * 16,
	MOO_DFL_SYMTAB_SIZE = 5000,
	MOO_DFL_SYSDIC_SIZE = 5000,
	MOO_DFL_PROCSTK_SIZE = 5000
};
typedef enum moo_option_dflval_t moo_option_dflval_t;
 
enum moo_trait_t
{
#if defined(MOO_BUILD_DEBUG)
	MOO_DEBUG_GC     = (1 << 0),
	MOO_DEBUG_BIGINT = (1 << 1),
#endif
 
	/* perform no garbage collection when the heap is full. 
	 * you still can use moo_gc() explicitly. */
	MOO_NOGC = (1 << 8),
 
	/* wait for running process when exiting from the main method */
	MOO_AWAIT_PROCS = (1 << 9)
};
typedef enum moo_trait_t moo_trait_t;
 
 
 
typedef struct moo_obj_t           moo_obj_t;
typedef struct moo_obj_t*          moo_oop_t;
 
/* these are more specialized types for moo_obj_t */
typedef struct moo_obj_oop_t       moo_obj_oop_t;
typedef struct moo_obj_char_t      moo_obj_char_t;
typedef struct moo_obj_byte_t      moo_obj_byte_t;
typedef struct moo_obj_halfword_t  moo_obj_halfword_t;
typedef struct moo_obj_word_t      moo_obj_word_t;
 
/* these are more specialized types for moo_oop_t */
typedef struct moo_obj_oop_t*      moo_oop_oop_t;
typedef struct moo_obj_char_t*     moo_oop_char_t;
typedef struct moo_obj_byte_t*     moo_oop_byte_t;
typedef struct moo_obj_halfword_t* moo_oop_halfword_t;
typedef struct moo_obj_word_t*     moo_oop_word_t;
 
#define MOO_OOW_BITS  (MOO_SIZEOF_OOW_T * 8)
#define MOO_OOI_BITS  (MOO_SIZEOF_OOI_T * 8)
#define MOO_OOP_BITS  (MOO_SIZEOF_OOP_T * 8)
#define MOO_OOHW_BITS (MOO_SIZEOF_OOHW_T * 8)
 
 
/* ========================================================================= */
/* BIGINT TYPES AND MACROS                                                   */
/* ========================================================================= */
#if (MOO_SIZEOF_UINTMAX_T > MOO_SIZEOF_OOW_T)
#	define MOO_USE_FULL_WORD
#endif
 
#if defined(MOO_USE_FULL_WORD)
	typedef moo_oow_t          moo_liw_t; /* large integer word */
	typedef moo_ooi_t          moo_lii_t;
	typedef moo_uintmax_t      moo_lidw_t; /* large integer double word */
	typedef moo_intmax_t       moo_lidi_t;
#	define MOO_SIZEOF_LIW_T    MOO_SIZEOF_OOW_T
#	define MOO_SIZEOF_LIDW_T   MOO_SIZEOF_UINTMAX_T
#	define MOO_LIW_BITS        MOO_OOW_BITS
#	define MOO_LIDW_BITS       (MOO_SIZEOF_UINTMAX_T * 8) 
 
	typedef moo_oop_word_t     moo_oop_liword_t;
#	define MOO_OBJ_TYPE_LIWORD MOO_OBJ_TYPE_WORD
 
#else
	typedef moo_oohw_t         moo_liw_t;
	typedef moo_oohi_t         moo_lii_t;
	typedef moo_oow_t          moo_lidw_t;
	typedef moo_ooi_t          moo_lidi_t;
#	define MOO_SIZEOF_LIW_T    MOO_SIZEOF_OOHW_T
#	define MOO_SIZEOF_LIDW_T   MOO_SIZEOF_OOW_T
#	define MOO_LIW_BITS        MOO_OOHW_BITS
#	define MOO_LIDW_BITS       MOO_OOW_BITS
 
	typedef moo_oop_halfword_t moo_oop_liword_t;
#	define MOO_OBJ_TYPE_LIWORD MOO_OBJ_TYPE_HALFWORD
 
#endif
 
enum moo_method_type_t
{
	MOO_METHOD_INSTANCE = 0,
	MOO_METHOD_CLASS    = 1,
	MOO_METHOD_DUAL     = 2
};
typedef enum moo_method_type_t moo_method_type_t;
 
/* 
 * OOP encoding
 * An object pointer(OOP) is an ordinary pointer value to an object.
 * but some simple numeric values are also encoded into OOP using a simple
 * bit-shifting and masking.
 *
 * A real OOP is stored without any bit-shifting while a non-pointer value encoded
 * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits
 * are set to 1 or 2.
 * 
 * This scheme works because the object allocators aligns the object size to
 * a multiple of sizeof(moo_oop_t). This way, the 2 least-significant bits
 * of a real OOP are always 0s.
 *
 * With 2 bits, i can encode only 3 special types except object pointers. 
 * Since I need more than 3 special types, I extend the tag bits up to 4 bits
 * to represent a special data type that doesn't require a range as wide
 * as a small integer. A unicode character, for instance, only requires 21 
 * bits at most. An error doesn't need to be as diverse as a small integer.
 */
 
#define MOO_OOP_TAG_BITS_LO     2
#define MOO_OOP_TAG_BITS_HI     2
 
#define MOO_OOP_TAG_SMOOI       1    /* 01 */
#define MOO_OOP_TAG_SMPTR       2    /* 10 */
#define MOO_OOP_TAG_EXTENDED    3    /* 11 - internal use only */
#define MOO_OOP_TAG_CHAR        3    /* 0011 */
#define MOO_OOP_TAG_ERROR       7    /* 0111 */
#define MOO_OOP_TAG_RESERVED0   11   /* 1011 */
#define MOO_OOP_TAG_RESERVED1   15   /* 1111 */
 
#define MOO_OOP_GET_TAG_LO(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO))
#define MOO_OOP_GET_TAG_LOHI(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
#define MOO_OOP_GET_TAG(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_EXTENDED? MOO_OOP_GET_TAG_LOHI(oop): MOO_OOP_GET_TAG_LO(oop))
 
#define MOO_OOP_IS_NUMERIC(oop) (MOO_OOP_GET_TAG_LO(oop) != 0)
#define MOO_OOP_IS_POINTER(oop) (MOO_OOP_GET_TAG_LO(oop) == 0)
 
#define MOO_OOP_IS_SMOOI(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMOOI)
#define MOO_OOP_IS_SMPTR(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMPTR)
 
#define MOO_SMOOI_TO_OOP(num) ((moo_oop_t)((((moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMOOI))
#define MOO_OOP_TO_SMOOI(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO)
/*
#define MOO_SMPTR_TO_OOP(num) ((moo_oop_t)((((moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMPTR))
#define MOO_OOP_TO_SMPTR(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO)
*/
#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)(((moo_oow_t)ptr) | MOO_OOP_TAG_SMPTR))
#define MOO_OOP_TO_SMPTR(oop) ((void*)(((moo_oow_t)oop) & ~MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)))
 
#define MOO_OOP_IS_CHAR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_CHAR)
#define MOO_OOP_IS_ERROR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_ERROR)
 
#define MOO_OOP_TO_CHAR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO))
#define MOO_CHAR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_CHAR))
#define MOO_OOP_TO_ERROR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO))
#define MOO_ERROR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_ERROR))
 
/* -------------------------------- */
 
/* SMOOI takes up 62 bits on a 64-bit architecture and 30 bits 
 * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits
 * respectively for the sign bit. */
#define MOO_SMOOI_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO)
#define MOO_SMOOI_ABS_BITS (MOO_SMOOI_BITS - 1)
#define MOO_SMOOI_MAX ((moo_ooi_t)(~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + 1)))
/* Sacrificing 1 bit pattern for a negative SMOOI makes 
 * implementation a lot eaisier in many aspects. */
/*#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX - 1)*/
#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX)
#define MOO_IN_SMOOI_RANGE(ooi) ((ooi) >= MOO_SMOOI_MIN && (ooi) <= MOO_SMOOI_MAX)
 
/* SMPTR is a special value which has been devised to encode an address value
 * whose low MOO_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer
 * returned by most of system functions would be aligned to the pointer size. 
 * you can use the followings macros when converting such a pointer without loss. */
#define MOO_IN_SMPTR_RANGE(ptr) ((((moo_oow_t)ptr) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) == 0)
 
#define MOO_CHAR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI)
#define MOO_CHAR_MIN 0
#define MOO_CHAR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
 
#define MOO_ERROR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI)
#define MOO_ERROR_MIN 0
#define MOO_ERROR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
 
/* TODO: There are untested code where a small integer is converted to moo_oow_t.
 *       for example, the spec making macro treats the number as moo_oow_t instead of moo_ooi_t.
 *       as of this writing, i skip testing that part with the spec value exceeding MOO_SMOOI_MAX.
 *       later, please verify it works, probably by limiting the value ranges in such macros
 */
 
/*
 * Object structure
 */
enum moo_obj_type_t
{
	MOO_OBJ_TYPE_OOP,
	MOO_OBJ_TYPE_CHAR,
	MOO_OBJ_TYPE_BYTE,
	MOO_OBJ_TYPE_HALFWORD,
	MOO_OBJ_TYPE_WORD
 
/*
	MOO_OBJ_TYPE_UINT8,
	MOO_OBJ_TYPE_UINT16,
	MOO_OBJ_TYPE_UINT32,
*/
 
/* NOTE: you can have MOO_OBJ_SHORT, MOO_OBJ_INT
 * MOO_OBJ_LONG, MOO_OBJ_FLOAT, MOO_OBJ_DOUBLE, etc 
 * type type field being 6 bits long, you can have up to 64 different types.
 
	MOO_OBJ_TYPE_SHORT,
	MOO_OBJ_TYPE_INT,
	MOO_OBJ_TYPE_LONG,
	MOO_OBJ_TYPE_FLOAT,
	MOO_OBJ_TYPE_DOUBLE */
};
typedef enum moo_obj_type_t moo_obj_type_t;
 
enum moo_gcfin_t
{
	MOO_GCFIN_FINALIZABLE = (1 << 0),
	MOO_GCFIN_FINALIZED   = (1 << 1),
	MOO_GCFIN_RESERVED_0  = (1 << 2),
	MOO_GCFIN_RESERVED_1  = (1 << 3)
};
typedef enum moo_gcfin_t moo_gcfin_t;
 
/* =========================================================================
 * Object header structure 
 * 
 * _flags:
 *   type: the type of a payload item. 
 *         one of MOO_OBJ_TYPE_OOP, MOO_OBJ_TYPE_CHAR, 
 *                MOO_OBJ_TYPE_BYTE, MOO_OBJ_TYPE_HALFWORD, MOO_OBJ_TYPE_WORD
 *   unit: the size of a payload item in bytes. 
 *   extra: 0 or 1. 1 indicates that the payload contains 1 more
 *          item than the value of the size field. used for a 
 *          terminating null in a variable-character object. internel
 *          use only.
 *   kernel: 0, 1, or 2. indicates that the object is a kernel object.
 *           VM disallows layout changes of a kernel object.
 *           internal use only. during ignition, it's set to 1.
 *           when full definition is available, it's set to 2.
 *   moved: 0 or 1. used by GC. internal use only.
 *   ngc: 0 or 1, used by GC. internal use only.
 *   rdonly: 0 or 1. indicates that an object is immutable.
 *   gcfin: represents finalzation state.
 *   trailer: 0 or 1. indicates that there are trailing bytes
 *            after the object payload. internal use only.
 *
 * _size: the number of payload items in an object.
 *        it doesn't include the header size.
 * 
 * The total number of bytes occupied by an object can be calculated
 * with this fomula:
 *    sizeof(moo_obj_t) + ALIGN((size + extra) * unit), sizeof(moo_oop_t))
 * 
 * If the type is known to be not MOO_OBJ_TYPE_CHAR, you can assume that 
 * 'extra' is 0. So you can simplify the fomula in such a context.
 *    sizeof(moo_obj_t) + ALIGN(size * unit), sizeof(moo_oop_t))
 *
 * The ALIGN() macro is used above since allocation adjusts the payload
 * size to a multiple of sizeof(moo_oop_t). it assumes that sizeof(moo_obj_t)
 * is a multiple of sizeof(moo_oop_t). See the MOO_BYTESOF() macro.
 * 
 * Due to the header structure, an object can only contain items of
 * homogeneous data types in the payload. 
 *
 * It's actually possible to split the size field into 2. For example,
 * the upper half contains the number of oops and the lower half contains
 * the number of bytes/chars. This way, a variable-byte class or a variable-char
 * class can have normal instance variables. On the contrary, the actual byte
 * size calculation and the access to the payload fields become more complex. 
 * Therefore, i've dropped the idea.
 * ========================================================================= */
#define MOO_OBJ_FLAGS_TYPE_BITS     6
#define MOO_OBJ_FLAGS_UNIT_BITS     5
#define MOO_OBJ_FLAGS_EXTRA_BITS    1
#define MOO_OBJ_FLAGS_KERNEL_BITS   2
#define MOO_OBJ_FLAGS_MOVED_BITS    1
#define MOO_OBJ_FLAGS_NGC_BITS      1
#define MOO_OBJ_FLAGS_RDONLY_BITS   1
#define MOO_OBJ_FLAGS_GCFIN_BITS    4
#define MOO_OBJ_FLAGS_TRAILER_BITS  1
 
#define MOO_OBJ_FLAGS_TYPE_SHIFT    (MOO_OBJ_FLAGS_UNIT_BITS    + MOO_OBJ_FLAGS_UNIT_SHIFT)
#define MOO_OBJ_FLAGS_UNIT_SHIFT    (MOO_OBJ_FLAGS_EXTRA_BITS   + MOO_OBJ_FLAGS_EXTRA_SHIFT)
#define MOO_OBJ_FLAGS_EXTRA_SHIFT   (MOO_OBJ_FLAGS_KERNEL_BITS  + MOO_OBJ_FLAGS_KERNEL_SHIFT)
#define MOO_OBJ_FLAGS_KERNEL_SHIFT  (MOO_OBJ_FLAGS_MOVED_BITS   + MOO_OBJ_FLAGS_MOVED_SHIFT)
#define MOO_OBJ_FLAGS_MOVED_SHIFT   (MOO_OBJ_FLAGS_NGC_BITS     + MOO_OBJ_FLAGS_NGC_SHIFT)
#define MOO_OBJ_FLAGS_NGC_SHIFT     (MOO_OBJ_FLAGS_RDONLY_BITS  + MOO_OBJ_FLAGS_RDONLY_SHIFT)
#define MOO_OBJ_FLAGS_RDONLY_SHIFT  (MOO_OBJ_FLAGS_GCFIN_BITS   + MOO_OBJ_FLAGS_GCFIN_SHIFT)
#define MOO_OBJ_FLAGS_GCFIN_SHIFT   (MOO_OBJ_FLAGS_TRAILER_BITS + MOO_OBJ_FLAGS_TRAILER_SHIFT)
#define MOO_OBJ_FLAGS_TRAILER_SHIFT (0)
 
#define MOO_OBJ_GET_FLAGS_TYPE(oop)       MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT,    MOO_OBJ_FLAGS_TYPE_BITS)
#define MOO_OBJ_GET_FLAGS_UNIT(oop)       MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_UNIT_SHIFT,    MOO_OBJ_FLAGS_UNIT_BITS)
#define MOO_OBJ_GET_FLAGS_EXTRA(oop)      MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_EXTRA_SHIFT,   MOO_OBJ_FLAGS_EXTRA_BITS)
#define MOO_OBJ_GET_FLAGS_KERNEL(oop)     MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_KERNEL_SHIFT,  MOO_OBJ_FLAGS_KERNEL_BITS)
#define MOO_OBJ_GET_FLAGS_MOVED(oop)      MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT,   MOO_OBJ_FLAGS_MOVED_BITS)
#define MOO_OBJ_GET_FLAGS_NGC(oop)        MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT,     MOO_OBJ_FLAGS_NGC_BITS)
#define MOO_OBJ_GET_FLAGS_RDONLY(oop)     MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT,  MOO_OBJ_FLAGS_RDONLY_BITS)
#define MOO_OBJ_GET_FLAGS_GCFIN(oop)      MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_GCFIN_SHIFT,   MOO_OBJ_FLAGS_GCFIN_BITS)
#define MOO_OBJ_GET_FLAGS_TRAILER(oop)    MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS)
 
#define MOO_OBJ_SET_FLAGS_TYPE(oop,v)     MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT,    MOO_OBJ_FLAGS_TYPE_BITS,     v)
#define MOO_OBJ_SET_FLAGS_UNIT(oop,v)     MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_UNIT_SHIFT,    MOO_OBJ_FLAGS_UNIT_BITS,     v)
#define MOO_OBJ_SET_FLAGS_EXTRA(oop,v)    MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_EXTRA_SHIFT,   MOO_OBJ_FLAGS_EXTRA_BITS,    v)
#define MOO_OBJ_SET_FLAGS_KERNEL(oop,v)   MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_KERNEL_SHIFT,  MOO_OBJ_FLAGS_KERNEL_BITS,   v)
#define MOO_OBJ_SET_FLAGS_MOVED(oop,v)    MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT,   MOO_OBJ_FLAGS_MOVED_BITS,    v)
#define MOO_OBJ_SET_FLAGS_NGC(oop,v)      MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT,     MOO_OBJ_FLAGS_NGC_BITS,      v)
#define MOO_OBJ_SET_FLAGS_RDONLY(oop,v)   MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT,  MOO_OBJ_FLAGS_RDONLY_BITS,   v)
#define MOO_OBJ_SET_FLAGS_GCFIN(oop,v)    MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_GCFIN_SHIFT,   MOO_OBJ_FLAGS_GCFIN_BITS,    v)
#define MOO_OBJ_SET_FLAGS_TRAILER(oop,v)  MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS,  v)
 
#define MOO_OBJ_GET_SIZE(oop) ((oop)->_size)
#define MOO_OBJ_GET_CLASS(oop) ((moo_oop_class_t)((oop)->_class))
 
#define MOO_OBJ_SET_SIZE(oop,v) ((oop)->_size = (v))
#define MOO_OBJ_SET_CLASS(oop,c) ((oop)->_class = (moo_oop_t)(c))
 
/* [NOTE] this macro doesn't include the size of the trailer */
#define MOO_OBJ_BYTESOF(oop) ((MOO_OBJ_GET_SIZE(oop) + MOO_OBJ_GET_FLAGS_EXTRA(oop)) * MOO_OBJ_GET_FLAGS_UNIT(oop))
 
#define MOO_OBJ_IS_OOP_POINTER(oop)      (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_OOP))
#define MOO_OBJ_IS_CHAR_POINTER(oop)     (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_CHAR))
#define MOO_OBJ_IS_BYTE_POINTER(oop)     (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_BYTE))
#define MOO_OBJ_IS_HALFWORD_POINTER(oop) (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_HALFWORD))
#define MOO_OBJ_IS_WORD_POINTER(oop)     (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_WORD))
 
/* [NOTE] this macro doesn't check the range of the actual value.
 *        make sure that the value of each bit fields given falls within the 
 *        possible range of the defined bits */
#define MOO_OBJ_MAKE_FLAGS(t,u,e,k,m,g,r) ( \
	(((moo_oow_t)(t)) << MOO_OBJ_FLAGS_TYPE_SHIFT) | \
	(((moo_oow_t)(u)) << MOO_OBJ_FLAGS_UNIT_SHIFT) | \
	(((moo_oow_t)(e)) << MOO_OBJ_FLAGS_EXTRA_SHIFT) | \
	(((moo_oow_t)(k)) << MOO_OBJ_FLAGS_KERNEL_SHIFT) | \
	(((moo_oow_t)(m)) << MOO_OBJ_FLAGS_MOVED_SHIFT) | \
	(((moo_oow_t)(g)) << MOO_OBJ_FLAGS_NGC_SHIFT) | \
	(((moo_oow_t)(r)) << MOO_OBJ_FLAGS_TRAILER_SHIFT) \
)
 
#define MOO_OBJ_HEADER \
	moo_oow_t _flags; \
	moo_oow_t _size; \
	moo_oop_t _class
 
struct moo_obj_t
{
	MOO_OBJ_HEADER;
};
 
struct moo_obj_oop_t
{
	MOO_OBJ_HEADER;
	moo_oop_t slot[1];
};
 
struct moo_obj_char_t
{
	MOO_OBJ_HEADER;
	moo_ooch_t slot[1];
};
 
struct moo_obj_byte_t
{
	MOO_OBJ_HEADER;
	moo_oob_t slot[1];
};
 
struct moo_obj_halfword_t
{
	MOO_OBJ_HEADER;
	moo_oohw_t slot[1];
};
 
struct moo_obj_word_t
{
	MOO_OBJ_HEADER;
	moo_oow_t slot[1];
};
 
#define MOO_OBJ_GET_OOP_SLOT(oop)      (((moo_oop_oop_t)(oop))->slot)
#define MOO_OBJ_GET_CHAR_SLOT(oop)     (((moo_oop_char_t)(oop))->slot)
#define MOO_OBJ_GET_BYTE_SLOT(oop)     (((moo_oop_byte_t)(oop))->slot)
#define MOO_OBJ_GET_HALFWORD_SLOT(oop) (((moo_oop_halfword_t)(oop))->slot)
#define MOO_OBJ_GET_WORD_SLOT(oop)     (((moo_oop_word_t)(oop))->slot)
 
typedef struct moo_trailer_t moo_trailer_t;
struct moo_trailer_t
{
	moo_oow_t size;
	moo_oob_t slot[1];
};
 
#define MOO_OBJ_GET_TRAILER_BYTE(oop) ((moo_oob_t*)&((moo_oop_oop_t)oop)->slot[MOO_OBJ_GET_SIZE(oop) + 1])
#define MOO_OBJ_GET_TRAILER_SIZE(oop) ((moo_oow_t)((moo_oop_oop_t)oop)->slot[MOO_OBJ_GET_SIZE(oop)])
 
#define MOO_DIC_NAMED_INSTVARS 2
typedef struct moo_dic_t moo_dic_t;
typedef struct moo_dic_t* moo_oop_dic_t;
struct moo_dic_t
{
	MOO_OBJ_HEADER;
	moo_oop_t     tally;  /* SmallInteger */
	moo_oop_oop_t bucket; /* Array */
};
 
/* [NOTE] the beginning of the moo_nsdic_t structure
 *        must be identical to the moo_dic_t streucture */
#define MOO_NSDIC_NAMED_INSTVARS 4
typedef struct moo_nsdic_t moo_nsdic_t;
typedef struct moo_nsdic_t* moo_oop_nsdic_t;
 
#define MOO_CLASS_NAMED_INSTVARS 18
typedef struct moo_class_t moo_class_t;
typedef struct moo_class_t* moo_oop_class_t;
 
struct moo_nsdic_t
{
	MOO_OBJ_HEADER;
	moo_oop_t tally;
	moo_oop_t bucket;
	/* same as moo_dic_t so far */
 
	moo_oop_char_t name; /* a symbol. if it belongs to a class, it will be the same as the name of the class */
	moo_oop_t nsup; /* a class if it belongs to the class. another nsdic if it doesn't */
};
 
struct moo_class_t
{
	MOO_OBJ_HEADER;
 
	moo_oop_t      spec;          /* SmallInteger. instance specification */
	moo_oop_t      selfspec;      /* SmallInteger. specification of the class object itself */
 
	moo_oop_t      superclass;    /* Another class */
	moo_oop_t      subclasses;    /* Array of subclasses */
 
	moo_oop_char_t name;          /* Symbol */
	moo_oop_t      modname;       /* Symbol if importing a module. nil if not. */
 
	/* == NEVER CHANGE THIS ORDER OF 3 ITEMS BELOW == */
	moo_oop_char_t instvars;      /* String */
	moo_oop_char_t classinstvars; /* String */
	moo_oop_char_t classvars;     /* String */
	/* == NEVER CHANGE THE ORDER OF 3 ITEMS ABOVE == */
 
	moo_oop_char_t pooldics;      /* String - pool dictionaries imported */
 
	/* [0] - instance methods, MethodDictionary
	 * [1] - class methods, MethodDictionary */
	moo_oop_dic_t  mthdic[2];      
 
	moo_oop_nsdic_t nsup; /* pointer to the upper namespace */
	moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */
 
	moo_oop_t      trsize; /* trailer size for new instances */
	moo_oop_t      trgc; /* trailer gc callback */
 
	/* [0] - initial values for instance variables of new instances 
	 * [1] - initial values for class instance variables */
	moo_oop_t      initv[2]; 
 
	/* indexed part afterwards */
	moo_oop_t      slot[1];   /* class instance variables and class variables. */
};
 
#define MOO_ASSOCIATION_NAMED_INSTVARS 2
typedef struct moo_association_t moo_association_t;
typedef struct moo_association_t* moo_oop_association_t;
struct moo_association_t
{
	MOO_OBJ_HEADER;
	moo_oop_t key;
	moo_oop_t value;
};
 
#if defined(MOO_USE_METHOD_TRAILER)
#	define MOO_METHOD_NAMED_INSTVARS 8
#else
#	define MOO_METHOD_NAMED_INSTVARS 9
#endif
typedef struct moo_method_t moo_method_t;
typedef struct moo_method_t* moo_oop_method_t;
struct moo_method_t
{
	MOO_OBJ_HEADER;
 
	moo_oop_class_t owner; /* Class */
 
	moo_oop_char_t  name; /* Symbol, method name */
 
	/* primitive number */
	moo_oop_t       preamble; /* SmallInteger */
	moo_oop_t       preamble_data[2]; /* SmallInteger */
 
	/* number of temporaries including arguments */
	moo_oop_t       tmpr_count; /* SmallInteger */
 
	/* number of arguments in temporaries */
	moo_oop_t       tmpr_nargs; /* SmallInteger */
 
#if defined(MOO_USE_METHOD_TRAILER)
	/* no code field is used */
#else
	moo_oop_byte_t  code; /* ByteArray */
#endif
 
	moo_oop_t       source; /* TODO: what should I put? */
 
	/* == variable indexed part == */
	moo_oop_t       slot[1]; /* it stores literals */
};
 
#if defined(MOO_USE_METHOD_TRAILER)
 
	/* if m is to be type-cast to moo_oop_method_t, the macro must be
	 * redefined to this:
	 *   (&((moo_oop_method_t)m)>slot[MOO_OBJ_GET_SIZE(m) + 1 - MOO_METHOD_NAMED_INSTVARS])
	 */
 
	/*((moo_oob_t*)&((moo_oop_oop_t)m)->slot[MOO_OBJ_GET_SIZE(m) + 1])*/
#	define MOO_METHOD_GET_CODE_BYTE(m) MOO_OBJ_GET_TRAILER_BYTE(m)
	/*((moo_oow_t)((moo_oop_oop_t)m)->slot[MOO_OBJ_GET_SIZE(m)])*/
#	define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_TRAILER_SIZE(m) 
#else
#	define MOO_METHOD_GET_CODE_BYTE(m) ((m)->code->slot)
#	define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_SIZE((m)->code)
#endif
 
/* The preamble field is composed of:
 *    4-bit flag
 *    5-bit code  (0 to 31)
 *    16-bit index
 *
 * The code can be one of the following values:
 *  0 - no special action
 *  1 - return self (receiver)
 *  2 - return thisContext (not used)
 *  3 - return thisProcess
 *  4 - return nil
 *  5 - return true
 *  6 - return false 
 *  7 - return index.
 *  8 - return -index.
 *  9 - return selfns
 * 10 - return instvar[index] 
 * 11 - do primitive[index]
 * 12 - do named primitive[index]
 * 13 - exception handler
 * 14 - ensure block
 */
 
/* [NOTE] changing preamble code bit structure requires changes to CompiledMethod>>preambleCode */
#define MOO_METHOD_MAKE_PREAMBLE(code,index,flags)  ((((moo_ooi_t)index) << 9) | ((moo_ooi_t)code << 4) | flags)
#define MOO_METHOD_GET_PREAMBLE_CODE(preamble) ((((moo_ooi_t)preamble) >> 4) & 0x1F)
#define MOO_METHOD_GET_PREAMBLE_INDEX(preamble) (((moo_ooi_t)preamble) >> 9)
#define MOO_METHOD_GET_PREAMBLE_FLAGS(preamble) (((moo_ooi_t)preamble) & 0xF)
 
/* preamble codes */
#define MOO_METHOD_PREAMBLE_NONE                0
#define MOO_METHOD_PREAMBLE_RETURN_RECEIVER     1
#define MOO_METHOD_PREAMBLE_RETURN_CONTEXT      2
#define MOO_METHOD_PREAMBLE_RETURN_PROCESS      3
#define MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS  4
#define MOO_METHOD_PREAMBLE_RETURN_NIL          5
#define MOO_METHOD_PREAMBLE_RETURN_TRUE         6
#define MOO_METHOD_PREAMBLE_RETURN_FALSE        7
#define MOO_METHOD_PREAMBLE_RETURN_INDEX        8
#define MOO_METHOD_PREAMBLE_RETURN_NEGINDEX     9
#define MOO_METHOD_PREAMBLE_RETURN_INSTVAR      10
#define MOO_METHOD_PREAMBLE_PRIMITIVE           11
#define MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE     12 /* index is an index to the symbol table */
#define MOO_METHOD_PREAMBLE_EXCEPTION           13 /* NOTE changing this requires changes in Except.st */
#define MOO_METHOD_PREAMBLE_ENSURE              14 /* NOTE changing this requires changes in Except.st */
 
/* the index is an 16-bit unsigned integer. */
#define MOO_METHOD_PREAMBLE_INDEX_MIN 0x0000
#define MOO_METHOD_PREAMBLE_INDEX_MAX 0xFFFF
#define MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(num) ((num) >= MOO_METHOD_PREAMBLE_INDEX_MIN && (num) <= MOO_METHOD_PREAMBLE_INDEX_MAX)
 
/* preamble flags */
#define MOO_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 0)  /* allows variable arguments. but all named paramenters must be passed in */
#define MOO_METHOD_PREAMBLE_FLAG_LIBERAL  (1 << 1)  /* not all named parameters need to get passed in */
#define MOO_METHOD_PREAMBLE_FLAG_DUAL     (1 << 2)
#define MOO_METHOD_PREAMBLE_FLAG_LENIENT  (1 << 3)  /* lenient primitive method - no exception upon failure. return an error instead */
 
/* NOTE: if you change the number of instance variables for moo_context_t,
 *       you need to change the defintion of BlockContext and MethodContext.
 *       plus, you need to update various exception handling code in MethodContext */
#define MOO_CONTEXT_NAMED_INSTVARS 8
typedef struct moo_context_t moo_context_t;
typedef struct moo_context_t* moo_oop_context_t;
struct moo_context_t
{
	MOO_OBJ_HEADER;
 
	/* it points to the active context at the moment when
	 * this context object has been activated. a new method context
	 * is activated as a result of normal message sending and a block
	 * context is activated when it is sent 'value'. it's set to
	 * nil if a block context created hasn't received 'value'. */
	moo_oop_context_t  sender;
 
	/* SmallInteger, instruction pointer */
	moo_oop_t          ip;
 
	/* SmallInteger, stack pointer. the actual stack pointer is in the active
	 * process. For a method context, it stores the stack pointer of the active
	 * process before it gets activated. the stack pointer of the active 
	 * process is restored using this value upon returning. This field is
	 * almost useless for a block context. */
	moo_oop_t          sp;
 
	/* SmallInteger. Number of temporaries.
	 * For a block context, it's inclusive of the temporaries
	 * defined its 'home'. */
	moo_oop_t          ntmprs;
 
	/* CompiledMethod for a method context, 
	 * SmallInteger for a block context */
	moo_oop_t          method_or_nargs;
 
	/* it points to the receiver of the message for a method context.
	 * a base block context(created but not yet activated) has nil in this 
	 * field. if a block context is activated by 'value', it points 
	 * to the block context object used as a base for shallow-copy. */
	moo_oop_t          receiver_or_source;
 
	/* it is set to nil for a method context.
	 * for a block context, it points to the active context at the 
	 * moment the block context was created. that is, it points to 
	 * a method context where the base block has been defined. 
	 * an activated block context copies this field from the source. */
	moo_oop_t          home;
 
	/* when a method context is created, it is set to itself. no change is
	 * made when the method context is activated. when a block context is 
	 * created (when MAKE_BLOCK or BLOCK_COPY is executed), it is set to the
	 * origin of the active context. when the block context is shallow-copied
	 * for activation (when it is sent 'value'), it is set to the origin of
	 * the source block context. */
	moo_oop_context_t  origin; 
 
	/* variable indexed part - actual arguments and temporaries are placed here */
	moo_oop_t          slot[1]; /* stack */
};
 
 
#define MOO_PROCESS_NAMED_INSTVARS 12
typedef struct moo_process_t moo_process_t;
typedef struct moo_process_t* moo_oop_process_t;
 
#define MOO_SEMAPHORE_NAMED_INSTVARS 13
typedef struct moo_semaphore_t moo_semaphore_t;
typedef struct moo_semaphore_t* moo_oop_semaphore_t;
 
#define MOO_SEMAPHORE_GROUP_NAMED_INSTVARS 8
typedef struct moo_semaphore_group_t moo_semaphore_group_t;
typedef struct moo_semaphore_group_t* moo_oop_semaphore_group_t;
 
struct moo_process_t
{
	MOO_OBJ_HEADER;
	moo_oop_context_t   initial_context;
	moo_oop_context_t   current_context;
 
	moo_oop_t           id;    /* SmallInteger */
	moo_oop_t           state; /* SmallInteger */
	moo_oop_t           sp;    /* stack pointer. SmallInteger */
 
	struct
	{
		moo_oop_process_t   prev;
		moo_oop_process_t   next;
	} ps; /* links to use with the process scheduler */
 
	struct
	{
		moo_oop_process_t   prev;
		moo_oop_process_t   next;
	} sem_wait; /* links to use with a semaphore */
 
	moo_oop_t sem; /* nil, semaphore, or semaphore group */
	moo_oop_t perr; /* last error set by a primitive function */
	moo_oop_t perrmsg;
 
	/* == variable indexed part == */
	moo_oop_t slot[1]; /* process stack */
};
 
enum moo_semaphore_io_type_t 
{
	MOO_SEMAPHORE_IO_TYPE_INPUT   = 0,
	MOO_SEMAPHORE_IO_TYPE_OUTPUT  = 1
};
typedef enum moo_semaphore_io_type_t moo_semaphore_io_type_t;
 
enum moo_semaphore_io_mask_t
{
	MOO_SEMAPHORE_IO_MASK_INPUT   = (1 << 0),
	MOO_SEMAPHORE_IO_MASK_OUTPUT  = (1 << 1),
	MOO_SEMAPHORE_IO_MASK_HANGUP  = (1 << 2),
	MOO_SEMAPHORE_IO_MASK_ERROR   = (1 << 3)
};
typedef enum moo_semaphore_io_mask_t moo_semaphore_io_mask_t;
 
struct moo_semaphore_t
{
	MOO_OBJ_HEADER;
 
	/* [IMPORTANT] make sure that the position of 'waiting' in moo_semaphore_t
	 *             must be exactly the same as its position in moo_semaphore_group_t */
	struct
	{
		moo_oop_process_t first;
		moo_oop_process_t last;
	} waiting; /* list of processes waiting on this semaphore */
	/* [END IMPORTANT] */
 
	moo_oop_t count; /* SmallInteger */
 
	moo_oop_t heap_index; /* index to the heap */
	moo_oop_t heap_ftime_sec; /* firing time */
	moo_oop_t heap_ftime_nsec; /* firing time */
 
	moo_oop_t io_index; 
	moo_oop_t io_handle;
	moo_oop_t io_type; /* SmallInteger */
 
	moo_oop_t signal_action;
 
	moo_oop_semaphore_group_t group; /* nil or belonging semaphore group */
	struct
	{
		moo_oop_semaphore_t prev;
		moo_oop_semaphore_t next;
	} grm; /* group membership chain */
};
 
#define MOO_SEMAPHORE_GROUP_SEMS_UNSIG 0
#define MOO_SEMAPHORE_GROUP_SEMS_SIG   1
 
struct moo_semaphore_group_t
{
	MOO_OBJ_HEADER;
 
	/* [IMPORTANT] make sure that the position of 'waiting' in moo_semaphore_group_t
	 *             must be exactly the same as its position in moo_semaphore_t */
	struct
	{
		moo_oop_process_t first;
		moo_oop_process_t last; 
	} waiting; /* list of processes waiting on this semaphore group */
	/* [END IMPORTANT] */
 
	struct
	{
		moo_oop_semaphore_t first;
		moo_oop_semaphore_t last;
	} sems[2]; /* sems[0] - unsignaled semaphores, sems[1] - signaled semaphores */
 
	moo_oop_t sem_io_count; /* the number of io semaphores in the group */
	moo_oop_t sem_count; /* the total number of semaphores in the group */
};
 
#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 9
typedef struct moo_process_scheduler_t moo_process_scheduler_t;
typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t;
struct moo_process_scheduler_t
{
	MOO_OBJ_HEADER;
	moo_oop_process_t active; /*  pointer to an active process in the runnable process list */
	moo_oop_t should_exit; /* Boolean */
	moo_oop_t total_count; /* SmallIntger, total number of processes - runnable/running/suspended */
 
	struct
	{
		moo_oop_t count; /* SmallInteger, the number of runnable/running processes */
		moo_oop_process_t first;
		moo_oop_process_t last;
	} runnable; /* runnable process list */
 
	struct
	{
		moo_oop_t count; /* SmallInteger - suspended*/
		moo_oop_process_t first;
		moo_oop_process_t last;
	} suspended;
};
 
/**
 * The MOO_CLASSOF() macro return the class of an object including a numeric
 * object encoded into a pointer.
 */
#define MOO_CLASSOF(moo,oop) \
	(MOO_OOP_GET_TAG(oop)? (*(moo)->tagged_classes[MOO_OOP_GET_TAG(oop)]): MOO_OBJ_GET_CLASS(oop))
 
/**
 * The MOO_BYTESOF() macro returns the size of the payload of
 * an object in bytes. If the pointer given encodes a numeric value, 
 * it returns the size of #moo_oow_t in bytes.
 */
#define MOO_BYTESOF(moo,oop) \
	(MOO_OOP_IS_NUMERIC(oop)? MOO_SIZEOF(moo_oow_t): MOO_OBJ_BYTESOF(oop))
 
 
typedef struct moo_heap_t moo_heap_t;
 
struct moo_heap_t
{
	moo_uint8_t* base;  /* start of a heap */
	moo_uint8_t* limit; /* end of a heap */
	moo_uint8_t* ptr;   /* next allocation pointer */
};
 
/* =========================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 * VIRTUAL MACHINE PRIMITIVES
 * ========================================================================= */
 
typedef void* (*moo_alloc_heap_t) (
	moo_t*    moo, 
	moo_oow_t size
);
 
typedef void (*moo_free_heap_t) (
	moo_t*    moo,
	void*     ptr
);
 
typedef void (*moo_log_write_t) (
	moo_t*             moo,
	moo_oow_t          mask,
	const moo_ooch_t*  msg,
	moo_oow_t          len
);
 
typedef void (*moo_syserrstrb_t) (
	moo_t*             moo,
	int                syserr,
	moo_bch_t*         buf,
	moo_oow_t          len
);
 
typedef void (*moo_syserrstru_t) (
	moo_t*             moo,
	int                syserr,
	moo_uch_t*         buf,
	moo_oow_t          len
);
 
enum moo_vmprim_dlopen_flag_t
{
	MOO_VMPRIM_DLOPEN_PFMOD = (1 << 0)
};
typedef enum moo_vmprim_dlopen_flag_t moo_vmprim_dlopen_flag_t;
 
typedef void* (*moo_vmprim_dlopen_t) (
	moo_t*                  moo,
	const moo_ooch_t*       name,
	int                     flags
);
 
typedef void (*moo_vmprim_dlclose_t) (
	moo_t*                  moo,
	void*                   handle
);
 
typedef void* (*moo_vmprimt_dlgetsym_t) (
	moo_t*                  moo,
	void*                   handle,
	const moo_ooch_t*       name
);
 
typedef int (*moo_vmprim_startup_t) (
	moo_t*                  moo
);
 
typedef void (*moo_vmprim_cleanup_t) (
	moo_t*                  moo
);
 
typedef void (*moo_vmprim_gettime_t) (
	moo_t*                  moo,
	moo_ntime_t*            now
);
 
typedef int (*moo_vmprim_muxadd_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle,
	moo_ooi_t               masks
);
 
typedef int (*moo_vmprim_muxmod_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle,
	moo_ooi_t               masks
);
 
typedef int (*moo_vmprim_muxdel_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle
);
 
typedef void (*moo_vmprim_muxwait_cb_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle,
	moo_ooi_t               masks
);
 
typedef void (*moo_vmprim_muxwait_t) (
	moo_t*                  moo,
	const moo_ntime_t*      duration,
	moo_vmprim_muxwait_cb_t muxwcb
);
 
typedef void (*moo_vmprim_sleep_t) (
	moo_t*                  moo,
	const moo_ntime_t*      duration
);
 
struct moo_vmprim_t
{
	moo_alloc_heap_t      alloc_heap;
	moo_free_heap_t       free_heap;
 
	moo_log_write_t        log_write;
	moo_syserrstrb_t       syserrstrb;
	moo_syserrstru_t       syserrstru;
 
	moo_vmprim_dlopen_t    dl_open;
	moo_vmprim_dlclose_t   dl_close;
	moo_vmprimt_dlgetsym_t dl_getsym;
 
	moo_vmprim_startup_t   vm_startup;
	moo_vmprim_cleanup_t   vm_cleanup;
	moo_vmprim_gettime_t   vm_gettime;
	moo_vmprim_muxadd_t    vm_muxadd;
	moo_vmprim_muxdel_t    vm_muxdel;
	moo_vmprim_muxmod_t    vm_muxmod;
	moo_vmprim_muxwait_t   vm_muxwait;
	moo_vmprim_sleep_t     vm_sleep;
};
 
typedef struct moo_vmprim_t moo_vmprim_t;
 
 
/* =========================================================================
 * CALLBACK MANIPULATION
 * ========================================================================= */
typedef void (*moo_cbimpl_t) (moo_t* moo);
 
typedef struct moo_cb_t moo_cb_t;
struct moo_cb_t
{
	moo_cbimpl_t gc;
	moo_cbimpl_t fini;
 
	/* private below */
	moo_cb_t*     prev;
	moo_cb_t*     next;
};
 
 
/* =========================================================================
 * PRIMITIVE FUNCTIONS
 * ========================================================================= */
enum moo_pfrc_t
{
	MOO_PF_HARD_FAILURE = -1,
	MOO_PF_FAILURE      = 0,
	MOO_PF_SUCCESS      = 1
};
typedef enum moo_pfrc_t moo_pfrc_t;
 
/* primitive function implementation type */
typedef moo_pfrc_t (*moo_pfimpl_t) (
	moo_t*    moo,
	moo_ooi_t nargs
);
 
typedef struct moo_pfbase_t moo_pfbase_t;
struct moo_pfbase_t
{
	moo_pfimpl_t handler;
	moo_oow_t    minargs;
	moo_oow_t    maxargs;
};
 
typedef struct moo_pfinfo_t moo_pfinfo_t;
struct moo_pfinfo_t
{
	moo_method_type_t type;
	moo_ooch_t        mthname[32];
	int               variadic;
	moo_pfbase_t      base;
};
 
 
/* receiver check failure leads to hard failure.
 * RATIONAL: the primitive handler should be used by relevant classes and
 *           objects only. if the receiver check fails, you must review
 *           your class library */
#define MOO_PF_CHECK_RCV(moo,cond) do { \
	if (!(cond)) { moo_seterrnum((moo), MOO_EMSGRCV); return MOO_PF_HARD_FAILURE; } \
} while(0)
 
/* argument check failure causes the wrapping method to return an error.
 * RATIONAL: Being a typeless language, it's hard to control the kinds of
 *           arguments.
 */
#define MOO_PF_CHECK_ARGS(moo,nargs,cond) do { \
	if (!(cond)) { moo_seterrnum (moo, MOO_EINVAL); return MOO_PF_FAILURE; } \
} while(0)
 
/* =========================================================================
 * MODULE MANIPULATION
 * ========================================================================= */
#define MOO_MOD_NAME_LEN_MAX 120
 
typedef struct moo_mod_t moo_mod_t;
 
enum moo_mod_hint_t
{
	MOO_MOD_LOAD_FOR_IMPORT = (1 << 0)
};
typedef enum moo_mod_hint_t moo_mod_hint_t;
 
typedef int (*moo_mod_load_t) (
	moo_t*     moo,
	moo_mod_t* mod
);
 
typedef int (*moo_mod_import_t) (
	moo_t*           moo,
	moo_mod_t*       mod,
	moo_oop_class_t  _class
);
 
typedef moo_pfbase_t* (*moo_mod_query_t) (
	moo_t*            moo,
	moo_mod_t*        mod,
	const moo_ooch_t* name,
	moo_oow_t         namelen
);
 
typedef void (*moo_mod_unload_t) (
	moo_t*     moo,
	moo_mod_t* mod
);
 
typedef void (*moo_mod_gc_t) (
	moo_t*     moo,
	moo_mod_t* mod
);
 
struct moo_mod_t
{
	/* input */
	moo_ooch_t   name[MOO_MOD_NAME_LEN_MAX + 1];
	void*        inctx;
	unsigned int hints; /* bitwised-ORed of moo_mod_hint_t enumerators */
 
	/* user-defined data */
	moo_mod_import_t import;
	moo_mod_query_t  query;
	moo_mod_unload_t unload;
	moo_mod_gc_t     gc;
	void*            ctx;
};
 
struct moo_mod_data_t 
{
	void*           handle;
	moo_rbt_pair_t* pair; /* internal backreference to moo->modtab */
	moo_mod_t       mod;
};
typedef struct moo_mod_data_t moo_mod_data_t;
 
struct moo_sbuf_t
{
	moo_ooch_t* ptr;
	moo_oow_t   len;
	moo_oow_t   capa;
};
typedef struct moo_sbuf_t moo_sbuf_t;
 
struct moo_sem_tuple_t
{
	moo_oop_semaphore_t sem[2]; /* [0] input, [1] output */
	moo_ooi_t handle; /* io handle */
	moo_ooi_t mask;
};
typedef struct moo_sem_tuple_t moo_sem_tuple_t;
 
typedef struct moo_finalizable_t moo_finalizable_t;
struct moo_finalizable_t
{
	moo_oop_t oop;
	moo_finalizable_t* prev;
	moo_finalizable_t* next;
};
 
/* special callback to be called for trailer */
typedef void (*moo_trgc_t) (moo_t* moo, moo_oop_t obj);
 
/* =========================================================================
 * MOO VM
 * ========================================================================= */
#if defined(MOO_INCLUDE_COMPILER)
typedef struct moo_compiler_t moo_compiler_t;
#endif
 
#define MOO_ERRMSG_CAPA (2048)
 
struct moo_t
{
	moo_mmgr_t*  mmgr;
	moo_cmgr_t*  cmgr;
	moo_errnum_t errnum;
	struct
	{
		union
		{
			moo_ooch_t ooch[MOO_ERRMSG_CAPA];
			moo_bch_t bch[MOO_ERRMSG_CAPA];
			moo_uch_t uch[MOO_ERRMSG_CAPA];
		} tmpbuf;
		moo_ooch_t buf[MOO_ERRMSG_CAPA];
		moo_oow_t len;
	} errmsg;
	int shuterr;
 
	struct
	{
		unsigned int trait;
		unsigned int log_mask;
		moo_oow_t log_maxcapa;
		moo_oow_t dfl_symtab_size;
		moo_oow_t dfl_sysdic_size;
		moo_oow_t dfl_procstk_size; 
 
		void* mod_inctx;
 
	#if defined(MOO_BUILD_DEBUG)
		/* set automatically when trait is set */
		moo_oow_t karatsuba_cutoff; 
	#endif
	} option;
 
	moo_vmprim_t vmprim;
 
	moo_cb_t* cblist;
	moo_rbt_t modtab; /* primitive module table */
 
	struct
	{
		moo_ooch_t* ptr;
		moo_oow_t len;
		moo_oow_t capa;
		int last_mask;
		int default_type_mask;
	} log;
 
	/* ========================= */
 
	moo_heap_t* permheap; /* TODO: put kernel objects to here */
	moo_heap_t* curheap;
	moo_heap_t* newheap;
 
	/* =============================================================
	 * nil, true, false
	 * ============================================================= */
	moo_oop_t _nil;  /* pointer to the nil object */
	moo_oop_t _true;
	moo_oop_t _false;
 
	/* =============================================================
	 * KERNEL CLASSES 
	 *  Be sure to Keep these kernel class pointers registered in the 
	 *  kernel_classes table in gc.c
	 * ============================================================= */
	moo_oop_class_t _apex; /* Apex */
	moo_oop_class_t _undefined_object; /* UndefinedObject */
	moo_oop_class_t _class; /* Class */
	moo_oop_class_t _object; /* Object */
	moo_oop_class_t _string; /* String */
 
	moo_oop_class_t _symbol; /* Symbol */
	moo_oop_class_t _array; /* Array */
	moo_oop_class_t _byte_array; /* ByteArray */
	moo_oop_class_t _symbol_set; /* SymbolSet */
	moo_oop_class_t _dictionary;
 
	moo_oop_class_t _namespace; /* Namespace */
	moo_oop_class_t _pool_dictionary; /* PoolDictionary */
	moo_oop_class_t _method_dictionary; /* MethodDictionary */
	moo_oop_class_t _method; /* CompiledMethod */
	moo_oop_class_t _association; /* Association */
 
	moo_oop_class_t _method_context; /* MethodContext */
	moo_oop_class_t _block_context; /* BlockContext */
	moo_oop_class_t _process; /* Process */
	moo_oop_class_t _semaphore; /* Semaphore */
	moo_oop_class_t _semaphore_group; /* SemaphoreGroup */
	moo_oop_class_t _process_scheduler; /* ProcessScheduler */
 
	moo_oop_class_t _error_class; /* Error */
	moo_oop_class_t _true_class; /* True */
	moo_oop_class_t _false_class; /* False */
	moo_oop_class_t _character; /* Character */
	moo_oop_class_t _small_integer; /* SmallInteger */
 
	moo_oop_class_t _large_positive_integer; /* LargePositiveInteger */
	moo_oop_class_t _large_negative_integer; /* LargeNegativeInteger */
 
	moo_oop_class_t _small_pointer;
	moo_oop_class_t _system;
	/* =============================================================
	 * END KERNEL CLASSES 
	 * ============================================================= */
 
	/* =============================================================
	 * KEY SYSTEM DICTIONARIES
	 * ============================================================= */
	/* 2 tag bits(lo) + 2 extended tag bits(hi). not all slots are used
	 * because the 2 high extended bits are used only if the low tag bits
	 * are 3 */
	moo_oop_class_t* tagged_classes[16]; 
 
	moo_oop_dic_t symtab; /* system-wide symbol table. instance of SymbolSet */
	moo_oop_nsdic_t sysdic; /* system dictionary. instance of Namespace */
	moo_oop_process_scheduler_t processor; /* instance of ProcessScheduler */
	moo_oop_process_t nil_process; /* instance of Process */
	moo_oop_char_t dicnewsym; /* symbol new: for dictionary */
	moo_oop_char_t dicputassocsym; /* symbol put_assoc: for dictionary */
 
	/* pending asynchronous semaphores */
	moo_oop_semaphore_t* sem_list;
	moo_oow_t sem_list_count;
	moo_oow_t sem_list_capa;
 
	/* semaphores sorted according to time-out. 
	 * organize entries using heap as the earliest entry
	 * needs to be checked first */
	moo_oop_semaphore_t* sem_heap;
	moo_oow_t sem_heap_count;
	moo_oow_t sem_heap_capa;
 
	/* semaphores for I/O handling. plain array */
	/*moo_oop_semaphore_t* sem_io;*/
	moo_sem_tuple_t* sem_io_tuple;
	moo_oow_t sem_io_tuple_count;
	moo_oow_t sem_io_tuple_capa;
 
	moo_oow_t sem_io_count;
	moo_oow_t sem_io_wait_count;
 
	moo_ooi_t* sem_io_map;
	moo_oow_t sem_io_map_capa;
 
	/* semaphore to notify finalizable objects */
	moo_oop_semaphore_t sem_gcfin;
	int sem_gcfin_sigreq;
 
	moo_oop_t* tmp_stack[256]; /* stack for temporaries */
	moo_oow_t tmp_count;
 
 
	moo_oop_t* proc_map;
	moo_oow_t proc_map_capa;
	moo_ooi_t proc_map_free_first;
	moo_ooi_t proc_map_free_last;
 
	/* =============================================================
	 * EXECUTION REGISTERS
	 * ============================================================= */
	moo_oop_context_t initial_context; /* fake initial context */
	moo_oop_context_t active_context;
	moo_oop_method_t active_method;
	moo_oob_t* active_code;
	moo_ooi_t sp;
	moo_ooi_t ip;
	int proc_switched; /* TODO: this is temporary. implement something else to skip immediate context switching */
	int switch_proc;
	int abort_req;
	moo_ntime_t exec_start_time;
	moo_ntime_t exec_end_time;
	/* =============================================================
	 * END EXECUTION REGISTERS
	 * ============================================================= */
 
	/* == BIGINT CONVERSION == */
	struct
	{
		int safe_ndigits;
		moo_oow_t multiplier;
	} bigint[37];
 
	struct
	{
		struct
		{
			moo_ooch_t* ptr;
			moo_oow_t capa;
			moo_oow_t len;
		} xbuf;
		struct
		{
			moo_liw_t* ptr;
			moo_oow_t capa;
		} t;
	} inttostr;
	/* == END BIGINT CONVERSION == */
 
	moo_sbuf_t sbuf[64];
 
	struct
	{
		moo_finalizable_t* first;
		moo_finalizable_t* last;
	} collectable;
 
	struct
	{
		moo_finalizable_t* first;
		moo_finalizable_t* last;
	} finalizable;
 
	moo_uintmax_t inst_counter;
	moo_ooi_t last_inst_pointer;
 
#if defined(MOO_INCLUDE_COMPILER)
	moo_compiler_t* c;
#endif
};
 
/* TODO: proper stack bound check when pushing */
#define MOO_STACK_PUSH(moo,v) \
	do { \
		(moo)->sp = (moo)->sp + 1; \
		MOO_ASSERT (moo, (moo)->sp < (moo_ooi_t)(MOO_OBJ_GET_SIZE((moo)->processor->active) - MOO_PROCESS_NAMED_INSTVARS)); \
		(moo)->processor->active->slot[(moo)->sp] = v; \
	} while(0)
 
#define MOO_STACK_GET(moo,v_sp) ((moo)->processor->active->slot[v_sp])
#define MOO_STACK_SET(moo,v_sp,v_obj) \
	do { \
		MOO_ASSERT (moo, (v_sp) < (moo_ooi_t)(MOO_OBJ_GET_SIZE((moo)->processor->active) - MOO_PROCESS_NAMED_INSTVARS)); \
		(moo)->processor->active->slot[v_sp] = v_obj; \
	} while(0)
 
#define MOO_STACK_GETTOP(moo) MOO_STACK_GET(moo, (moo)->sp)
#define MOO_STACK_SETTOP(moo,v_obj) MOO_STACK_SET(moo, (moo)->sp, v_obj)
 
#define MOO_STACK_POP(moo) ((moo)->sp = (moo)->sp - 1)
#define MOO_STACK_POPS(moo,count) ((moo)->sp = (moo)->sp - (count))
#define MOO_STACK_ISEMPTY(moo) ((moo)->sp <= -1)
 
/* get the stack pointer of the argument at the given index */
#define MOO_STACK_GETARGSP(moo,nargs,idx) ((moo)->sp - ((nargs) - (idx) - 1))
/* get the argument at the given index */
#define MOO_STACK_GETARG(moo,nargs,idx) MOO_STACK_GET(moo, (moo)->sp - ((nargs) - (idx) - 1))
/* get the receiver of a message */
#define MOO_STACK_GETRCV(moo,nargs) MOO_STACK_GET(moo, (moo)->sp - nargs)
 
/* you can't access arguments and receiver after these macros. 
 * also you must not call this macro more than once */
#define MOO_STACK_SETRET(moo,nargs,retv) \
	do { \
		MOO_STACK_POPS(moo, nargs); \
		MOO_STACK_SETTOP(moo, (retv)); \
	} while(0)
#define MOO_STACK_SETRETTORCV(moo,nargs) (MOO_STACK_POPS(moo, nargs))
#define MOO_STACK_SETRETTOERRNUM(moo,nargs) MOO_STACK_SETRET(moo, nargs, MOO_ERROR_TO_OOP(moo->errnum))
#define MOO_STACK_SETRETTOERROR(moo,nargs,ec) MOO_STACK_SETRET(moo, nargs, MOO_ERROR_TO_OOP(ec))
 
/* =========================================================================
 * MOO VM LOGGING
 * ========================================================================= */
 
enum moo_log_mask_t
{
	MOO_LOG_DEBUG      = (1 << 0),
	MOO_LOG_INFO       = (1 << 1),
	MOO_LOG_WARN       = (1 << 2),
	MOO_LOG_ERROR      = (1 << 3),
	MOO_LOG_FATAL      = (1 << 4),
 
	MOO_LOG_UNTYPED    = (1 << 6), /* only to be used by MOO_DEBUGx() and MOO_INFOx() */
	MOO_LOG_COMPILER   = (1 << 7),
	MOO_LOG_VM         = (1 << 8),
	MOO_LOG_MNEMONIC   = (1 << 9), /* bytecode mnemonic */
	MOO_LOG_GC         = (1 << 10),
	MOO_LOG_IC         = (1 << 11), /* instruction cycle, fetch-decode-execute */
	MOO_LOG_PRIMITIVE  = (1 << 12),
	MOO_LOG_APP        = (1 << 13), /* moo applications, set by moo logging primitive */
 
	MOO_LOG_ALL_LEVELS = (MOO_LOG_DEBUG  | MOO_LOG_INFO | MOO_LOG_WARN | MOO_LOG_ERROR | MOO_LOG_FATAL),
	MOO_LOG_ALL_TYPES  = (MOO_LOG_UNTYPED | MOO_LOG_COMPILER | MOO_LOG_VM | MOO_LOG_MNEMONIC | MOO_LOG_GC | MOO_LOG_IC | MOO_LOG_PRIMITIVE | MOO_LOG_APP),
 
 
	MOO_LOG_STDOUT     = (1 << 14), /* write log messages to stdout without timestamp. MOO_LOG_STDOUT wins over MOO_LOG_STDERR. */
	MOO_LOG_STDERR     = (1 << 15)  /* write log messages to stderr without timestamp. */
 
};
typedef enum moo_log_mask_t moo_log_mask_t;
 
/* all bits must be set to get enabled */
#define MOO_LOG_ENABLED(moo,mask) (((moo)->option.log_mask & (mask)) == (mask))
 
#define MOO_LOG0(moo,mask,fmt) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt); } while(0)
#define MOO_LOG1(moo,mask,fmt,a1) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1); } while(0)
#define MOO_LOG2(moo,mask,fmt,a1,a2) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2); } while(0)
#define MOO_LOG3(moo,mask,fmt,a1,a2,a3) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3); } while(0)
#define MOO_LOG4(moo,mask,fmt,a1,a2,a3,a4) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3, a4); } while(0)
#define MOO_LOG5(moo,mask,fmt,a1,a2,a3,a4,a5) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3, a4, a5); } while(0)
#define MOO_LOG6(moo,mask,fmt,a1,a2,a3,a4,a5,a6) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3, a4, a5, a6); } while(0)
 
#if defined(MOO_BUILD_RELEASE)
	/* [NOTE]
	 *  get rid of debugging message totally regardless of
	 *  the log mask in the release build.
	 */
#	define MOO_DEBUG0(moo,fmt)
#	define MOO_DEBUG1(moo,fmt,a1)
#	define MOO_DEBUG2(moo,fmt,a1,a2)
#	define MOO_DEBUG3(moo,fmt,a1,a2,a3)
#	define MOO_DEBUG4(moo,fmt,a1,a2,a3,a4)
#	define MOO_DEBUG5(moo,fmt,a1,a2,a3,a4,a5)
#	define MOO_DEBUG6(moo,fmt,a1,a2,a3,a4,a5,a6)
#else
#	define MOO_DEBUG0(moo,fmt) MOO_LOG0(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt)
#	define MOO_DEBUG1(moo,fmt,a1) MOO_LOG1(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1)
#	define MOO_DEBUG2(moo,fmt,a1,a2) MOO_LOG2(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2)
#	define MOO_DEBUG3(moo,fmt,a1,a2,a3) MOO_LOG3(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3)
#	define MOO_DEBUG4(moo,fmt,a1,a2,a3,a4) MOO_LOG4(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4)
#	define MOO_DEBUG5(moo,fmt,a1,a2,a3,a4,a5) MOO_LOG5(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5)
#	define MOO_DEBUG6(moo,fmt,a1,a2,a3,a4,a5,a6) MOO_LOG6(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6)
#endif
 
#define MOO_INFO0(moo,fmt) MOO_LOG0(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt)
#define MOO_INFO1(moo,fmt,a1) MOO_LOG1(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1)
#define MOO_INFO2(moo,fmt,a1,a2) MOO_LOG2(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2)
#define MOO_INFO3(moo,fmt,a1,a2,a3) MOO_LOG3(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3)
#define MOO_INFO4(moo,fmt,a1,a2,a3,a4) MOO_LOG4(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4)
#define MOO_INFO5(moo,fmt,a1,a2,a3,a4,a5) MOO_LOG5(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5)
#define MOO_INFO6(moo,fmt,a1,a2,a3,a4,a5,a6) MOO_LOG6(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6)
 
 
/* =========================================================================
 * MOO ASSERTION
 * ========================================================================= */
#if defined(MOO_BUILD_RELEASE)
#	define MOO_ASSERT(moo,expr) ((void)0)
#else
#	define MOO_ASSERT(moo,expr) ((void)((expr) || (moo_assertfailed (moo, #expr, __FILE__, __LINE__), 0)))
#endif
 
 
#if defined(MOO_INCLUDE_COMPILER)
enum moo_iocmd_t
{
	MOO_IO_OPEN,
	MOO_IO_CLOSE,
	MOO_IO_READ
};
typedef enum moo_iocmd_t moo_iocmd_t;
 
struct moo_ioloc_t
{
	moo_oow_t line; /**< line */
	moo_oow_t colm; /**< column */
	const moo_ooch_t* file; /**< file specified in #include */
};
typedef struct moo_ioloc_t moo_ioloc_t;
 
typedef struct moo_ioarg_t moo_ioarg_t;
 
typedef moo_ooi_t (*moo_ioimpl_t) (
	moo_t*       moo,
	moo_iocmd_t  cmd,
	moo_ioarg_t* arg
);
 
enum moo_synerrnum_t
{
	MOO_SYNERR_NOERR,
	MOO_SYNERR_ILCHR,           /* illegal character */
	MOO_SYNERR_CMTNC,           /* comment not closed */
	MOO_SYNERR_STRNC,           /* string not closed */
	MOO_SYNERR_CLTNT,           /* character literal not terminated */
	MOO_SYNERR_HLTNT,           /* hashed literal not terminated */
	MOO_SYNERR_CHARLITINVAL,    /* wrong character literal */
	MOO_SYNERR_COLON,           /* : expected */
	MOO_SYNERR_STRING,          /* string expected */
	MOO_SYNERR_RADIXINVAL,      /* invalid radix */
	MOO_SYNERR_RADNUMLITINVAL,  /* invalid numeric literal with radix */
	MOO_SYNERR_BYTERANGE,       /* byte too small or too large */
	MOO_SYNERR_ERRLITINVAL,     /* wrong error literal */
	MOO_SYNERR_LBRACE,          /* { expected */
	MOO_SYNERR_RBRACE,          /* } expected */
	MOO_SYNERR_LPAREN,          /* ( expected */
	MOO_SYNERR_RPAREN,          /* ) expected */
	MOO_SYNERR_RBRACK,          /* ] expected */
	MOO_SYNERR_PERIOD,          /* . expected */
	MOO_SYNERR_COMMA,           /* , expected */
	MOO_SYNERR_VBAR,            /* | expected */
	MOO_SYNERR_GT,              /* > expected */
	MOO_SYNERR_ASSIGN,          /* := expected */
	MOO_SYNERR_IDENT,           /* identifier expected */
	MOO_SYNERR_INTEGER,         /* integer expected */
	MOO_SYNERR_PRIMITIVE,       /* primitive: expected */
	MOO_SYNERR_DIRECTIVEINVAL,  /* wrong directive */
	MOO_SYNERR_CLASSUNDEF,      /* undefined class */
	MOO_SYNERR_CLASSDUPL,       /* duplicate class */
	MOO_SYNERR_CLASSCONTRA,     /* contradictory class */
	MOO_SYNERR_CLASSNAMEINVAL,  /* wrong class name */
	MOO_SYNERR_NPINSTSIZEINVAL, /* invalid non-pointer instance size */
	MOO_SYNERR_INHERITBANNED,   /* prohibited inheritance */
	MOO_SYNERR_VARDCLBANNED,    /* variable declaration not allowed */
	MOO_SYNERR_MODIFIER,        /* modifier expected */
	MOO_SYNERR_MODIFIERINVAL,   /* wrong modifier */
	MOO_SYNERR_MODIFIERBANNED,  /* modifier not allowed */
	MOO_SYNERR_MODIFIERDUPL,    /* duplicate modifier */
	MOO_SYNERR_MTHNAME,         /* method name expected */
	MOO_SYNERR_MTHNAMEDUPL,     /* duplicate method name */
	MOO_SYNERR_VARIADMTHINVAL,  /* invalid variadic method definition */
	MOO_SYNERR_VARNAME,         /* variable name expected */
	MOO_SYNERR_ARGNAMEDUPL,     /* duplicate argument name */
	MOO_SYNERR_TMPRNAMEDUPL,    /* duplicate temporary variable name */
	MOO_SYNERR_VARNAMEDUPL,     /* duplicate variable name */
	MOO_SYNERR_BLKARGNAMEDUPL,  /* duplicate block argument name */
	MOO_SYNERR_VARUNDCL,        /* undeclared variable */
	MOO_SYNERR_VARUNUSE,        /* unsuable variable in compiled code */
	MOO_SYNERR_VARINACC,        /* inaccessible variable - e.g. accessing an instance variable from a class method is not allowed. */
	MOO_SYNERR_VARAMBIG,        /* ambiguious variable - e.g. the variable is found in multiple pool dictionaries imported */
	MOO_SYNERR_VARFLOOD,        /* too many instance/class variables */
	MOO_SYNERR_SELFINACC,       /* inaccessible self */
	MOO_SYNERR_PRIMARYINVAL,    /* wrong expression primary */
	MOO_SYNERR_TMPRFLOOD,       /* too many temporaries */
	MOO_SYNERR_ARGFLOOD,        /* too many arguments */
	MOO_SYNERR_BLKTMPRFLOOD,    /* too many block temporaries */
	MOO_SYNERR_BLKARGFLOOD,     /* too many block arguments */
	MOO_SYNERR_BLKFLOOD,        /* too large block */
	MOO_SYNERR_ARREXPFLOOD,     /* too large array expression */
	MOO_SYNERR_PFNUMINVAL,      /* wrong primitive function number */
	MOO_SYNERR_PFIDINVAL,       /* wrong primitive function identifier */
	MOO_SYNERR_PFARGDEFINVAL,   /* wrong primitive function argument definition */
	MOO_SYNERR_MODNAMEINVAL,    /* wrong module name */
	MOO_SYNERR_MODIMPFAIL,      /* failed to import module */
	MOO_SYNERR_INCLUDE,         /* #include error */
	MOO_SYNERR_PRAGMAINVAL,     /* wrong pragma name */
	MOO_SYNERR_NAMESPACEINVAL,  /* wrong namespace name */
	MOO_SYNERR_POOLDICINVAL,    /* wrong pool dictionary */
	MOO_SYNERR_POOLDICDUPL,     /* duplicate pool dictionary */
	MOO_SYNERR_LITERAL,         /* literal expected */
	MOO_SYNERR_NOTINLOOP,       /* break or continue not within a loop */
	MOO_SYNERR_INBLOCK,         /* break or continue within a block */
	MOO_SYNERR_WHILE            /* while expected */
};
typedef enum moo_synerrnum_t moo_synerrnum_t;
 
struct moo_synerr_t
{
	moo_synerrnum_t num;
	moo_ioloc_t     loc;
	moo_oocs_t      tgt;
};
typedef struct moo_synerr_t moo_synerr_t;
#endif
 
#if defined(__cplusplus)
extern "C" {
#endif
 
MOO_EXPORT moo_t* moo_open (
	moo_mmgr_t*         mmgr,
	moo_oow_t           xtnsize,
	moo_oow_t           heapsize,
	const moo_vmprim_t* vmprim,
	moo_errnum_t*       errnum
);
 
MOO_EXPORT void moo_close (
	moo_t* moo
);
 
MOO_EXPORT int moo_init (
	moo_t*              moo,
	moo_mmgr_t*         mmgr,
	moo_oow_t           heapsize,
	const moo_vmprim_t* vmprim
);
 
MOO_EXPORT void moo_fini (
	moo_t* moo
);
 
#if defined(MOO_HAVE_INLINE)
	static MOO_INLINE moo_mmgr_t* moo_getmmgr (moo_t* moo) { return moo->mmgr; }
	static MOO_INLINE void* moo_getxtn (moo_t* moo) { return (void*)(moo + 1); }
 
	static MOO_INLINE moo_cmgr_t* moo_getcmgr (moo_t* moo) { return moo->cmgr; }
	static MOO_INLINE void moo_setcmgr (moo_t* moo, moo_cmgr_t* cmgr) { moo->cmgr = cmgr; }
 
	static MOO_INLINE moo_errnum_t moo_geterrnum (moo_t* moo) { return moo->errnum; }
#else
#	define moo_getmmgr(moo) ((moo)->mmgr)
#	define moo_getxtn(moo) ((void*)((moo) + 1))
 
#	define moo_getcmgr(moo) ((moo)->cmgr)
#	define moo_setcmgr(moo,mgr) ((moo)->cmgr = (mgr))
 
#	define moo_geterrnum(moo) ((moo)->errnum)
#endif
 
MOO_EXPORT void moo_seterrnum (
	moo_t*       moo, 
	moo_errnum_t errnum
);
 
MOO_EXPORT void moo_seterrwithsyserr (
	moo_t* moo,
	int    syserr
);
 
MOO_EXPORT void moo_seterrbfmt (
	moo_t*           moo,
	moo_errnum_t     errnum,
	const moo_bch_t* fmt,
	...
);
 
MOO_EXPORT void moo_seterrufmt (
	moo_t*           moo,
	moo_errnum_t     errnum,
	const moo_uch_t* fmt,
	...
);
 
MOO_EXPORT const moo_ooch_t* moo_geterrstr (
	moo_t* moo
);
 
MOO_EXPORT const moo_ooch_t* moo_geterrmsg (
	moo_t* moo
);
 
MOO_EXPORT const moo_ooch_t* moo_backuperrmsg (
	moo_t* moo
);
 
/**
 * The moo_getoption() function gets the value of an option
 * specified by \a id into the buffer pointed to by \a value.
 *
 * \return 0 on success, -1 on failure
 */
MOO_EXPORT int moo_getoption (
	moo_t*        moo,
	moo_option_t  id,
	void*         value
);
 
/**
 * The moo_setoption() function sets the value of an option 
 * specified by \a id to the value pointed to by \a value.
 *
 * \return 0 on success, -1 on failure
 */
MOO_EXPORT int moo_setoption (
	moo_t*       moo,
	moo_option_t id,
	const void*   value
);
 
 
MOO_EXPORT moo_cb_t* moo_regcb (
	moo_t*    moo,
	moo_cb_t* tmpl
);
 
MOO_EXPORT void moo_deregcb (
	moo_t*    moo,
	moo_cb_t* cb
);
 
/**
 * The moo_gc() function performs garbage collection.
 * It is not affected by #MOO_NOGC.
 */
MOO_EXPORT void moo_gc (
	moo_t* moo
);
 
 
/**
 * The moo_moveoop() function moves an object and returns an updated pointer
 * after having moved. it must be called in the GC callback context only.
 */
MOO_EXPORT moo_oop_t moo_moveoop (
	moo_t*     moo,
	moo_oop_t  oop
);
 
/**
 * The moo_instantiate() function creates a new object instance of the class 
 * \a _class. The size of the fixed part is taken from the information
 * contained in the class defintion. The \a vlen parameter specifies the length
 * of the variable part. The \a vptr parameter points to the memory area to
 * copy into the variable part of the new object. If \a vptr is #MOO_NULL,
 * the variable part is initialized to 0 or an equivalent value depending
 * on the type. \a vptr is not used when the new instance is of the 
 * #MOO_OBJ_TYPE_OOP type.
 * 
 */
MOO_EXPORT moo_oop_t moo_instantiate (
	moo_t*           moo,
	moo_oop_class_t  _class,
	const void*      vptr,
	moo_oow_t        vlen
);
 
MOO_EXPORT moo_oop_t moo_instantiatewithtrailer (
	moo_t*           moo, 
	moo_oop_class_t  _class,
	moo_oow_t        vlen,
	const moo_oob_t* trptr,
	moo_oow_t        trlen
);
 
MOO_EXPORT moo_oop_t moo_shallowcopy (
	moo_t*          moo,
	moo_oop_t       oop
);
 
/**
 * The moo_ignite() function creates key initial objects.
 */
MOO_EXPORT int moo_ignite (
	moo_t* moo
);
 
/**
 * The moo_execute() function executes an activated context.
 */
MOO_EXPORT int moo_execute (
	moo_t* moo
);
 
/**
 * The moo_invoke() function sends a message named \a mthname to an object
 * named \a objname.
 */
MOO_EXPORT int moo_invoke (
	moo_t*            moo,
	const moo_oocs_t* objname,
	const moo_oocs_t* mthname
);
 
MOO_EXPORT void moo_abort (
	moo_t* moo
);
 
 
#if defined(MOO_HAVE_INLINE)
	static MOO_INLINE void moo_switchprocess(moo_t* moo) { moo->switch_proc = 1; }
#else
#	define moo_switchprocess(moo) ((moo)->switch_proc = 1)
#endif
 
/* =========================================================================
 * COMMON OBJECT MANAGEMENT FUNCTIONS
 * ========================================================================= */
MOO_EXPORT moo_oop_t moo_makesymbol (
	moo_t*             moo,
	const moo_ooch_t*  ptr,
	moo_oow_t          len
);
 
MOO_EXPORT moo_oop_t moo_makestringwithuchars (
	moo_t*            moo, 
	const moo_uch_t*  ptr, 
	moo_oow_t         len
);
 
MOO_EXPORT moo_oop_t moo_makestringwithbchars (
	moo_t*            moo, 
	const moo_bch_t*  ptr, 
	moo_oow_t         len
);
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_makestring(moo,ptr,len) moo_makestringwithuchars(moo,ptr,len)
#else
#	define moo_makestring(moo,ptr,len) moo_makestringwithbchars(moo,ptr,len)
#endif
 
MOO_EXPORT moo_oop_t moo_oowtoint (
	moo_t*    moo,
	moo_oow_t w
);
 
MOO_EXPORT moo_oop_t moo_ooitoint (
	moo_t*    moo,
	moo_ooi_t i
);
 
 
MOO_EXPORT int moo_inttooow (
	moo_t*     moo,
	moo_oop_t  x,
	moo_oow_t* w
);
 
MOO_EXPORT int moo_inttoooi (
	moo_t*     moo,
	moo_oop_t  x,
	moo_ooi_t* i
);
 
MOO_EXPORT moo_oop_t moo_findclass (
	moo_t*            moo,
	moo_oop_nsdic_t   nsdic,
	const moo_ooch_t* name
);
 
MOO_EXPORT int moo_iskindof (
	moo_t*          moo,
	moo_oop_t       obj,
	moo_oop_class_t _class
);
 
/* =========================================================================
 * TRAILER MANAGEMENT
 * ========================================================================= */
MOO_EXPORT int moo_setclasstrsize (
	moo_t*          moo,
	moo_oop_class_t _class,
	moo_oow_t       size,
	moo_trgc_t      trgc
);
 
MOO_EXPORT void* moo_getobjtrailer (
	moo_t*      moo,
	moo_oop_t   obj,
	moo_oow_t*  size
);
 
/* =========================================================================
 * TEMPORARY OOP MANAGEMENT FUNCTIONS
 * ========================================================================= */
MOO_EXPORT void moo_pushtmp (
	moo_t*     moo,
	moo_oop_t* oop_ptr
);
 
MOO_EXPORT void moo_poptmp (
	moo_t*     moo
);
 
MOO_EXPORT void moo_poptmps (
	moo_t*     moo,
	moo_oow_t  count
);
 
/* =========================================================================
 * SYSTEM MEMORY MANAGEMENT FUCNTIONS VIA MMGR
 * ========================================================================= */
MOO_EXPORT void* moo_allocmem (
	moo_t*     moo,
	moo_oow_t  size
);
 
MOO_EXPORT void* moo_callocmem (
	moo_t*     moo,
	moo_oow_t  size
);
 
MOO_EXPORT void* moo_reallocmem (
	moo_t*      moo,
	void*       ptr,
	moo_oow_t   size
);
 
MOO_EXPORT void moo_freemem (
	moo_t*  moo,
	void*   ptr
);
 
/* =========================================================================
 * PRIMITIVE METHOD MANIPULATION
 * ========================================================================= */
MOO_EXPORT int moo_genpfmethod (
	moo_t*            moo,
	moo_mod_t*        mod,
	moo_oop_class_t   _class,
	moo_method_type_t type,
	const moo_ooch_t* mthname,
	int               variadic,
	const moo_ooch_t* name
);
 
/*
MOO_EXPORT int moo_genpfmethods (
	moo_t*              moo,
	moo_mod_t*          mod,
	moo_oop_class_t     _class,
	const moo_pfinfo_t* pfinfo,
	moo_oow_t           pfcount
);
*/
 
MOO_EXPORT moo_pfbase_t* moo_findpfbase (
	moo_t*              moo,
	moo_pfinfo_t*       pfinfo,
	moo_oow_t           pfcount,
	const moo_ooch_t*   name,
	moo_oow_t           namelen
);
 
/* =========================================================================
 * STRING ENCODING CONVERSION
 * ========================================================================= */
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_convootobchars(moo,oocs,oocslen,bcs,bcslen) moo_convutobchars(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convbtooochars(moo,bcs,bcslen,oocs,oocslen) moo_convbtouchars(moo,bcs,bcslen,oocs,oocslen)
#	define moo_convootobcstr(moo,oocs,oocslen,bcs,bcslen) moo_convutobcstr(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convbtooocstr(moo,bcs,bcslen,oocs,oocslen) moo_convbtoucstr(moo,bcs,bcslen,oocs,oocslen)
#else
#	define moo_convootouchars(moo,oocs,oocslen,bcs,bcslen) moo_convbtouchars(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convutooochars(moo,bcs,bcslen,oocs,oocslen) moo_convutobchars(moo,bcs,bcslen,oocs,oocslen)
#	define moo_convootoucstr(moo,oocs,oocslen,bcs,bcslen) moo_convbtoucstr(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convutooocstr(moo,bcs,bcslen,oocs,oocslen) moo_convutobcstr(moo,bcs,bcslen,oocs,oocslen)
#endif
 
MOO_EXPORT int moo_convbtouchars (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t*       bcslen,
	moo_uch_t*       ucs,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT int moo_convutobchars (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t*       ucslen,
	moo_bch_t*       bcs,
	moo_oow_t*       bcslen
);
 
 
/**
 * The moo_convbtoucstr() function converts a null-terminated byte string 
 * to a wide string.
 */
MOO_EXPORT int moo_convbtoucstr (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t*       bcslen,
	moo_uch_t*       ucs,
	moo_oow_t*       ucslen
);
 
 
/**
 * The moo_convutobcstr() function converts a null-terminated wide string
 * to a byte string.
 */
MOO_EXPORT int moo_convutobcstr (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t*       ucslen,
	moo_bch_t*       bcs,
	moo_oow_t*       bcslen
);
 
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_dupootobcharswithheadroom(moo,hrb,oocs,oocslen,bcslen) moo_duputobcharswithheadroom(moo,hrb,oocs,oocslen,bcslen)
#	define moo_dupbtooocharswithheadroom(moo,hrb,bcs,bcslen,oocslen) moo_dupbtoucharswithheadroom(moo,hrb,bcs,bcslen,oocslen)
#	define moo_dupootobchars(moo,oocs,oocslen,bcslen) moo_duputobchars(moo,oocs,oocslen,bcslen)
#	define moo_dupbtooochars(moo,bcs,bcslen,oocslen) moo_dupbtouchars(moo,bcs,bcslen,oocslen)
 
#	define moo_dupootobcstrwithheadroom(moo,hrb,oocs,bcslen) moo_duputobcstrwithheadroom(moo,hrb,oocs,bcslen)
#	define moo_dupbtooocstrwithheadroom(moo,hrb,bcs,oocslen) moo_dupbtoucstrwithheadroom(moo,hrb,bcs,oocslen)
#	define moo_dupootobcstr(moo,oocs,bcslen) moo_duputobcstr(moo,oocs,bcslen)
#	define moo_dupbtooocstr(moo,bcs,oocslen) moo_dupbtoucstr(moo,bcs,oocslen)
#else
#	define moo_dupootoucharswithheadroom(moo,hrb,oocs,oocslen,ucslen) moo_dupbtoucharswithheadroom(moo,hrb,oocs,oocslen,ucslen)
#	define moo_duputooocharswithheadroom(moo,hrb,ucs,ucslen,oocslen) moo_duputobcharswithheadroom(moo,hrb,ucs,ucslen,oocslen)
#	define moo_dupootouchars(moo,oocs,oocslen,ucslen) moo_dupbtouchars(moo,oocs,oocslen,ucslen)
#	define moo_duputooochars(moo,ucs,ucslen,oocslen) moo_duputobchars(moo,ucs,ucslen,oocslen)
 
#	define moo_dupootoucstrwithheadroom(moo,hrb,oocs,ucslen) moo_dupbtoucstrwithheadroom(moo,hrb,oocs,ucslen)
#	define moo_duputooocstrwithheadroom(moo,hrb,ucs,oocslen) moo_duputobcstrwithheadroom(moo,hrb,ucs,oocslen)
#	define moo_dupootoucstr(moo,oocs,ucslen) moo_dupbtoucstr(moo,oocs,ucslen)
#	define moo_duputooocstr(moo,ucs,oocslen) moo_duputobcstr(moo,ucs,oocslen)
#endif
 
 
MOO_EXPORT moo_uch_t* moo_dupbtoucharswithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_bch_t* bcs,
	moo_oow_t        bcslen,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT moo_bch_t* moo_duputobcharswithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_uch_t* ucs,
	moo_oow_t        ucslen,
	moo_oow_t*       bcslen
);
 
MOO_EXPORT moo_uch_t* moo_dupbtouchars (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t        bcslen,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT moo_bch_t* moo_duputobchars (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t        ucslen,
	moo_oow_t*       bcslen
);
 
 
MOO_EXPORT moo_uch_t* moo_dupbtoucstrwithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_bch_t* bcs,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT moo_bch_t* moo_duputobcstrwithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_uch_t* ucs,
	moo_oow_t* bcslen
);
 
MOO_EXPORT moo_uch_t* moo_dupbtoucstr (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t*       ucslen /* optional: length of returned string */
);
 
MOO_EXPORT moo_bch_t* moo_duputobcstr (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t*       bcslen /* optional: length of returned string */
);
 
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_dupoochars(moo,oocs,oocslen) moo_dupuchars(moo,oocs,oocslen)
#else
#	define moo_dupoochars(moo,oocs,oocslen) moo_dupbchars(moo,oocs,oocslen)
#endif
 
MOO_EXPORT moo_uch_t* moo_dupuchars (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t        ucslen
);
 
MOO_EXPORT moo_bch_t* moo_dupbchars (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t        bcslen
);
 
 
/* =========================================================================
 * MOO VM LOGGING
 * ========================================================================= */
 
MOO_EXPORT moo_ooi_t moo_logbfmt (
	moo_t*           moo,
	moo_oow_t        mask,
	const moo_bch_t* fmt,
	...
);
 
MOO_EXPORT moo_ooi_t moo_logufmt (
	moo_t*            moo,
	moo_oow_t         mask,
	const moo_uch_t*  fmt,
	...
);
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_logoofmt moo_logufmt
#else
#	define moo_logoofmt moo_logbfmt
#endif
 
/* =========================================================================
 * MISCELLANEOUS HELPER FUNCTIONS
 * ========================================================================= */
 
MOO_EXPORT int moo_decode (
	moo_t*            moo,
	moo_oop_method_t  mth,
	const moo_oocs_t* classfqn
);
 
MOO_EXPORT void moo_assertfailed (
	moo_t*           moo,
	const moo_bch_t* expr,
	const moo_bch_t* file,
	moo_oow_t        line
);
 
MOO_EXPORT moo_errnum_t moo_syserr_to_errnum (
	int syserr
);
 
MOO_EXPORT const moo_ooch_t* moo_errnum_to_errstr (
	moo_errnum_t errnum
);
 
/**
 * The moo_releaseiohandle() function deletes resources associated with
 * the given IO handle. The resources include IO semaphores. You should call
 * this function before closing an IO handle.
 */
MOO_EXPORT void moo_releaseiohandle (
	moo_t*    moo,
	moo_ooi_t io_handle
);
 
#if defined(MOO_INCLUDE_COMPILER)
 
/* =========================================================================
 * COMPILER FUNCTIONS
 * ========================================================================= */
 
MOO_EXPORT int moo_compile (
	moo_t*       moo,
	moo_ioimpl_t io
);
 
MOO_EXPORT void moo_getsynerr (
	moo_t*        moo,
	moo_synerr_t* synerr
);
 
#endif
 
#if defined(__cplusplus)
}
#endif
 
 
#endif
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557                                                                         15581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270/*
 * $Id$
 *
    Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved.
 
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:
    1. Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
 
    THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
#ifndef _MOO_H_
#define _MOO_H_
 
#include "moo-cmn.h"
#include "moo-rbt.h"
 
/* TODO: move this macro out to the build files.... */
#define MOO_INCLUDE_COMPILER
 
/* define this to allow an pointer(OOP) object to have trailing bytes 
 * this is used to embed bytes codes into the back of a compile method
 * object instead of putting in in a separate byte array. */
#define MOO_USE_METHOD_TRAILER
 
/* ========================================================================== */
 
/**
 * The moo_errnum_t type defines the error codes.
 */
enum moo_errnum_t
{
	MOO_ENOERR,   /**< no error */
	MOO_EGENERIC, /**< generic error */
 
	MOO_ENOIMPL,  /**< not implemented */
	MOO_ESYSERR,  /**< system error */
	MOO_EINTERN,  /**< internal error */
	MOO_ESYSMEM,  /**< insufficient system memory */
	MOO_EOOMEM,   /**< insufficient object memory */
	MOO_ETYPE,    /**< invalid class/type */
 
	MOO_EINVAL,   /**< invalid parameter or data */
	MOO_ENOENT,   /**< data not found */
	MOO_EEXIST,   /**< existing/duplicate data */
	MOO_EBUSY, 
	MOO_EACCES,
	MOO_EPERM,
	MOO_ENOTDIR,
	MOO_EINTR,
	MOO_EPIPE,
	MOO_EAGAIN,
	MOO_EBADHND,
 
	MOO_EXXXXX1,  /**< **** not used ****/
	MOO_EMSGRCV,  /**< mesasge receiver error */
	MOO_EMSGSND,  /**< message sending error. even doesNotUnderstand: is not found */
	MOO_ENUMARGS, /**< wrong number of arguments */
	MOO_ERANGE,   /**< range error. overflow and underflow */
	MOO_EBCFULL,  /**< byte-code full */
	MOO_EDFULL,   /**< dictionary full */
	MOO_EPFULL,   /**< processor full */
	MOO_ESEMFLOOD,/**< too many semaphores */
	MOO_EXXXXX2,  /**< **** not used ***** */
	MOO_EDIVBY0,  /**< divide by zero */
	MOO_EIOERR,   /**< I/O error */
	MOO_EECERR,   /**< encoding conversion error */
	MOO_EBUFFULL, /**< buffer full */
 
#if defined(MOO_INCLUDE_COMPILER)
	MOO_ESYNERR  /** < syntax error */
#endif
};
typedef enum moo_errnum_t moo_errnum_t;
 
enum moo_option_t
{
	MOO_TRAIT,
	MOO_LOG_MASK,
	MOO_LOG_MAXCAPA,
	MOO_SYMTAB_SIZE,  /* default system table size */
	MOO_SYSDIC_SIZE,  /* default system dictionary size */
	MOO_PROCSTK_SIZE, /* default process stack size */
	MOO_MOD_INCTX
};
typedef enum moo_option_t moo_option_t;
 
/* [NOTE] ensure that it is a power of 2 */
#define MOO_LOG_CAPA_ALIGN 512
 
enum moo_option_dflval_t
{
	MOO_DFL_LOG_MAXCAPA = MOO_LOG_CAPA_ALIGN * 16,
	MOO_DFL_SYMTAB_SIZE = 5000,
	MOO_DFL_SYSDIC_SIZE = 5000,
	MOO_DFL_PROCSTK_SIZE = 5000
};
typedef enum moo_option_dflval_t moo_option_dflval_t;
 
enum moo_trait_t
{
#if defined(MOO_BUILD_DEBUG)
	MOO_DEBUG_GC     = (1u << 0),
	MOO_DEBUG_BIGINT = (1u << 1),
#endif
 
	/* perform no garbage collection when the heap is full. 
	 * you still can use moo_gc() explicitly. */
	MOO_NOGC = (1u << 8),
 
	/* wait for running process when exiting from the main method */
	MOO_AWAIT_PROCS = (1u << 9)
};
typedef enum moo_trait_t moo_trait_t;
 
typedef unsigned int moo_traits_t;
 
typedef struct moo_obj_t           moo_obj_t;
typedef struct moo_obj_t*          moo_oop_t;
 
/* these are more specialized types for moo_obj_t */
typedef struct moo_obj_oop_t       moo_obj_oop_t;
typedef struct moo_obj_char_t      moo_obj_char_t;
typedef struct moo_obj_byte_t      moo_obj_byte_t;
typedef struct moo_obj_halfword_t  moo_obj_halfword_t;
typedef struct moo_obj_word_t      moo_obj_word_t;
 
/* these are more specialized types for moo_oop_t */
typedef struct moo_obj_oop_t*      moo_oop_oop_t;
typedef struct moo_obj_char_t*     moo_oop_char_t;
typedef struct moo_obj_byte_t*     moo_oop_byte_t;
typedef struct moo_obj_halfword_t* moo_oop_halfword_t;
typedef struct moo_obj_word_t*     moo_oop_word_t;
 
#define MOO_OOW_BITS  (MOO_SIZEOF_OOW_T * 8)
#define MOO_OOI_BITS  (MOO_SIZEOF_OOI_T * 8)
#define MOO_OOP_BITS  (MOO_SIZEOF_OOP_T * 8)
#define MOO_OOHW_BITS (MOO_SIZEOF_OOHW_T * 8)
 
 
/* ========================================================================= */
/* BIGINT TYPES AND MACROS                                                   */
/* ========================================================================= */
#if (MOO_SIZEOF_UINTMAX_T > MOO_SIZEOF_OOW_T)
#	define MOO_USE_FULL_WORD
#endif
 
#if defined(MOO_USE_FULL_WORD)
	typedef moo_oow_t          moo_liw_t; /* large integer word */
	typedef moo_ooi_t          moo_lii_t;
	typedef moo_uintmax_t      moo_lidw_t; /* large integer double word */
	typedef moo_intmax_t       moo_lidi_t;
#	define MOO_SIZEOF_LIW_T    MOO_SIZEOF_OOW_T
#	define MOO_SIZEOF_LIDW_T   MOO_SIZEOF_UINTMAX_T
#	define MOO_LIW_BITS        MOO_OOW_BITS
#	define MOO_LIDW_BITS       (MOO_SIZEOF_UINTMAX_T * 8) 
 
	typedef moo_oop_word_t     moo_oop_liword_t;
#	define MOO_OBJ_TYPE_LIWORD MOO_OBJ_TYPE_WORD
 
#else
	typedef moo_oohw_t         moo_liw_t;
	typedef moo_oohi_t         moo_lii_t;
	typedef moo_oow_t          moo_lidw_t;
	typedef moo_ooi_t          moo_lidi_t;
#	define MOO_SIZEOF_LIW_T    MOO_SIZEOF_OOHW_T
#	define MOO_SIZEOF_LIDW_T   MOO_SIZEOF_OOW_T
#	define MOO_LIW_BITS        MOO_OOHW_BITS
#	define MOO_LIDW_BITS       MOO_OOW_BITS
 
	typedef moo_oop_halfword_t moo_oop_liword_t;
#	define MOO_OBJ_TYPE_LIWORD MOO_OBJ_TYPE_HALFWORD
 
#endif
 
enum moo_method_type_t
{
	MOO_METHOD_INSTANCE = 0,
	MOO_METHOD_CLASS    = 1,
	MOO_METHOD_DUAL     = 2
};
typedef enum moo_method_type_t moo_method_type_t;
 
/* 
 * OOP encoding
 * An object pointer(OOP) is an ordinary pointer value to an object.
 * but some simple numeric values are also encoded into OOP using a simple
 * bit-shifting and masking.
 *
 * A real OOP is stored without any bit-shifting while a non-pointer value encoded
 * in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits
 * are set to 1 or 2.
 * 
 * This scheme works because the object allocators aligns the object size to
 * a multiple of sizeof(moo_oop_t). This way, the 2 least-significant bits
 * of a real OOP are always 0s.
 *
 * With 2 bits, i can encode only 3 special types except object pointers. 
 * Since I need more than 3 special types, I extend the tag bits up to 4 bits
 * to represent a special data type that doesn't require a range as wide
 * as a small integer. A unicode character, for instance, only requires 21 
 * bits at most. An error doesn't need to be as diverse as a small integer.
 */
 
#define MOO_OOP_TAG_BITS_LO     2
#define MOO_OOP_TAG_BITS_HI     2
 
#define MOO_OOP_TAG_SMOOI       1    /* 01 */
#define MOO_OOP_TAG_SMPTR       2    /* 10 */
#define MOO_OOP_TAG_EXTENDED    3    /* 11 - internal use only */
#define MOO_OOP_TAG_CHAR        3    /* 0011 */
#define MOO_OOP_TAG_ERROR       7    /* 0111 */
#define MOO_OOP_TAG_RESERVED0   11   /* 1011 */
#define MOO_OOP_TAG_RESERVED1   15   /* 1111 */
 
#define MOO_OOP_GET_TAG_LO(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO))
#define MOO_OOP_GET_TAG_LOHI(oop) (((moo_oow_t)oop) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
#define MOO_OOP_GET_TAG(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_EXTENDED? MOO_OOP_GET_TAG_LOHI(oop): MOO_OOP_GET_TAG_LO(oop))
 
#define MOO_OOP_IS_NUMERIC(oop) (MOO_OOP_GET_TAG_LO(oop) != 0)
#define MOO_OOP_IS_POINTER(oop) (MOO_OOP_GET_TAG_LO(oop) == 0)
 
#define MOO_OOP_IS_SMOOI(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMOOI)
#define MOO_OOP_IS_SMPTR(oop) (MOO_OOP_GET_TAG_LO(oop) == MOO_OOP_TAG_SMPTR)
 
#define MOO_SMOOI_TO_OOP(num) ((moo_oop_t)((((moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMOOI))
#define MOO_OOP_TO_SMOOI(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO)
/*
#define MOO_SMPTR_TO_OOP(num) ((moo_oop_t)((((moo_ooi_t)(num)) << MOO_OOP_TAG_BITS_LO) | MOO_OOP_TAG_SMPTR))
#define MOO_OOP_TO_SMPTR(oop) (((moo_ooi_t)oop) >> MOO_OOP_TAG_BITS_LO)
*/
#define MOO_SMPTR_TO_OOP(ptr) ((moo_oop_t)(((moo_oow_t)ptr) | MOO_OOP_TAG_SMPTR))
#define MOO_OOP_TO_SMPTR(oop) ((void*)(((moo_oow_t)oop) & ~MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)))
 
#define MOO_OOP_IS_CHAR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_CHAR)
#define MOO_OOP_IS_ERROR(oop) (MOO_OOP_GET_TAG(oop) == MOO_OOP_TAG_ERROR)
 
#define MOO_OOP_TO_CHAR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO))
#define MOO_CHAR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_CHAR))
#define MOO_OOP_TO_ERROR(oop) (((moo_oow_t)oop) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO))
#define MOO_ERROR_TO_OOP(num) ((moo_oop_t)((((moo_oow_t)(num)) << (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_LO)) | MOO_OOP_TAG_ERROR))
 
/* -------------------------------- */
 
/* SMOOI takes up 62 bits on a 64-bit architecture and 30 bits 
 * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits
 * respectively for the sign bit. */
#define MOO_SMOOI_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO)
#define MOO_SMOOI_ABS_BITS (MOO_SMOOI_BITS - 1)
#define MOO_SMOOI_MAX ((moo_ooi_t)(~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + 1)))
/* Sacrificing 1 bit pattern for a negative SMOOI makes 
 * implementation a lot eaisier in many aspects. */
/*#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX - 1)*/
#define MOO_SMOOI_MIN (-MOO_SMOOI_MAX)
#define MOO_IN_SMOOI_RANGE(ooi) ((ooi) >= MOO_SMOOI_MIN && (ooi) <= MOO_SMOOI_MAX)
 
/* SMPTR is a special value which has been devised to encode an address value
 * whose low MOO_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer
 * returned by most of system functions would be aligned to the pointer size. 
 * you can use the followings macros when converting such a pointer without loss. */
#define MOO_IN_SMPTR_RANGE(ptr) ((((moo_oow_t)ptr) & MOO_LBMASK(moo_oow_t, MOO_OOP_TAG_BITS_LO)) == 0)
 
#define MOO_CHAR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI)
#define MOO_CHAR_MIN 0
#define MOO_CHAR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
 
#define MOO_ERROR_BITS (MOO_OOI_BITS - MOO_OOP_TAG_BITS_LO - MOO_OOP_TAG_BITS_HI)
#define MOO_ERROR_MIN 0
#define MOO_ERROR_MAX (~((moo_oow_t)0) >> (MOO_OOP_TAG_BITS_LO + MOO_OOP_TAG_BITS_HI))
 
/* TODO: There are untested code where a small integer is converted to moo_oow_t.
 *       for example, the spec making macro treats the number as moo_oow_t instead of moo_ooi_t.
 *       as of this writing, i skip testing that part with the spec value exceeding MOO_SMOOI_MAX.
 *       later, please verify it works, probably by limiting the value ranges in such macros
 */
 
/*
 * Object structure
 */
enum moo_obj_type_t
{
	MOO_OBJ_TYPE_OOP,
	MOO_OBJ_TYPE_CHAR,
	MOO_OBJ_TYPE_BYTE,
	MOO_OBJ_TYPE_HALFWORD,
	MOO_OBJ_TYPE_WORD
 
/*
	MOO_OBJ_TYPE_UINT8,
	MOO_OBJ_TYPE_UINT16,
	MOO_OBJ_TYPE_UINT32,
*/
 
/* NOTE: you can have MOO_OBJ_SHORT, MOO_OBJ_INT
 * MOO_OBJ_LONG, MOO_OBJ_FLOAT, MOO_OBJ_DOUBLE, etc 
 * type type field being 6 bits long, you can have up to 64 different types.
 
	MOO_OBJ_TYPE_SHORT,
	MOO_OBJ_TYPE_INT,
	MOO_OBJ_TYPE_LONG,
	MOO_OBJ_TYPE_FLOAT,
	MOO_OBJ_TYPE_DOUBLE */
};
typedef enum moo_obj_type_t moo_obj_type_t;
 
enum moo_gcfin_t
{
	MOO_GCFIN_FINALIZABLE = (1 << 0),
	MOO_GCFIN_FINALIZED   = (1 << 1),
	MOO_GCFIN_RESERVED_0  = (1 << 2),
	MOO_GCFIN_RESERVED_1  = (1 << 3)
};
typedef enum moo_gcfin_t moo_gcfin_t;
 
/* =========================================================================
 * Object header structure 
 * 
 * _flags:
 *   type: the type of a payload item. 
 *         one of MOO_OBJ_TYPE_OOP, MOO_OBJ_TYPE_CHAR, 
 *                MOO_OBJ_TYPE_BYTE, MOO_OBJ_TYPE_HALFWORD, MOO_OBJ_TYPE_WORD
 *   unit: the size of a payload item in bytes. 
 *   extra: 0 or 1. 1 indicates that the payload contains 1 more
 *          item than the value of the size field. used for a 
 *          terminating null in a variable-character object. internel
 *          use only.
 *   kernel: 0, 1, or 2. indicates that the object is a kernel object.
 *           VM disallows layout changes of a kernel object.
 *           internal use only. during ignition, it's set to 1.
 *           when full definition is available, it's set to 2.
 *   moved: 0 or 1. used by GC. internal use only.
 *   ngc: 0 or 1, used by GC. internal use only.
 *   rdonly: 0 or 1. indicates that an object is immutable.
 *   gcfin: represents finalzation state.
 *   trailer: 0 or 1. indicates that there are trailing bytes
 *            after the object payload. internal use only.
 *
 * _size: the number of payload items in an object.
 *        it doesn't include the header size.
 * 
 * The total number of bytes occupied by an object can be calculated
 * with this fomula:
 *    sizeof(moo_obj_t) + ALIGN((size + extra) * unit), sizeof(moo_oop_t))
 * 
 * If the type is known to be not MOO_OBJ_TYPE_CHAR, you can assume that 
 * 'extra' is 0. So you can simplify the fomula in such a context.
 *    sizeof(moo_obj_t) + ALIGN(size * unit), sizeof(moo_oop_t))
 *
 * The ALIGN() macro is used above since allocation adjusts the payload
 * size to a multiple of sizeof(moo_oop_t). it assumes that sizeof(moo_obj_t)
 * is a multiple of sizeof(moo_oop_t). See the MOO_BYTESOF() macro.
 * 
 * Due to the header structure, an object can only contain items of
 * homogeneous data types in the payload. 
 *
 * It's actually possible to split the size field into 2. For example,
 * the upper half contains the number of oops and the lower half contains
 * the number of bytes/chars. This way, a variable-byte class or a variable-char
 * class can have normal instance variables. On the contrary, the actual byte
 * size calculation and the access to the payload fields become more complex. 
 * Therefore, i've dropped the idea.
 * ========================================================================= */
#define MOO_OBJ_FLAGS_TYPE_BITS     6
#define MOO_OBJ_FLAGS_UNIT_BITS     5
#define MOO_OBJ_FLAGS_EXTRA_BITS    1
#define MOO_OBJ_FLAGS_KERNEL_BITS   2
#define MOO_OBJ_FLAGS_MOVED_BITS    1
#define MOO_OBJ_FLAGS_NGC_BITS      1
#define MOO_OBJ_FLAGS_RDONLY_BITS   1
#define MOO_OBJ_FLAGS_GCFIN_BITS    4
#define MOO_OBJ_FLAGS_TRAILER_BITS  1
 
#define MOO_OBJ_FLAGS_TYPE_SHIFT    (MOO_OBJ_FLAGS_UNIT_BITS    + MOO_OBJ_FLAGS_UNIT_SHIFT)
#define MOO_OBJ_FLAGS_UNIT_SHIFT    (MOO_OBJ_FLAGS_EXTRA_BITS   + MOO_OBJ_FLAGS_EXTRA_SHIFT)
#define MOO_OBJ_FLAGS_EXTRA_SHIFT   (MOO_OBJ_FLAGS_KERNEL_BITS  + MOO_OBJ_FLAGS_KERNEL_SHIFT)
#define MOO_OBJ_FLAGS_KERNEL_SHIFT  (MOO_OBJ_FLAGS_MOVED_BITS   + MOO_OBJ_FLAGS_MOVED_SHIFT)
#define MOO_OBJ_FLAGS_MOVED_SHIFT   (MOO_OBJ_FLAGS_NGC_BITS     + MOO_OBJ_FLAGS_NGC_SHIFT)
#define MOO_OBJ_FLAGS_NGC_SHIFT     (MOO_OBJ_FLAGS_RDONLY_BITS  + MOO_OBJ_FLAGS_RDONLY_SHIFT)
#define MOO_OBJ_FLAGS_RDONLY_SHIFT  (MOO_OBJ_FLAGS_GCFIN_BITS   + MOO_OBJ_FLAGS_GCFIN_SHIFT)
#define MOO_OBJ_FLAGS_GCFIN_SHIFT   (MOO_OBJ_FLAGS_TRAILER_BITS + MOO_OBJ_FLAGS_TRAILER_SHIFT)
#define MOO_OBJ_FLAGS_TRAILER_SHIFT (0)
 
#define MOO_OBJ_GET_FLAGS_TYPE(oop)       MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT,    MOO_OBJ_FLAGS_TYPE_BITS)
#define MOO_OBJ_GET_FLAGS_UNIT(oop)       MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_UNIT_SHIFT,    MOO_OBJ_FLAGS_UNIT_BITS)
#define MOO_OBJ_GET_FLAGS_EXTRA(oop)      MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_EXTRA_SHIFT,   MOO_OBJ_FLAGS_EXTRA_BITS)
#define MOO_OBJ_GET_FLAGS_KERNEL(oop)     MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_KERNEL_SHIFT,  MOO_OBJ_FLAGS_KERNEL_BITS)
#define MOO_OBJ_GET_FLAGS_MOVED(oop)      MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT,   MOO_OBJ_FLAGS_MOVED_BITS)
#define MOO_OBJ_GET_FLAGS_NGC(oop)        MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT,     MOO_OBJ_FLAGS_NGC_BITS)
#define MOO_OBJ_GET_FLAGS_RDONLY(oop)     MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT,  MOO_OBJ_FLAGS_RDONLY_BITS)
#define MOO_OBJ_GET_FLAGS_GCFIN(oop)      MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_GCFIN_SHIFT,   MOO_OBJ_FLAGS_GCFIN_BITS)
#define MOO_OBJ_GET_FLAGS_TRAILER(oop)    MOO_GETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS)
 
#define MOO_OBJ_SET_FLAGS_TYPE(oop,v)     MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TYPE_SHIFT,    MOO_OBJ_FLAGS_TYPE_BITS,     v)
#define MOO_OBJ_SET_FLAGS_UNIT(oop,v)     MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_UNIT_SHIFT,    MOO_OBJ_FLAGS_UNIT_BITS,     v)
#define MOO_OBJ_SET_FLAGS_EXTRA(oop,v)    MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_EXTRA_SHIFT,   MOO_OBJ_FLAGS_EXTRA_BITS,    v)
#define MOO_OBJ_SET_FLAGS_KERNEL(oop,v)   MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_KERNEL_SHIFT,  MOO_OBJ_FLAGS_KERNEL_BITS,   v)
#define MOO_OBJ_SET_FLAGS_MOVED(oop,v)    MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_MOVED_SHIFT,   MOO_OBJ_FLAGS_MOVED_BITS,    v)
#define MOO_OBJ_SET_FLAGS_NGC(oop,v)      MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_NGC_SHIFT,     MOO_OBJ_FLAGS_NGC_BITS,      v)
#define MOO_OBJ_SET_FLAGS_RDONLY(oop,v)   MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_RDONLY_SHIFT,  MOO_OBJ_FLAGS_RDONLY_BITS,   v)
#define MOO_OBJ_SET_FLAGS_GCFIN(oop,v)    MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_GCFIN_SHIFT,   MOO_OBJ_FLAGS_GCFIN_BITS,    v)
#define MOO_OBJ_SET_FLAGS_TRAILER(oop,v)  MOO_SETBITS(moo_oow_t, (oop)->_flags, MOO_OBJ_FLAGS_TRAILER_SHIFT, MOO_OBJ_FLAGS_TRAILER_BITS,  v)
 
#define MOO_OBJ_GET_SIZE(oop) ((oop)->_size)
#define MOO_OBJ_GET_CLASS(oop) ((moo_oop_class_t)((oop)->_class))
 
#define MOO_OBJ_SET_SIZE(oop,v) ((oop)->_size = (v))
#define MOO_OBJ_SET_CLASS(oop,c) ((oop)->_class = (moo_oop_t)(c))
 
/* [NOTE] this macro doesn't include the size of the trailer */
#define MOO_OBJ_BYTESOF(oop) ((MOO_OBJ_GET_SIZE(oop) + MOO_OBJ_GET_FLAGS_EXTRA(oop)) * MOO_OBJ_GET_FLAGS_UNIT(oop))
 
#define MOO_OBJ_IS_OOP_POINTER(oop)      (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_OOP))
#define MOO_OBJ_IS_CHAR_POINTER(oop)     (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_CHAR))
#define MOO_OBJ_IS_BYTE_POINTER(oop)     (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_BYTE))
#define MOO_OBJ_IS_HALFWORD_POINTER(oop) (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_HALFWORD))
#define MOO_OBJ_IS_WORD_POINTER(oop)     (MOO_OOP_IS_POINTER(oop) && (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_WORD))
 
/* [NOTE] this macro doesn't check the range of the actual value.
 *        make sure that the value of each bit fields given falls within the 
 *        possible range of the defined bits */
#define MOO_OBJ_MAKE_FLAGS(t,u,e,k,m,g,r) ( \
	(((moo_oow_t)(t)) << MOO_OBJ_FLAGS_TYPE_SHIFT) | \
	(((moo_oow_t)(u)) << MOO_OBJ_FLAGS_UNIT_SHIFT) | \
	(((moo_oow_t)(e)) << MOO_OBJ_FLAGS_EXTRA_SHIFT) | \
	(((moo_oow_t)(k)) << MOO_OBJ_FLAGS_KERNEL_SHIFT) | \
	(((moo_oow_t)(m)) << MOO_OBJ_FLAGS_MOVED_SHIFT) | \
	(((moo_oow_t)(g)) << MOO_OBJ_FLAGS_NGC_SHIFT) | \
	(((moo_oow_t)(r)) << MOO_OBJ_FLAGS_TRAILER_SHIFT) \
)
 
#define MOO_OBJ_HEADER \
	moo_oow_t _flags; \
	moo_oow_t _size; \
	moo_oop_t _class
 
struct moo_obj_t
{
	MOO_OBJ_HEADER;
};
 
struct moo_obj_oop_t
{
	MOO_OBJ_HEADER;
	moo_oop_t slot[1];
};
 
struct moo_obj_char_t
{
	MOO_OBJ_HEADER;
	moo_ooch_t slot[1];
};
 
struct moo_obj_byte_t
{
	MOO_OBJ_HEADER;
	moo_oob_t slot[1];
};
 
struct moo_obj_halfword_t
{
	MOO_OBJ_HEADER;
	moo_oohw_t slot[1];
};
 
struct moo_obj_word_t
{
	MOO_OBJ_HEADER;
	moo_oow_t slot[1];
};
 
#define MOO_OBJ_GET_OOP_SLOT(oop)      (((moo_oop_oop_t)(oop))->slot)
#define MOO_OBJ_GET_CHAR_SLOT(oop)     (((moo_oop_char_t)(oop))->slot)
#define MOO_OBJ_GET_BYTE_SLOT(oop)     (((moo_oop_byte_t)(oop))->slot)
#define MOO_OBJ_GET_HALFWORD_SLOT(oop) (((moo_oop_halfword_t)(oop))->slot)
#define MOO_OBJ_GET_WORD_SLOT(oop)     (((moo_oop_word_t)(oop))->slot)
 
typedef struct moo_trailer_t moo_trailer_t;
struct moo_trailer_t
{
	moo_oow_t size;
	moo_oob_t slot[1];
};
 
#define MOO_OBJ_GET_TRAILER_BYTE(oop) ((moo_oob_t*)&((moo_oop_oop_t)oop)->slot[MOO_OBJ_GET_SIZE(oop) + 1])
#define MOO_OBJ_GET_TRAILER_SIZE(oop) ((moo_oow_t)((moo_oop_oop_t)oop)->slot[MOO_OBJ_GET_SIZE(oop)])
 
#define MOO_DIC_NAMED_INSTVARS 2
typedef struct moo_dic_t moo_dic_t;
typedef struct moo_dic_t* moo_oop_dic_t;
struct moo_dic_t
{
	MOO_OBJ_HEADER;
	moo_oop_t     tally;  /* SmallInteger */
	moo_oop_oop_t bucket; /* Array */
};
 
/* [NOTE] the beginning of the moo_nsdic_t structure
 *        must be identical to the moo_dic_t streucture */
#define MOO_NSDIC_NAMED_INSTVARS 4
typedef struct moo_nsdic_t moo_nsdic_t;
typedef struct moo_nsdic_t* moo_oop_nsdic_t;
 
#define MOO_CLASS_NAMED_INSTVARS 18
typedef struct moo_class_t moo_class_t;
typedef struct moo_class_t* moo_oop_class_t;
 
struct moo_nsdic_t
{
	MOO_OBJ_HEADER;
	moo_oop_t tally;
	moo_oop_t bucket;
	/* same as moo_dic_t so far */
 
	moo_oop_char_t name; /* a symbol. if it belongs to a class, it will be the same as the name of the class */
	moo_oop_t nsup; /* a class if it belongs to the class. another nsdic if it doesn't */
};
 
struct moo_class_t
{
	MOO_OBJ_HEADER;
 
	moo_oop_t      spec;          /* SmallInteger. instance specification */
	moo_oop_t      selfspec;      /* SmallInteger. specification of the class object itself */
 
	moo_oop_t      superclass;    /* Another class */
	moo_oop_t      subclasses;    /* Array of subclasses */
 
	moo_oop_char_t name;          /* Symbol */
	moo_oop_t      modname;       /* Symbol if importing a module. nil if not. */
 
	/* == NEVER CHANGE THIS ORDER OF 3 ITEMS BELOW == */
	moo_oop_char_t instvars;      /* String */
	moo_oop_char_t classinstvars; /* String */
	moo_oop_char_t classvars;     /* String */
	/* == NEVER CHANGE THE ORDER OF 3 ITEMS ABOVE == */
 
	moo_oop_char_t pooldics;      /* String - pool dictionaries imported */
 
	/* [0] - instance methods, MethodDictionary
	 * [1] - class methods, MethodDictionary */
	moo_oop_dic_t  mthdic[2];      
 
	moo_oop_nsdic_t nsup; /* pointer to the upper namespace */
	moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */
 
	moo_oop_t      trsize; /* trailer size for new instances */
	moo_oop_t      trgc; /* trailer gc callback */
 
	/* [0] - initial values for instance variables of new instances 
	 * [1] - initial values for class instance variables */
	moo_oop_t      initv[2]; 
 
	/* indexed part afterwards */
	moo_oop_t      slot[1];   /* class instance variables and class variables. */
};
 
#define MOO_ASSOCIATION_NAMED_INSTVARS 2
typedef struct moo_association_t moo_association_t;
typedef struct moo_association_t* moo_oop_association_t;
struct moo_association_t
{
	MOO_OBJ_HEADER;
	moo_oop_t key;
	moo_oop_t value;
};
 
#if defined(MOO_USE_METHOD_TRAILER)
#	define MOO_METHOD_NAMED_INSTVARS 8
#else
#	define MOO_METHOD_NAMED_INSTVARS 9
#endif
typedef struct moo_method_t moo_method_t;
typedef struct moo_method_t* moo_oop_method_t;
struct moo_method_t
{
	MOO_OBJ_HEADER;
 
	moo_oop_class_t owner; /* Class */
 
	moo_oop_char_t  name; /* Symbol, method name */
 
	/* primitive number */
	moo_oop_t       preamble; /* SmallInteger */
	moo_oop_t       preamble_data[2]; /* SmallInteger */
 
	/* number of temporaries including arguments */
	moo_oop_t       tmpr_count; /* SmallInteger */
 
	/* number of arguments in temporaries */
	moo_oop_t       tmpr_nargs; /* SmallInteger */
 
#if defined(MOO_USE_METHOD_TRAILER)
	/* no code field is used */
#else
	moo_oop_byte_t  code; /* ByteArray */
#endif
 
	moo_oop_t       source; /* TODO: what should I put? */
 
	/* == variable indexed part == */
	moo_oop_t       slot[1]; /* it stores literals */
};
 
#if defined(MOO_USE_METHOD_TRAILER)
 
	/* if m is to be type-cast to moo_oop_method_t, the macro must be
	 * redefined to this:
	 *   (&((moo_oop_method_t)m)>slot[MOO_OBJ_GET_SIZE(m) + 1 - MOO_METHOD_NAMED_INSTVARS])
	 */
 
	/*((moo_oob_t*)&((moo_oop_oop_t)m)->slot[MOO_OBJ_GET_SIZE(m) + 1])*/
#	define MOO_METHOD_GET_CODE_BYTE(m) MOO_OBJ_GET_TRAILER_BYTE(m)
	/*((moo_oow_t)((moo_oop_oop_t)m)->slot[MOO_OBJ_GET_SIZE(m)])*/
#	define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_TRAILER_SIZE(m) 
#else
#	define MOO_METHOD_GET_CODE_BYTE(m) ((m)->code->slot)
#	define MOO_METHOD_GET_CODE_SIZE(m) MOO_OBJ_GET_SIZE((m)->code)
#endif
 
/* The preamble field is composed of:
 *    4-bit flag
 *    5-bit code  (0 to 31)
 *    16-bit index
 *
 * The code can be one of the following values:
 *  0 - no special action
 *  1 - return self (receiver)
 *  2 - return thisContext (not used)
 *  3 - return thisProcess
 *  4 - return nil
 *  5 - return true
 *  6 - return false 
 *  7 - return index.
 *  8 - return -index.
 *  9 - return selfns
 * 10 - return instvar[index] 
 * 11 - do primitive[index]
 * 12 - do named primitive[index]
 * 13 - exception handler
 * 14 - ensure block
 */
 
/* [NOTE] changing preamble code bit structure requires changes to CompiledMethod>>preambleCode */
#define MOO_METHOD_MAKE_PREAMBLE(code,index,flags)  ((((moo_ooi_t)index) << 9) | ((moo_ooi_t)code << 4) | flags)
#define MOO_METHOD_GET_PREAMBLE_CODE(preamble) ((((moo_ooi_t)preamble) >> 4) & 0x1F)
#define MOO_METHOD_GET_PREAMBLE_INDEX(preamble) (((moo_ooi_t)preamble) >> 9)
#define MOO_METHOD_GET_PREAMBLE_FLAGS(preamble) (((moo_ooi_t)preamble) & 0xF)
 
/* preamble codes */
#define MOO_METHOD_PREAMBLE_NONE                0
#define MOO_METHOD_PREAMBLE_RETURN_RECEIVER     1
#define MOO_METHOD_PREAMBLE_RETURN_CONTEXT      2
#define MOO_METHOD_PREAMBLE_RETURN_PROCESS      3
#define MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS  4
#define MOO_METHOD_PREAMBLE_RETURN_NIL          5
#define MOO_METHOD_PREAMBLE_RETURN_TRUE         6
#define MOO_METHOD_PREAMBLE_RETURN_FALSE        7
#define MOO_METHOD_PREAMBLE_RETURN_INDEX        8
#define MOO_METHOD_PREAMBLE_RETURN_NEGINDEX     9
#define MOO_METHOD_PREAMBLE_RETURN_INSTVAR      10
#define MOO_METHOD_PREAMBLE_PRIMITIVE           11
#define MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE     12 /* index is an index to the symbol table */
#define MOO_METHOD_PREAMBLE_EXCEPTION           13 /* NOTE changing this requires changes in Except.st */
#define MOO_METHOD_PREAMBLE_ENSURE              14 /* NOTE changing this requires changes in Except.st */
 
/* the index is an 16-bit unsigned integer. */
#define MOO_METHOD_PREAMBLE_INDEX_MIN 0x0000
#define MOO_METHOD_PREAMBLE_INDEX_MAX 0xFFFF
#define MOO_OOI_IN_METHOD_PREAMBLE_INDEX_RANGE(num) ((num) >= MOO_METHOD_PREAMBLE_INDEX_MIN && (num) <= MOO_METHOD_PREAMBLE_INDEX_MAX)
 
/* preamble flags */
#define MOO_METHOD_PREAMBLE_FLAG_VARIADIC (1 << 0)  /* allows variable arguments. but all named paramenters must be passed in */
#define MOO_METHOD_PREAMBLE_FLAG_LIBERAL  (1 << 1)  /* not all named parameters need to get passed in */
#define MOO_METHOD_PREAMBLE_FLAG_DUAL     (1 << 2)
#define MOO_METHOD_PREAMBLE_FLAG_LENIENT  (1 << 3)  /* lenient primitive method - no exception upon failure. return an error instead */
 
/* NOTE: if you change the number of instance variables for moo_context_t,
 *       you need to change the defintion of BlockContext and MethodContext.
 *       plus, you need to update various exception handling code in MethodContext */
#define MOO_CONTEXT_NAMED_INSTVARS 8
typedef struct moo_context_t moo_context_t;
typedef struct moo_context_t* moo_oop_context_t;
struct moo_context_t
{
	MOO_OBJ_HEADER;
 
	/* it points to the active context at the moment when
	 * this context object has been activated. a new method context
	 * is activated as a result of normal message sending and a block
	 * context is activated when it is sent 'value'. it's set to
	 * nil if a block context created hasn't received 'value'. */
	moo_oop_context_t  sender;
 
	/* SmallInteger, instruction pointer */
	moo_oop_t          ip;
 
	/* SmallInteger, stack pointer. the actual stack pointer is in the active
	 * process. For a method context, it stores the stack pointer of the active
	 * process before it gets activated. the stack pointer of the active 
	 * process is restored using this value upon returning. This field is
	 * almost useless for a block context. */
	moo_oop_t          sp;
 
	/* SmallInteger. Number of temporaries.
	 * For a block context, it's inclusive of the temporaries
	 * defined its 'home'. */
	moo_oop_t          ntmprs;
 
	/* CompiledMethod for a method context, 
	 * SmallInteger for a block context */
	moo_oop_t          method_or_nargs;
 
	/* it points to the receiver of the message for a method context.
	 * a base block context(created but not yet activated) has nil in this 
	 * field. if a block context is activated by 'value', it points 
	 * to the block context object used as a base for shallow-copy. */
	moo_oop_t          receiver_or_source;
 
	/* it is set to nil for a method context.
	 * for a block context, it points to the active context at the 
	 * moment the block context was created. that is, it points to 
	 * a method context where the base block has been defined. 
	 * an activated block context copies this field from the source. */
	moo_oop_t          home;
 
	/* when a method context is created, it is set to itself. no change is
	 * made when the method context is activated. when a block context is 
	 * created (when MAKE_BLOCK or BLOCK_COPY is executed), it is set to the
	 * origin of the active context. when the block context is shallow-copied
	 * for activation (when it is sent 'value'), it is set to the origin of
	 * the source block context. */
	moo_oop_context_t  origin; 
 
	/* variable indexed part - actual arguments and temporaries are placed here */
	moo_oop_t          slot[1]; /* stack */
};
 
 
#define MOO_PROCESS_NAMED_INSTVARS 12
typedef struct moo_process_t moo_process_t;
typedef struct moo_process_t* moo_oop_process_t;
 
#define MOO_SEMAPHORE_NAMED_INSTVARS 13
typedef struct moo_semaphore_t moo_semaphore_t;
typedef struct moo_semaphore_t* moo_oop_semaphore_t;
 
#define MOO_SEMAPHORE_GROUP_NAMED_INSTVARS 8
typedef struct moo_semaphore_group_t moo_semaphore_group_t;
typedef struct moo_semaphore_group_t* moo_oop_semaphore_group_t;
 
struct moo_process_t
{
	MOO_OBJ_HEADER;
	moo_oop_context_t   initial_context;
	moo_oop_context_t   current_context;
 
	moo_oop_t           id;    /* SmallInteger */
	moo_oop_t           state; /* SmallInteger */
	moo_oop_t           sp;    /* stack pointer. SmallInteger */
 
	struct
	{
		moo_oop_process_t   prev;
		moo_oop_process_t   next;
	} ps; /* links to use with the process scheduler */
 
	struct
	{
		moo_oop_process_t   prev;
		moo_oop_process_t   next;
	} sem_wait; /* links to use with a semaphore */
 
	moo_oop_t sem; /* nil, semaphore, or semaphore group */
	moo_oop_t perr; /* last error set by a primitive function */
	moo_oop_t perrmsg;
 
	/* == variable indexed part == */
	moo_oop_t slot[1]; /* process stack */
};
 
enum moo_semaphore_io_type_t 
{
	MOO_SEMAPHORE_IO_TYPE_INPUT   = 0,
	MOO_SEMAPHORE_IO_TYPE_OUTPUT  = 1
};
typedef enum moo_semaphore_io_type_t moo_semaphore_io_type_t;
 
enum moo_semaphore_io_mask_t
{
	MOO_SEMAPHORE_IO_MASK_INPUT   = (1 << 0),
	MOO_SEMAPHORE_IO_MASK_OUTPUT  = (1 << 1),
	MOO_SEMAPHORE_IO_MASK_HANGUP  = (1 << 2),
	MOO_SEMAPHORE_IO_MASK_ERROR   = (1 << 3)
};
typedef enum moo_semaphore_io_mask_t moo_semaphore_io_mask_t;
 
struct moo_semaphore_t
{
	MOO_OBJ_HEADER;
 
	/* [IMPORTANT] make sure that the position of 'waiting' in moo_semaphore_t
	 *             must be exactly the same as its position in moo_semaphore_group_t */
	struct
	{
		moo_oop_process_t first;
		moo_oop_process_t last;
	} waiting; /* list of processes waiting on this semaphore */
	/* [END IMPORTANT] */
 
	moo_oop_t count; /* SmallInteger */
 
	moo_oop_t heap_index; /* index to the heap */
	moo_oop_t heap_ftime_sec; /* firing time */
	moo_oop_t heap_ftime_nsec; /* firing time */
 
	moo_oop_t io_index; 
	moo_oop_t io_handle;
	moo_oop_t io_type; /* SmallInteger */
 
	moo_oop_t signal_action;
 
	moo_oop_semaphore_group_t group; /* nil or belonging semaphore group */
	struct
	{
		moo_oop_semaphore_t prev;
		moo_oop_semaphore_t next;
	} grm; /* group membership chain */
};
 
#define MOO_SEMAPHORE_GROUP_SEMS_UNSIG 0
#define MOO_SEMAPHORE_GROUP_SEMS_SIG   1
 
struct moo_semaphore_group_t
{
	MOO_OBJ_HEADER;
 
	/* [IMPORTANT] make sure that the position of 'waiting' in moo_semaphore_group_t
	 *             must be exactly the same as its position in moo_semaphore_t */
	struct
	{
		moo_oop_process_t first;
		moo_oop_process_t last; 
	} waiting; /* list of processes waiting on this semaphore group */
	/* [END IMPORTANT] */
 
	struct
	{
		moo_oop_semaphore_t first;
		moo_oop_semaphore_t last;
	} sems[2]; /* sems[0] - unsignaled semaphores, sems[1] - signaled semaphores */
 
	moo_oop_t sem_io_count; /* the number of io semaphores in the group */
	moo_oop_t sem_count; /* the total number of semaphores in the group */
};
 
#define MOO_PROCESS_SCHEDULER_NAMED_INSTVARS 9
typedef struct moo_process_scheduler_t moo_process_scheduler_t;
typedef struct moo_process_scheduler_t* moo_oop_process_scheduler_t;
struct moo_process_scheduler_t
{
	MOO_OBJ_HEADER;
	moo_oop_process_t active; /*  pointer to an active process in the runnable process list */
	moo_oop_t should_exit; /* Boolean */
	moo_oop_t total_count; /* SmallIntger, total number of processes - runnable/running/suspended */
 
	struct
	{
		moo_oop_t count; /* SmallInteger, the number of runnable/running processes */
		moo_oop_process_t first;
		moo_oop_process_t last;
	} runnable; /* runnable process list */
 
	struct
	{
		moo_oop_t count; /* SmallInteger - suspended*/
		moo_oop_process_t first;
		moo_oop_process_t last;
	} suspended;
};
 
/**
 * The MOO_CLASSOF() macro return the class of an object including a numeric
 * object encoded into a pointer.
 */
#define MOO_CLASSOF(moo,oop) \
	(MOO_OOP_GET_TAG(oop)? (*(moo)->tagged_classes[MOO_OOP_GET_TAG(oop)]): MOO_OBJ_GET_CLASS(oop))
 
/**
 * The MOO_BYTESOF() macro returns the size of the payload of
 * an object in bytes. If the pointer given encodes a numeric value, 
 * it returns the size of #moo_oow_t in bytes.
 */
#define MOO_BYTESOF(moo,oop) \
	(MOO_OOP_IS_NUMERIC(oop)? MOO_SIZEOF(moo_oow_t): MOO_OBJ_BYTESOF(oop))
 
 
typedef struct moo_heap_t moo_heap_t;
 
struct moo_heap_t
{
	moo_uint8_t* base;  /* start of a heap */
	moo_uint8_t* limit; /* end of a heap */
	moo_uint8_t* ptr;   /* next allocation pointer */
};
 
/* =========================================================================
 * MOO VM LOGGING
 * ========================================================================= */
 
enum moo_log_mask_t
{
	MOO_LOG_DEBUG      = (1u << 0),
	MOO_LOG_INFO       = (1u << 1),
	MOO_LOG_WARN       = (1u << 2),
	MOO_LOG_ERROR      = (1u << 3),
	MOO_LOG_FATAL      = (1u << 4),
 
	MOO_LOG_UNTYPED    = (1u << 6), /* only to be used by MOO_DEBUGx() and MOO_INFOx() */
	MOO_LOG_COMPILER   = (1u << 7),
	MOO_LOG_VM         = (1u << 8),
	MOO_LOG_MNEMONIC   = (1u << 9), /* bytecode mnemonic */
	MOO_LOG_GC         = (1u << 10),
	MOO_LOG_IC         = (1u << 11), /* instruction cycle, fetch-decode-execute */
	MOO_LOG_PRIMITIVE  = (1u << 12),
	MOO_LOG_APP        = (1u << 13), /* moo applications, set by moo logging primitive */
 
	MOO_LOG_ALL_LEVELS = (MOO_LOG_DEBUG  | MOO_LOG_INFO | MOO_LOG_WARN | MOO_LOG_ERROR | MOO_LOG_FATAL),
	MOO_LOG_ALL_TYPES  = (MOO_LOG_UNTYPED | MOO_LOG_COMPILER | MOO_LOG_VM | MOO_LOG_MNEMONIC | MOO_LOG_GC | MOO_LOG_IC | MOO_LOG_PRIMITIVE | MOO_LOG_APP),
 
 
	MOO_LOG_STDOUT     = (1u << 14), /* write log messages to stdout without timestamp. MOO_LOG_STDOUT wins over MOO_LOG_STDERR. */
	MOO_LOG_STDERR     = (1u << 15)  /* write log messages to stderr without timestamp. */
 
};
typedef enum moo_log_mask_t moo_log_mask_t;
 
typedef unsigned int moo_log_masks_t;
 
/* all bits must be set to get enabled */
#define MOO_LOG_ENABLED(moo,mask) (((moo)->option.log_mask & (mask)) == (mask))
 
#define MOO_LOG0(moo,mask,fmt) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt); } while(0)
#define MOO_LOG1(moo,mask,fmt,a1) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1); } while(0)
#define MOO_LOG2(moo,mask,fmt,a1,a2) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2); } while(0)
#define MOO_LOG3(moo,mask,fmt,a1,a2,a3) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3); } while(0)
#define MOO_LOG4(moo,mask,fmt,a1,a2,a3,a4) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3, a4); } while(0)
#define MOO_LOG5(moo,mask,fmt,a1,a2,a3,a4,a5) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3, a4, a5); } while(0)
#define MOO_LOG6(moo,mask,fmt,a1,a2,a3,a4,a5,a6) do { if (MOO_LOG_ENABLED(moo,mask)) moo_logbfmt(moo, mask, fmt, a1, a2, a3, a4, a5, a6); } while(0)
 
#if defined(MOO_BUILD_RELEASE)
	/* [NOTE]
	 *  get rid of debugging message totally regardless of
	 *  the log mask in the release build.
	 */
#	define MOO_DEBUG0(moo,fmt)
#	define MOO_DEBUG1(moo,fmt,a1)
#	define MOO_DEBUG2(moo,fmt,a1,a2)
#	define MOO_DEBUG3(moo,fmt,a1,a2,a3)
#	define MOO_DEBUG4(moo,fmt,a1,a2,a3,a4)
#	define MOO_DEBUG5(moo,fmt,a1,a2,a3,a4,a5)
#	define MOO_DEBUG6(moo,fmt,a1,a2,a3,a4,a5,a6)
#else
#	define MOO_DEBUG0(moo,fmt) MOO_LOG0(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt)
#	define MOO_DEBUG1(moo,fmt,a1) MOO_LOG1(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1)
#	define MOO_DEBUG2(moo,fmt,a1,a2) MOO_LOG2(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2)
#	define MOO_DEBUG3(moo,fmt,a1,a2,a3) MOO_LOG3(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3)
#	define MOO_DEBUG4(moo,fmt,a1,a2,a3,a4) MOO_LOG4(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4)
#	define MOO_DEBUG5(moo,fmt,a1,a2,a3,a4,a5) MOO_LOG5(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5)
#	define MOO_DEBUG6(moo,fmt,a1,a2,a3,a4,a5,a6) MOO_LOG6(moo, MOO_LOG_DEBUG | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6)
#endif
 
#define MOO_INFO0(moo,fmt) MOO_LOG0(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt)
#define MOO_INFO1(moo,fmt,a1) MOO_LOG1(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1)
#define MOO_INFO2(moo,fmt,a1,a2) MOO_LOG2(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2)
#define MOO_INFO3(moo,fmt,a1,a2,a3) MOO_LOG3(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3)
#define MOO_INFO4(moo,fmt,a1,a2,a3,a4) MOO_LOG4(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4)
#define MOO_INFO5(moo,fmt,a1,a2,a3,a4,a5) MOO_LOG5(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5)
#define MOO_INFO6(moo,fmt,a1,a2,a3,a4,a5,a6) MOO_LOG6(moo, MOO_LOG_INFO | MOO_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6)
 
 
/* =========================================================================
 * VIRTUAL MACHINE PRIMITIVES
 * ========================================================================= */
 
typedef void* (*moo_alloc_heap_t) (
	moo_t*    moo, 
	moo_oow_t size
);
 
typedef void (*moo_free_heap_t) (
	moo_t*    moo,
	void*     ptr
);
 
typedef void (*moo_log_write_t) (
	moo_t*             moo,
	moo_log_masks_t    mask,
	const moo_ooch_t*  msg,
	moo_oow_t          len
);
 
typedef void (*moo_syserrstrb_t) (
	moo_t*             moo,
	int                syserr,
	moo_bch_t*         buf,
	moo_oow_t          len
);
 
typedef void (*moo_syserrstru_t) (
	moo_t*             moo,
	int                syserr,
	moo_uch_t*         buf,
	moo_oow_t          len
);
 
enum moo_vmprim_dlopen_flag_t
{
	MOO_VMPRIM_DLOPEN_PFMOD = (1 << 0)
};
typedef enum moo_vmprim_dlopen_flag_t moo_vmprim_dlopen_flag_t;
 
typedef void* (*moo_vmprim_dlopen_t) (
	moo_t*                  moo,
	const moo_ooch_t*       name,
	int                     flags
);
 
typedef void (*moo_vmprim_dlclose_t) (
	moo_t*                  moo,
	void*                   handle
);
 
typedef void* (*moo_vmprimt_dlgetsym_t) (
	moo_t*                  moo,
	void*                   handle,
	const moo_ooch_t*       name
);
 
typedef int (*moo_vmprim_startup_t) (
	moo_t*                  moo
);
 
typedef void (*moo_vmprim_cleanup_t) (
	moo_t*                  moo
);
 
typedef void (*moo_vmprim_gettime_t) (
	moo_t*                  moo,
	moo_ntime_t*            now
);
 
typedef int (*moo_vmprim_muxadd_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle,
	moo_ooi_t               masks
);
 
typedef int (*moo_vmprim_muxmod_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle,
	moo_ooi_t               masks
);
 
typedef int (*moo_vmprim_muxdel_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle
);
 
typedef void (*moo_vmprim_muxwait_cb_t) (
	moo_t*                  moo,
	moo_ooi_t               io_handle,
	moo_ooi_t               masks
);
 
typedef void (*moo_vmprim_muxwait_t) (
	moo_t*                  moo,
	const moo_ntime_t*      duration,
	moo_vmprim_muxwait_cb_t muxwcb
);
 
typedef void (*moo_vmprim_sleep_t) (
	moo_t*                  moo,
	const moo_ntime_t*      duration
);
 
struct moo_vmprim_t
{
	moo_alloc_heap_t      alloc_heap;
	moo_free_heap_t       free_heap;
 
	moo_log_write_t        log_write;
	moo_syserrstrb_t       syserrstrb;
	moo_syserrstru_t       syserrstru;
 
	moo_vmprim_dlopen_t    dl_open;
	moo_vmprim_dlclose_t   dl_close;
	moo_vmprimt_dlgetsym_t dl_getsym;
 
	moo_vmprim_startup_t   vm_startup;
	moo_vmprim_cleanup_t   vm_cleanup;
	moo_vmprim_gettime_t   vm_gettime;
	moo_vmprim_muxadd_t    vm_muxadd;
	moo_vmprim_muxdel_t    vm_muxdel;
	moo_vmprim_muxmod_t    vm_muxmod;
	moo_vmprim_muxwait_t   vm_muxwait;
	moo_vmprim_sleep_t     vm_sleep;
};
 
typedef struct moo_vmprim_t moo_vmprim_t;
 
 
/* =========================================================================
 * CALLBACK MANIPULATION
 * ========================================================================= */
typedef void (*moo_cbimpl_t) (moo_t* moo);
 
typedef struct moo_cb_t moo_cb_t;
struct moo_cb_t
{
	moo_cbimpl_t gc;
	moo_cbimpl_t fini;
 
	/* private below */
	moo_cb_t*     prev;
	moo_cb_t*     next;
};
 
 
/* =========================================================================
 * PRIMITIVE FUNCTIONS
 * ========================================================================= */
enum moo_pfrc_t
{
	MOO_PF_HARD_FAILURE = -1,
	MOO_PF_FAILURE      = 0,
	MOO_PF_SUCCESS      = 1
};
typedef enum moo_pfrc_t moo_pfrc_t;
 
/* primitive function implementation type */
typedef moo_pfrc_t (*moo_pfimpl_t) (
	moo_t*    moo,
	moo_ooi_t nargs
);
 
typedef struct moo_pfbase_t moo_pfbase_t;
struct moo_pfbase_t
{
	moo_pfimpl_t handler;
	moo_oow_t    minargs;
	moo_oow_t    maxargs;
};
 
typedef struct moo_pfinfo_t moo_pfinfo_t;
struct moo_pfinfo_t
{
	moo_method_type_t type;
	moo_ooch_t        mthname[32];
	int               variadic;
	moo_pfbase_t      base;
};
 
 
/* receiver check failure leads to hard failure.
 * RATIONAL: the primitive handler should be used by relevant classes and
 *           objects only. if the receiver check fails, you must review
 *           your class library */
#define MOO_PF_CHECK_RCV(moo,cond) do { \
	if (!(cond)) { moo_seterrnum((moo), MOO_EMSGRCV); return MOO_PF_HARD_FAILURE; } \
} while(0)
 
/* argument check failure causes the wrapping method to return an error.
 * RATIONAL: Being a typeless language, it's hard to control the kinds of
 *           arguments.
 */
#define MOO_PF_CHECK_ARGS(moo,nargs,cond) do { \
	if (!(cond)) { moo_seterrnum (moo, MOO_EINVAL); return MOO_PF_FAILURE; } \
} while(0)
 
/* =========================================================================
 * MODULE MANIPULATION
 * ========================================================================= */
#define MOO_MOD_NAME_LEN_MAX 120
 
typedef struct moo_mod_t moo_mod_t;
 
enum moo_mod_hint_t
{
	MOO_MOD_LOAD_FOR_IMPORT = (1 << 0)
};
typedef enum moo_mod_hint_t moo_mod_hint_t;
 
typedef int (*moo_mod_load_t) (
	moo_t*     moo,
	moo_mod_t* mod
);
 
typedef int (*moo_mod_import_t) (
	moo_t*           moo,
	moo_mod_t*       mod,
	moo_oop_class_t  _class
);
 
typedef moo_pfbase_t* (*moo_mod_query_t) (
	moo_t*            moo,
	moo_mod_t*        mod,
	const moo_ooch_t* name,
	moo_oow_t         namelen
);
 
typedef void (*moo_mod_unload_t) (
	moo_t*     moo,
	moo_mod_t* mod
);
 
typedef void (*moo_mod_gc_t) (
	moo_t*     moo,
	moo_mod_t* mod
);
 
struct moo_mod_t
{
	/* input */
	moo_ooch_t   name[MOO_MOD_NAME_LEN_MAX + 1];
	void*        inctx;
	unsigned int hints; /* bitwised-ORed of moo_mod_hint_t enumerators */
 
	/* user-defined data */
	moo_mod_import_t import;
	moo_mod_query_t  query;
	moo_mod_unload_t unload;
	moo_mod_gc_t     gc;
	void*            ctx;
};
 
struct moo_mod_data_t 
{
	void*           handle;
	moo_rbt_pair_t* pair; /* internal backreference to moo->modtab */
	moo_mod_t       mod;
};
typedef struct moo_mod_data_t moo_mod_data_t;
 
struct moo_sbuf_t
{
	moo_ooch_t* ptr;
	moo_oow_t   len;
	moo_oow_t   capa;
};
typedef struct moo_sbuf_t moo_sbuf_t;
 
struct moo_sem_tuple_t
{
	moo_oop_semaphore_t sem[2]; /* [0] input, [1] output */
	moo_ooi_t handle; /* io handle */
	moo_ooi_t mask;
};
typedef struct moo_sem_tuple_t moo_sem_tuple_t;
 
typedef struct moo_finalizable_t moo_finalizable_t;
struct moo_finalizable_t
{
	moo_oop_t oop;
	moo_finalizable_t* prev;
	moo_finalizable_t* next;
};
 
/* special callback to be called for trailer */
typedef void (*moo_trgc_t) (moo_t* moo, moo_oop_t obj);
 
/* =========================================================================
 * MOO VM
 * ========================================================================= */
#if defined(MOO_INCLUDE_COMPILER)
typedef struct moo_compiler_t moo_compiler_t;
#endif
 
#define MOO_ERRMSG_CAPA (2048)
 
struct moo_t
{
	moo_mmgr_t*  mmgr;
	moo_cmgr_t*  cmgr;
	moo_errnum_t errnum;
	struct
	{
		union
		{
			moo_ooch_t ooch[MOO_ERRMSG_CAPA];
			moo_bch_t bch[MOO_ERRMSG_CAPA];
			moo_uch_t uch[MOO_ERRMSG_CAPA];
		} tmpbuf;
		moo_ooch_t buf[MOO_ERRMSG_CAPA];
		moo_oow_t len;
	} errmsg;
	int shuterr;
 
	struct
	{
		moo_traits_t trait;
		moo_log_masks_t log_mask;
		moo_oow_t log_maxcapa;
		moo_oow_t dfl_symtab_size;
		moo_oow_t dfl_sysdic_size;
		moo_oow_t dfl_procstk_size; 
 
		void* mod_inctx;
 
	#if defined(MOO_BUILD_DEBUG)
		/* set automatically when trait is set */
		moo_oow_t karatsuba_cutoff; 
	#endif
	} option;
 
	moo_vmprim_t vmprim;
 
	moo_cb_t* cblist;
	moo_rbt_t modtab; /* primitive module table */
 
	struct
	{
		moo_ooch_t* ptr;
		moo_oow_t len;
		moo_oow_t capa;
		moo_log_masks_t last_mask;
		moo_log_masks_t default_type_mask;
	} log;
 
	/* ========================= */
 
	moo_heap_t* permheap; /* TODO: put kernel objects to here */
	moo_heap_t* curheap;
	moo_heap_t* newheap;
 
	/* =============================================================
	 * nil, true, false
	 * ============================================================= */
	moo_oop_t _nil;  /* pointer to the nil object */
	moo_oop_t _true;
	moo_oop_t _false;
 
	/* =============================================================
	 * KERNEL CLASSES 
	 *  Be sure to Keep these kernel class pointers registered in the 
	 *  kernel_classes table in gc.c
	 * ============================================================= */
	moo_oop_class_t _apex; /* Apex */
	moo_oop_class_t _undefined_object; /* UndefinedObject */
	moo_oop_class_t _class; /* Class */
	moo_oop_class_t _object; /* Object */
	moo_oop_class_t _string; /* String */
 
	moo_oop_class_t _symbol; /* Symbol */
	moo_oop_class_t _array; /* Array */
	moo_oop_class_t _byte_array; /* ByteArray */
	moo_oop_class_t _symbol_set; /* SymbolSet */
	moo_oop_class_t _dictionary;
 
	moo_oop_class_t _namespace; /* Namespace */
	moo_oop_class_t _pool_dictionary; /* PoolDictionary */
	moo_oop_class_t _method_dictionary; /* MethodDictionary */
	moo_oop_class_t _method; /* CompiledMethod */
	moo_oop_class_t _association; /* Association */
 
	moo_oop_class_t _method_context; /* MethodContext */
	moo_oop_class_t _block_context; /* BlockContext */
	moo_oop_class_t _process; /* Process */
	moo_oop_class_t _semaphore; /* Semaphore */
	moo_oop_class_t _semaphore_group; /* SemaphoreGroup */
	moo_oop_class_t _process_scheduler; /* ProcessScheduler */
 
	moo_oop_class_t _error_class; /* Error */
	moo_oop_class_t _true_class; /* True */
	moo_oop_class_t _false_class; /* False */
	moo_oop_class_t _character; /* Character */
	moo_oop_class_t _small_integer; /* SmallInteger */
 
	moo_oop_class_t _large_positive_integer; /* LargePositiveInteger */
	moo_oop_class_t _large_negative_integer; /* LargeNegativeInteger */
 
	moo_oop_class_t _small_pointer;
	moo_oop_class_t _system;
	/* =============================================================
	 * END KERNEL CLASSES 
	 * ============================================================= */
 
	/* =============================================================
	 * KEY SYSTEM DICTIONARIES
	 * ============================================================= */
	/* 2 tag bits(lo) + 2 extended tag bits(hi). not all slots are used
	 * because the 2 high extended bits are used only if the low tag bits
	 * are 3 */
	moo_oop_class_t* tagged_classes[16]; 
 
	moo_oop_dic_t symtab; /* system-wide symbol table. instance of SymbolSet */
	moo_oop_nsdic_t sysdic; /* system dictionary. instance of Namespace */
	moo_oop_process_scheduler_t processor; /* instance of ProcessScheduler */
	moo_oop_process_t nil_process; /* instance of Process */
	moo_oop_char_t dicnewsym; /* symbol new: for dictionary */
	moo_oop_char_t dicputassocsym; /* symbol put_assoc: for dictionary */
 
	/* pending asynchronous semaphores */
	moo_oop_semaphore_t* sem_list;
	moo_oow_t sem_list_count;
	moo_oow_t sem_list_capa;
 
	/* semaphores sorted according to time-out. 
	 * organize entries using heap as the earliest entry
	 * needs to be checked first */
	moo_oop_semaphore_t* sem_heap;
	moo_oow_t sem_heap_count;
	moo_oow_t sem_heap_capa;
 
	/* semaphores for I/O handling. plain array */
	/*moo_oop_semaphore_t* sem_io;*/
	moo_sem_tuple_t* sem_io_tuple;
	moo_oow_t sem_io_tuple_count;
	moo_oow_t sem_io_tuple_capa;
 
	moo_oow_t sem_io_count;
	moo_oow_t sem_io_wait_count;
 
	moo_ooi_t* sem_io_map;
	moo_oow_t sem_io_map_capa;
 
	/* semaphore to notify finalizable objects */
	moo_oop_semaphore_t sem_gcfin;
	int sem_gcfin_sigreq;
 
	moo_oop_t* tmp_stack[256]; /* stack for temporaries */
	moo_oow_t tmp_count;
 
 
	moo_oop_t* proc_map;
	moo_oow_t proc_map_capa;
	moo_ooi_t proc_map_free_first;
	moo_ooi_t proc_map_free_last;
 
	/* =============================================================
	 * EXECUTION REGISTERS
	 * ============================================================= */
	moo_oop_context_t initial_context; /* fake initial context */
	moo_oop_context_t active_context;
	moo_oop_method_t active_method;
	moo_oob_t* active_code;
	moo_ooi_t sp;
	moo_ooi_t ip;
	int proc_switched; /* TODO: this is temporary. implement something else to skip immediate context switching */
	int switch_proc;
	int abort_req;
	moo_ntime_t exec_start_time;
	moo_ntime_t exec_end_time;
	/* =============================================================
	 * END EXECUTION REGISTERS
	 * ============================================================= */
 
	/* == BIGINT CONVERSION == */
	struct
	{
		int safe_ndigits;
		moo_oow_t multiplier;
	} bigint[37];
 
	struct
	{
		struct
		{
			moo_ooch_t* ptr;
			moo_oow_t capa;
			moo_oow_t len;
		} xbuf;
		struct
		{
			moo_liw_t* ptr;
			moo_oow_t capa;
		} t;
	} inttostr;
	/* == END BIGINT CONVERSION == */
 
	moo_sbuf_t sbuf[64];
 
	struct
	{
		moo_finalizable_t* first;
		moo_finalizable_t* last;
	} collectable;
 
	struct
	{
		moo_finalizable_t* first;
		moo_finalizable_t* last;
	} finalizable;
 
	moo_uintmax_t inst_counter;
	moo_ooi_t last_inst_pointer;
 
#if defined(MOO_INCLUDE_COMPILER)
	moo_compiler_t* c;
#endif
};
 
/* TODO: proper stack bound check when pushing */
#define MOO_STACK_PUSH(moo,v) \
	do { \
		(moo)->sp = (moo)->sp + 1; \
		MOO_ASSERT (moo, (moo)->sp < (moo_ooi_t)(MOO_OBJ_GET_SIZE((moo)->processor->active) - MOO_PROCESS_NAMED_INSTVARS)); \
		(moo)->processor->active->slot[(moo)->sp] = v; \
	} while(0)
 
#define MOO_STACK_GET(moo,v_sp) ((moo)->processor->active->slot[v_sp])
#define MOO_STACK_SET(moo,v_sp,v_obj) \
	do { \
		MOO_ASSERT (moo, (v_sp) < (moo_ooi_t)(MOO_OBJ_GET_SIZE((moo)->processor->active) - MOO_PROCESS_NAMED_INSTVARS)); \
		(moo)->processor->active->slot[v_sp] = v_obj; \
	} while(0)
 
#define MOO_STACK_GETTOP(moo) MOO_STACK_GET(moo, (moo)->sp)
#define MOO_STACK_SETTOP(moo,v_obj) MOO_STACK_SET(moo, (moo)->sp, v_obj)
 
#define MOO_STACK_POP(moo) ((moo)->sp = (moo)->sp - 1)
#define MOO_STACK_POPS(moo,count) ((moo)->sp = (moo)->sp - (count))
#define MOO_STACK_ISEMPTY(moo) ((moo)->sp <= -1)
 
/* get the stack pointer of the argument at the given index */
#define MOO_STACK_GETARGSP(moo,nargs,idx) ((moo)->sp - ((nargs) - (idx) - 1))
/* get the argument at the given index */
#define MOO_STACK_GETARG(moo,nargs,idx) MOO_STACK_GET(moo, (moo)->sp - ((nargs) - (idx) - 1))
/* get the receiver of a message */
#define MOO_STACK_GETRCV(moo,nargs) MOO_STACK_GET(moo, (moo)->sp - nargs)
 
/* you can't access arguments and receiver after these macros. 
 * also you must not call this macro more than once */
#define MOO_STACK_SETRET(moo,nargs,retv) \
	do { \
		MOO_STACK_POPS(moo, nargs); \
		MOO_STACK_SETTOP(moo, (retv)); \
	} while(0)
#define MOO_STACK_SETRETTORCV(moo,nargs) (MOO_STACK_POPS(moo, nargs))
#define MOO_STACK_SETRETTOERRNUM(moo,nargs) MOO_STACK_SETRET(moo, nargs, MOO_ERROR_TO_OOP(moo->errnum))
#define MOO_STACK_SETRETTOERROR(moo,nargs,ec) MOO_STACK_SETRET(moo, nargs, MOO_ERROR_TO_OOP(ec))
 
/* =========================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 * MOO ASSERTION
 * ========================================================================= */
#if defined(MOO_BUILD_RELEASE)
#	define MOO_ASSERT(moo,expr) ((void)0)
#else
#	define MOO_ASSERT(moo,expr) ((void)((expr) || (moo_assertfailed (moo, #expr, __FILE__, __LINE__), 0)))
#endif
 
 
#if defined(MOO_INCLUDE_COMPILER)
enum moo_iocmd_t
{
	MOO_IO_OPEN,
	MOO_IO_CLOSE,
	MOO_IO_READ
};
typedef enum moo_iocmd_t moo_iocmd_t;
 
struct moo_ioloc_t
{
	moo_oow_t line; /**< line */
	moo_oow_t colm; /**< column */
	const moo_ooch_t* file; /**< file specified in #include */
};
typedef struct moo_ioloc_t moo_ioloc_t;
 
typedef struct moo_ioarg_t moo_ioarg_t;
 
typedef moo_ooi_t (*moo_ioimpl_t) (
	moo_t*       moo,
	moo_iocmd_t  cmd,
	moo_ioarg_t* arg
);
 
enum moo_synerrnum_t
{
	MOO_SYNERR_NOERR,
	MOO_SYNERR_ILCHR,           /* illegal character */
	MOO_SYNERR_CMTNC,           /* comment not closed */
	MOO_SYNERR_STRNC,           /* string not closed */
	MOO_SYNERR_CLTNT,           /* character literal not terminated */
	MOO_SYNERR_HLTNT,           /* hashed literal not terminated */
	MOO_SYNERR_CHARLITINVAL,    /* wrong character literal */
	MOO_SYNERR_COLON,           /* : expected */
	MOO_SYNERR_STRING,          /* string expected */
	MOO_SYNERR_RADIXINVAL,      /* invalid radix */
	MOO_SYNERR_RADNUMLITINVAL,  /* invalid numeric literal with radix */
	MOO_SYNERR_BYTERANGE,       /* byte too small or too large */
	MOO_SYNERR_ERRLITINVAL,     /* wrong error literal */
	MOO_SYNERR_LBRACE,          /* { expected */
	MOO_SYNERR_RBRACE,          /* } expected */
	MOO_SYNERR_LPAREN,          /* ( expected */
	MOO_SYNERR_RPAREN,          /* ) expected */
	MOO_SYNERR_RBRACK,          /* ] expected */
	MOO_SYNERR_PERIOD,          /* . expected */
	MOO_SYNERR_COMMA,           /* , expected */
	MOO_SYNERR_VBAR,            /* | expected */
	MOO_SYNERR_GT,              /* > expected */
	MOO_SYNERR_ASSIGN,          /* := expected */
	MOO_SYNERR_IDENT,           /* identifier expected */
	MOO_SYNERR_INTEGER,         /* integer expected */
	MOO_SYNERR_PRIMITIVE,       /* primitive: expected */
	MOO_SYNERR_DIRECTIVEINVAL,  /* wrong directive */
	MOO_SYNERR_CLASSUNDEF,      /* undefined class */
	MOO_SYNERR_CLASSDUPL,       /* duplicate class */
	MOO_SYNERR_CLASSCONTRA,     /* contradictory class */
	MOO_SYNERR_CLASSNAMEINVAL,  /* wrong class name */
	MOO_SYNERR_NPINSTSIZEINVAL, /* invalid non-pointer instance size */
	MOO_SYNERR_INHERITBANNED,   /* prohibited inheritance */
	MOO_SYNERR_VARDCLBANNED,    /* variable declaration not allowed */
	MOO_SYNERR_MODIFIER,        /* modifier expected */
	MOO_SYNERR_MODIFIERINVAL,   /* wrong modifier */
	MOO_SYNERR_MODIFIERBANNED,  /* modifier not allowed */
	MOO_SYNERR_MODIFIERDUPL,    /* duplicate modifier */
	MOO_SYNERR_MTHNAME,         /* method name expected */
	MOO_SYNERR_MTHNAMEDUPL,     /* duplicate method name */
	MOO_SYNERR_VARIADMTHINVAL,  /* invalid variadic method definition */
	MOO_SYNERR_VARNAME,         /* variable name expected */
	MOO_SYNERR_ARGNAMEDUPL,     /* duplicate argument name */
	MOO_SYNERR_TMPRNAMEDUPL,    /* duplicate temporary variable name */
	MOO_SYNERR_VARNAMEDUPL,     /* duplicate variable name */
	MOO_SYNERR_BLKARGNAMEDUPL,  /* duplicate block argument name */
	MOO_SYNERR_VARUNDCL,        /* undeclared variable */
	MOO_SYNERR_VARUNUSE,        /* unsuable variable in compiled code */
	MOO_SYNERR_VARINACC,        /* inaccessible variable - e.g. accessing an instance variable from a class method is not allowed. */
	MOO_SYNERR_VARAMBIG,        /* ambiguious variable - e.g. the variable is found in multiple pool dictionaries imported */
	MOO_SYNERR_VARFLOOD,        /* too many instance/class variables */
	MOO_SYNERR_SELFINACC,       /* inaccessible self */
	MOO_SYNERR_PRIMARYINVAL,    /* wrong expression primary */
	MOO_SYNERR_TMPRFLOOD,       /* too many temporaries */
	MOO_SYNERR_ARGFLOOD,        /* too many arguments */
	MOO_SYNERR_BLKTMPRFLOOD,    /* too many block temporaries */
	MOO_SYNERR_BLKARGFLOOD,     /* too many block arguments */
	MOO_SYNERR_BLKFLOOD,        /* too large block */
	MOO_SYNERR_ARREXPFLOOD,     /* too large array expression */
	MOO_SYNERR_PFNUMINVAL,      /* wrong primitive function number */
	MOO_SYNERR_PFIDINVAL,       /* wrong primitive function identifier */
	MOO_SYNERR_PFARGDEFINVAL,   /* wrong primitive function argument definition */
	MOO_SYNERR_MODNAMEINVAL,    /* wrong module name */
	MOO_SYNERR_MODIMPFAIL,      /* failed to import module */
	MOO_SYNERR_INCLUDE,         /* #include error */
	MOO_SYNERR_PRAGMAINVAL,     /* wrong pragma name */
	MOO_SYNERR_NAMESPACEINVAL,  /* wrong namespace name */
	MOO_SYNERR_POOLDICINVAL,    /* wrong pool dictionary */
	MOO_SYNERR_POOLDICDUPL,     /* duplicate pool dictionary */
	MOO_SYNERR_LITERAL,         /* literal expected */
	MOO_SYNERR_NOTINLOOP,       /* break or continue not within a loop */
	MOO_SYNERR_INBLOCK,         /* break or continue within a block */
	MOO_SYNERR_WHILE            /* while expected */
};
typedef enum moo_synerrnum_t moo_synerrnum_t;
 
struct moo_synerr_t
{
	moo_synerrnum_t num;
	moo_ioloc_t     loc;
	moo_oocs_t      tgt;
};
typedef struct moo_synerr_t moo_synerr_t;
#endif
 
#if defined(__cplusplus)
extern "C" {
#endif
 
MOO_EXPORT moo_t* moo_open (
	moo_mmgr_t*         mmgr,
	moo_oow_t           xtnsize,
	moo_oow_t           heapsize,
	const moo_vmprim_t* vmprim,
	moo_errnum_t*       errnum
);
 
MOO_EXPORT void moo_close (
	moo_t* moo
);
 
MOO_EXPORT int moo_init (
	moo_t*              moo,
	moo_mmgr_t*         mmgr,
	moo_oow_t           heapsize,
	const moo_vmprim_t* vmprim
);
 
MOO_EXPORT void moo_fini (
	moo_t* moo
);
 
#if defined(MOO_HAVE_INLINE)
	static MOO_INLINE moo_mmgr_t* moo_getmmgr (moo_t* moo) { return moo->mmgr; }
	static MOO_INLINE void* moo_getxtn (moo_t* moo) { return (void*)(moo + 1); }
 
	static MOO_INLINE moo_cmgr_t* moo_getcmgr (moo_t* moo) { return moo->cmgr; }
	static MOO_INLINE void moo_setcmgr (moo_t* moo, moo_cmgr_t* cmgr) { moo->cmgr = cmgr; }
 
	static MOO_INLINE moo_errnum_t moo_geterrnum (moo_t* moo) { return moo->errnum; }
#else
#	define moo_getmmgr(moo) ((moo)->mmgr)
#	define moo_getxtn(moo) ((void*)((moo) + 1))
 
#	define moo_getcmgr(moo) ((moo)->cmgr)
#	define moo_setcmgr(moo,mgr) ((moo)->cmgr = (mgr))
 
#	define moo_geterrnum(moo) ((moo)->errnum)
#endif
 
MOO_EXPORT void moo_seterrnum (
	moo_t*       moo, 
	moo_errnum_t errnum
);
 
MOO_EXPORT void moo_seterrwithsyserr (
	moo_t* moo,
	int    syserr
);
 
MOO_EXPORT void moo_seterrbfmt (
	moo_t*           moo,
	moo_errnum_t     errnum,
	const moo_bch_t* fmt,
	...
);
 
MOO_EXPORT void moo_seterrufmt (
	moo_t*           moo,
	moo_errnum_t     errnum,
	const moo_uch_t* fmt,
	...
);
 
MOO_EXPORT const moo_ooch_t* moo_geterrstr (
	moo_t* moo
);
 
MOO_EXPORT const moo_ooch_t* moo_geterrmsg (
	moo_t* moo
);
 
MOO_EXPORT const moo_ooch_t* moo_backuperrmsg (
	moo_t* moo
);
 
/**
 * The moo_getoption() function gets the value of an option
 * specified by \a id into the buffer pointed to by \a value.
 *
 * \return 0 on success, -1 on failure
 */
MOO_EXPORT int moo_getoption (
	moo_t*        moo,
	moo_option_t  id,
	void*         value
);
 
/**
 * The moo_setoption() function sets the value of an option 
 * specified by \a id to the value pointed to by \a value.
 *
 * \return 0 on success, -1 on failure
 */
MOO_EXPORT int moo_setoption (
	moo_t*       moo,
	moo_option_t id,
	const void*   value
);
 
 
MOO_EXPORT moo_cb_t* moo_regcb (
	moo_t*    moo,
	moo_cb_t* tmpl
);
 
MOO_EXPORT void moo_deregcb (
	moo_t*    moo,
	moo_cb_t* cb
);
 
/**
 * The moo_gc() function performs garbage collection.
 * It is not affected by #MOO_NOGC.
 */
MOO_EXPORT void moo_gc (
	moo_t* moo
);
 
 
/**
 * The moo_moveoop() function moves an object and returns an updated pointer
 * after having moved. it must be called in the GC callback context only.
 */
MOO_EXPORT moo_oop_t moo_moveoop (
	moo_t*     moo,
	moo_oop_t  oop
);
 
/**
 * The moo_instantiate() function creates a new object instance of the class 
 * \a _class. The size of the fixed part is taken from the information
 * contained in the class defintion. The \a vlen parameter specifies the length
 * of the variable part. The \a vptr parameter points to the memory area to
 * copy into the variable part of the new object. If \a vptr is #MOO_NULL,
 * the variable part is initialized to 0 or an equivalent value depending
 * on the type. \a vptr is not used when the new instance is of the 
 * #MOO_OBJ_TYPE_OOP type.
 * 
 */
MOO_EXPORT moo_oop_t moo_instantiate (
	moo_t*           moo,
	moo_oop_class_t  _class,
	const void*      vptr,
	moo_oow_t        vlen
);
 
MOO_EXPORT moo_oop_t moo_instantiatewithtrailer (
	moo_t*           moo, 
	moo_oop_class_t  _class,
	moo_oow_t        vlen,
	const moo_oob_t* trptr,
	moo_oow_t        trlen
);
 
MOO_EXPORT moo_oop_t moo_shallowcopy (
	moo_t*          moo,
	moo_oop_t       oop
);
 
/**
 * The moo_ignite() function creates key initial objects.
 */
MOO_EXPORT int moo_ignite (
	moo_t* moo
);
 
/**
 * The moo_execute() function executes an activated context.
 */
MOO_EXPORT int moo_execute (
	moo_t* moo
);
 
/**
 * The moo_invoke() function sends a message named \a mthname to an object
 * named \a objname.
 */
MOO_EXPORT int moo_invoke (
	moo_t*            moo,
	const moo_oocs_t* objname,
	const moo_oocs_t* mthname
);
 
MOO_EXPORT void moo_abort (
	moo_t* moo
);
 
 
#if defined(MOO_HAVE_INLINE)
	static MOO_INLINE void moo_switchprocess(moo_t* moo) { moo->switch_proc = 1; }
#else
#	define moo_switchprocess(moo) ((moo)->switch_proc = 1)
#endif
 
/* =========================================================================
 * COMMON OBJECT MANAGEMENT FUNCTIONS
 * ========================================================================= */
MOO_EXPORT moo_oop_t moo_makesymbol (
	moo_t*             moo,
	const moo_ooch_t*  ptr,
	moo_oow_t          len
);
 
MOO_EXPORT moo_oop_t moo_makestringwithuchars (
	moo_t*            moo, 
	const moo_uch_t*  ptr, 
	moo_oow_t         len
);
 
MOO_EXPORT moo_oop_t moo_makestringwithbchars (
	moo_t*            moo, 
	const moo_bch_t*  ptr, 
	moo_oow_t         len
);
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_makestring(moo,ptr,len) moo_makestringwithuchars(moo,ptr,len)
#else
#	define moo_makestring(moo,ptr,len) moo_makestringwithbchars(moo,ptr,len)
#endif
 
MOO_EXPORT moo_oop_t moo_oowtoint (
	moo_t*    moo,
	moo_oow_t w
);
 
MOO_EXPORT moo_oop_t moo_ooitoint (
	moo_t*    moo,
	moo_ooi_t i
);
 
 
MOO_EXPORT int moo_inttooow (
	moo_t*     moo,
	moo_oop_t  x,
	moo_oow_t* w
);
 
MOO_EXPORT int moo_inttoooi (
	moo_t*     moo,
	moo_oop_t  x,
	moo_ooi_t* i
);
 
MOO_EXPORT moo_oop_t moo_findclass (
	moo_t*            moo,
	moo_oop_nsdic_t   nsdic,
	const moo_ooch_t* name
);
 
MOO_EXPORT int moo_iskindof (
	moo_t*          moo,
	moo_oop_t       obj,
	moo_oop_class_t _class
);
 
/* =========================================================================
 * TRAILER MANAGEMENT
 * ========================================================================= */
MOO_EXPORT int moo_setclasstrsize (
	moo_t*          moo,
	moo_oop_class_t _class,
	moo_oow_t       size,
	moo_trgc_t      trgc
);
 
MOO_EXPORT void* moo_getobjtrailer (
	moo_t*      moo,
	moo_oop_t   obj,
	moo_oow_t*  size
);
 
/* =========================================================================
 * TEMPORARY OOP MANAGEMENT FUNCTIONS
 * ========================================================================= */
MOO_EXPORT void moo_pushtmp (
	moo_t*     moo,
	moo_oop_t* oop_ptr
);
 
MOO_EXPORT void moo_poptmp (
	moo_t*     moo
);
 
MOO_EXPORT void moo_poptmps (
	moo_t*     moo,
	moo_oow_t  count
);
 
/* =========================================================================
 * SYSTEM MEMORY MANAGEMENT FUCNTIONS VIA MMGR
 * ========================================================================= */
MOO_EXPORT void* moo_allocmem (
	moo_t*     moo,
	moo_oow_t  size
);
 
MOO_EXPORT void* moo_callocmem (
	moo_t*     moo,
	moo_oow_t  size
);
 
MOO_EXPORT void* moo_reallocmem (
	moo_t*      moo,
	void*       ptr,
	moo_oow_t   size
);
 
MOO_EXPORT void moo_freemem (
	moo_t*  moo,
	void*   ptr
);
 
/* =========================================================================
 * PRIMITIVE METHOD MANIPULATION
 * ========================================================================= */
MOO_EXPORT int moo_genpfmethod (
	moo_t*            moo,
	moo_mod_t*        mod,
	moo_oop_class_t   _class,
	moo_method_type_t type,
	const moo_ooch_t* mthname,
	int               variadic,
	const moo_ooch_t* name
);
 
/*
MOO_EXPORT int moo_genpfmethods (
	moo_t*              moo,
	moo_mod_t*          mod,
	moo_oop_class_t     _class,
	const moo_pfinfo_t* pfinfo,
	moo_oow_t           pfcount
);
*/
 
MOO_EXPORT moo_pfbase_t* moo_findpfbase (
	moo_t*              moo,
	moo_pfinfo_t*       pfinfo,
	moo_oow_t           pfcount,
	const moo_ooch_t*   name,
	moo_oow_t           namelen
);
 
/* =========================================================================
 * STRING ENCODING CONVERSION
 * ========================================================================= */
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_convootobchars(moo,oocs,oocslen,bcs,bcslen) moo_convutobchars(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convbtooochars(moo,bcs,bcslen,oocs,oocslen) moo_convbtouchars(moo,bcs,bcslen,oocs,oocslen)
#	define moo_convootobcstr(moo,oocs,oocslen,bcs,bcslen) moo_convutobcstr(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convbtooocstr(moo,bcs,bcslen,oocs,oocslen) moo_convbtoucstr(moo,bcs,bcslen,oocs,oocslen)
#else
#	define moo_convootouchars(moo,oocs,oocslen,bcs,bcslen) moo_convbtouchars(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convutooochars(moo,bcs,bcslen,oocs,oocslen) moo_convutobchars(moo,bcs,bcslen,oocs,oocslen)
#	define moo_convootoucstr(moo,oocs,oocslen,bcs,bcslen) moo_convbtoucstr(moo,oocs,oocslen,bcs,bcslen)
#	define moo_convutooocstr(moo,bcs,bcslen,oocs,oocslen) moo_convutobcstr(moo,bcs,bcslen,oocs,oocslen)
#endif
 
MOO_EXPORT int moo_convbtouchars (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t*       bcslen,
	moo_uch_t*       ucs,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT int moo_convutobchars (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t*       ucslen,
	moo_bch_t*       bcs,
	moo_oow_t*       bcslen
);
 
 
/**
 * The moo_convbtoucstr() function converts a null-terminated byte string 
 * to a wide string.
 */
MOO_EXPORT int moo_convbtoucstr (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t*       bcslen,
	moo_uch_t*       ucs,
	moo_oow_t*       ucslen
);
 
 
/**
 * The moo_convutobcstr() function converts a null-terminated wide string
 * to a byte string.
 */
MOO_EXPORT int moo_convutobcstr (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t*       ucslen,
	moo_bch_t*       bcs,
	moo_oow_t*       bcslen
);
 
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_dupootobcharswithheadroom(moo,hrb,oocs,oocslen,bcslen) moo_duputobcharswithheadroom(moo,hrb,oocs,oocslen,bcslen)
#	define moo_dupbtooocharswithheadroom(moo,hrb,bcs,bcslen,oocslen) moo_dupbtoucharswithheadroom(moo,hrb,bcs,bcslen,oocslen)
#	define moo_dupootobchars(moo,oocs,oocslen,bcslen) moo_duputobchars(moo,oocs,oocslen,bcslen)
#	define moo_dupbtooochars(moo,bcs,bcslen,oocslen) moo_dupbtouchars(moo,bcs,bcslen,oocslen)
 
#	define moo_dupootobcstrwithheadroom(moo,hrb,oocs,bcslen) moo_duputobcstrwithheadroom(moo,hrb,oocs,bcslen)
#	define moo_dupbtooocstrwithheadroom(moo,hrb,bcs,oocslen) moo_dupbtoucstrwithheadroom(moo,hrb,bcs,oocslen)
#	define moo_dupootobcstr(moo,oocs,bcslen) moo_duputobcstr(moo,oocs,bcslen)
#	define moo_dupbtooocstr(moo,bcs,oocslen) moo_dupbtoucstr(moo,bcs,oocslen)
#else
#	define moo_dupootoucharswithheadroom(moo,hrb,oocs,oocslen,ucslen) moo_dupbtoucharswithheadroom(moo,hrb,oocs,oocslen,ucslen)
#	define moo_duputooocharswithheadroom(moo,hrb,ucs,ucslen,oocslen) moo_duputobcharswithheadroom(moo,hrb,ucs,ucslen,oocslen)
#	define moo_dupootouchars(moo,oocs,oocslen,ucslen) moo_dupbtouchars(moo,oocs,oocslen,ucslen)
#	define moo_duputooochars(moo,ucs,ucslen,oocslen) moo_duputobchars(moo,ucs,ucslen,oocslen)
 
#	define moo_dupootoucstrwithheadroom(moo,hrb,oocs,ucslen) moo_dupbtoucstrwithheadroom(moo,hrb,oocs,ucslen)
#	define moo_duputooocstrwithheadroom(moo,hrb,ucs,oocslen) moo_duputobcstrwithheadroom(moo,hrb,ucs,oocslen)
#	define moo_dupootoucstr(moo,oocs,ucslen) moo_dupbtoucstr(moo,oocs,ucslen)
#	define moo_duputooocstr(moo,ucs,oocslen) moo_duputobcstr(moo,ucs,oocslen)
#endif
 
 
MOO_EXPORT moo_uch_t* moo_dupbtoucharswithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_bch_t* bcs,
	moo_oow_t        bcslen,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT moo_bch_t* moo_duputobcharswithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_uch_t* ucs,
	moo_oow_t        ucslen,
	moo_oow_t*       bcslen
);
 
MOO_EXPORT moo_uch_t* moo_dupbtouchars (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t        bcslen,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT moo_bch_t* moo_duputobchars (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t        ucslen,
	moo_oow_t*       bcslen
);
 
 
MOO_EXPORT moo_uch_t* moo_dupbtoucstrwithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_bch_t* bcs,
	moo_oow_t*       ucslen
);
 
MOO_EXPORT moo_bch_t* moo_duputobcstrwithheadroom (
	moo_t*           moo,
	moo_oow_t        headroom_bytes,
	const moo_uch_t* ucs,
	moo_oow_t* bcslen
);
 
MOO_EXPORT moo_uch_t* moo_dupbtoucstr (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t*       ucslen /* optional: length of returned string */
);
 
MOO_EXPORT moo_bch_t* moo_duputobcstr (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t*       bcslen /* optional: length of returned string */
);
 
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_dupoochars(moo,oocs,oocslen) moo_dupuchars(moo,oocs,oocslen)
#else
#	define moo_dupoochars(moo,oocs,oocslen) moo_dupbchars(moo,oocs,oocslen)
#endif
 
MOO_EXPORT moo_uch_t* moo_dupuchars (
	moo_t*           moo,
	const moo_uch_t* ucs,
	moo_oow_t        ucslen
);
 
MOO_EXPORT moo_bch_t* moo_dupbchars (
	moo_t*           moo,
	const moo_bch_t* bcs,
	moo_oow_t        bcslen
);
 
 
/* =========================================================================
 * MOO VM LOGGING
 * ========================================================================= */
 
MOO_EXPORT moo_ooi_t moo_logbfmt (
	moo_t*           moo,
	moo_log_mask_t   mask,
	const moo_bch_t* fmt,
	...
);
 
MOO_EXPORT moo_ooi_t moo_logufmt (
	moo_t*            moo,
	moo_log_mask_t    mask,
	const moo_uch_t*  fmt,
	...
);
 
#if defined(MOO_OOCH_IS_UCH)
#	define moo_logoofmt moo_logufmt
#else
#	define moo_logoofmt moo_logbfmt
#endif
 
/* =========================================================================
 * MISCELLANEOUS HELPER FUNCTIONS
 * ========================================================================= */
 
MOO_EXPORT int moo_decode (
	moo_t*            moo,
	moo_oop_method_t  mth,
	const moo_oocs_t* classfqn
);
 
MOO_EXPORT void moo_assertfailed (
	moo_t*           moo,
	const moo_bch_t* expr,
	const moo_bch_t* file,
	moo_oow_t        line
);
 
MOO_EXPORT moo_errnum_t moo_syserr_to_errnum (
	int syserr
);
 
MOO_EXPORT const moo_ooch_t* moo_errnum_to_errstr (
	moo_errnum_t errnum
);
 
/**
 * The moo_releaseiohandle() function deletes resources associated with
 * the given IO handle. The resources include IO semaphores. You should call
 * this function before closing an IO handle.
 */
MOO_EXPORT void moo_releaseiohandle (
	moo_t*    moo,
	moo_ooi_t io_handle
);
 
#if defined(MOO_INCLUDE_COMPILER)
 
/* =========================================================================
 * COMPILER FUNCTIONS
 * ========================================================================= */
 
MOO_EXPORT int moo_compile (
	moo_t*       moo,
	moo_ioimpl_t io
);
 
MOO_EXPORT void moo_getsynerr (
	moo_t*        moo,
	moo_synerr_t* synerr
);
 
#endif
 
#if defined(__cplusplus)
}
#endif
 
 
#endif