3483 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3483 lines
		
	
	
		
			100 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|     Copyright (c) 2016-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 _HAK_H_
 | |
| #define _HAK_H_
 | |
| 
 | |
| #include <hak-cmn.h>
 | |
| #include <hak-rbt.h>
 | |
| #include <hak-xma.h>
 | |
| #include <stdarg.h>
 | |
| 
 | |
| /* TODO: move this macro out to the build files.... */
 | |
| #define HAK_INCLUDE_COMPILER
 | |
| 
 | |
| /* ========================================================================== */
 | |
| 
 | |
| typedef struct hak_mod_t hak_mod_t;
 | |
| 
 | |
| /* ========================================================================== */
 | |
| 
 | |
| struct hak_bloc_t
 | |
| {
 | |
| 	hak_oow_t line; /**< line */
 | |
| 	hak_oow_t colm; /**< column */
 | |
| 	const hak_bch_t* file; /**< file specified in #include */
 | |
| };
 | |
| typedef struct hak_bloc_t hak_bloc_t;
 | |
| 
 | |
| struct hak_uloc_t
 | |
| {
 | |
| 	hak_oow_t line; /**< line */
 | |
| 	hak_oow_t colm; /**< column */
 | |
| 	const hak_uch_t* file; /**< file specified in #include */
 | |
| };
 | |
| typedef struct hak_uloc_t hak_uloc_t;
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| typedef hak_uloc_t hak_loc_t;
 | |
| #else
 | |
| typedef hak_bloc_t hak_loc_t;
 | |
| #endif
 | |
| 
 | |
| /* ========================================================================== */
 | |
| 
 | |
| /**
 | |
|  * The hak_errnum_t type defines the error codes.
 | |
|  */
 | |
| enum hak_errnum_t
 | |
| {
 | |
| 	HAK_ENOERR,   /**< no error */
 | |
| 	HAK_EGENERIC, /**< generic error */
 | |
| 	HAK_ENOIMPL,  /**< not implemented */
 | |
| 	HAK_ESYSERR,  /**< subsystem error */
 | |
| 	HAK_EINTERN,  /**< internal error */
 | |
| 
 | |
| 	HAK_ESYSMEM,  /**< insufficient system memory */
 | |
| 	HAK_EOOMEM,   /**< insufficient object memory */
 | |
| 	HAK_ETYPE,    /**< invalid class/type */
 | |
| 	HAK_EINVAL,   /**< invalid parameter or data */
 | |
| 	HAK_ENOENT,   /**< data not found */
 | |
| 
 | |
| 	HAK_EEXIST,   /**< existing/duplicate data */
 | |
| 	HAK_EBUSY,
 | |
| 	HAK_EACCES,
 | |
| 	HAK_EPERM,
 | |
| 	HAK_ENOTDIR,
 | |
| 
 | |
| 	HAK_EINTR,
 | |
| 	HAK_EPIPE,
 | |
| 	HAK_EAGAIN,
 | |
| 	HAK_EBADHND,
 | |
| 	HAK_EFRMFLOOD,  /**< too many frames */
 | |
| 
 | |
| 	HAK_EMSGRCV,    /**< mesasge receiver error */
 | |
| 	HAK_EMSGSND,    /**< message sending error. even doesNotUnderstand: is not found */
 | |
| 	HAK_ENUMARGS,   /**< wrong number of arguments */
 | |
| 	HAK_ERANGE,     /**< range error. overflow and underflow */
 | |
| 	HAK_EBCFULL,    /**< byte-code full */
 | |
| 
 | |
| 	HAK_EDFULL,     /**< dictionary full */
 | |
| 	HAK_EPFULL,     /**< processor full */
 | |
| 	HAK_EFINIS,     /**< unexpected end of data/input/stream/etc */
 | |
| 	HAK_EFLOOD,     /**< too many items/data */
 | |
| 	HAK_EDIVBY0,    /**< divide by zero */
 | |
| 
 | |
| 	HAK_EIOERR,     /**< I/O error */
 | |
| 	HAK_EECERR,     /**< encoding conversion error */
 | |
| 	HAK_EBUFFULL,   /**< buffer full */
 | |
| 	HAK_ESYNERR,    /**< syntax error */
 | |
| 	HAK_ECALL,      /**< runtime error - cannot call */
 | |
| 	HAK_ECALLARG,   /**< runtime error - wrong number of arguments to call */
 | |
| 	HAK_ECALLRET,   /**< runtime error - wrong number of return variables to call */
 | |
| 	HAK_ESEMFLOOD,  /**< runtime error - too many semaphores */
 | |
| 	HAK_EEXCEPT,    /**< runtime error - exception not handled */
 | |
| 	HAK_ESTKOVRFLW, /**< runtime error - stack overflow */
 | |
| 	HAK_ESTKUNDFLW, /**< runtime error - stack overflow */
 | |
| 	HAK_EUNDEFVAR   /**< runtime error - undefined variable access */
 | |
| };
 | |
| typedef enum hak_errnum_t hak_errnum_t;
 | |
| /**/
 | |
| 
 | |
| enum hak_synerrnum_t
 | |
| {
 | |
| 	HAK_SYNERR_NOERR,
 | |
| 	HAK_SYNERR_INTERN,        /* internal error */
 | |
| 	HAK_SYNERR_CNODE,         /* unexpected compiler node */
 | |
| 	HAK_SYNERR_ILCHR,         /* illegal character */
 | |
| 	HAK_SYNERR_ILTOK,         /* invalid token */
 | |
| 	HAK_SYNERR_CMTNC,         /* comment not closed */
 | |
| 	HAK_SYNERR_CHARLIT,       /* wrong character literal */
 | |
| 	HAK_SYNERR_STRLIT,        /* wrong string literal */
 | |
| 	HAK_SYNERR_SYMLIT,        /* wrong symbol literal */
 | |
| 	HAK_SYNERR_NUMLIT ,       /* invalid numeric literal */
 | |
| 	HAK_SYNERR_NUMRANGE,      /* number range error */
 | |
| 	HAK_SYNERR_ERRLIT,        /* wrong error literal */
 | |
| 	HAK_SYNERR_SMPTRLIT,      /* wrong smptr literal */
 | |
| 	HAK_SYNERR_RADIX,         /* invalid radix for a numeric literal */
 | |
| 
 | |
| 	HAK_SYNERR_EOF,           /* sudden end of input */
 | |
| 	HAK_SYNERR_LPAREN,        /* ( expected */
 | |
| 	HAK_SYNERR_RPAREN,        /* ) expected */
 | |
| 	HAK_SYNERR_RBRACK,        /* ] expected */
 | |
| 	HAK_SYNERR_RBRACE,        /* } expected */
 | |
| 	HAK_SYNERR_VBAR,          /* | expected */
 | |
| 
 | |
| 	HAK_SYNERR_IDENT,         /* identifier expected */
 | |
| 	HAK_SYNERR_STRING,        /* string expected */
 | |
| 	HAK_SYNERR_BYTERANGE,     /* byte too small or too large */
 | |
| 	HAK_SYNERR_NESTING,       /* nesting level too deep */
 | |
| 
 | |
| 	HAK_SYNERR_COMMA,         /* , expected */
 | |
| 	HAK_SYNERR_VBARBANNED,    /* | disallowed */
 | |
| 	HAK_SYNERR_DOTBANNED,     /* . disallowed */
 | |
| 	HAK_SYNERR_COMMABANNED,   /* , disallowed */
 | |
| 	HAK_SYNERR_COLONBANNED,   /* : disallowed */
 | |
| 	HAK_SYNERR_COLONEQBANNED, /* := disallowed */
 | |
| 	HAK_SYNERR_COMMANOVALUE,  /* no value after , */
 | |
| 	HAK_SYNERR_COLONNOVALUE,  /* no value after : */
 | |
| 	HAK_SYNERR_NOVALUE,       /* missing value */
 | |
| 	HAK_SYNERR_NOSEP,         /* no separator between array/dictionary elements */
 | |
| 	HAK_SYNERR_INCLUDE,       /* #include error */
 | |
| 
 | |
| 	HAK_SYNERR_ELLIPSISBANNED, /* ... disallowed */
 | |
| 	HAK_SYNERR_TRPCOLONSBANNED, /* ::: disallowed */
 | |
| 	HAK_SYNERR_LOOPFLOOD,     /* loop body too big */
 | |
| 	HAK_SYNERR_IFFLOOD,       /* if body too big */
 | |
| 	HAK_SYNERR_BLKFLOOD,      /* block too big */
 | |
| 	HAK_SYNERR_BLKDEPTH,      /* block too deep */
 | |
| 	HAK_SYNERR_ARGNAMELIST,   /* argument name list expected */
 | |
| 	HAK_SYNERR_ARGNAME,       /* argument name expected */
 | |
| 	HAK_SYNERR_ARGNAMEDUP,    /* duplicate argument name  */
 | |
| 	HAK_SYNERR_VARNAME,       /* variable name expected */
 | |
| 	HAK_SYNERR_ARGCOUNT,      /* wrong number of arguments */
 | |
| 	HAK_SYNERR_ARGFLOOD,      /* too many arguments defined */
 | |
| 	HAK_SYNERR_VARFLOOD,      /* too many variables defined */
 | |
| 	HAK_SYNERR_VARDCLBANNED,  /* variable declaration disallowed */
 | |
| 	HAK_SYNERR_VARNAMEDUP,    /* duplicate variable name */
 | |
| 	HAK_SYNERR_VARNAMEUNKNOWN, /* unknown variable name */
 | |
| 
 | |
| 	HAK_SYNERR_BANNEDVARNAME, /* disallowed varible name */
 | |
| 	HAK_SYNERR_BANNEDARGNAME, /* disallowed argument name */
 | |
| 	HAK_SYNERR_BANNED,        /* prohibited */
 | |
| 
 | |
| 	HAK_SYNERR_CLASS,         /* invalid class definition */
 | |
| 	HAK_SYNERR_FUN,           /* invalid function definition */
 | |
| 	HAK_SYNERR_VAR,           /* invalid variable declaration */
 | |
| 	HAK_SYNERR_ELIF,          /* elif without if */
 | |
| 	HAK_SYNERR_ELSE,          /* else without if */
 | |
| 	HAK_SYNERR_CATCH,         /* catch outside try */
 | |
| 	HAK_SYNERR_BREAK,         /* break outside loop */
 | |
| 
 | |
| 	HAK_SYNERR_CALLABLE,      /* invalid callable */
 | |
| 	HAK_SYNERR_MESSAGE,       /* invalid message */
 | |
| 	HAK_SYNERR_UNBALKV,       /* unbalanced key/value pair */
 | |
| 	HAK_SYNERR_UNBALPBB,      /* unbalanced parenthesis/brace/bracket */
 | |
| 	HAK_SYNERR_SEMICOLON,     /* unexpected semicolon */
 | |
| 	HAK_SYNERR_BACKSLASH,     /* stray backslash */
 | |
| 	HAK_SYNERR_BLOCK,         /* block expression expected */
 | |
| 	HAK_SYNERR_BLOCKBANNED,   /* block expression disallowed */
 | |
| 	HAK_SYNERR_LVALUE,        /* invalid lvalue */
 | |
| 	HAK_SYNERR_RVALUE         /* invalid rvalue */
 | |
| };
 | |
| typedef enum hak_synerrnum_t hak_synerrnum_t;
 | |
| 
 | |
| 
 | |
| /* ========================================================================== */
 | |
| 
 | |
| #define HAK_ERRMSG_CAPA (2048)
 | |
| 
 | |
| /**
 | |
|  * The hak_errbinf_t type defines a placeholder for error information.
 | |
|  */
 | |
| struct hak_errbinf_t
 | |
| {
 | |
| 	hak_errnum_t num;                  /**< error number */
 | |
| 	hak_bch_t    msg[HAK_ERRMSG_CAPA]; /**< error message */
 | |
| 	hak_bloc_t   loc;                  /**< error location */
 | |
| };
 | |
| typedef struct hak_errbinf_t hak_errbinf_t;
 | |
| 
 | |
| struct hak_erruinf_t
 | |
| {
 | |
| 	hak_errnum_t num;                  /**< error number */
 | |
| 	hak_uch_t    msg[HAK_ERRMSG_CAPA]; /**< error message */
 | |
| 	hak_uloc_t   loc;                  /**< error location */
 | |
| };
 | |
| typedef struct hak_erruinf_t hak_erruinf_t;
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| typedef hak_erruinf_t hak_errinf_t;
 | |
| #else
 | |
| typedef hak_errbinf_t hak_errinf_t;
 | |
| #endif
 | |
| 
 | |
| /* ========================================================================== */
 | |
| 
 | |
| enum hak_option_t
 | |
| {
 | |
| 	HAK_TRAIT,
 | |
| 	HAK_LOG_MASK,
 | |
| 	HAK_LOG_MAXCAPA,
 | |
| 
 | |
| 	HAK_LOG_TARGET_BCSTR,
 | |
| 	HAK_LOG_TARGET_UCSTR,
 | |
| 	HAK_LOG_TARGET_BCS,
 | |
| 	HAK_LOG_TARGET_UCS,
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define HAK_LOG_TARGET HAK_LOG_TARGET_UCSTR
 | |
| #	define HAK_LOG_TARGET_OOCSTR HAK_LOG_TARGET_UCSTR
 | |
| #	define HAK_LOG_TARGET_OOCS HAK_LOG_TARGET_UCS
 | |
| #else
 | |
| #	define HAK_LOG_TARGET HAK_LOG_TARGET_BCSTR
 | |
| #	define HAK_LOG_TARGET_OOCSTR HAK_LOG_TARGET_BCSTR
 | |
| #	define HAK_LOG_TARGET_OOCS HAK_LOG_TARGET_BCS
 | |
| #endif
 | |
| 
 | |
| 	HAK_SYMTAB_SIZE,  /* default system table size */
 | |
| 	HAK_SYSDIC_SIZE,  /* default system dictionary size */
 | |
| 	HAK_PROCSTK_SIZE, /* default process stack size */
 | |
| 
 | |
| 	HAK_MOD_LIBDIRS,
 | |
| 	HAK_MOD_PREFIX,
 | |
| 	HAK_MOD_POSTFIX,
 | |
| 
 | |
| 	HAK_MOD_INCTX
 | |
| };
 | |
| typedef enum hak_option_t hak_option_t;
 | |
| 
 | |
| /* [NOTE] ensure that it is a power of 2 */
 | |
| #define HAK_LOG_CAPA_ALIGN 512
 | |
| 
 | |
| enum hak_option_dflval_t
 | |
| {
 | |
| 	HAK_DFL_LOG_MAXCAPA = HAK_LOG_CAPA_ALIGN * 16,
 | |
| 	HAK_DFL_SYMTAB_SIZE = 5000,
 | |
| 	HAK_DFL_SYSDIC_SIZE = 5000,
 | |
| 	HAK_DFL_PROCSTK_SIZE = 5000
 | |
| };
 | |
| typedef enum hak_option_dflval_t hak_option_dflval_t;
 | |
| 
 | |
| enum hak_trait_t
 | |
| {
 | |
| #if defined(HAK_BUILD_DEBUG)
 | |
| 	HAK_TRAIT_DEBUG_GC     = (((hak_bitmask_t)1) << 0),
 | |
| 	HAK_TRAIT_DEBUG_BIGINT = (((hak_bitmask_t)1) << 1),
 | |
| #endif
 | |
| 
 | |
| 	HAK_TRAIT_INTERACTIVE = (((hak_bitmask_t)1) << 7),
 | |
| 
 | |
| 	/* perform no garbage collection when the heap is full.
 | |
| 	 * you still can use hak_gc() explicitly. */
 | |
| 	HAK_TRAIT_NOGC = (((hak_bitmask_t)1) << 8),
 | |
| 
 | |
| 	/* wait for running process when exiting from the main method */
 | |
| 	HAK_TRAIT_AWAIT_PROCS = (((hak_bitmask_t)1) << 9),
 | |
| 
 | |
| 	/* return EOL as a token */ /* TODO: make this pragma controllable */
 | |
| 	HAK_TRAIT_LANG_ENABLE_EOL = (((hak_bitmask_t)1) << 14),
 | |
| 
 | |
| 	/* TODO: make this pragma controllable */
 | |
| 	HAK_TRAIT_LANG_LIBERAL = ((hak_bitmask_t)1) << 15
 | |
| };
 | |
| typedef enum hak_trait_t hak_trait_t;
 | |
| 
 | |
| /* =========================================================================
 | |
|  * SPECIALIZED OOP TYPES
 | |
|  * ========================================================================= */
 | |
| 
 | |
| /* hak_oop_t defined in hak-cmn.h
 | |
|  * hak_obj_t defined further down */
 | |
| 
 | |
| /* these are more specialized types for hak_obj_t */
 | |
| typedef struct hak_obj_oop_t       hak_obj_oop_t;
 | |
| typedef struct hak_obj_char_t      hak_obj_char_t;
 | |
| typedef struct hak_obj_byte_t      hak_obj_byte_t;
 | |
| typedef struct hak_obj_halfword_t  hak_obj_halfword_t;
 | |
| typedef struct hak_obj_word_t      hak_obj_word_t;
 | |
| 
 | |
| /* these are more specialized types for hak_oop_t */
 | |
| typedef struct hak_obj_oop_t*      hak_oop_oop_t;
 | |
| typedef struct hak_obj_char_t*     hak_oop_char_t;
 | |
| typedef struct hak_obj_byte_t*     hak_oop_byte_t;
 | |
| typedef struct hak_obj_halfword_t* hak_oop_halfword_t;
 | |
| typedef struct hak_obj_word_t*     hak_oop_word_t;
 | |
| 
 | |
| #define HAK_OOP_BITS  (HAK_SIZEOF_OOP_T * HAK_BITS_PER_BYTE)
 | |
| 
 | |
| #if defined(HAK_USE_OOW_FOR_LIW)
 | |
| 	typedef hak_oop_word_t     hak_oop_liword_t;
 | |
| #	define HAK_OBJ_TYPE_LIWORD HAK_OBJ_TYPE_WORD
 | |
| #else
 | |
| 	typedef hak_oop_halfword_t hak_oop_liword_t;
 | |
| #	define HAK_OBJ_TYPE_LIWORD HAK_OBJ_TYPE_HALFWORD
 | |
| #endif
 | |
| 
 | |
| /* =========================================================================
 | |
|  * HEADER FOR GC IMPLEMENTATION
 | |
|  * ========================================================================= */
 | |
| typedef struct hak_gchdr_t hak_gchdr_t;
 | |
| struct hak_gchdr_t
 | |
| {
 | |
|         hak_gchdr_t* next;
 | |
| };
 | |
| /* The size of hak_gchdr_t must be aligned to HAK_SIZEOF_OOP_T */
 | |
| 
 | |
| /* =========================================================================
 | |
|  * OBJECT STRUCTURE
 | |
|  * ========================================================================= */
 | |
| enum hak_obj_type_t
 | |
| {
 | |
| 	HAK_OBJ_TYPE_OOP,
 | |
| 	HAK_OBJ_TYPE_CHAR,
 | |
| 	HAK_OBJ_TYPE_BYTE,
 | |
| 	HAK_OBJ_TYPE_HALFWORD,
 | |
| 	HAK_OBJ_TYPE_WORD
 | |
| 
 | |
| /*
 | |
| 	HAK_OBJ_TYPE_UINT8,
 | |
| 	HAK_OBJ_TYPE_UINT16,
 | |
| 	HAK_OBJ_TYPE_UINT32,
 | |
| */
 | |
| 
 | |
| /* NOTE: you can have HAK_OBJ_SHORT, HAK_OBJ_INT
 | |
|  * HAK_OBJ_LONG, HAK_OBJ_FLOAT, HAK_OBJ_DOUBLE, etc
 | |
|  * type field being 6 bits long, you can have up to 64 different types.
 | |
| 
 | |
| 	HAK_OBJ_TYPE_SHORT,
 | |
| 	HAK_OBJ_TYPE_INT,
 | |
| 	HAK_OBJ_TYPE_LONG,
 | |
| 	HAK_OBJ_TYPE_FLOAT,
 | |
| 	HAK_OBJ_TYPE_DOUBLE */
 | |
| };
 | |
| typedef enum hak_obj_type_t hak_obj_type_t;
 | |
| 
 | |
| /* =========================================================================
 | |
|  * Object header structure
 | |
|  *
 | |
|  * _flags:
 | |
|  *   type: the type of a payload item.
 | |
|  *         one of HAK_OBJ_TYPE_OOP, HAK_OBJ_TYPE_CHAR,
 | |
|  *                HAK_OBJ_TYPE_BYTE, HAK_OBJ_TYPE_HALFWORD, HAK_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-char object. internel
 | |
|  *          use only.
 | |
|  *   kernel: 0 - ordinary object.
 | |
|  *           1 - kernel object. can survive hak_resetcode().
 | |
|  *           2 - kernel object. can survive hak_resetcode().
 | |
|  *               a symbol object with 2 in the kernel bits cannot be assigned a
 | |
|  *               value with the 'set' special form.
 | |
|  *   moved: 0 or 1. used by GC. internal use only.
 | |
|  *   ngc: 0 or 1, used by GC. internal use only.
 | |
|  *   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(hak_obj_t) + ALIGN((size + extra) * unit), sizeof(hak_oop_t))
 | |
|  *
 | |
|  * If the type is known to be not HAK_OBJ_TYPE_CHAR, you can assume that
 | |
|  * 'extra' is 0. So you can simplify the fomula in such a context.
 | |
|  *    sizeof(hak_obj_t) + ALIGN(size * unit), sizeof(hak_oop_t))
 | |
|  *
 | |
|  * The ALIGN() macro is used above since allocation adjusts the payload
 | |
|  * size to a multiple of sizeof(hak_oop_t). it assumes that sizeof(hak_obj_t)
 | |
|  * is a multiple of sizeof(hak_oop_t). See the HAK_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 HAK_OBJ_FLAGS_TYPE_BITS      (6) /* 6 */
 | |
| #define HAK_OBJ_FLAGS_UNIT_BITS      (5) /* 11 */
 | |
| #define HAK_OBJ_FLAGS_EXTRA_BITS     (1) /* 12 */
 | |
| #define HAK_OBJ_FLAGS_KERNEL_BITS    (2) /* 14 */
 | |
| #define HAK_OBJ_FLAGS_MOVED_BITS     (2) /* 16 */
 | |
| #define HAK_OBJ_FLAGS_NGC_BITS       (1) /* 17 */
 | |
| #define HAK_OBJ_FLAGS_TRAILER_BITS   (1) /* 18 */
 | |
| #define HAK_OBJ_FLAGS_CONCODE_BITS   (4) /* 22 - concode for cons */
 | |
| #define HAK_OBJ_FLAGS_FLEXI_BITS     (1) /* 23 */
 | |
| #define HAK_OBJ_FLAGS_RDONLY_BITS    (1) /* 24 */
 | |
| #define HAK_OBJ_FLAGS_PROC_BITS      (1) /* 25 */
 | |
| 
 | |
| /*
 | |
| #define HAK_OBJ_FLAGS_PERM_BITS       1
 | |
| #define HAK_OBJ_FLAGS_MOVED_BITS      2
 | |
| #define HAK_OBJ_FLAGS_GCFIN_BITS      4
 | |
| #define HAK_OBJ_FLAGS_TRAILER_BITS    1
 | |
| #define HAK_OBJ_FLAGS_HASH_BITS       2
 | |
| #define HAK_OBJ_FLAGS_UNCOPYABLE_BITS 1
 | |
| */
 | |
| 
 | |
| #define HAK_OBJ_FLAGS_TYPE_SHIFT        (HAK_OBJ_FLAGS_UNIT_BITS      + HAK_OBJ_FLAGS_UNIT_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_UNIT_SHIFT        (HAK_OBJ_FLAGS_EXTRA_BITS     + HAK_OBJ_FLAGS_EXTRA_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_EXTRA_SHIFT       (HAK_OBJ_FLAGS_KERNEL_BITS    + HAK_OBJ_FLAGS_KERNEL_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_KERNEL_SHIFT      (HAK_OBJ_FLAGS_MOVED_BITS     + HAK_OBJ_FLAGS_MOVED_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_MOVED_SHIFT       (HAK_OBJ_FLAGS_NGC_BITS       + HAK_OBJ_FLAGS_NGC_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_NGC_SHIFT         (HAK_OBJ_FLAGS_TRAILER_BITS   + HAK_OBJ_FLAGS_TRAILER_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_TRAILER_SHIFT     (HAK_OBJ_FLAGS_CONCODE_BITS   + HAK_OBJ_FLAGS_CONCODE_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_CONCODE_SHIFT     (HAK_OBJ_FLAGS_FLEXI_BITS     + HAK_OBJ_FLAGS_FLEXI_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_FLEXI_SHIFT       (HAK_OBJ_FLAGS_RDONLY_BITS    + HAK_OBJ_FLAGS_RDONLY_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_RDONLY_SHIFT      (HAK_OBJ_FLAGS_PROC_BITS      + HAK_OBJ_FLAGS_PROC_SHIFT)
 | |
| #define HAK_OBJ_FLAGS_PROC_SHIFT        (0)
 | |
| 
 | |
| #define HAK_OBJ_GET_FLAGS_TYPE(oop)        HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_TYPE_SHIFT,      HAK_OBJ_FLAGS_TYPE_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_UNIT(oop)        HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_UNIT_SHIFT,      HAK_OBJ_FLAGS_UNIT_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_EXTRA(oop)       HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_EXTRA_SHIFT,     HAK_OBJ_FLAGS_EXTRA_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_KERNEL(oop)      HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_KERNEL_SHIFT,    HAK_OBJ_FLAGS_KERNEL_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_MOVED(oop)       HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_MOVED_SHIFT,     HAK_OBJ_FLAGS_MOVED_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_NGC(oop)         HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_NGC_SHIFT,       HAK_OBJ_FLAGS_NGC_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_TRAILER(oop)     HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_TRAILER_SHIFT,   HAK_OBJ_FLAGS_TRAILER_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_CONCODE(oop)     HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_CONCODE_SHIFT,   HAK_OBJ_FLAGS_CONCODE_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_FLEXI(oop)       HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_FLEXI_SHIFT,     HAK_OBJ_FLAGS_FLEXI_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_RDONLY(oop)      HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_RDONLY_SHIFT,    HAK_OBJ_FLAGS_RDONLY_BITS)
 | |
| #define HAK_OBJ_GET_FLAGS_PROC(oop)        HAK_GETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_PROC_SHIFT,      HAK_OBJ_FLAGS_PROC_BITS)
 | |
| 
 | |
| #define HAK_OBJ_SET_FLAGS_TYPE(oop,v)      HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_TYPE_SHIFT,      HAK_OBJ_FLAGS_TYPE_BITS,      v)
 | |
| #define HAK_OBJ_SET_FLAGS_UNIT(oop,v)      HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_UNIT_SHIFT,      HAK_OBJ_FLAGS_UNIT_BITS,      v)
 | |
| #define HAK_OBJ_SET_FLAGS_EXTRA(oop,v)     HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_EXTRA_SHIFT,     HAK_OBJ_FLAGS_EXTRA_BITS,     v)
 | |
| #define HAK_OBJ_SET_FLAGS_KERNEL(oop,v)    HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_KERNEL_SHIFT,    HAK_OBJ_FLAGS_KERNEL_BITS,    v)
 | |
| #define HAK_OBJ_SET_FLAGS_MOVED(oop,v)     HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_MOVED_SHIFT,     HAK_OBJ_FLAGS_MOVED_BITS,     v)
 | |
| #define HAK_OBJ_SET_FLAGS_NGC(oop,v)       HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_NGC_SHIFT,       HAK_OBJ_FLAGS_NGC_BITS,       v)
 | |
| #define HAK_OBJ_SET_FLAGS_TRAILER(oop,v)   HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_TRAILER_SHIFT,   HAK_OBJ_FLAGS_TRAILER_BITS,   v)
 | |
| #define HAK_OBJ_SET_FLAGS_CONCODE(oop,v)   HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_CONCODE_SHIFT,   HAK_OBJ_FLAGS_CONCODE_BITS,   v)
 | |
| #define HAK_OBJ_SET_FLAGS_FLEXI(oop,v)     HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_FLEXI_SHIFT,     HAK_OBJ_FLAGS_FLEXI_BITS, v)
 | |
| #define HAK_OBJ_SET_FLAGS_RDONLY(oop,v)    HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_RDONLY_SHIFT,    HAK_OBJ_FLAGS_RDONLY_BITS, v)
 | |
| #define HAK_OBJ_SET_FLAGS_PROC(oop,v)      HAK_SETBITS(hak_oow_t, (oop)->_flags, HAK_OBJ_FLAGS_PROC_SHIFT,      HAK_OBJ_FLAGS_PROC_BITS, v)
 | |
| 
 | |
| /* [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 HAK_OBJ_MAKE_FLAGS(t,u,e,k,m,g,r) ( \
 | |
| 	(((hak_oow_t)(t)) << HAK_OBJ_FLAGS_TYPE_SHIFT) | \
 | |
| 	(((hak_oow_t)(u)) << HAK_OBJ_FLAGS_UNIT_SHIFT) | \
 | |
| 	(((hak_oow_t)(e)) << HAK_OBJ_FLAGS_EXTRA_SHIFT) | \
 | |
| 	(((hak_oow_t)(k)) << HAK_OBJ_FLAGS_KERNEL_SHIFT) | \
 | |
| 	(((hak_oow_t)(m)) << HAK_OBJ_FLAGS_MOVED_SHIFT) | \
 | |
| 	(((hak_oow_t)(g)) << HAK_OBJ_FLAGS_NGC_SHIFT) | \
 | |
| 	(((hak_oow_t)(r)) << HAK_OBJ_FLAGS_TRAILER_SHIFT) \
 | |
| )
 | |
| 
 | |
| #define HAK_OBJ_FLAGS_KERNEL_USER     0  /* not a kernel object */
 | |
| #define HAK_OBJ_FLAGS_KERNEL_IMMATURE 1  /* incomplete kernel object. defined in gc.c for bootstrapping. but no complete class definition has been read */
 | |
| #define HAK_OBJ_FLAGS_KERNEL_MATURE   2  /* kernel  object with its full class defintion read in */
 | |
| 
 | |
| #define HAK_OBJ_GET_SIZE(oop) ((oop)->_size)
 | |
| #define HAK_OBJ_GET_CLASS(oop) ((oop)->_class)
 | |
| 
 | |
| #define HAK_OBJ_SET_SIZE(oop,v) ((oop)->_size = (v))
 | |
| #define HAK_OBJ_SET_CLASS(oop,c) ((oop)->_class = (c))
 | |
| 
 | |
| /* [NOTE] this macro doesn't include the size of the trailer */
 | |
| #define HAK_OBJ_BYTESOF(oop) ((HAK_OBJ_GET_SIZE(oop) + HAK_OBJ_GET_FLAGS_EXTRA(oop)) * HAK_OBJ_GET_FLAGS_UNIT(oop))
 | |
| 
 | |
| #define HAK_OBJ_IS_OOP_POINTER(oop)      (HAK_OOP_IS_POINTER(oop) && (HAK_OBJ_GET_FLAGS_TYPE(oop) == HAK_OBJ_TYPE_OOP))
 | |
| #define HAK_OBJ_IS_CHAR_POINTER(oop)     (HAK_OOP_IS_POINTER(oop) && (HAK_OBJ_GET_FLAGS_TYPE(oop) == HAK_OBJ_TYPE_CHAR))
 | |
| #define HAK_OBJ_IS_BYTE_POINTER(oop)     (HAK_OOP_IS_POINTER(oop) && (HAK_OBJ_GET_FLAGS_TYPE(oop) == HAK_OBJ_TYPE_BYTE))
 | |
| #define HAK_OBJ_IS_HALFWORD_POINTER(oop) (HAK_OOP_IS_POINTER(oop) && (HAK_OBJ_GET_FLAGS_TYPE(oop) == HAK_OBJ_TYPE_HALFWORD))
 | |
| #define HAK_OBJ_IS_WORD_POINTER(oop)     (HAK_OOP_IS_POINTER(oop) && (HAK_OBJ_GET_FLAGS_TYPE(oop) == HAK_OBJ_TYPE_WORD))
 | |
| 
 | |
| #define HAK_STORE_OOP(hak,var,val) (*(var) = val)
 | |
| 
 | |
| #define HAK_OBJ_HEADER \
 | |
| 	hak_oow_t _flags; \
 | |
| 	hak_oow_t _size; \
 | |
| 	hak_oop_t _class
 | |
| 
 | |
| struct hak_obj_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| };
 | |
| 
 | |
| struct hak_obj_oop_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oop_t slot[1];
 | |
| };
 | |
| 
 | |
| struct hak_obj_char_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_ooch_t slot[1];
 | |
| };
 | |
| 
 | |
| struct hak_obj_byte_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oob_t slot[1];
 | |
| };
 | |
| 
 | |
| struct hak_obj_halfword_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oohw_t slot[1];
 | |
| };
 | |
| 
 | |
| struct hak_obj_word_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oow_t slot[1];
 | |
| };
 | |
| 
 | |
| #define HAK_OBJ_GET_OOP_SLOT(oop)      (((hak_oop_oop_t)(oop))->slot)
 | |
| #define HAK_OBJ_GET_CHAR_SLOT(oop)     (((hak_oop_char_t)(oop))->slot)
 | |
| #define HAK_OBJ_GET_BYTE_SLOT(oop)     (((hak_oop_byte_t)(oop))->slot)
 | |
| #define HAK_OBJ_GET_HALFWORD_SLOT(oop) (((hak_oop_halfword_t)(oop))->slot)
 | |
| #define HAK_OBJ_GET_WORD_SLOT(oop)     (((hak_oop_word_t)(oop))->slot)
 | |
| #define HAK_OBJ_GET_LIWORD_SLOT(oop)   (((hak_oop_liword_t)(oop))->slot)
 | |
| 
 | |
| #define HAK_OBJ_GET_OOP_PTR(oop,idx)      (&(((hak_oop_oop_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_CHAR_PTR(oop,idx)     (&(((hak_oop_char_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_BYTE_PTR(oop,idx)     (&(((hak_oop_byte_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_HALFWORD_PTR(oop,idx) (&(((hak_oop_halfword_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_WORD_PTR(oop,idx)     (&(((hak_oop_word_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_LIWORD_PTR(oop,idx)   (&(((hak_oop_liword_t)(oop))->slot)[idx])
 | |
| 
 | |
| #define HAK_OBJ_GET_OOP_VAL(oop,idx)      ((((hak_oop_oop_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_CHAR_VAL(oop,idx)     ((((hak_oop_char_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_BYTE_VAL(oop,idx)     ((((hak_oop_byte_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_HALFWORD_VAL(oop,idx) ((((hak_oop_halfword_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_WORD_VAL(oop,idx)     ((((hak_oop_word_t)(oop))->slot)[idx])
 | |
| #define HAK_OBJ_GET_LIWORD_VAL(oop,idx)   ((((hak_oop_liword_t)(oop))->slot)[idx])
 | |
| 
 | |
| #define HAK_OBJ_SET_OOP_VAL(oop,idx,val)      ((((hak_oop_oop_t)(oop))->slot)[idx] = (val))
 | |
| #define HAK_OBJ_SET_CHAR_VAL(oop,idx,val)     ((((hak_oop_char_t)(oop))->slot)[idx] = (val))
 | |
| #define HAK_OBJ_SET_BYTE_VAL(oop,idx,val)     ((((hak_oop_byte_t)(oop))->slot)[idx] = (val))
 | |
| #define HAK_OBJ_SET_HALFWORD_VAL(oop,idx,val) ((((hak_oop_halfword_t)(oop))->slot)[idx] = (val))
 | |
| #define HAK_OBJ_SET_WORD_VAL(oop,idx,val)     ((((hak_oop_word_t)(oop))->slot)[idx] = (val))
 | |
| #define HAK_OBJ_SET_LIWORD_VAL(oop,idx,val)   ((((hak_oop_liword_t)(oop))->slot)[idx] = (val))
 | |
| 
 | |
| typedef struct hak_trailer_t hak_trailer_t;
 | |
| struct hak_trailer_t
 | |
| {
 | |
| 	hak_oow_t size;
 | |
| 	hak_oob_t slot[1];
 | |
| };
 | |
| 
 | |
| #define HAK_OBJ_GET_TRAILER_BYTE(oop) ((hak_oob_t*)&((hak_oop_oop_t)oop)->slot[HAK_OBJ_GET_SIZE(oop) + 1])
 | |
| #define HAK_OBJ_GET_TRAILER_SIZE(oop) ((hak_oow_t)((hak_oop_oop_t)oop)->slot[HAK_OBJ_GET_SIZE(oop)])
 | |
| 
 | |
| #define HAK_PRIM_NAMED_INSTVARS 4
 | |
| typedef struct hak_prim_t hak_prim_t;
 | |
| typedef struct hak_prim_t* hak_oop_prim_t;
 | |
| struct hak_prim_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oow_t impl;
 | |
| 	hak_oow_t min_nargs;
 | |
| 	hak_oow_t max_nargs;
 | |
| 	hak_oow_t mod;
 | |
| };
 | |
| 
 | |
| #define HAK_CONS_NAMED_INSTVARS 2
 | |
| typedef struct hak_cons_t hak_cons_t;
 | |
| typedef struct hak_cons_t* hak_oop_cons_t;
 | |
| struct hak_cons_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oop_t car;
 | |
| 	hak_oop_t cdr;
 | |
| };
 | |
| 
 | |
| #define HAK_DIC_NAMED_INSTVARS 2
 | |
| typedef struct hak_dic_t hak_dic_t;
 | |
| typedef struct hak_dic_t* hak_oop_dic_t;
 | |
| struct hak_dic_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oop_t     tally;  /* SmallInteger */
 | |
| 	hak_oop_oop_t bucket; /* Array */
 | |
| };
 | |
| 
 | |
| #define HAK_FPDEC_NAMED_INSTVARS 2
 | |
| typedef struct hak_fpdec_t hak_fpdec_t;
 | |
| typedef struct hak_fpdec_t* hak_oop_fpdec_t;
 | |
| struct hak_fpdec_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oop_t value; /* smooi or bigint */
 | |
| 	hak_oop_t scale; /* smooi, positive */
 | |
| };
 | |
| 
 | |
| /* the first byte after the main payload is the trailer size
 | |
|  * the code bytes are placed after the trailer size.
 | |
|  *
 | |
|  * code bytes -> ((hak_oob_t*)&((hak_oop_oop_t)m)->slot[HAK_OBJ_GET_SIZE(m) + 1]) or
 | |
|  *               ((hak_oob_t*)&((hak_oop_function_t)m)->literal_frame[HAK_OBJ_GET_SIZE(m) + 1 - HAK_METHOD_NAMED_INSTVARS])
 | |
|  * size -> ((hak_oow_t)((hak_oop_oop_t)m)->slot[HAK_OBJ_GET_SIZE(m)])*/
 | |
| #define HAK_FUNCTION_GET_CODE_BYTE(m) HAK_OBJ_GET_TRAILER_BYTE(m)
 | |
| #define HAK_FUNCTION_GET_CODE_SIZE(m) HAK_OBJ_GET_TRAILER_SIZE(m)
 | |
| 
 | |
| #define HAK_FUNCTION_NAMED_INSTVARS 5   /* this excludes literal frames and byte codes */
 | |
| typedef struct hak_function_t hak_function_t;
 | |
| typedef struct hak_function_t* hak_oop_function_t;
 | |
| 
 | |
| #define HAK_BLOCK_NAMED_INSTVARS 4
 | |
| typedef struct hak_block_t hak_block_t;
 | |
| typedef struct hak_block_t* hak_oop_block_t;
 | |
| 
 | |
| #define HAK_CONTEXT_NAMED_INSTVARS 11
 | |
| typedef struct hak_context_t hak_context_t;
 | |
| typedef struct hak_context_t* hak_oop_context_t;
 | |
| 
 | |
| struct hak_function_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	hak_oop_t         attr_mask; /* smooi */
 | |
| 	hak_oop_t         name; /* symbol or nil */
 | |
| 	hak_oop_context_t home; /* home context. nil for the initial function */
 | |
| 
 | |
| 	hak_oop_t dbgi; /* byte array containing debug information. nil if not available */
 | |
| 	hak_oop_t literal_frame_size;
 | |
| 
 | |
| 	/* == variable indexed part == */
 | |
| 	hak_oop_t literal_frame[1]; /* it stores literals. it may not exist */
 | |
| 
 | |
| 	/* after the literal frame comes the actual byte code */
 | |
| };
 | |
| 
 | |
| /* hak_function_t copies the byte codes and literal frames into itself
 | |
|  * hak_block_t contains minimal information(ip) for referening byte codes
 | |
|  * and literal frames available in home->origin. it represents the compiled block.
 | |
|  */
 | |
| struct hak_block_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	hak_oop_t         attr_mask; /* smooi */
 | |
| 	hak_oop_t         name; /* symbol or nil */
 | |
| 	hak_oop_context_t home; /* home context */
 | |
| 	hak_oop_t         ip; /* smooi. instruction pointer where the byte code begins in home->base */
 | |
| };
 | |
| 
 | |
| struct hak_context_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	/* SmallInteger */
 | |
| 	hak_oop_t          req_nrets;
 | |
| 
 | |
| 	/* SmallInteger. */
 | |
| 	hak_oop_t          attr_mask;
 | |
| 	hak_oop_t          name; /* symbol or nil. copied from the compiled block.  TODO: is it better to maintain the backward pointer to the compiled block itself? */
 | |
| 
 | |
| 	/* SmallInteger, instruction pointer */
 | |
| 	hak_oop_t          ip;
 | |
| 
 | |
| 	/* the initial context is created with the initial function object in this field.
 | |
| 	 * a function-based context is created with the activating function object.
 | |
| 	 * a block-based context is created with the function object that the base field of
 | |
| 	 * the home context of the activating block context points to. */
 | |
| 	hak_oop_function_t base; /* function */
 | |
| 
 | |
| 	/* 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'. */
 | |
| 	hak_oop_context_t  sender; /* context or nil */
 | |
| 
 | |
| 	/* it points to the receiver of the message for a method context.
 | |
| 	 * a block context points to a block object and a function context
 | |
| 	 * points to a function object */
 | |
| 	hak_oop_t          receiver;
 | |
| 
 | |
| 	/* 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 base block context. */
 | |
| 	hak_oop_context_t  home; /* context or nil */
 | |
| 
 | |
| 	/* it is set to itself for a method context, nil for other contexts.
 | |
| 	 * TODO: this field may not be needed.. mthhome access has been commented out.. so remove this field */
 | |
| 	hak_oop_context_t mthhome;
 | |
| 
 | |
| 	/* instance variable access instructions hold the index to a variable within
 | |
| 	 * the the containing class. If the class inherits from a superclass and the
 | |
| 	 * superclass chain contains instance variables, the actual index must be
 | |
| 	 * added with the number of instance variables in the superclass chain.
 | |
| 	 *
 | |
| 	 * for example, the following instruction accesses the instance variable slot
 | |
| 	 * at index 3. if the class of the instance has 4 instance variables in the
 | |
| 	 * superclass side, the method context activated has 4 in thie field.
 | |
| 	 * therefore, the instruction accesses the instance variable slot at index 7.
 | |
| 	 *   push_ivar 3
 | |
| 	 * the debug output shows this instruction as "push_ivar 3; [4]"
 | |
| 	 */
 | |
| 	hak_oop_t          ivaroff;
 | |
| 
 | |
| 	/* method owner if this context is created of a message send. nil otherwise */
 | |
| 	hak_oop_t          owner;  /* class(hak_oop_class_t) or nil */
 | |
| 
 | |
| 	/* variable indexed part */
 | |
| 	hak_oop_t          slot[1]; /* arguments, return variables, local variables, other arguments, etc */
 | |
| };
 | |
| 
 | |
| #define HAK_PROCESS_NAMED_INSTVARS (15)
 | |
| typedef struct hak_process_t hak_process_t;
 | |
| typedef struct hak_process_t* hak_oop_process_t;
 | |
| 
 | |
| #define HAK_SEMAPHORE_NAMED_INSTVARS (11)
 | |
| typedef struct hak_semaphore_t hak_semaphore_t;
 | |
| typedef struct hak_semaphore_t* hak_oop_semaphore_t;
 | |
| 
 | |
| #define HAK_SEMAPHORE_GROUP_NAMED_INSTVARS (8)
 | |
| typedef struct hak_semaphore_group_t hak_semaphore_group_t;
 | |
| typedef struct hak_semaphore_group_t* hak_oop_semaphore_group_t;
 | |
| 
 | |
| 
 | |
| #define HAK_PROCESS_STATE_RUNNING (3)
 | |
| #define HAK_PROCESS_STATE_WAITING (2)
 | |
| #define HAK_PROCESS_STATE_RUNNABLE (1)
 | |
| #define HAK_PROCESS_STATE_SUSPENDED (0)
 | |
| #define HAK_PROCESS_STATE_TERMINATED (-1)
 | |
| 
 | |
| struct hak_process_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 	hak_oop_context_t initial_context;
 | |
| 	hak_oop_context_t current_context;
 | |
| 
 | |
| 	hak_oop_t         id; /* SmallInteger */
 | |
| 	hak_oop_t         state; /* SmallInteger */
 | |
| 
 | |
| 	hak_oop_t         sp;   /* stack pointer. SmallInteger */
 | |
| 	hak_oop_t         st;   /* stack top */
 | |
| 
 | |
| 	hak_oop_t         exsp; /* exception stack pointer. SmallInteger */
 | |
| 	hak_oop_t         exst; /* exception stack top */
 | |
| 
 | |
| 	hak_oop_t         clsp; /* class stack pointer */
 | |
| 	hak_oop_t         clst; /* class stack  top */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_process_t prev;
 | |
| 		hak_oop_process_t next;
 | |
| 	} ps;  /* links to use with the process scheduler */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_process_t prev;
 | |
| 		hak_oop_process_t next;
 | |
| 	} sem_wait; /* links to use with a semaphore */
 | |
| 
 | |
| 	hak_oop_t sem; /* nil, semaphore, or semaphore group */
 | |
| 
 | |
| 	/* == variable indexed part == */
 | |
| 	hak_oop_t slot[1]; /* process stack */
 | |
| 
 | |
| 	/* after the process stack comes the exception stack.
 | |
| 	 * the exception stack is composed of instruction pointers and some context values.
 | |
| 	 * the instruction pointers are OOPs of small integers. safe without GC.
 | |
| 	 * the context values must be referenced by the active call chain. GC doesn't need to scan this area.
 | |
| 	 * If this assumption is not correct, GC code must be modified.
 | |
| 	 * so the garbage collector is free to ignore the exception stack */
 | |
| };
 | |
| 
 | |
| enum hak_semaphore_subtype_t
 | |
| {
 | |
| 	HAK_SEMAPHORE_SUBTYPE_TIMED = 0,
 | |
| 	HAK_SEMAPHORE_SUBTYPE_IO    = 1
 | |
| };
 | |
| typedef enum hak_semaphore_subtype_t hak_semaphore_subtype_t;
 | |
| 
 | |
| enum hak_semaphore_io_type_t
 | |
| {
 | |
| 	HAK_SEMAPHORE_IO_TYPE_INPUT   = 0,
 | |
| 	HAK_SEMAPHORE_IO_TYPE_OUTPUT  = 1
 | |
| };
 | |
| typedef enum hak_semaphore_io_type_t hak_semaphore_io_type_t;
 | |
| 
 | |
| enum hak_semaphore_io_mask_t
 | |
| {
 | |
| 	HAK_SEMAPHORE_IO_MASK_INPUT   = (1 << 0),
 | |
| 	HAK_SEMAPHORE_IO_MASK_OUTPUT  = (1 << 1),
 | |
| 	HAK_SEMAPHORE_IO_MASK_HANGUP  = (1 << 2),
 | |
| 	HAK_SEMAPHORE_IO_MASK_ERROR   = (1 << 3)
 | |
| };
 | |
| typedef enum hak_semaphore_io_mask_t hak_semaphore_io_mask_t;
 | |
| 
 | |
| struct hak_semaphore_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	/* [IMPORTANT] make sure that the position of 'waiting' in hak_semaphore_t
 | |
| 	 *             must be exactly the same as its position in hak_semaphore_group_t */
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_process_t first;
 | |
| 		hak_oop_process_t last;
 | |
| 	} waiting; /* list of processes waiting on this semaphore */
 | |
| 	/* [END IMPORTANT] */
 | |
| 
 | |
| 	hak_oop_t count; /* SmallInteger */
 | |
| 
 | |
| 	/* nil for normal. SmallInteger if associated with
 | |
| 	 * timer(HAK_SEMAPHORE_SUBTYPE_TIMED) or IO(HAK_SEMAPHORE_SUBTYPE_IO). */
 | |
| 	hak_oop_t subtype;
 | |
| 
 | |
| 	union
 | |
| 	{
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_oop_t index; /* index to the heap that stores timed semaphores */
 | |
| 			hak_oop_t ftime_sec; /* firing time */
 | |
| 			hak_oop_t ftime_nsec; /* firing time */
 | |
| 		} timed;
 | |
| 
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_oop_t index; /* index to sem_io_tuple */
 | |
| 			hak_oop_t handle;
 | |
| 			hak_oop_t type; /* SmallInteger */
 | |
| 		} io;
 | |
| 	} u;
 | |
| 
 | |
| 	hak_oop_t signal_action;
 | |
| 
 | |
| 	hak_oop_semaphore_group_t group; /* nil or belonging semaphore group */
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_semaphore_t prev;
 | |
| 		hak_oop_semaphore_t next;
 | |
| 	} grm; /* group membership chain */
 | |
| };
 | |
| 
 | |
| #define HAK_SEMAPHORE_GROUP_SEMS_UNSIG 0
 | |
| #define HAK_SEMAPHORE_GROUP_SEMS_SIG   1
 | |
| 
 | |
| struct hak_semaphore_group_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	/* [IMPORTANT] make sure that the position of 'waiting' in hak_semaphore_group_t
 | |
| 	 *             must be exactly the same as its position in hak_semaphore_t */
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_process_t first;
 | |
| 		hak_oop_process_t last;
 | |
| 	} waiting; /* list of processes waiting on this semaphore group */
 | |
| 	/* [END IMPORTANT] */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_semaphore_t first;
 | |
| 		hak_oop_semaphore_t last;
 | |
| 	} sems[2]; /* sems[0] - unsignaled semaphores, sems[1] - signaled semaphores */
 | |
| 
 | |
| 	hak_oop_t sem_io_count; /* the number of io semaphores in the group */
 | |
| 	hak_oop_t sem_count; /* the total number of semaphores in the group */
 | |
| };
 | |
| 
 | |
| #define HAK_PROCESS_SCHEDULER_NAMED_INSTVARS 8
 | |
| typedef struct hak_process_scheduler_t hak_process_scheduler_t;
 | |
| typedef struct hak_process_scheduler_t* hak_oop_process_scheduler_t;
 | |
| struct hak_process_scheduler_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	hak_oop_process_t active; /*  pointer to an active process in the runnable process list */
 | |
| 	hak_oop_t total_count;  /* smooi, total number of processes - runnable/running/suspended */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_t         count; /* smooi, the number of runnable/running processes */
 | |
| 		hak_oop_process_t first; /* runnable process list */
 | |
| 		hak_oop_process_t last; /* runnable process list */
 | |
| 	} runnable;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_t         count; /* smooi, the number of suspended processes */
 | |
| 		hak_oop_process_t first; /* suspended process list */
 | |
| 		hak_oop_process_t last; /* suspended process list */
 | |
| 	} suspended;
 | |
| };
 | |
| 
 | |
| 
 | |
| #define HAK_CLASS_NAMED_INSTVARS 9
 | |
| typedef struct hak_class_t hak_class_t;
 | |
| typedef struct hak_class_t* hak_oop_class_t;
 | |
| struct hak_class_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	hak_oop_t name; /* class name. nil for unnamed class */
 | |
| 	hak_oop_t mdic; /* method dictionary. nil or a dictionary object */
 | |
| 
 | |
| 	hak_oop_t spec;     /* SmallInteger. instance specification */
 | |
| 	hak_oop_t selfspec; /* SmallInteger. specification of the class object itself */
 | |
| 
 | |
| 	hak_oop_t superclass;
 | |
| 	hak_oop_t nivars_super; /* SmallInteger */
 | |
| 	hak_oop_t ibrand; /* SmallInteger */
 | |
| 
 | |
| 	hak_oop_char_t ivarnames;
 | |
| 	hak_oop_char_t cvarnames;
 | |
| 
 | |
| 	/* indexed part afterwards - not included in HAK_CLASS_NAMED_INSTVARS */
 | |
| 	hak_oop_t      cvar[1];   /* class variables. */
 | |
| };
 | |
| 
 | |
| #if 0
 | |
| struct hak_class_t
 | |
| {
 | |
| 	HAK_OBJ_HEADER;
 | |
| 
 | |
| 	/* === the following five fields must be in sync with hak_methowner_t === */
 | |
| 	hak_oop_char_t name; /* Symbol */
 | |
| 
 | |
| 	/* [0] - instance methods, MethodDictionary
 | |
| 	 * [1] - class methods, MethodDictionary */
 | |
| 	hak_oop_dic_t  mthdic[2];
 | |
| 
 | |
| 	hak_oop_nsdic_t nsup; /* pointer to the upper namespace */
 | |
| 	hak_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */
 | |
| 	/* ===================================================================== */
 | |
| 
 | |
| 	hak_oop_t      spec;          /* SmallInteger. instance specification */
 | |
| 	hak_oop_t      selfspec;      /* SmallInteger. specification of the class object itself */
 | |
| 
 | |
| 	hak_oop_t      superclass;    /* Another class */
 | |
| 	hak_oop_t      subclasses;    /* Array of subclasses */
 | |
| 
 | |
| 	hak_oop_t      modname;       /* Symbol if importing a module. nil if not. */
 | |
| 
 | |
| 	/* == NEVER CHANGE THIS ORDER OF 3 ITEMS BELOW == */
 | |
| 	hak_oop_char_t ivars;  /* String */
 | |
| 	hak_oop_char_t civars; /* String */
 | |
| 	hak_oop_char_t cvars;  /* String */
 | |
| 	/* == NEVER CHANGE THE ORDER OF 3 ITEMS ABOVE == */
 | |
| 
 | |
| #if 0
 | |
| 	hak_oop_char_t pooldics;      /* String - pool dictionaries imported */
 | |
| 
 | |
| 	hak_oop_t      trsize; /* trailer size for new instances */
 | |
| 	hak_oop_t      trgc; /* trailer gc callback */
 | |
| 
 | |
| 	/* [0] - initial values for instance variables of new instances
 | |
| 	 * [1] - initial values for class instance variables */
 | |
| 	hak_oop_t      initv[2];
 | |
| #endif
 | |
| 	/* indexed part afterwards */
 | |
| 	hak_oop_t      cvar[1];   /* class instance variables and class variables. */
 | |
| };
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * The HAK_CLASSOF() macro return the class of an object including a numeric
 | |
|  * object encoded into a pointer.
 | |
|  */
 | |
| #define HAK_CLASSOF(hak,oop) \
 | |
| 	(HAK_OOP_GET_TAG(oop)? ((hak_oop_t)(*(hak)->tagged_classes[HAK_OOP_GET_TAG(oop)])): HAK_OBJ_GET_CLASS(oop))
 | |
| /**/
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The HAK_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 #hak_oow_t in bytes.
 | |
|  */
 | |
| #define HAK_BYTESOF(hak,oop) \
 | |
| 	(HAK_OOP_IS_NUMERIC(oop)? HAK_SIZEOF(hak_oow_t): HAK_OBJ_BYTESOF(oop))
 | |
| /**/
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The HAK_ISTYPEOF() macro is a safe replacement for HAK_OBJ_GET_FLAGS_TYPE()
 | |
|  */
 | |
| #define HAK_ISTYPEOF(hak,oop,type) \
 | |
| 	(!HAK_OOP_IS_NUMERIC(oop) && HAK_OBJ_GET_FLAGS_TYPE(oop) == (type))
 | |
| /**/
 | |
| 
 | |
| /* =========================================================================
 | |
|  * HEAP
 | |
|  * ========================================================================= */
 | |
| 
 | |
| typedef struct hak_heap_t hak_heap_t;
 | |
| 
 | |
| struct hak_heap_t
 | |
| {
 | |
| 	hak_uint8_t* base;  /* start of a heap */
 | |
| 	hak_oow_t    size;
 | |
| 	hak_xma_t*   xma;
 | |
| 	hak_mmgr_t   xmmgr;
 | |
| };
 | |
| 
 | |
| /* =========================================================================
 | |
|  * VM LOGGING
 | |
|  * ========================================================================= */
 | |
| 
 | |
| enum hak_log_mask_t
 | |
| {
 | |
| 	HAK_LOG_DEBUG       = ((hak_bitmask_t)1 << 0),
 | |
| 	HAK_LOG_INFO        = ((hak_bitmask_t)1 << 1),
 | |
| 	HAK_LOG_WARN        = ((hak_bitmask_t)1 << 2),
 | |
| 	HAK_LOG_ERROR       = ((hak_bitmask_t)1 << 3),
 | |
| 	HAK_LOG_FATAL       = ((hak_bitmask_t)1 << 4),
 | |
| 
 | |
| 	HAK_LOG_UNTYPED     = ((hak_bitmask_t)1 << 6), /* only to be used by HAK_DEBUGx() and HAK_INFOx() */
 | |
| 	HAK_LOG_COMPILER    = ((hak_bitmask_t)1 << 7),
 | |
| 	HAK_LOG_VM          = ((hak_bitmask_t)1 << 8),
 | |
| 	HAK_LOG_MNEMONIC    = ((hak_bitmask_t)1 << 9), /* bytecode mnemonic */
 | |
| 	HAK_LOG_GC          = ((hak_bitmask_t)1 << 10),
 | |
| 	HAK_LOG_IC          = ((hak_bitmask_t)1 << 11), /* instruction cycle, fetch-decode-execute */
 | |
| 	HAK_LOG_PRIMITIVE   = ((hak_bitmask_t)1 << 12),
 | |
| 
 | |
| 	HAK_LOG_APP         = ((hak_bitmask_t)1 << 13), /* hak applications, set by hak logging primitive */
 | |
| 	HAK_LOG_APP_X1      = ((hak_bitmask_t)1 << 14), /* more hak applications, you can choose to use one of APP_X? randomly */
 | |
| 	HAK_LOG_APP_X2      = ((hak_bitmask_t)1 << 15),
 | |
| 	HAK_LOG_APP_X3      = ((hak_bitmask_t)1 << 16),
 | |
| 
 | |
| 	HAK_LOG_ALL_LEVELS  = (HAK_LOG_DEBUG  | HAK_LOG_INFO | HAK_LOG_WARN | HAK_LOG_ERROR | HAK_LOG_FATAL),
 | |
| 	HAK_LOG_ALL_TYPES   = (HAK_LOG_UNTYPED | HAK_LOG_COMPILER | HAK_LOG_VM | HAK_LOG_MNEMONIC | HAK_LOG_GC | HAK_LOG_IC | HAK_LOG_PRIMITIVE | HAK_LOG_APP | HAK_LOG_APP_X1 | HAK_LOG_APP_X2 | HAK_LOG_APP_X3),
 | |
| 
 | |
| 
 | |
| 	HAK_LOG_STDOUT      = ((hak_bitmask_t)1 << 20),  /* write log messages to stdout without timestamp. HAK_LOG_STDOUT wins over HAK_LOG_STDERR. */
 | |
| 	HAK_LOG_STDERR      = ((hak_bitmask_t)1 << 21),  /* write log messages to stderr without timestamp. */
 | |
| 
 | |
| 	HAK_LOG_PREFER_JSON = ((hak_bitmask_t)1 << 30)   /* write a object in the json format. don't set this explicitly. use %J instead */
 | |
| };
 | |
| typedef enum hak_log_mask_t hak_log_mask_t;
 | |
| 
 | |
| /* all bits must be set to get enabled */
 | |
| #define HAK_LOG_ENABLED(hak,mask) (((hak)->option.log_mask & (mask)) == (mask))
 | |
| 
 | |
| #define HAK_LOG0(hak,mask,fmt) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt); } while(0)
 | |
| #define HAK_LOG1(hak,mask,fmt,a1) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1); } while(0)
 | |
| #define HAK_LOG2(hak,mask,fmt,a1,a2) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2); } while(0)
 | |
| #define HAK_LOG3(hak,mask,fmt,a1,a2,a3) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3); } while(0)
 | |
| #define HAK_LOG4(hak,mask,fmt,a1,a2,a3,a4) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3, a4); } while(0)
 | |
| #define HAK_LOG5(hak,mask,fmt,a1,a2,a3,a4,a5) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3, a4, a5); } while(0)
 | |
| #define HAK_LOG6(hak,mask,fmt,a1,a2,a3,a4,a5,a6) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3, a4, a5, a6); } while(0)
 | |
| #define HAK_LOG7(hak,mask,fmt,a1,a2,a3,a4,a5,a6,a7) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3, a4, a5, a6, a7); } while(0)
 | |
| #define HAK_LOG8(hak,mask,fmt,a1,a2,a3,a4,a5,a6,a7,a8) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3, a4, a5, a6, a7, a8); } while(0)
 | |
| #define HAK_LOG9(hak,mask,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) do { if (HAK_LOG_ENABLED(hak,mask)) hak_logbfmt(hak, mask, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); } while(0)
 | |
| 
 | |
| #if defined(HAK_BUILD_RELEASE)
 | |
| 	/* [NOTE]
 | |
| 	 *  get rid of debugging message totally regardless of
 | |
| 	 *  the log mask in the release build.
 | |
| 	 */
 | |
| #	define HAK_DEBUG0(hak,fmt)
 | |
| #	define HAK_DEBUG1(hak,fmt,a1)
 | |
| #	define HAK_DEBUG2(hak,fmt,a1,a2)
 | |
| #	define HAK_DEBUG3(hak,fmt,a1,a2,a3)
 | |
| #	define HAK_DEBUG4(hak,fmt,a1,a2,a3,a4)
 | |
| #	define HAK_DEBUG5(hak,fmt,a1,a2,a3,a4,a5)
 | |
| #	define HAK_DEBUG6(hak,fmt,a1,a2,a3,a4,a5,a6)
 | |
| #	define HAK_DEBUG7(hak,fmt,a1,a2,a3,a4,a5,a6,a7)
 | |
| #	define HAK_DEBUG8(hak,fmt,a1,a2,a3,a4,a5,a6,a7,a8)
 | |
| #	define HAK_DEBUG9(hak,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
 | |
| #else
 | |
| #	define HAK_DEBUG0(hak,fmt) HAK_LOG0(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt)
 | |
| #	define HAK_DEBUG1(hak,fmt,a1) HAK_LOG1(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1)
 | |
| #	define HAK_DEBUG2(hak,fmt,a1,a2) HAK_LOG2(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2)
 | |
| #	define HAK_DEBUG3(hak,fmt,a1,a2,a3) HAK_LOG3(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3)
 | |
| #	define HAK_DEBUG4(hak,fmt,a1,a2,a3,a4) HAK_LOG4(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4)
 | |
| #	define HAK_DEBUG5(hak,fmt,a1,a2,a3,a4,a5) HAK_LOG5(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5)
 | |
| #	define HAK_DEBUG6(hak,fmt,a1,a2,a3,a4,a5,a6) HAK_LOG6(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6)
 | |
| #	define HAK_DEBUG7(hak,fmt,a1,a2,a3,a4,a5,a6,a7) HAK_LOG7(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6, a7)
 | |
| #	define HAK_DEBUG8(hak,fmt,a1,a2,a3,a4,a5,a6,a7,a8) HAK_LOG8(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6, a7, a8)
 | |
| #	define HAK_DEBUG9(hak,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) HAK_LOG9(hak, HAK_LOG_DEBUG | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 | |
| #endif
 | |
| 
 | |
| #define HAK_INFO0(hak,fmt) HAK_LOG0(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt)
 | |
| #define HAK_INFO1(hak,fmt,a1) HAK_LOG1(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1)
 | |
| #define HAK_INFO2(hak,fmt,a1,a2) HAK_LOG2(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2)
 | |
| #define HAK_INFO3(hak,fmt,a1,a2,a3) HAK_LOG3(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3)
 | |
| #define HAK_INFO4(hak,fmt,a1,a2,a3,a4) HAK_LOG4(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4)
 | |
| #define HAK_INFO5(hak,fmt,a1,a2,a3,a4,a5) HAK_LOG5(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5)
 | |
| #define HAK_INFO6(hak,fmt,a1,a2,a3,a4,a5,a6) HAK_LOG6(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6)
 | |
| #define HAK_INFO7(hak,fmt,a1,a2,a3,a4,a5,a6,a7) HAK_LOG7(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6, a7)
 | |
| #define HAK_INFO8(hak,fmt,a1,a2,a3,a4,a5,a6,a7,a8) HAK_LOG8(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6, a7, a8)
 | |
| #define HAK_INFO9(hak,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) HAK_LOG9(hak, HAK_LOG_INFO | HAK_LOG_UNTYPED, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * VIRTUAL MACHINE PRIMITIVES
 | |
|  * ========================================================================= */
 | |
| 
 | |
| typedef void* (*hak_alloc_heap_t) (
 | |
| 	hak_t*             hak,
 | |
| 	hak_oow_t*         size /* [IN] requested size, [OUT] allocated size */
 | |
| );
 | |
| 
 | |
| typedef void (*hak_free_heap_t) (
 | |
| 	hak_t*             hak,
 | |
| 	void*              ptr
 | |
| );
 | |
| 
 | |
| typedef void (*hak_log_write_t) (
 | |
| 	hak_t*             hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_ooch_t*  msg,
 | |
| 	hak_oow_t          len
 | |
| );
 | |
| 
 | |
| typedef hak_errnum_t (*hak_syserrstrb_t) (
 | |
| 	hak_t*             hak,
 | |
| 	int                syserr_type,
 | |
| 	int                syserr_code,
 | |
| 	hak_bch_t*         buf,
 | |
| 	hak_oow_t          len
 | |
| );
 | |
| 
 | |
| typedef hak_errnum_t (*hak_syserrstru_t) (
 | |
| 	hak_t*             hak,
 | |
| 	int                syserr_type,
 | |
| 	int                syserr_code,
 | |
| 	hak_uch_t*         buf,
 | |
| 	hak_oow_t          len
 | |
| );
 | |
| 
 | |
| typedef void (*hak_assertfail_t) (
 | |
| 	hak_t*             hak,
 | |
| 	const hak_bch_t*   expr,
 | |
| 	const hak_bch_t*   file,
 | |
| 	hak_oow_t          line
 | |
| );
 | |
| 
 | |
| enum hak_vmprim_dlopen_flag_t
 | |
| {
 | |
| 	HAK_VMPRIM_DLOPEN_PFMOD = (1 << 0)
 | |
| };
 | |
| typedef enum hak_vmprim_dlopen_flag_t hak_vmprim_dlopen_flag_t;
 | |
| 
 | |
| typedef void (*hak_vmprim_dlstartup_t) (
 | |
| 	hak_t*             hak
 | |
| );
 | |
| 
 | |
| typedef void (*hak_vmprim_dlcleanup_t) (
 | |
| 	hak_t*             hak
 | |
| );
 | |
| 
 | |
| typedef void* (*hak_vmprim_dlopen_t) (
 | |
| 	hak_t*             hak,
 | |
| 	const hak_ooch_t*  name,
 | |
| 	int                flags
 | |
| );
 | |
| 
 | |
| typedef void (*hak_vmprim_dlclose_t) (
 | |
| 	hak_t*             hak,
 | |
| 	void*              handle
 | |
| );
 | |
| 
 | |
| typedef void* (*hak_vmprim_dlgetsym_t) (
 | |
| 	hak_t*             hak,
 | |
| 	void*              handle,
 | |
| 	const hak_ooch_t*  name
 | |
| );
 | |
| 
 | |
| typedef void (*hak_vmprim_gettime_t) (
 | |
| 	hak_t*             hak,
 | |
| 	hak_ntime_t*       now
 | |
| );
 | |
| 
 | |
| typedef int (*hak_vmprim_muxadd_t) (
 | |
| 	hak_t*                  hak,
 | |
| 	hak_ooi_t               io_handle,
 | |
| 	hak_ooi_t               masks
 | |
| );
 | |
| 
 | |
| typedef int (*hak_vmprim_muxmod_t) (
 | |
| 	hak_t*                  hak,
 | |
| 	hak_ooi_t               io_handle,
 | |
| 	hak_ooi_t               masks
 | |
| );
 | |
| 
 | |
| typedef int (*hak_vmprim_muxdel_t) (
 | |
| 	hak_t*                  hak,
 | |
| 	hak_ooi_t               io_handle
 | |
| );
 | |
| 
 | |
| typedef void (*hak_vmprim_muxwait_cb_t) (
 | |
| 	hak_t*                  hak,
 | |
| 	hak_ooi_t               io_handle,
 | |
| 	hak_ooi_t               masks
 | |
| );
 | |
| 
 | |
| typedef void (*hak_vmprim_muxwait_t) (
 | |
| 	hak_t*                  hak,
 | |
| 	const hak_ntime_t*      duration,
 | |
| 	hak_vmprim_muxwait_cb_t muxwcb
 | |
| );
 | |
| 
 | |
| typedef int (*hak_vmprim_sleep_t) (
 | |
| 	hak_t*             hak,
 | |
| 	const hak_ntime_t* duration
 | |
| );
 | |
| 
 | |
| typedef hak_ooi_t (*hak_vmprim_getsigfd_t) (
 | |
| 	hak_t*             hak
 | |
| );
 | |
| 
 | |
| typedef int (*hak_vmprim_getsig_t) (
 | |
| 	hak_t*             hak,
 | |
| 	hak_uint8_t*       sig
 | |
| );
 | |
| 
 | |
| typedef int (*hak_vmprim_setsig_t) (
 | |
| 	hak_t*             hak,
 | |
| 	hak_uint8_t        sig
 | |
| );
 | |
| 
 | |
| struct hak_vmprim_t
 | |
| {
 | |
| 	/* The alloc_heap callback function is called very earlier
 | |
| 	 * before hak is fully initialized. so few features are availble
 | |
| 	 * in this callback function. If it's not provided, the default
 | |
| 	 * implementation is used. */
 | |
| 	hak_alloc_heap_t       alloc_heap; /* optional */
 | |
| 
 | |
| 	/* If you customize the heap allocator by providing the alloc_heap
 | |
| 	 * callback, you should implement the heap freer. otherwise the default
 | |
| 	 * implementation doesn't know how to free the heap allocated by
 | |
| 	 * the allocator callback. */
 | |
| 	hak_free_heap_t        free_heap; /* optional */
 | |
| 
 | |
| 	hak_log_write_t        log_write; /* required */
 | |
| 	hak_syserrstrb_t       syserrstrb; /* one of syserrstrb or syserrstru required */
 | |
| 	hak_syserrstru_t       syserrstru;
 | |
| 	hak_assertfail_t       assertfail;
 | |
| 
 | |
| 	hak_vmprim_dlstartup_t dl_startup; /* optional */
 | |
| 	hak_vmprim_dlcleanup_t dl_cleanup; /* optional */
 | |
| 	hak_vmprim_dlopen_t    dl_open; /* required */
 | |
| 	hak_vmprim_dlclose_t   dl_close; /* required */
 | |
| 	hak_vmprim_dlgetsym_t  dl_getsym; /* requried */
 | |
| 
 | |
| 	hak_vmprim_gettime_t   vm_gettime; /* required */
 | |
| 	hak_vmprim_muxadd_t    vm_muxadd;
 | |
| 	hak_vmprim_muxdel_t    vm_muxdel;
 | |
| 	hak_vmprim_muxmod_t    vm_muxmod;
 | |
| 	hak_vmprim_muxwait_t   vm_muxwait;
 | |
| 	hak_vmprim_sleep_t     vm_sleep; /* required */
 | |
| 
 | |
| 	hak_vmprim_getsigfd_t  vm_getsigfd;
 | |
| 	hak_vmprim_getsig_t    vm_getsig;
 | |
| 	hak_vmprim_setsig_t    vm_setsig;
 | |
| };
 | |
| 
 | |
| typedef struct hak_vmprim_t hak_vmprim_t;
 | |
| 
 | |
| /* =========================================================================
 | |
|  * IO MANIPULATION
 | |
|  * ========================================================================= */
 | |
| 
 | |
| enum hak_io_cmd_t
 | |
| {
 | |
| 	HAK_IO_OPEN,
 | |
| 	HAK_IO_CLOSE,
 | |
| 	HAK_IO_READ,
 | |
| 	HAK_IO_READ_BYTES,
 | |
| 	HAK_IO_WRITE,
 | |
| 	HAK_IO_WRITE_BYTES,
 | |
| 	HAK_IO_FLUSH
 | |
| };
 | |
| typedef enum hak_io_cmd_t hak_io_cmd_t;
 | |
| 
 | |
| struct hak_lxc_t
 | |
| {
 | |
| 	hak_ooci_t   c; /**< character */
 | |
| 	hak_loc_t    l; /**< location */
 | |
| };
 | |
| typedef struct hak_lxc_t hak_lxc_t;
 | |
| 
 | |
| #if !defined(HAK_CCI_BUF_LEN)
 | |
| #define HAK_CCI_BUF_LEN (2048)
 | |
| #endif
 | |
| 
 | |
| /**
 | |
|  * The hak_io_cciarg_t defines the input stream to the compiler.
 | |
|  */
 | |
| typedef struct hak_io_cciarg_t hak_io_cciarg_t;
 | |
| struct hak_io_cciarg_t
 | |
| {
 | |
| 	/**
 | |
| 	 * [IN] I/O object name.
 | |
| 	 * It is #HAK_NULL for the main stream and points to a non-NULL string
 | |
| 	 * for an included stream.
 | |
| 	 */
 | |
| 	const hak_ooch_t* name;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] I/O handle set by a handler.
 | |
| 	 * The source stream handler can set this field when it opens a stream.
 | |
| 	 * All subsequent operations on the stream see this field as set
 | |
| 	 * during opening.
 | |
| 	 */
 | |
| 	void* handle;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] set this to non-zero in HAK_IO_OPEN if the handler fills the buffer with bytes.
 | |
| 	 *       the caller issues HAK_IO_READ_BYTES if it's set to non-zero, expecting bytes.
 | |
| 	 *       otherwise it issues HAK_IO_READ expecting characters.
 | |
| 	 */
 | |
| 	int byte_oriented;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] place data here for #HAK_IO_READ or #HAK_IO_READ_BYTES
 | |
| 	 */
 | |
| 	union
 | |
| 	{
 | |
| 		hak_ooch_t c[HAK_CCI_BUF_LEN];
 | |
| 		hak_uint8_t b[HAK_CCI_BUF_LEN * HAK_SIZEOF(hak_ooch_t)];
 | |
| 	} buf;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] place the number of characters read here for #HAK_IO_READ
 | |
| 	 */
 | |
| 	hak_oow_t  xlen;
 | |
| 
 | |
| 	/**
 | |
| 	 * [IN] points to the data of the includer. It is #HAK_NULL for the
 | |
| 	 * main stream.
 | |
| 	 */
 | |
| 	hak_io_cciarg_t* includer;
 | |
| 
 | |
| 	/*-----------------------------------------------------------------*/
 | |
| 	/*----------- from here down, internal use only -------------------*/
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oow_t pos;
 | |
| 		hak_oow_t len;
 | |
| 	} b; /* buffer(buf.c or buf.b) usage status */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_uint8_t buf[HAK_MBLEN_MAX];
 | |
| 		hak_oow_t len;
 | |
| 	} rsd; /* residue bytes for HAK_IO_READ_BYTES */
 | |
| 
 | |
| 	hak_oow_t line;
 | |
| 	hak_oow_t colm;
 | |
| 	hak_ooci_t nl;
 | |
| 
 | |
| 	hak_lxc_t lxc;
 | |
| 	/*-----------------------------------------------------------------*/
 | |
| };
 | |
| /**/
 | |
| 
 | |
| /**
 | |
|  * The hak_io_udiarg_t defines the user-defined input stream handler.
 | |
|  */
 | |
| typedef struct hak_io_udiarg_t hak_io_udiarg_t;
 | |
| struct hak_io_udiarg_t
 | |
| {
 | |
| 	/**
 | |
| 	 * [OUT] I/O handle set by a handler.
 | |
| 	 * The stream handler can set this field when it opens a stream.
 | |
| 	 * All subsequent operations on the stream see this field as set
 | |
| 	 * during opening.
 | |
| 	 */
 | |
| 	void* handle;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] indicates if HAK_IO_READ_BYTES is implemented
 | |
| 	 */
 | |
| 	int byte_oriented;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] place data in c for #HAK_IO_READ and in d for #HAK_IO_READ_BYTES
 | |
| 	 */
 | |
| 	union {
 | |
| 		hak_ooch_t  c[2048]; /* TODO: resize this if necessary */
 | |
| 		hak_uint8_t b[2048 * HAK_SIZEOF(hak_ooch_t)]; /* TODO: resize this if necessary */
 | |
| 	} buf;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] place the number of characters read here for
 | |
| 	 * #HAK_IO_READ or #HAK_IO_READ_BYTES
 | |
| 	 */
 | |
| 	hak_oow_t xlen;
 | |
| 
 | |
| 
 | |
| 	/*-----------------------------------------------------------------*/
 | |
| 	/*----------- from here down, internal use only -------------------*/
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oow_t pos;
 | |
| 		hak_oow_t len;
 | |
| 	} b; /* buffer(buf.c or buf.b) usage status */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_uint8_t buf[HAK_MBLEN_MAX];
 | |
| 		hak_oow_t len;
 | |
| 	} rsd; /* residue bytes for HAK_IO_READ_BYTES */
 | |
| 
 | |
| 	int eof_reached;
 | |
| };
 | |
| /**/
 | |
| 
 | |
| /**
 | |
|  * The hak_io_udiarg_t defines the user-defined output stream handler.
 | |
|  */
 | |
| typedef struct hak_io_udoarg_t hak_io_udoarg_t;
 | |
| struct hak_io_udoarg_t
 | |
| {
 | |
| 	/**
 | |
| 	 * [OUT] I/O handle set by a handler.
 | |
| 	 * The stream handler can set this field when it opens a stream.
 | |
| 	 * All subsequent operations on the stream see this field as set
 | |
| 	 * during opening.
 | |
| 	 */
 | |
| 	void* handle;
 | |
| 
 | |
| 	/**
 | |
| 	 * [IN] the pointer to the beginning of the character/byte string
 | |
| 	 *      to write.
 | |
| 	 *      hak_ooch_t* for HAK_IO_WRITE
 | |
| 	 *      hak_bch_t* or hak_uint8_t* for HAK_IO_WRITE_BYTES
 | |
| 	 */
 | |
| 	void* ptr;
 | |
| 
 | |
| 	/**
 | |
| 	 * [IN] total number of characters/bytes to write
 | |
| 	 */
 | |
| 	hak_oow_t len;
 | |
| 
 | |
| 	/**
 | |
| 	 * [OUT] place the number of characters/bytes written here for
 | |
| 	 *       #HAK_IO_WRITE or #HAK_IO_WRITE_BYTES
 | |
| 	 */
 | |
| 	hak_oow_t xlen;
 | |
| };
 | |
| /**/
 | |
| 
 | |
| /**
 | |
|  * The hak_io_impl_t type defines a callback function prototype
 | |
|  * for I/O operations.
 | |
|  */
 | |
| typedef int (*hak_io_impl_t) (
 | |
| 	hak_t*        hak,
 | |
| 	hak_io_cmd_t  cmd,
 | |
| 	void*         arg /* one of hak_io_cciarg_t*, hak_io_udiarg_t*, hak_io_udoarg_t* */
 | |
| );
 | |
| /**/
 | |
| 
 | |
| /* =========================================================================
 | |
|  * CALLBACK MANIPULATION
 | |
|  * ========================================================================= */
 | |
| 
 | |
| 
 | |
| typedef void (*hak_cb_on_fini_t)    (hak_t* hak);
 | |
| typedef void (*hak_cb_on_halting_t) (hak_t* hak);
 | |
| typedef void (*hak_cb_on_option_t)  (hak_t* hak, hak_option_t id, const void* val);
 | |
| typedef void (*hak_cb_on_gc_t)      (hak_t* hak);
 | |
| typedef int  (*hak_cb_vm_startup_t) (hak_t* hak);
 | |
| typedef void (*hak_cb_vm_cleanup_t) (hak_t* hak);
 | |
| typedef void (*hak_cb_vm_checkbc_t) (hak_t* hak, hak_oob_t bcode);
 | |
| 
 | |
| typedef struct hak_cb_t hak_cb_t;
 | |
| struct hak_cb_t
 | |
| {
 | |
| 	hak_cb_on_fini_t    on_fini; /* called from hak_fini() */
 | |
| 	hak_cb_on_halting_t halting;
 | |
| 	hak_cb_on_option_t  on_option; /* called from hak_setoption() */
 | |
| 	hak_cb_on_gc_t      on_gc; /* called from hak_gc() */
 | |
| 
 | |
| 	hak_cb_vm_startup_t vm_startup;
 | |
| 	hak_cb_vm_cleanup_t vm_cleanup;
 | |
| 	hak_cb_vm_checkbc_t vm_checkbc;
 | |
| 
 | |
| 	/* private below */
 | |
| 	hak_cb_t*     prev;
 | |
| 	hak_cb_t*     next;
 | |
| };
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * PRIMITIVE FUNCTIONS
 | |
|  * ========================================================================= */
 | |
| enum hak_pfrc_t
 | |
| {
 | |
| 	HAK_PF_FAILURE = -1,
 | |
| 	HAK_PF_SUCCESS = 0
 | |
| };
 | |
| typedef enum hak_pfrc_t hak_pfrc_t;
 | |
| 
 | |
| typedef hak_pfrc_t (*hak_pfimpl_t) (
 | |
| 	hak_t*     hak,
 | |
| 	hak_mod_t* mod,
 | |
| 	hak_ooi_t  nargs
 | |
| );
 | |
| 
 | |
| enum hak_pfbase_type_t
 | |
| {
 | |
| 	HAK_PFBASE_FUNC  = 0,
 | |
| 	HAK_PFBASE_VAR   = 1,
 | |
| 	HAK_PFBASE_CONST = 2
 | |
| };
 | |
| typedef enum hak_pfbase_type_t hak_pfbase_type_t;
 | |
| 
 | |
| typedef struct hak_pfbase_t hak_pfbase_t;
 | |
| struct hak_pfbase_t
 | |
| {
 | |
| 	hak_pfbase_type_t type;
 | |
| 	hak_pfimpl_t      handler;
 | |
| 	hak_oow_t         minargs;
 | |
| 	hak_oow_t         maxargs;
 | |
| };
 | |
| 
 | |
| typedef struct hak_pfinfo_t hak_pfinfo_t;
 | |
| struct hak_pfinfo_t
 | |
| {
 | |
| 	const hak_bch_t*  mthname;
 | |
| 	hak_pfbase_t      base;
 | |
| };
 | |
| /* =========================================================================
 | |
|  * PRIMITIVE MODULE MANIPULATION
 | |
|  * ========================================================================= */
 | |
| #define HAK_MOD_NAME_LEN_MAX 120
 | |
| 
 | |
| typedef int (*hak_mod_load_t) (
 | |
| 	hak_t*     hak,
 | |
| 	hak_mod_t* mod
 | |
| );
 | |
| 
 | |
| typedef hak_pfbase_t* (*hak_mod_query_t) (
 | |
| 	hak_t*            hak,
 | |
| 	hak_mod_t*        mod,
 | |
| 	const hak_ooch_t* name,
 | |
| 	hak_oow_t         namelen
 | |
| );
 | |
| 
 | |
| typedef void (*hak_mod_unload_t) (
 | |
| 	hak_t*     hak,
 | |
| 	hak_mod_t* mod
 | |
| );
 | |
| 
 | |
| typedef void (*hak_mod_gc_t) (
 | |
| 	hak_t*     hak,
 | |
| 	hak_mod_t* mod
 | |
| );
 | |
| 
 | |
| struct hak_mod_t
 | |
| {
 | |
| 	/* input */
 | |
| 	hak_ooch_t       name[HAK_MOD_NAME_LEN_MAX + 1];
 | |
| 	void*            inctx;
 | |
| 
 | |
| 	/* user-defined data - the module intializer shoudl fill in the following fields. */
 | |
| 	hak_mod_query_t  query;
 | |
| 	hak_mod_unload_t unload;
 | |
| 	hak_mod_gc_t     gc;
 | |
| 	void*            ctx;
 | |
| };
 | |
| 
 | |
| struct hak_mod_data_t
 | |
| {
 | |
| 	void*           handle;
 | |
| 	hak_rbt_pair_t* pair; /* internal backreference to hak->modtab */
 | |
| 	hak_mod_t       mod;
 | |
| };
 | |
| typedef struct hak_mod_data_t hak_mod_data_t;
 | |
| 
 | |
| 
 | |
| struct hak_sem_tuple_t
 | |
| {
 | |
| 	hak_oop_semaphore_t sem[2]; /* [0] input, [1] output */
 | |
| 	hak_ooi_t handle; /* io handle */
 | |
| 	hak_ooi_t mask;
 | |
| };
 | |
| typedef struct hak_sem_tuple_t hak_sem_tuple_t;
 | |
| 
 | |
| /* =========================================================================
 | |
|  * HAK VM
 | |
|  * ========================================================================= */
 | |
| typedef struct hak_synerrb_t hak_synerrb_t;
 | |
| struct hak_synerrb_t
 | |
| {
 | |
| 	hak_synerrnum_t num;
 | |
| 	hak_bloc_t      loc;
 | |
| };
 | |
| 
 | |
| typedef struct hak_synerru_t hak_synerru_t;
 | |
| struct hak_synerru_t
 | |
| {
 | |
| 	hak_synerrnum_t num;
 | |
| 	hak_uloc_t      loc;
 | |
| };
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| typedef hak_synerru_t hak_synerr_t;
 | |
| #else
 | |
| typedef hak_synerrb_t hak_synerr_t;
 | |
| #endif
 | |
| 
 | |
| typedef struct hak_dbgi_t hak_dbgi_t;
 | |
| struct hak_dbgi_t
 | |
| {
 | |
| 	const hak_ooch_t* fname; /* file name */
 | |
| 	hak_oow_t sline; /* source line in the file */
 | |
| };
 | |
| 
 | |
| #if defined(HAK_INCLUDE_COMPILER)
 | |
| typedef struct hak_compiler_t hak_compiler_t;
 | |
| typedef struct hak_cnode_t hak_cnode_t;
 | |
| 
 | |
| typedef int (*hak_on_cnode_t) (hak_t* hak, hak_cnode_t* obj);
 | |
| 
 | |
| enum hak_compile_flag_t
 | |
| {
 | |
| 	/* clear byte codes at the beginnign of hak_compile() */
 | |
| 	HAK_COMPILE_CLEAR_CODE  = (1 << 0),
 | |
| 
 | |
| 	/* clear the top-level function block at the end of hak_compile() */
 | |
| 	HAK_COMPILE_CLEAR_FUNBLK = (1 << 1)
 | |
| };
 | |
| typedef enum hak_compile_flag_t hak_compile_flag_t;
 | |
| #endif
 | |
| 
 | |
| #define HAK_ERRMSG_CAPA (2048)
 | |
| 
 | |
| struct hak_code_t
 | |
| {
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oob_t* ptr; /* byte code array */
 | |
| 		hak_oow_t len;
 | |
| 		hak_oow_t capa;
 | |
| 	} bc;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_oop_oop_t arr; /* literal array - not part of object memory */
 | |
| 		hak_oow_t len;
 | |
| 	} lit;
 | |
| 
 | |
| 	/* the cumulative number of temporaries collected at the global(top-level) level */
 | |
| 	hak_oow_t ngtmprs;
 | |
| 
 | |
| 	/* array that holds the location of the byte code emitted */
 | |
| 	hak_dbgi_t* dbgi;
 | |
| };
 | |
| typedef struct hak_code_t hak_code_t;
 | |
| 
 | |
| struct hak_t
 | |
| {
 | |
| 	hak_oow_t    _instsize;
 | |
| 	hak_mmgr_t*  _mmgr;
 | |
| 	hak_cmgr_t*  _cmgr;
 | |
| 
 | |
| 	hak_errnum_t errnum;
 | |
| 	struct
 | |
| 	{
 | |
| 		union
 | |
| 		{
 | |
| 			hak_ooch_t ooch[HAK_ERRMSG_CAPA];
 | |
| 			hak_bch_t bch[HAK_ERRMSG_CAPA];
 | |
| 			hak_uch_t uch[HAK_ERRMSG_CAPA];
 | |
| 		} tmpbuf;
 | |
| 	#if defined(HAK_OOCH_IS_UCH)
 | |
| 		hak_bch_t  xerrmsg[HAK_ERRMSG_CAPA * 2];
 | |
| 		hak_bch_t  xerrlocfile[256 * 2];
 | |
| 	#else
 | |
| 		hak_uch_t  xerrmsg[HAK_ERRMSG_CAPA];
 | |
| 		hak_uch_t  xerrlocfile[256];
 | |
| 	#endif
 | |
| 		hak_ooch_t buf[HAK_ERRMSG_CAPA];
 | |
| 		hak_oow_t len;
 | |
| 	} errmsg;
 | |
| 	hak_loc_t errloc;
 | |
| 	int shuterr;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_bitmask_t trait;
 | |
| 		hak_bitmask_t log_mask;
 | |
| 		hak_oow_t log_maxcapa;
 | |
| 		hak_bch_t* log_target_b;
 | |
| 		hak_uch_t* log_target_u;
 | |
| 		hak_oow_t dfl_symtab_size;
 | |
| 		hak_oow_t dfl_sysdic_size;
 | |
| 		hak_oow_t dfl_procstk_size;
 | |
| 		void* mod_inctx;
 | |
| 
 | |
| 		hak_oocs_t mod[3];
 | |
| 
 | |
| 	#if defined(HAK_BUILD_DEBUG)
 | |
| 		/* set automatically when trait is set */
 | |
| 		hak_oow_t karatsuba_cutoff;
 | |
| 	#endif
 | |
| 	} option;
 | |
| 
 | |
| 	hak_vmprim_t vmprim;
 | |
| 
 | |
| 	hak_oow_t vm_checkbc_cb_count;
 | |
| 	hak_cb_t* cblist;
 | |
| 	hak_rbt_t modtab; /* primitive module table */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_ooch_t* ptr;
 | |
| 		hak_oow_t len;
 | |
| 		hak_oow_t capa;
 | |
| 		hak_bitmask_t last_mask;
 | |
| 		hak_bitmask_t default_type_mask;
 | |
| 	} log;
 | |
| 	/* ========================= */
 | |
| 
 | |
| 	hak_heap_t* heap;
 | |
| 
 | |
| 	/* ========================= */
 | |
| 	hak_oop_t _undef; /* special internal value for uninitialized global variables */
 | |
| 	hak_oop_t _nil;  /* pointer to the nil object */
 | |
| 	hak_oop_t _true;
 | |
| 	hak_oop_t _false;
 | |
| 
 | |
| 	hak_oop_dic_t symtab; /* system-wide symbol table. */
 | |
| 	hak_oop_dic_t sysdic; /* system dictionary. */
 | |
| 	hak_oop_process_scheduler_t processor; /* instance of ProcessScheduler */
 | |
| 	hak_oop_process_t nil_process; /* instance of Process */
 | |
| 
 | |
| 	/* =============================================================
 | |
| 	 * KERNEL CLASSES
 | |
| 	 *  Be sure to Keep these kernel class pointers registered in the
 | |
| 	 *  kernel_classes table in gc.c
 | |
| 	 * ============================================================= */
 | |
| 	hak_oop_class_t c_apex; /* Apex */
 | |
| 	hak_oop_class_t c_class; /* Class */
 | |
| 	hak_oop_class_t c_undefobj; /* UndefinedObject */
 | |
| 	hak_oop_class_t c_nilobj; /* NilObject */
 | |
| #if 0
 | |
| 	hak_oop_class_t c_interface; /* Interface */
 | |
| #endif
 | |
| 	hak_oop_class_t c_object; /* Object */
 | |
| 
 | |
| 	hak_oop_class_t c_collection; /* Collection */
 | |
| 	hak_oop_class_t c_indexed_collection; /* IndexedCollection */
 | |
| 	hak_oop_class_t c_fixed_sized_collection; /* FixedSizedCollection */
 | |
| 	hak_oop_class_t c_string; /* String */
 | |
| 	hak_oop_class_t c_byte_string; /* String */
 | |
| 	hak_oop_class_t c_symbol; /* Symbol */
 | |
| 	hak_oop_class_t c_array; /* Array */
 | |
| 	hak_oop_class_t c_character_array; /* CharacterArray */
 | |
| 	hak_oop_class_t c_byte_array; /* ByteArray */
 | |
| 	hak_oop_class_t c_symtab; /* SymbolTable */
 | |
| 	hak_oop_class_t c_dictionary;
 | |
| 	hak_oop_class_t c_cons; /* Cons */
 | |
| 
 | |
| #if 0
 | |
| 	hak_oop_class_t c_namespace; /* Namespace */
 | |
| 	hak_oop_class_t c_pool_dictionary; /* PoolDictionary */
 | |
| #endif
 | |
| 	hak_oop_class_t c_method_dictionary; /* MethodDictionary */
 | |
| #if 0
 | |
| 	hak_oop_class_t c_method; /* CompiledMethod */
 | |
| 	hak_oop_class_t c_methsig; /* MethodSignature */
 | |
| #endif
 | |
| 	hak_oop_class_t c_function; /* Function */
 | |
| 	hak_oop_class_t c_primitive; /* Primitive */
 | |
| 	hak_oop_class_t c_compiled_block; /* CompiledBlock */
 | |
| 
 | |
| 	hak_oop_class_t c_block_context; /* BlockContext */
 | |
| 	hak_oop_class_t c_process; /* Process */
 | |
| 	hak_oop_class_t c_semaphore; /* Semaphore */
 | |
| 	hak_oop_class_t c_semaphore_group; /* SemaphoreGroup */
 | |
| 	hak_oop_class_t c_process_scheduler; /* ProcessScheduler */
 | |
| 
 | |
| 	hak_oop_class_t c_error; /* Error */
 | |
| 	hak_oop_class_t c_true; /* True */
 | |
| 	hak_oop_class_t c_false; /* False */
 | |
| 	hak_oop_class_t c_magnitude; /* Magnitude */
 | |
| 	hak_oop_class_t c_character; /* Character */
 | |
| 	hak_oop_class_t c_number; /* Number */
 | |
| 	hak_oop_class_t c_small_integer; /* SmallInteger */
 | |
| 
 | |
| 	hak_oop_class_t c_large_positive_integer; /* LargePositiveInteger */
 | |
| 	hak_oop_class_t c_large_negative_integer; /* LargeNegativeInteger */
 | |
| 	hak_oop_class_t c_fixed_point_decimal; /* FixedPointDecimal */
 | |
| 
 | |
| 	hak_oop_class_t c_small_pointer;
 | |
| 	hak_oop_class_t c_large_pointer;
 | |
| 	hak_oop_class_t c_system;
 | |
| 
 | |
| 	/* ============================================================================= */
 | |
| 
 | |
| 	/* pending asynchronous semaphores */
 | |
| 	hak_oop_semaphore_t* sem_list;
 | |
| 	hak_oow_t sem_list_count;
 | |
| 	hak_oow_t sem_list_capa;
 | |
| 
 | |
| 	/* semaphores sorted according to time-out.
 | |
| 	 * organize entries using heap as the earliest entry
 | |
| 	 * needs to be checked first */
 | |
| 	hak_oop_semaphore_t* sem_heap;
 | |
| 	hak_oow_t sem_heap_count;
 | |
| 	hak_oow_t sem_heap_capa;
 | |
| 
 | |
| 	/* semaphores for I/O handling. plain array */
 | |
| 	/*hak_oop_semaphore_t* sem_io;*/
 | |
| 	hak_sem_tuple_t* sem_io_tuple;
 | |
| 	hak_oow_t sem_io_tuple_count;
 | |
| 	hak_oow_t sem_io_tuple_capa;
 | |
| 
 | |
| 	hak_oow_t sem_io_count;
 | |
| 	hak_oow_t sem_io_wait_count; /* number of processes waiting on an IO semaphore */
 | |
| 
 | |
| 	hak_ooi_t* sem_io_map;
 | |
| 	hak_oow_t sem_io_map_capa;
 | |
| 	/* ============================================================================= */
 | |
| 
 | |
| 	hak_oop_t* proc_map;
 | |
| 	hak_oow_t proc_map_capa;
 | |
| 	hak_oow_t proc_map_used;
 | |
| 	hak_ooi_t proc_map_free_first;
 | |
| 	hak_ooi_t proc_map_free_last;
 | |
| 
 | |
| 	/* 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 */
 | |
| 	int tagged_brands[16];
 | |
| 	hak_oop_class_t* tagged_classes[16]; /* this is a pointer to hak_oop_class_t which is also a pointer */
 | |
| 
 | |
| 	hak_oop_t* volat_stack[256]; /* stack for temporaries */
 | |
| 	hak_oow_t volat_count;
 | |
| 
 | |
| 	/* == EXECUTION REGISTERS == */
 | |
| 	hak_oop_function_t initial_function;
 | |
| 	hak_oop_context_t initial_context; /* fake initial context */
 | |
| 	hak_oop_context_t active_context;
 | |
| 	hak_oop_function_t active_function;
 | |
| 	hak_oob_t* active_code;
 | |
| 	hak_ooi_t sp;
 | |
| 	hak_ooi_t ip;
 | |
| 	int no_proc_switch; /* process switching disabled */
 | |
| 	int proc_switched; /* TODO: this is temporary. implement something else to skip immediate context switching */
 | |
| 	int switch_proc;
 | |
| 	int abort_req;
 | |
| 	hak_ntime_t exec_start_time;
 | |
| 	hak_ntime_t exec_end_time;
 | |
| 	hak_oop_t last_retv;
 | |
| 	/* == END EXECUTION REGISTERS == */
 | |
| 
 | |
| 	/* == BIGINT CONVERSION == */
 | |
| 	struct
 | |
| 	{
 | |
| 		int safe_ndigits;
 | |
| 		hak_oow_t multiplier;
 | |
| 	} bigint[37];
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_ooch_t* ptr;
 | |
| 			hak_oow_t capa;
 | |
| 			hak_oow_t len;
 | |
| 		} xbuf;
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_liw_t* ptr;
 | |
| 			hak_oow_t capa;
 | |
| 		} t;
 | |
| 	} inttostr;
 | |
| 	/* == END BIGINT CONVERSION == */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_ooch_t* ptr;
 | |
| 			hak_oow_t capa;
 | |
| 			hak_oow_t len;
 | |
| 		} xbuf; /* buffer to support sprintf */
 | |
| 	} sprintf;
 | |
| 
 | |
| 	hak_code_t code;
 | |
| 
 | |
| 	/* == PRINTER to udo stream == */
 | |
| 	struct
 | |
| 	{
 | |
| 		struct
 | |
| 		{
 | |
| 			void*        ptr;
 | |
| 			hak_oow_t    capa;
 | |
| 			hak_oow_t    size;
 | |
| 		} s;
 | |
| 		hak_oop_t e; /* top entry being printed */
 | |
| 	} p;
 | |
| 	/* == PRINTER to udo stream == */
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		hak_gchdr_t* b; /* object blocks allocated */
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_gchdr_t* curr;
 | |
| 			hak_gchdr_t* prev;
 | |
| 		} ls;
 | |
| 		hak_oow_t bsz; /* total size of object blocks allocated */
 | |
| 		hak_oow_t threshold;
 | |
| 		int lazy_sweep;
 | |
| 
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_oop_t* ptr;
 | |
| 			hak_oow_t capa;
 | |
| 			hak_oow_t len;
 | |
| 			hak_oow_t max;
 | |
| 		} stack;
 | |
| 
 | |
| 		struct
 | |
| 		{
 | |
| 			hak_ntime_t alloc;
 | |
| 			hak_ntime_t mark;
 | |
| 			hak_ntime_t sweep;
 | |
| 		} stat;
 | |
| 	} gci;
 | |
| 
 | |
| 	struct
 | |
| 	{
 | |
| 		/* input handler */
 | |
| 		hak_io_impl_t udi_rdr;
 | |
| 		hak_io_udiarg_t udi_arg;
 | |
| 
 | |
| 		/* output handler */
 | |
| 		hak_io_impl_t udo_wrtr;
 | |
| 		hak_io_udoarg_t udo_arg;
 | |
| 	} io;
 | |
| 
 | |
| #if defined(HAK_INCLUDE_COMPILER)
 | |
| 	hak_compiler_t* c;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| 
 | |
| /* TODO: stack bound check when pushing */
 | |
| #define HAK_STACK_PUSH(hak,v) \
 | |
| 	do { \
 | |
| 		if (HAK_UNLIKELY((hak)->sp >= HAK_OOP_TO_SMOOI((hak)->processor->active->st))) \
 | |
| 		{ \
 | |
| 			hak_seterrbfmt(hak, HAK_EOOMEM, "process stack overflow"); \
 | |
| 			(hak)->abort_req = -1; \
 | |
| 		} \
 | |
| 		(hak)->sp = (hak)->sp + 1; \
 | |
| 		(hak)->processor->active->slot[(hak)->sp] = v; \
 | |
| 	} while (0)
 | |
| 
 | |
| #define HAK_STACK_GET(hak,sp_) ((hak)->processor->active->slot[sp_])
 | |
| #define HAK_STACK_SET(hak,sp_,obj_) ((hak)->processor->active->slot[sp_] = obj_)
 | |
| 
 | |
| #define HAK_STACK_GETTOP(hak) HAK_STACK_GET(hak, (hak)->sp)
 | |
| #define HAK_STACK_SETTOP(hak,obj_) HAK_STACK_SET(hak, (hak)->sp, obj_)
 | |
| 
 | |
| /* [NOTE]
 | |
|  *  the following macros don't commit the active stack pointer(hak->sp)
 | |
|  *  to hak->processor->active->sp immediately.
 | |
|  */
 | |
| #define HAK_STACK_POP(hak) ((hak)->sp = (hak)->sp - 1)
 | |
| #define HAK_STACK_POPS(hak,count) ((hak)->sp = (hak)->sp - (count))
 | |
| #define HAK_STACK_POP_TO(hak,v) \
 | |
| 	do { \
 | |
| 		v = HAK_STACK_GETTOP(hak); \
 | |
| 		HAK_STACK_POP (hak); \
 | |
| 	} while(0)
 | |
| 
 | |
| #define HAK_STACK_GET_ST(hak) HAK_OOP_TO_SMOOI((hak)->processor->active->st)
 | |
| #define HAK_STACK_GET_SP(hak) ((hak)->sp)
 | |
| #define HAK_STACK_IS_EMPTY(hak) ((hak)->sp <= -1)
 | |
| 
 | |
| /* get the stack pointer of the argument at the given index */
 | |
| #define HAK_STACK_GETARGSP(hak,nargs,idx) ((hak)->sp - ((nargs) - (idx) - 1))
 | |
| /* get the argument at the given index */
 | |
| #define HAK_STACK_GETARG(hak,nargs,idx) HAK_STACK_GET(hak, (hak)->sp - ((nargs) - (idx) - 1))
 | |
| /* get the receiver of a message */
 | |
| #define HAK_STACK_GETRCV(hak,nargs) HAK_STACK_GET(hak, (hak)->sp - nargs - 1)
 | |
| /* get the operator such as the called function/block/method */
 | |
| #define HAK_STACK_GETOP(hak,nargs) HAK_STACK_GET(hak, (hak)->sp - nargs)
 | |
| 
 | |
| /* change the receiver of a message */
 | |
| #define HAK_STACK_SETRCV(hak,nargs,newrcv) HAK_STACK_SET(hak, (hak)->sp - nargs - 1, newrcv)
 | |
| 
 | |
| /*
 | |
|  * .....
 | |
|  * argument 1
 | |
|  * argument 0
 | |
|  * operator
 | |
|  * receiver
 | |
|  */
 | |
| 
 | |
| /* you can't access arguments and receiver after this macro.
 | |
|  * also you must not call this macro more than once */
 | |
| 
 | |
| #define HAK_STACK_SETRET(hak,nargs,retv) \
 | |
| 	do { \
 | |
| 		HAK_STACK_POPS(hak, nargs + 1); \
 | |
| 		HAK_STACK_SETTOP(hak, (retv)); \
 | |
| 	} while(0)
 | |
| 
 | |
| #define HAK_STACK_SETRETTOERRNUM(hak,nargs) HAK_STACK_SETRET(hak, nargs, HAK_ERROR_TO_OOP(hak->errnum))
 | |
| #define HAK_STACK_SETRETTOERROR(hak,nargs,ec) HAK_STACK_SETRET(hak, nargs, HAK_ERROR_TO_OOP(ec))
 | |
| 
 | |
| /* =========================================================================
 | |
|  * HAK ASSERTION
 | |
|  * ========================================================================= */
 | |
| #if defined(HAK_BUILD_RELEASE)
 | |
| #	define HAK_ASSERT(hak,expr) ((void)0)
 | |
| #else
 | |
| #	define HAK_ASSERT(hak,expr) ((void)((expr) || ((hak)->vmprim.assertfail (hak, #expr, __FILE__, __LINE__), 0)))
 | |
| #endif
 | |
| 
 | |
| /* =========================================================================
 | |
|  * HAK COMMON OBJECTS
 | |
|  * ========================================================================= */
 | |
| enum hak_brand_t
 | |
| {
 | |
| 	HAK_BRAND_SMOOI = 1, /* never used because a small integer is encoded in an object pointer */
 | |
| 	HAK_BRAND_SMPTR,
 | |
| 	HAK_BRAND_ERROR,
 | |
| 	HAK_BRAND_CHARACTER,
 | |
| 
 | |
| 	HAK_BRAND_UNDEF,
 | |
| 	HAK_BRAND_NIL,
 | |
| 	HAK_BRAND_TRUE,
 | |
| 	HAK_BRAND_FALSE,
 | |
| 
 | |
| 	HAK_BRAND_PBIGINT, /* positive big integer */
 | |
| 	HAK_BRAND_NBIGINT, /* negative big integer */
 | |
| 	HAK_BRAND_CONS,
 | |
| 	HAK_BRAND_ARRAY,
 | |
| 	HAK_BRAND_BYTE_ARRAY,
 | |
| 	HAK_BRAND_CHARACTER_ARRAY,
 | |
| 	HAK_BRAND_SYMBOL,
 | |
| 	HAK_BRAND_STRING,
 | |
| 	HAK_BRAND_BYTE_STRING,
 | |
| 	HAK_BRAND_DIC,
 | |
| 	HAK_BRAND_FPDEC, /* fixed-point decimal */
 | |
| 
 | |
| 	HAK_BRAND_PRIM,
 | |
| 
 | |
| 	HAK_BRAND_FUNCTION,
 | |
| 	HAK_BRAND_BLOCK,
 | |
| 	HAK_BRAND_CONTEXT,
 | |
| 	HAK_BRAND_PROCESS,
 | |
| 	HAK_BRAND_PROCESS_SCHEDULER,
 | |
| 	HAK_BRAND_SEMAPHORE,
 | |
| 	HAK_BRAND_SEMAPHORE_GROUP,
 | |
| 	HAK_BRAND_CLASS,
 | |
| 	HAK_BRAND_INSTANCE
 | |
| 
 | |
| 
 | |
| 	/* [NOTE] each enumerator must not exceed the maximum value that can be
 | |
| 	 *        represented with HAK_OBJ_FLAGS_BRAND_BITS bits */
 | |
| };
 | |
| typedef enum hak_brand_t hak_brand_t;
 | |
| 
 | |
| /* TODO: this concode stuff has become mostly useless as the bits are never set as of now */
 | |
| enum hak_concode_t
 | |
| {
 | |
| 	/* these can be set in the CONCODE flags for a cons cell */
 | |
| 	/* if you have more than 16 elements, increase HAK_OBJ_FLAGS_CONCODE_BITS */
 | |
| 
 | |
| 	HAK_CONCODE_XLIST = 0,  /* ( ) - executable list */
 | |
| 	HAK_CONCODE_MLIST,      /* (obj:message) - message send list */
 | |
| 	HAK_CONCODE_ALIST,      /* (a := 20) assignment list */
 | |
| 	HAK_CONCODE_BLIST,      /* (10 + 20) expression with binary operator */
 | |
| 	HAK_CONCODE_BLOCK,      /* { } */
 | |
| 	HAK_CONCODE_ARRAY,      /* #[ ] */
 | |
| 	HAK_CONCODE_BYTEARRAY,  /* #b[ ] */
 | |
| 	HAK_CONCODE_CHARARRAY,  /* #c[ ] */
 | |
| 	HAK_CONCODE_DIC,        /* #{ } */
 | |
| 	HAK_CONCODE_QLIST,      /* #( ) - data list */
 | |
| 	HAK_CONCODE_TUPLE,      /* [ ] */
 | |
| 	HAK_CONCODE_VLIST       /* | | - symbol list */
 | |
| };
 | |
| typedef enum hak_concode_t hak_concode_t;
 | |
| 
 | |
| #define HAK_IS_UNDEF(hak,v) (v == (hak)->_undef)
 | |
| #define HAK_IS_NIL(hak,v) (v == (hak)->_nil)
 | |
| #define HAK_IS_TRUE(hak,v) (v == (hak)->_true)
 | |
| #define HAK_IS_FALSE(hak,v) (v == (hak)->_false)
 | |
| 
 | |
| #define HAK_IS_SYMBOL(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_symbol)
 | |
| #define HAK_IS_STRING(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_string)
 | |
| #define HAK_IS_CONTEXT(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_block_context)
 | |
| #define HAK_IS_FUNCTION(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_function)
 | |
| #define HAK_IS_COMPILED_BLOCK(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_compiled_block)
 | |
| #define HAK_IS_CLASS(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_class)
 | |
| #define HAK_IS_INSTANCE(hak,v) (HAK_OOP_IS_POINTER(v) && HAK_OBJ_GET_FLAGS_BRAND(v) == HAK_BRAND_INSTANCE)
 | |
| #define HAK_IS_CONS(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_cons)
 | |
| #define HAK_IS_CONS_CONCODED(hak,v,concode) (HAK_IS_CONS(hak,v) && HAK_OBJ_GET_FLAGS_CONCODE(v) == (concode))
 | |
| #define HAK_IS_ARRAY(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_array)
 | |
| #define HAK_IS_BYTEARRAY(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_byte_array)
 | |
| #define HAK_IS_DIC(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_dictionary)
 | |
| #define HAK_IS_PRIM(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_primitive)
 | |
| #define HAK_IS_PBIGINT(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_large_positive_integer)
 | |
| #define HAK_IS_NBIGINT(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_large_negative_integer)
 | |
| #define HAK_IS_BIGINT(hak,v) (HAK_OOP_IS_POINTER(v) && (HAK_OBJ_GET_CLASS(v) == (hak_oop_t)(hak)->c_large_positive_integer || HAK_OBJ_GET_CLASS(v) == (hak_oop_t)(hak)->c_large_negative_integer))
 | |
| #define HAK_IS_FPDEC(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_fixed_point_decimal)
 | |
| #define HAK_IS_PROCESS(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_process)
 | |
| #define HAK_IS_SEMAPHORE(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_semaphore)
 | |
| #define HAK_IS_SEMAPHORE_GROUP(hak,v) (HAK_CLASSOF(hak,v) == (hak_oop_t)(hak)->c_semaphore_group)
 | |
| 
 | |
| #define HAK_CONS_CAR(v)  (((hak_cons_t*)(v))->car)
 | |
| #define HAK_CONS_CDR(v)  (((hak_cons_t*)(v))->cdr)
 | |
| 
 | |
| typedef int (*hak_dic_walker_t) (
 | |
| 	hak_t*          hak,
 | |
| 	hak_oop_dic_t   dic,
 | |
| 	hak_oop_cons_t  pair,
 | |
| 	void*           ctx
 | |
| );
 | |
| 
 | |
| typedef int (*hak_xchg_reader_t) (
 | |
| 	hak_t*      hak,
 | |
| 	void*       buf,
 | |
| 	hak_oow_t   len,
 | |
| 	void*       ctx
 | |
| );
 | |
| 
 | |
| typedef int (*hak_xchg_writer_t) (
 | |
| 	hak_t*      hak,
 | |
| 	const void* ptr,
 | |
| 	hak_oow_t   len,
 | |
| 	void*       ctx
 | |
| );
 | |
| 
 | |
| #if defined(__cplusplus)
 | |
| extern "C" {
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_get_sizeof_uch (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| HAK_EXPORT const hak_bch_t* hak_obj_type_to_bcstr (
 | |
| 	hak_obj_type_t type
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_open() function creates a hak object.
 | |
|  */
 | |
| HAK_EXPORT hak_t* hak_open (
 | |
| 	hak_mmgr_t*         mmgr,
 | |
| 	hak_oow_t           xtnsize,
 | |
| 	const hak_vmprim_t* vmprim,
 | |
| 	hak_errinf_t*       errinf
 | |
| );
 | |
| /**/
 | |
| 
 | |
| /**
 | |
|  * The hak_openstdwithmmgr() function creates a hak objuect with the default primitve functions.
 | |
|  */
 | |
| HAK_EXPORT hak_t* hak_openstdwithmmgr (
 | |
| 	hak_mmgr_t*         mmgr,
 | |
| 	hak_oow_t           xtnsize,
 | |
| 	hak_errinf_t*       errinf
 | |
| );
 | |
| /**/
 | |
| 
 | |
| HAK_EXPORT hak_t* hak_openstd (
 | |
| 	hak_oow_t           xtnsize,
 | |
| 	hak_errinf_t*       errinf
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_close() function destroys a hak object.
 | |
|  */
 | |
| HAK_EXPORT void hak_close (
 | |
| 	hak_t* hak
 | |
| );
 | |
| /**/
 | |
| 
 | |
| HAK_EXPORT int hak_init (
 | |
| 	hak_t*              hak,
 | |
| 	hak_mmgr_t*         mmgr,
 | |
| 	const hak_vmprim_t* vmprim
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_fini (
 | |
| 	hak_t*              hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_cmgr_t* hak_getcmgr (
 | |
| 	hak_t* hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_setcmgr (
 | |
| 	hak_t*      hak,
 | |
| 	hak_cmgr_t* cmgr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_errnum_t hak_geterrnum (
 | |
| 	hak_t* hak
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrnum (
 | |
| 	hak_t*       hak,
 | |
| 	hak_errnum_t errnum
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_geterrloc (
 | |
| 	hak_t*     hak,
 | |
| 	hak_loc_t* loc
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrbmsg (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_bch_t* errmsg
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrumsg (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_uch_t* errmsg
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrwithsyserr (
 | |
| 	hak_t*       hak,
 | |
| 	int          syserr_type,
 | |
| 	int          syserr_code
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrbfmtwithsyserr (
 | |
| 	hak_t*           hak,
 | |
| 	int              syserr_type,
 | |
| 	int              syserr_code,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_2(1,4);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrufmtwithsyserr (
 | |
| 	hak_t*           hak,
 | |
| 	int              syserr_type,
 | |
| 	int              syserr_code,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_2(1,4);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrbfmt (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_2(1,3);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrufmt (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_2(1,3);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrbfmtloc (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_loc_t* loc,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_3(1,3,4);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrufmtloc (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_loc_t* loc,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_3(1,3,4);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrbfmtv (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	va_list          ap
 | |
| ) HAK_NONNULL_2(1,3);
 | |
| 
 | |
| HAK_EXPORT void hak_seterrufmtv (
 | |
| 	hak_t*           hak,
 | |
| 	hak_errnum_t     errnum,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	va_list          ap
 | |
| ) HAK_NONNULL_2(1,3);
 | |
| 
 | |
| HAK_EXPORT const hak_ooch_t* hak_geterrstr (
 | |
| 	hak_t* hak
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT const hak_uch_t* hak_geterrumsg (
 | |
| 	hak_t* hak
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT const hak_bch_t* hak_geterrbmsg (
 | |
| 	hak_t* hak
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT void hak_geterrbinf (
 | |
| 	hak_t*         hak,
 | |
| 	hak_errbinf_t* errinf
 | |
| ) HAK_NONNULL_2(1,2);
 | |
| 
 | |
| HAK_EXPORT void hak_geterruinf (
 | |
| 	hak_t*         hak,
 | |
| 	hak_erruinf_t* errinf
 | |
| ) HAK_NONNULL_2(1,2);
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_geterrinf hak_geterruinf
 | |
| #else
 | |
| #	define hak_geterrinf hak_geterrbinf
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_copyerrbmsg (
 | |
| 	hak_t*     hak,
 | |
| 	hak_bch_t* buf,
 | |
| 	hak_oow_t  len
 | |
| ) HAK_NONNULL_2(1,2);
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_copyerrumsg (
 | |
| 	hak_t*     hak,
 | |
| 	hak_uch_t* buf,
 | |
| 	hak_oow_t  len
 | |
| ) HAK_NONNULL_2(1,2);
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_geterrmsg  hak_geterrumsg
 | |
| #	define hak_seterrmsg  hak_seterrumsg
 | |
| #	define hak_copyerrmsg hak_copyerrumsg
 | |
| #else
 | |
| #	define hak_geterrmsg  hak_geterrbmsg
 | |
| #	define hak_seterrmsg  hak_seterrbmsg
 | |
| #	define hak_copyerrmsg hak_copyerrbmsg
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT const hak_ooch_t* hak_backuperrmsg (
 | |
| 	hak_t* hak
 | |
| ) HAK_NONNULL_1(1);
 | |
| 
 | |
| HAK_EXPORT int hak_errnum_is_synerr (
 | |
| 	hak_errnum_t errnum
 | |
| );
 | |
| 
 | |
| HAK_EXPORT const hak_ooch_t* hak_errnum_to_errstr (
 | |
| 	hak_errnum_t errnum
 | |
| );
 | |
| 
 | |
| HAK_EXPORT const hak_bch_t* hak_errnum_to_errbcstr (
 | |
| 	hak_errnum_t errnum,
 | |
| 	hak_bch_t*   buf,
 | |
| 	hak_oow_t    len
 | |
| ) HAK_NONNULL_1(2);
 | |
| 
 | |
| HAK_EXPORT const hak_uch_t* hak_errnum_to_errucstr (
 | |
| 	hak_errnum_t errnum,
 | |
| 	hak_uch_t*   buf,
 | |
| 	hak_oow_t    len
 | |
| ) HAK_NONNULL_1(2);
 | |
| 
 | |
| HAK_EXPORT const hak_bch_t* hak_synerr_to_errbcstr (
 | |
| 	hak_synerrnum_t errnum
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_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
 | |
|  */
 | |
| HAK_EXPORT int hak_getoption (
 | |
| 	hak_t*         hak,
 | |
| 	hak_option_t   id,
 | |
| 	void*          value
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_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
 | |
|  */
 | |
| HAK_EXPORT int hak_setoption (
 | |
| 	hak_t*        hak,
 | |
| 	hak_option_t  id,
 | |
| 	const void*   value
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_cb_t* hak_regcb (
 | |
| 	hak_t*    hak,
 | |
| 	hak_cb_t* tmpl
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_deregcb (
 | |
| 	hak_t*    hak,
 | |
| 	hak_cb_t* cb
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_gc() function performs garbage collection.
 | |
|  * It is not affected by #HAK_TRAIT_NOGC.
 | |
|  */
 | |
| HAK_EXPORT void hak_gc (
 | |
| 	hak_t* hak,
 | |
| 	int    full
 | |
| );
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hak_moveoop() function is used to move a live object to a new
 | |
|  * location in hak_gc(). When hak_gc() invokes registered gc callbacks,
 | |
|  * you may call this function to protect extra objects you might have
 | |
|  * allocated manually.
 | |
|  */
 | |
| hak_oop_t hak_moveoop (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  oop
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_shallowcopy (
 | |
| 	hak_t*      hak,
 | |
| 	hak_oop_t   oop
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_ignite() function creates key initial objects.
 | |
|  */
 | |
| HAK_EXPORT int hak_ignite (
 | |
| 	hak_t*      hak,
 | |
| 	hak_oow_t   heapsize
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_addbuiltinprims (
 | |
| 	hak_t*      hak
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_execute() function executes an activated context.
 | |
|  */
 | |
| HAK_EXPORT hak_oop_t hak_execute (
 | |
| 	hak_t* hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_abort (
 | |
| 	hak_t* hak
 | |
| );
 | |
| 
 | |
| 
 | |
| #if defined(HAK_HAVE_INLINE)
 | |
| 	static HAK_INLINE void hak_switchprocess (hak_t* hak) { hak->switch_proc = 1; }
 | |
| #else
 | |
| #	define hak_switchprocess(hak) ((hak)->switch_proc = 1)
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT void hak_setbasesrloc (
 | |
| 	hak_t*    hak,
 | |
| 	hak_oow_t line,
 | |
| 	hak_oow_t colm
 | |
| );
 | |
| 
 | |
| /* if you should read charcters from the input stream before hak_read(),
 | |
|  * you can call hak_readbasesrchar() */
 | |
| HAK_EXPORT hak_lxc_t* hak_readbasesrchar (
 | |
| 	hak_t* hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_attachccio (
 | |
| 	hak_t*        hak,
 | |
| 	hak_io_impl_t cci_rdr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_detachccio (
 | |
| 	hak_t*        hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_attachudio (
 | |
| 	hak_t*        hak,
 | |
| 	hak_io_impl_t udi_rdr,
 | |
| 	hak_io_impl_t udo_wrtr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_detachudio (
 | |
| 	hak_t*        hak
 | |
| );
 | |
| 
 | |
| 
 | |
| HAK_EXPORT int hak_attachcciostdwithucstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* cci_file
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_attachcciostdwithbcstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* cci_file
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_attachudiostdwithucstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* udi_file,
 | |
| 	const hak_uch_t* udo_file
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_attachudiostdwithbcstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* udi_file,
 | |
| 	const hak_bch_t* udo_file
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_detachio (
 | |
| 	hak_t*       hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_flushudio (
 | |
| 	hak_t*       hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_print (
 | |
| 	hak_t*       hak,
 | |
| 	hak_oop_t    obj
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_proutbfmt (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_proutufmt (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| #if defined(HAK_INCLUDE_COMPILER)
 | |
| 
 | |
| HAK_EXPORT void hak_freecnode (
 | |
| 	hak_t*       hak,
 | |
| 	hak_cnode_t* cnode
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_beginfeed (
 | |
| 	hak_t*            hak,
 | |
| 	hak_on_cnode_t    on_cnode
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_feed (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_ooch_t* data,
 | |
| 	hak_oow_t         len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_feeduchars (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* data,
 | |
| 	hak_oow_t        len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_feedbchars (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* data,
 | |
| 	hak_oow_t        len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_feedpending (
 | |
| 	hak_t*           hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_resetfeed (
 | |
| 	hak_t*           hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_resetfeedloc (
 | |
| 	hak_t*           hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT  void hak_getfeedloc (
 | |
| 	hak_t*           hak,
 | |
| 	hak_loc_t*       loc
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_endfeed (
 | |
| 	hak_t*            hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_compile (
 | |
| 	hak_t*       hak,
 | |
| 	hak_cnode_t* obj,
 | |
| 	int          flags
 | |
| );
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT int hak_addliteraltocode (
 | |
| 	hak_t*        hak,
 | |
| 	hak_code_t*   code,
 | |
| 	hak_oop_t     obj,
 | |
| 	hak_oow_t     lfbase,
 | |
| 	hak_oow_t*    index
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_brewcode() initializes the structure pointed to by \a code partially or entirely.
 | |
|  * The part already initialized is not destroyed and/or reinitialized.
 | |
|  */
 | |
| HAK_EXPORT int hak_brewcode (
 | |
| 	hak_t*      hak,
 | |
| 	hak_code_t* code
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_purgecode() function cleans up the data held in code space memory
 | |
|  * pointed to by \a code.
 | |
|  */
 | |
| HAK_EXPORT void hak_purgecode (
 | |
| 	hak_t*       hak,
 | |
| 	hak_code_t*  code
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_decode() function decodes instructions from the position
 | |
|  * \a start to the position \a end - 1, and prints the decoded instructions
 | |
|  * in the textual form.
 | |
|  */
 | |
| HAK_EXPORT int hak_decode (
 | |
| 	hak_t*             hak,
 | |
| 	const hak_code_t*  code,
 | |
| 	hak_oow_t          start,
 | |
| 	hak_oow_t          end
 | |
| );
 | |
| 
 | |
| /**
 | |
|  * The hak_resetcode() function some internal states back to the initial state.
 | |
|  * The affected internal states include byte code buffer, literal frame,
 | |
|  * ordinary global variables. You should take extra precaution as it is
 | |
|  * a risky function. For instance, a global variable inserted manually
 | |
|  * with hak_putatsysdic() gets deleted if the kernel bit is not set on
 | |
|  * the variable symbol.
 | |
|  */
 | |
| HAK_EXPORT void hak_resetcode (
 | |
| 	hak_t*   hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_clearcode (
 | |
| 	hak_t* hak
 | |
| );
 | |
| 
 | |
| #define HAK_XTN(hak) ((void*)((hak_uint8_t*)hak + ((hak_t*)hak)->_instsize))
 | |
| #define HAK_MMGR(hak) (((hak_t*)(hak))->_mmgr)
 | |
| #define HAK_CMGR(hak) (((hak_t*)(hak))->_cmgr)
 | |
| #define HAK_ERRNUM(hak) (((hak_t*)(hak))->errnum)
 | |
| 
 | |
| void* hak_getxtn (
 | |
| 	hak_t* hak
 | |
| );
 | |
| 
 | |
| 
 | |
| #if defined(HAK_HAVE_INLINE)
 | |
| static HAK_INLINE hak_code_t* hak_getcode (hak_t* hak) { return &hak->code; }
 | |
| static HAK_INLINE hak_oob_t* hak_getbcptr (hak_t* hak) { return hak->code.bc.ptr; }
 | |
| static HAK_INLINE hak_oow_t hak_getbclen (hak_t* hak) { return hak->code.bc.len; }
 | |
| static HAK_INLINE hak_oow_t hak_getlflen (hak_t* hak) { return hak->code.lit.len; }
 | |
| static HAK_INLINE hak_oow_t hak_getngtmprs (hak_t* hak) { return hak->code.ngtmprs; }
 | |
| static HAK_INLINE hak_ooi_t hak_getip (hak_t* hak) { return hak->ip; }
 | |
| #else
 | |
| #	define hak_getcode(hak) (&(hak)->code)
 | |
| #	define hak_getbcptr(hak) ((hak)->code.bc.ptr)
 | |
| #	define hak_getbclen(hak) ((hak)->code.bc.len)
 | |
| #	define hak_getlflen(hak) ((hak)->code.lit.len)
 | |
| #	define hak_getngtmprs(hak) ((hak)->code.ngtmprs)
 | |
| #	define hak_getip(hak) ((hak)->ip)
 | |
| #endif
 | |
| 
 | |
| /* =========================================================================
 | |
|  * SYNTAX ERROR HANDLING
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT void hak_getsynerrb (
 | |
| 	hak_t*             hak,
 | |
| 	hak_synerrb_t*     synerr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_getsynerru (
 | |
| 	hak_t*             hak,
 | |
| 	hak_synerru_t*     synerr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_getsynerr (
 | |
| 	hak_t*             hak,
 | |
| 	hak_synerr_t*      synerr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_synerrnum_t hak_getsynerrnum (
 | |
| 	hak_t*             hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_setsynerrbfmt (
 | |
| 	hak_t*              hak,
 | |
| 	hak_synerrnum_t     num,
 | |
| 	const hak_loc_t*    loc,
 | |
| 	const hak_bch_t*    msgfmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_2(1,4);
 | |
| 
 | |
| HAK_EXPORT void hak_setsynerrufmt (
 | |
| 	hak_t*              hak,
 | |
| 	hak_synerrnum_t     num,
 | |
| 	const hak_loc_t*    loc,
 | |
| 	const hak_uch_t*    msgfmt,
 | |
| 	...
 | |
| ) HAK_NONNULL_2(1,4);
 | |
| 
 | |
| /* =========================================================================
 | |
|  * TEMPORARY OOP MANAGEMENT FUNCTIONS
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT void hak_pushvolat (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t* oop_ptr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_popvolat (
 | |
| 	hak_t*     hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_popvolats (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oow_t  count
 | |
| );
 | |
| 
 | |
| /* =========================================================================
 | |
|  * SYSTEM MEMORY MANAGEMENT FUCNTIONS VIA MMGR
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT void* hak_allocmem (
 | |
| 	hak_t*    hak,
 | |
| 	hak_oow_t size
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void* hak_callocmem (
 | |
| 	hak_t*    hak,
 | |
| 	hak_oow_t size
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void* hak_reallocmem (
 | |
| 	hak_t*    hak,
 | |
| 	void*     ptr,
 | |
| 	hak_oow_t size
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_freemem (
 | |
| 	hak_t* hak,
 | |
| 	void*  ptr
 | |
| );
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * PRIMITIVE FUNCTION MANIPULATION
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT hak_pfbase_t* hak_findpfbase (
 | |
| 	hak_t*              hak,
 | |
| 	hak_pfinfo_t*       pfinfo,
 | |
| 	hak_oow_t           pfcount,
 | |
| 	const hak_ooch_t*   name,
 | |
| 	hak_oow_t           namelen
 | |
| );
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * LOGGING
 | |
|  * ========================================================================= */
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_logbfmt (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_logbfmtv (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	va_list          ap
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_logufmt (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_logufmtv (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bitmask_t    mask,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	va_list          ap
 | |
| );
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_logoofmt hak_logufmt
 | |
| #	define hak_logoofmtv hak_logufmtv
 | |
| #else
 | |
| #	define hak_logoofmt hak_logbfmt
 | |
| #	define hak_logoofmtv hak_logbfmtv
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_prbfmt (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_prbfmtv (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	va_list          ap
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_prufmt (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_ooi_t hak_prufmtv (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	va_list          ap
 | |
| );
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_proofmt hak_prufmt
 | |
| #	define hak_proofmtv hak_prufmtv
 | |
| #else
 | |
| #	define hak_proofmt hak_prbfmt
 | |
| #	define hak_proofmtv hak_prbfmtv
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * STRING FORMATTING
 | |
|  * ========================================================================= */
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_vfmttoucstr (
 | |
| 	hak_t*           hak,
 | |
| 	hak_uch_t*       buf,
 | |
| 	hak_oow_t        bufsz,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	va_list          ap
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_fmttoucstr (
 | |
| 	hak_t*           hak,
 | |
| 	hak_uch_t*       buf,
 | |
| 	hak_oow_t        bufsz,
 | |
| 	const hak_uch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_vfmttobcstr (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bch_t*       buf,
 | |
| 	hak_oow_t        bufsz,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	va_list          ap
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oow_t hak_fmttobcstr (
 | |
| 	hak_t*           hak,
 | |
| 	hak_bch_t*       buf,
 | |
| 	hak_oow_t        bufsz,
 | |
| 	const hak_bch_t* fmt,
 | |
| 	...
 | |
| );
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_vfmttooocstr hak_vfmttoucstr
 | |
| #	define hak_fmttooocstr hak_fmttoucstr
 | |
| #else
 | |
| #	define hak_vfmttooocstr hak_vfmttobcstr
 | |
| #	define hak_fmttooocstr hak_fmttobcstr
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * OBJECT MANAGEMENT
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT hak_oop_t hak_hatchundef (
 | |
| 	hak_t*     hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_hatchnil (
 | |
| 	hak_t*     hak
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_instantiate (
 | |
| 	hak_t*          hak,
 | |
| 	hak_oop_class_t _class,
 | |
| 	const void*     vptr,
 | |
| 	hak_oow_t       vlen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makecons (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  car,
 | |
| 	hak_oop_t  cdr
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makearray (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oow_t  len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makechararray (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_ooch_t* ptr,
 | |
| 	hak_oow_t         len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makebytearray (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_oob_t* ptr,
 | |
| 	hak_oow_t        len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makebytestringwithbytes (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_oob_t* ptr,
 | |
| 	hak_oow_t        len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makebytestring (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_ooch_t* ptr,
 | |
| 	hak_oow_t         len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makestring (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_ooch_t* ptr,
 | |
| 	hak_oow_t         len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makestringwithuchars (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_uch_t*  ptr,
 | |
| 	hak_oow_t         len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makestringwithbchars (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_bch_t*  ptr,
 | |
| 	hak_oow_t         len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makefpdec (
 | |
| 	hak_t*            hak,
 | |
| 	hak_oop_t         value,
 | |
| 	hak_ooi_t         scale
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makedic (
 | |
| 	hak_t*            hak,
 | |
| 	hak_oow_t         inisize /* initial bucket size */
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makeclass (
 | |
| 	hak_t*            hak,
 | |
| 	hak_oop_t         name,
 | |
| 	hak_oop_t         superclass,
 | |
| 	hak_ooi_t         spec,
 | |
| 	hak_ooi_t         selfspec,
 | |
| 	hak_oop_t         ivars_str,
 | |
| 	hak_oop_t         cvars_str
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_freengcobj (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_t        obj
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makengcbytearray (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_oob_t* ptr,
 | |
| 	hak_oow_t        len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_remakengcbytearray (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_t        obj,
 | |
| 	hak_oow_t        newsz
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makengcarray (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oow_t        len
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_remakengcarray (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_t        obj,
 | |
| 	hak_oow_t        newsz
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_makeprim (
 | |
| 	hak_t*          hak,
 | |
| 	hak_pfimpl_t    primimpl,
 | |
| 	hak_oow_t       minargs,
 | |
| 	hak_oow_t       maxargs,
 | |
| 	hak_mod_t*      mod
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_oowtoint (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oow_t  w
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_ooitoint (
 | |
| 	hak_t*    hak,
 | |
| 	hak_ooi_t i
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttooow_noseterr (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  x,
 | |
| 	hak_oow_t* w
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttooow (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  x,
 | |
| 	hak_oow_t* w
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttoooi_noseterr (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  x,
 | |
| 	hak_ooi_t* i
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttoooi (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  x,
 | |
| 	hak_ooi_t* i
 | |
| );
 | |
| 
 | |
| #if (HAK_SIZEOF_UINTMAX_T == HAK_SIZEOF_OOW_T)
 | |
| #   define hak_inttouintmax_noseterr hak_inttooow_noseterr
 | |
| #   define hak_inttouintmax hak_inttooow
 | |
| #   define hak_inttointmax_noseterr hak_inttoooi_noseterr
 | |
| #   define hak_inttointmax hak_inttoooi
 | |
| #   define hak_uintmaxtoint hak_oowtoint
 | |
| #   define hak_intmaxtoint hak_ooitoint
 | |
| #else
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_intmaxtoint (
 | |
| 	hak_t*       hak,
 | |
| 	hak_intmax_t i
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_uintmaxtoint (
 | |
| 	hak_t*        hak,
 | |
| 	hak_uintmax_t i
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttouintmax_noseterr (
 | |
| 	hak_t*         hak,
 | |
| 	hak_oop_t      x,
 | |
| 	hak_uintmax_t* w
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttouintmax (
 | |
| 	hak_t*         hak,
 | |
| 	hak_oop_t      x,
 | |
| 	hak_uintmax_t* w
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttointmax_noseterr (
 | |
| 	hak_t*        hak,
 | |
| 	hak_oop_t     x,
 | |
| 	hak_intmax_t* i
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_inttointmax (
 | |
| 	hak_t*        hak,
 | |
| 	hak_oop_t     x,
 | |
| 	hak_intmax_t* i
 | |
| );
 | |
| #endif
 | |
| 
 | |
| /* =========================================================================
 | |
|  * CONS OBJECT UTILITIES
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT hak_oow_t hak_countcons (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_t        cons
 | |
| );
 | |
| 
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_getlastconscdr (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_t        cons
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_t hak_reversecons (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_t        cons
 | |
| );
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * CODE MARSHALING/UNMARSHALING
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT int hak_marshalcode (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_code_t* code,
 | |
| 	hak_xchg_writer_t wrtr,
 | |
| 	void*             ctx
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_unmarshalcode (
 | |
| 	hak_t*            hak,
 | |
| 	hak_code_t*       code,
 | |
| 	hak_xchg_reader_t rdr,
 | |
| 	void*             ctx
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_marshalcodetomem (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_code_t* code,
 | |
| 	hak_ptlc_t*        dst
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_unmarshalcodefrommem (
 | |
| 	hak_t*            hak,
 | |
| 	hak_code_t*       code,
 | |
| 	const hak_ptl_t*  src
 | |
| );
 | |
| 
 | |
| /* =========================================================================
 | |
|  * DICTIONARY ACCESS FUNCTIONS
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT hak_oop_cons_t hak_putatsysdic (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  key,
 | |
| 	hak_oop_t  value
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_getatsysdic (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  key
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_lookupsysdicforsymbol (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_oocs_t* name
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_lookupsysdicforsymbol_noseterr (
 | |
| 	hak_t*            hak,
 | |
| 	const hak_oocs_t* name
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_zapatsysdic (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  key
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_lookupdicforsymbol (
 | |
| 	hak_t*            hak,
 | |
| 	hak_oop_dic_t     dic,
 | |
| 	const hak_oocs_t* name
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_lookupdicforsymbol_noseterr (
 | |
| 	hak_t*            hak,
 | |
| 	hak_oop_dic_t     dic,
 | |
| 	const hak_oocs_t* name
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_putatdic (
 | |
| 	hak_t*        hak,
 | |
| 	hak_oop_dic_t dic,
 | |
| 	hak_oop_t     key,
 | |
| 	hak_oop_t     value
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_oop_cons_t hak_getatdic (
 | |
| 	hak_t*        hak,
 | |
| 	hak_oop_dic_t dic,
 | |
| 	hak_oop_t     key
 | |
| );
 | |
| 
 | |
| 
 | |
| HAK_EXPORT int hak_zapatdic (
 | |
| 	hak_t*        hak,
 | |
| 	hak_oop_dic_t dic,
 | |
| 	hak_oop_t     key
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_walkdic (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oop_dic_t    dic,
 | |
| 	hak_dic_walker_t walker,
 | |
| 	void*            ctx
 | |
| );
 | |
| 
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * OBJECT HASHING AND COMPARISION
 | |
|  * ========================================================================= */
 | |
| 
 | |
| HAK_EXPORT int hak_hashobj (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  obj,
 | |
| 	hak_oow_t* xhv
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_equalobjs (
 | |
| 	hak_t*     hak,
 | |
| 	hak_oop_t  rcv,
 | |
| 	hak_oop_t  arg
 | |
| );
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * STRING ENCODING CONVERSION
 | |
|  * ========================================================================= */
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_convootobchars(hak,oocs,oocslen,bcs,bcslen) hak_convutobchars(hak,oocs,oocslen,bcs,bcslen)
 | |
| #	define hak_convbtooochars(hak,bcs,bcslen,oocs,oocslen) hak_convbtouchars(hak,bcs,bcslen,oocs,oocslen)
 | |
| #	define hak_convootobcstr(hak,oocs,oocslen,bcs,bcslen) hak_convutobcstr(hak,oocs,oocslen,bcs,bcslen)
 | |
| #	define hak_convbtooocstr(hak,bcs,bcslen,oocs,oocslen) hak_convbtoucstr(hak,bcs,bcslen,oocs,oocslen)
 | |
| #else
 | |
| #	define hak_convootouchars(hak,oocs,oocslen,ucs,ucslen) hak_convbtouchars(hak,oocs,oocslen,ucs,ucslen)
 | |
| #	define hak_convutooochars(hak,ucs,ucslen,oocs,oocslen) hak_convutobchars(hak,ucs,ucslen,oocs,oocslen)
 | |
| #	define hak_convootoucstr(hak,oocs,oocslen,ucs,ucslen) hak_convbtoucstr(hak,oocs,oocslen,ucs,ucslen)
 | |
| #	define hak_convutooocstr(hak,ucs,ucslen,oocs,oocslen) hak_convutobcstr(hak,ucs,ucslen,oocs,oocslen)
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT int hak_convbtouchars (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* bcs,
 | |
| 	hak_oow_t*       bcslen,
 | |
| 	hak_uch_t*       ucs,
 | |
| 	hak_oow_t*       ucslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT int hak_convutobchars (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* ucs,
 | |
| 	hak_oow_t*       ucslen,
 | |
| 	hak_bch_t*       bcs,
 | |
| 	hak_oow_t*       bcslen
 | |
| );
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hak_convbtoucstr() function converts a null-terminated byte string
 | |
|  * to a wide string.
 | |
|  */
 | |
| HAK_EXPORT int hak_convbtoucstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* bcs,
 | |
| 	hak_oow_t*       bcslen,
 | |
| 	hak_uch_t*       ucs,
 | |
| 	hak_oow_t*       ucslen
 | |
| );
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * The hak_convutobcstr() function converts a null-terminated wide string
 | |
|  * to a byte string.
 | |
|  */
 | |
| HAK_EXPORT int hak_convutobcstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* ucs,
 | |
| 	hak_oow_t*       ucslen,
 | |
| 	hak_bch_t*       bcs,
 | |
| 	hak_oow_t*       bcslen
 | |
| );
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_dupootobcharswithheadroom(hak,hrb,oocs,oocslen,bcslen) hak_duputobcharswithheadroom(hak,hrb,oocs,oocslen,bcslen)
 | |
| #	define hak_dupbtooocharswithheadroom(hak,hrb,bcs,bcslen,oocslen) hak_dupbtoucharswithheadroom(hak,hrb,bcs,bcslen,oocslen)
 | |
| #	define hak_dupootobchars(hak,oocs,oocslen,bcslen) hak_duputobchars(hak,oocs,oocslen,bcslen)
 | |
| #	define hak_dupbtooochars(hak,bcs,bcslen,oocslen) hak_dupbtouchars(hak,bcs,bcslen,oocslen)
 | |
| 
 | |
| #	define hak_dupootobcstrwithheadroom(hak,hrb,oocs,bcslen) hak_duputobcstrwithheadroom(hak,hrb,oocs,bcslen)
 | |
| #	define hak_dupbtooocstrwithheadroom(hak,hrb,bcs,oocslen) hak_dupbtoucstrwithheadroom(hak,hrb,bcs,oocslen)
 | |
| #	define hak_dupootobcstr(hak,oocs,bcslen) hak_duputobcstr(hak,oocs,bcslen)
 | |
| #	define hak_dupbtooocstr(hak,bcs,oocslen) hak_dupbtoucstr(hak,bcs,oocslen)
 | |
| 
 | |
| #	define hak_dupootoucstr(hak,oocs,ucslen) hak_dupucstr(hak,oocs,ucslen)
 | |
| #	define hak_duputooocstr(hak,ucs,oocslen) hak_dupucstr(hak,ucs,oocslen)
 | |
| 
 | |
| #else
 | |
| #	define hak_dupootoucharswithheadroom(hak,hrb,oocs,oocslen,ucslen) hak_dupbtoucharswithheadroom(hak,hrb,oocs,oocslen,ucslen)
 | |
| #	define hak_duputooocharswithheadroom(hak,hrb,ucs,ucslen,oocslen) hak_duputobcharswithheadroom(hak,hrb,ucs,ucslen,oocslen)
 | |
| #	define hak_dupootouchars(hak,oocs,oocslen,ucslen) hak_dupbtouchars(hak,oocs,oocslen,ucslen)
 | |
| #	define hak_duputooochars(hak,ucs,ucslen,oocslen) hak_duputobchars(hak,ucs,ucslen,oocslen)
 | |
| 
 | |
| #	define hak_dupootoucstrwithheadroom(hak,hrb,oocs,ucslen) hak_dupbtoucstrwithheadroom(hak,hrb,oocs,ucslen)
 | |
| #	define hak_duputooocstrwithheadroom(hak,hrb,ucs,oocslen) hak_duputobcstrwithheadroom(hak,hrb,ucs,oocslen)
 | |
| #	define hak_dupootoucstr(hak,oocs,ucslen) hak_dupbtoucstr(hak,oocs,ucslen)
 | |
| #	define hak_duputooocstr(hak,ucs,oocslen) hak_duputobcstr(hak,ucs,oocslen)
 | |
| 
 | |
| #	define hak_dupootobcstr(hak,oocs,bcslen) hak_dupbcstr(hak,oocs,bcslen)
 | |
| #	define hak_dupbtooocstr(hak,bcs,oocslen) hak_dupbcstr(hak,bcs,oocslen)
 | |
| #endif
 | |
| 
 | |
| 
 | |
| HAK_EXPORT hak_uch_t* hak_dupbtoucharswithheadroom (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oow_t        headroom_bytes,
 | |
| 	const hak_bch_t* bcs,
 | |
| 	hak_oow_t        bcslen,
 | |
| 	hak_oow_t*       ucslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_bch_t* hak_duputobcharswithheadroom (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oow_t        headroom_bytes,
 | |
| 	const hak_uch_t* ucs,
 | |
| 	hak_oow_t        ucslen,
 | |
| 	hak_oow_t*       bcslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_uch_t* hak_dupbtouchars (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* bcs,
 | |
| 	hak_oow_t        bcslen,
 | |
| 	hak_oow_t*       ucslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_bch_t* hak_duputobchars (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* ucs,
 | |
| 	hak_oow_t        ucslen,
 | |
| 	hak_oow_t*       bcslen
 | |
| );
 | |
| 
 | |
| 
 | |
| HAK_EXPORT hak_uch_t* hak_dupbtoucstrwithheadroom (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oow_t        headroom_bytes,
 | |
| 	const hak_bch_t* bcs,
 | |
| 	hak_oow_t*       ucslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_bch_t* hak_duputobcstrwithheadroom (
 | |
| 	hak_t*           hak,
 | |
| 	hak_oow_t        headroom_bytes,
 | |
| 	const hak_uch_t* ucs,
 | |
| 	hak_oow_t* bcslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_uch_t* hak_dupbtoucstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* bcs,
 | |
| 	hak_oow_t*       ucslen /* optional: length of returned string */
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_bch_t* hak_duputobcstr (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_uch_t* ucs,
 | |
| 	hak_oow_t*       bcslen /* optional: length of returned string */
 | |
| );
 | |
| 
 | |
| 
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| #	define hak_dupoochars(hak,oocs,oocslen) hak_dupuchars(hak,oocs,oocslen)
 | |
| #	define hak_dupoocstr(hak,oocs,oocslen) hak_dupucstr(hak,oocs,oocslen)
 | |
| #else
 | |
| #	define hak_dupoochars(hak,oocs,oocslen) hak_dupbchars(hak,oocs,oocslen)
 | |
| #	define hak_dupoocstr(hak,oocs,oocslen) hak_dupbcstr(hak,oocs,oocslen)
 | |
| #endif
 | |
| 
 | |
| HAK_EXPORT hak_uch_t* hak_dupuchars (
 | |
|     hak_t*           hak,
 | |
|     const hak_uch_t* ucs,
 | |
|     hak_oow_t        ucslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_bch_t* hak_dupbchars (
 | |
|     hak_t*           hak,
 | |
|     const hak_bch_t* bcs,
 | |
|     hak_oow_t        bcslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_uch_t* hak_dupucstr (
 | |
|     hak_t*           hak,
 | |
|     const hak_uch_t* ucs,
 | |
|     hak_oow_t*       ucslen
 | |
| );
 | |
| 
 | |
| HAK_EXPORT hak_bch_t* hak_dupbcstr (
 | |
|     hak_t*           hak,
 | |
|     const hak_bch_t* bcs,
 | |
|     hak_oow_t*       bcslen
 | |
| );
 | |
| 
 | |
| /* =========================================================================
 | |
|  * ASSERTION SUPPORT
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT void hak_assertfailed (
 | |
| 	hak_t*           hak,
 | |
| 	const hak_bch_t* expr,
 | |
| 	const hak_bch_t* file,
 | |
| 	hak_oow_t        line
 | |
| );
 | |
| 
 | |
| 
 | |
| /* =========================================================================
 | |
|  * HELPERS
 | |
|  * ========================================================================= */
 | |
| HAK_EXPORT void hak_start_ticker (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_stop_ticker (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_catch_termreq (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| HAK_EXPORT void hak_uncatch_termreq (
 | |
| 	void
 | |
| );
 | |
| 
 | |
| #if defined(__cplusplus)
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #endif
 |