diff options
Diffstat (limited to 'include')
35 files changed, 2254 insertions, 1100 deletions
diff --git a/include/mrbconf.h b/include/mrbconf.h index cc28acfaa..2a320f371 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -25,30 +25,73 @@ #endif /* configuration options: */ -/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */ -//#define MRB_USE_FLOAT +/* add -DMRB_USE_FLOAT32 to use float instead of double for floating-point numbers */ +//#define MRB_USE_FLOAT32 -/* exclude floating point numbers */ -//#define MRB_WITHOUT_FLOAT +/* exclude floating-point numbers */ +//#define MRB_NO_FLOAT -/* add -DMRB_METHOD_CACHE to use method cache to improve performance */ -//#define MRB_METHOD_CACHE +/* obsolete configuration */ +#if defined(MRB_USE_FLOAT) +# define MRB_USE_FLOAT32 +#endif + +/* obsolete configuration */ +#if defined(MRB_WITHOUT_FLOAT) +# define MRB_NO_FLOAT +#endif + +#if defined(MRB_USE_FLOAT32) && defined(MRB_NO_FLOAT) +#error Cannot define MRB_USE_FLOAT32 and MRB_NO_FLOAT at the same time +#endif + +/* add -DMRB_NO_METHOD_CACHE to disable method cache to save memory */ +//#define MRB_NO_METHOD_CACHE /* size of the method cache (need to be the power of 2) */ -//#define MRB_METHOD_CACHE_SIZE (1<<7) +//#define MRB_METHOD_CACHE_SIZE (1<<8) + +/* add -DMRB_USE_METHOD_T_STRUCT on machines that use higher bits of function pointers */ +/* no MRB_USE_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */ +#ifndef MRB_USE_METHOD_T_STRUCT + // can't use highest 2 bits of function pointers at least on 32bit + // Windows and 32bit Linux. +# ifdef MRB_32BIT +# define MRB_USE_METHOD_T_STRUCT +# endif +#endif -/* add -DMRB_METHOD_TABLE_INLINE to reduce the size of method table */ -/* MRB_METHOD_TABLE_INLINE requires LSB of function pointers to be zero */ -/* you might need to specify --falign-functions=n (where n>1) */ -//#define MRB_METHOD_TABLE_INLINE +/* define on big endian machines; used by MRB_NAN_BOXING, etc. */ +#ifndef MRB_ENDIAN_BIG +# if (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define MRB_ENDIAN_BIG +# endif +#endif -/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */ -//#define MRB_INT16 +/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT32 and MRB_NO_FLOAT */ +//#define MRB_NAN_BOXING -/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */ +/* represent mrb_value as a word (natural unit of data for the processor) */ +//#define MRB_WORD_BOXING + +/* represent mrb_value as a struct; occupies 2 words */ +//#define MRB_NO_BOXING + +/* if no specific boxing type is chosen */ +#if !defined(MRB_NAN_BOXING) && !defined(MRB_WORD_BOXING) && !defined(MRB_NO_BOXING) +# define MRB_WORD_BOXING +#endif + +/* add -DMRB_INT32 to use 32bit integer for mrb_int; conflict with MRB_INT64; + Default for 32-bit CPU mode. */ +//#define MRB_INT32 + +/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT32; + Default for 64-bit CPU mode (unless using MRB_NAN_BOXING). */ //#define MRB_INT64 /* if no specific integer type is chosen */ -#if !defined(MRB_INT16) && !defined(MRB_INT32) && !defined(MRB_INT64) +#if !defined(MRB_INT32) && !defined(MRB_INT64) # if defined(MRB_64BIT) && !defined(MRB_NAN_BOXING) /* Use 64bit integers on 64bit architecture (without MRB_NAN_BOXING) */ # define MRB_INT64 @@ -58,14 +101,8 @@ # endif #endif -/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT and MRB_WITHOUT_FLOAT */ -//#define MRB_NAN_BOXING - -/* define on big endian machines; used by MRB_NAN_BOXING */ -//#define MRB_ENDIAN_BIG - -/* represent mrb_value as a word (natural unit of data for the processor) */ -//#define MRB_WORD_BOXING +/* call malloc_trim(0) from mrb_full_gc() */ +//#define MRB_USE_MALLOC_TRIM /* string class to handle UTF-8 encoding */ //#define MRB_UTF8_STRING @@ -76,12 +113,13 @@ /* number of object per heap page */ //#define MRB_HEAP_PAGE_SIZE 1024 -/* if _etext and _edata available, mruby can reduce memory used by symbols */ -//#define MRB_USE_ETEXT_EDATA +/* if __ehdr_start is available, mruby can reduce memory used by symbols */ +//#define MRB_USE_LINK_TIME_RO_DATA_P -/* do not use __init_array_start to determine readonly data section; - effective only when MRB_USE_ETEXT_EDATA is defined */ -//#define MRB_NO_INIT_ARRAY_START +/* if MRB_USE_LINK_TIME_RO_DATA_P does not work, + you can try mrb_ro_data_p() that you have implemented yourself in any file; + prototype is `mrb_bool mrb_ro_data_p(const char *ptr)` */ +//#define MRB_USE_CUSTOM_RO_DATA_P /* turn off generational GC by default */ //#define MRB_GC_TURN_OFF_GENERATIONAL @@ -95,9 +133,6 @@ /* page size of memory pool */ //#define POOL_PAGE_SIZE 16000 -/* initial minimum size for string buffer */ -//#define MRB_STR_BUF_MIN_SIZE 128 - /* arena size */ //#define MRB_GC_ARENA_SIZE 100 @@ -110,34 +145,82 @@ /* fixed size state atexit stack */ //#define MRB_FIXED_STATE_ATEXIT_STACK -/* -DMRB_DISABLE_XXXX to drop following features */ -//#define MRB_DISABLE_STDIO /* use of stdio */ - -/* -DMRB_ENABLE_XXXX to enable following features */ -//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */ +/* -DMRB_NO_XXXX to drop following features */ +//#define MRB_NO_STDIO /* use of stdio */ -/* end of configuration */ +/* -DMRB_USE_XXXX to enable following features */ +//#define MRB_USE_DEBUG_HOOK /* hooks for debugger */ +//#define MRB_USE_ALL_SYMBOLS /* Symbol.all_symbols */ -/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */ -#ifdef DISABLE_STDIO -#define MRB_DISABLE_STDIO +/* obsolete configurations */ +#ifdef MRB_METHOD_T_STRUCT +# define MRB_USE_METHOD_T_STRUCT #endif - -/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */ -#ifdef ENABLE_DEBUG -#define MRB_ENABLE_DEBUG_HOOK +#if defined(DISABLE_STDIO) || defined(MRB_DISABLE_STDIO) +# define MRB_NO_STDIO +#endif +#ifdef MRB_DISABLE_DIRECT_THREADING +# define MRB_NO_DIRECT_THREADING +#endif +#if defined(ENABLE_DEBUG) || defined(MRB_ENABLE_DEBUG_HOOK) +# define MRB_USE_DEBUG_HOOK +#endif +#ifdef MRB_ENABLE_ALL_SYMBOLS +# define MRB_USE_ALL_SYMBOLS +#endif +#ifdef MRB_ENABLE_CXX_ABI +# define MRB_USE_CXX_ABI +#endif +#ifdef MRB_ENABLE_CXX_EXCEPTION +# define MRB_USE_CXX_EXCEPTION #endif -#ifndef MRB_DISABLE_STDIO +/* end of configuration */ + +#ifndef MRB_NO_STDIO # include <stdio.h> #endif -#ifndef FALSE -# define FALSE 0 -#endif +/* +** mruby tuning profiles +**/ + +/* A profile for micro controllers */ +#if defined(MRB_CONSTRAINED_BASELINE_PROFILE) +# ifndef MRB_NO_METHOD_CACHE +# define MRB_NO_METHOD_CACHE +# endif -#ifndef TRUE -# define TRUE 1 +# ifndef KHASH_DEFAULT_SIZE +# define KHASH_DEFAULT_SIZE 16 +# endif + +# ifndef MRB_HEAP_PAGE_SIZE +# define MRB_HEAP_PAGE_SIZE 256 +# endif + +/* A profile for default mruby */ +#elif defined(MRB_BASELINE_PROFILE) + +/* A profile for desktop computers or workstations; rich memory! */ +#elif defined(MRB_MAIN_PROFILE) +# ifndef MRB_METHOD_CACHE_SIZE +# define MRB_METHOD_CACHE_SIZE (1<<10) +# endif + +# ifndef MRB_HEAP_PAGE_SIZE +# define MRB_HEAP_PAGE_SIZE 4096 +# endif + +/* A profile for server; mruby vm is long life */ +#elif defined(MRB_HIGH_PROFILE) +# ifndef MRB_METHOD_CACHE_SIZE +# define MRB_METHOD_CACHE_SIZE (1<<12) +# endif + +# ifndef MRB_HEAP_PAGE_SIZE +# define MRB_HEAP_PAGE_SIZE 4096 +# endif #endif #endif /* MRUBYCONF_H */ diff --git a/include/mruby.h b/include/mruby.h index 8eff31746..93aab5672 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1,7 +1,7 @@ /* ** mruby - An embeddable Ruby implementation ** -** Copyright (c) mruby developers 2010-2018 +** Copyright (c) mruby developers 2010-2021 ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the @@ -22,9 +22,13 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** -** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] +** [ MIT license: https://www.opensource.org/licenses/mit-license.php ] */ +/** + * @file mruby.h + */ + #ifndef MRUBY_H #define MRUBY_H @@ -34,6 +38,7 @@ #define __STDC_FORMAT_MACROS #endif +#include <stdarg.h> #include <stdint.h> #include <stddef.h> #include <limits.h> @@ -48,6 +53,10 @@ #endif #endif +#ifdef _MSC_VER +# define __func__ __FUNCTION__ +#endif + #ifdef MRB_DEBUG #include <assert.h> #define mrb_assert(p) assert(p) @@ -57,15 +66,37 @@ #define mrb_assert_int_fit(t1,n,t2,max) ((void)0) #endif -#if __STDC_VERSION__ >= 201112L -#define mrb_static_assert(exp, str) _Static_assert(exp, str) +#if (defined __cplusplus && __cplusplus >= 201103L) || \ + (defined _MSC_VER) || \ + (defined __GXX_EXPERIMENTAL_CXX0X__) /* for old G++/Clang++ */ +# define mrb_static_assert(exp, str) static_assert(exp, str) +#elif defined __STDC_VERSION__ && \ + ((__STDC_VERSION__ >= 201112L) || \ + (defined __GNUC__ && __GNUC__ * 100 + __GNUC_MINOR__ >= 406)) +# define mrb_static_assert(exp, str) _Static_assert(exp, str) #else -#define mrb_static_assert(exp, str) mrb_assert(exp) +# /* alternative implementation of static_assert() */ +# define _mrb_static_assert_cat0(a, b) a##b +# define _mrb_static_assert_cat(a, b) _mrb_static_assert_cat0(a, b) +# ifdef __COUNTER__ +# define _mrb_static_assert_id(prefix) _mrb_static_assert_cat(prefix, __COUNTER__) +# else +# define _mrb_static_assert_id(prefix) _mrb_static_assert_cat(prefix, __LINE__) +# endif +# define mrb_static_assert(exp, str) \ + struct _mrb_static_assert_id(_mrb_static_assert_) { char x[(exp) ? 1 : -1]; } #endif +#define mrb_static_assert1(exp) mrb_static_assert(exp, #exp) #include "mrbconf.h" -#ifndef MRB_WITHOUT_FLOAT +#include <mruby/common.h> +#include <mruby/value.h> +#include <mruby/gc.h> +#include <mruby/version.h> + +#ifndef MRB_NO_FLOAT +#include <float.h> #ifndef FLT_EPSILON #define FLT_EPSILON (1.19209290e-07f) #endif @@ -76,18 +107,13 @@ #define LDBL_EPSILON (1.08420217248550443401e-19L) #endif -#ifdef MRB_USE_FLOAT +#ifdef MRB_USE_FLOAT32 #define MRB_FLOAT_EPSILON FLT_EPSILON #else #define MRB_FLOAT_EPSILON DBL_EPSILON #endif #endif -#include "mruby/common.h" -#include <mruby/value.h> -#include <mruby/gc.h> -#include <mruby/version.h> - /** * MRuby C API entry point */ @@ -96,11 +122,14 @@ MRB_BEGIN_DECL typedef uint8_t mrb_code; /** - * Required arguments signature type. + * \class mrb_aspec + * + * Specifies the number of arguments a function takes + * + * Example: `MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)` for a method that expects 2..3 arguments */ typedef uint32_t mrb_aspec; - struct mrb_irep; struct mrb_state; @@ -121,16 +150,15 @@ typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud); typedef struct { mrb_sym mid; - struct RProc *proc; - mrb_value *stackent; - uint16_t ridx; - uint16_t epos; - struct REnv *env; - mrb_code *pc; /* return address */ - mrb_code *err; /* error position */ - int argc; - int acc; - struct RClass *target_class; + int16_t argc; + int16_t acc; + const struct RProc *proc; + mrb_value *stack; + const mrb_code *pc; /* current address on iseq of this proc */ + union { + struct REnv *env; + struct RClass *target_class; + } u; } mrb_callinfo; enum mrb_fiber_state { @@ -145,37 +173,40 @@ enum mrb_fiber_state { struct mrb_context { struct mrb_context *prev; - mrb_value *stack; /* stack of virtual machine */ - mrb_value *stbase, *stend; + mrb_value *stbase, *stend; /* stack of virtual machine */ mrb_callinfo *ci; mrb_callinfo *cibase, *ciend; - uint16_t *rescue; /* exception handler stack */ - uint16_t rsize; - struct RProc **ensure; /* ensure handler stack */ - uint16_t esize, eidx; - - enum mrb_fiber_state status; - mrb_bool vmexec; + enum mrb_fiber_state status : 4; + mrb_bool vmexec : 1; struct RFiber *fib; }; #ifdef MRB_METHOD_CACHE_SIZE -# define MRB_METHOD_CACHE +# undef MRB_NO_METHOD_CACHE #else -/* default method cache size: 128 */ +/* default method cache size: 256 */ /* cache size needs to be power of 2 */ -# define MRB_METHOD_CACHE_SIZE (1<<7) +# define MRB_METHOD_CACHE_SIZE (1<<8) #endif -typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value); +/** + * Function pointer type for a function callable by mruby. + * + * The arguments to the function are stored on the mrb_state. To get them see mrb_get_args + * + * @param mrb The mruby state + * @param self The self object + * @return [mrb_value] The function's return value + */ +typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value self); -#ifdef MRB_METHOD_TABLE_INLINE +#ifndef MRB_USE_METHOD_T_STRUCT typedef uintptr_t mrb_method_t; #else typedef struct { - mrb_bool func_p; + uint8_t flags; union { struct RProc *proc; mrb_func_t func; @@ -183,7 +214,7 @@ typedef struct { } mrb_method_t; #endif -#ifdef MRB_METHOD_CACHE +#ifndef MRB_NO_METHOD_CACHE struct mrb_cache_entry { struct RClass *c, *c0; mrb_sym mid; @@ -195,13 +226,9 @@ struct mrb_jmpbuf; typedef void (*mrb_atexit_func)(struct mrb_state*); -#define MRB_STATE_NO_REGEXP 1 -#define MRB_STATE_REGEXP 2 - typedef struct mrb_state { struct mrb_jmpbuf *jmp; - uint32_t flags; mrb_allocf allocf; /* memory allocation function */ void *allocf_ud; /* auxiliary data of allocf */ @@ -221,31 +248,33 @@ typedef struct mrb_state { struct RClass *hash_class; struct RClass *range_class; -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT struct RClass *float_class; #endif - struct RClass *fixnum_class; + struct RClass *integer_class; struct RClass *true_class; struct RClass *false_class; struct RClass *nil_class; struct RClass *symbol_class; struct RClass *kernel_module; - struct alloca_header *mems; mrb_gc gc; -#ifdef MRB_METHOD_CACHE +#ifndef MRB_NO_METHOD_CACHE struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE]; #endif mrb_sym symidx; - struct kh_n2s *name2sym; /* symbol hash */ struct symbol_name *symtbl; /* symbol table */ + mrb_sym symhash[256]; size_t symcapa; +#ifndef MRB_USE_ALL_SYMBOLS + char symbuf[8]; /* buffer for small symbol names */ +#endif -#ifdef MRB_ENABLE_DEBUG_HOOK - void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); - void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); +#ifdef MRB_USE_DEBUG_HOOK + void (*code_fetch_hook)(struct mrb_state* mrb, const struct mrb_irep *irep, const mrb_code *pc, mrb_value *regs); + void (*debug_op_hook)(struct mrb_state* mrb, const struct mrb_irep *irep, const mrb_code *pc, mrb_value *regs); #endif #ifdef MRB_BYTECODE_DECODE_OPTION @@ -257,7 +286,7 @@ typedef struct mrb_state { struct RObject *nomem_err; /* pre-allocated NoMemoryError */ struct RObject *stack_err; /* pre-allocated SysStackError */ #ifdef MRB_GC_FIXED_ARENA - struct RObject *arena_err; /* pre-allocated arena overfow error */ + struct RObject *arena_err; /* pre-allocated arena overflow error */ #endif void *ud; /* auxiliary data */ @@ -267,7 +296,7 @@ typedef struct mrb_state { #else mrb_atexit_func *atexit_stack; #endif - mrb_int atexit_stack_len; + uint16_t atexit_stack_len; } mrb_state; /** @@ -285,23 +314,27 @@ typedef struct mrb_state { * //free(TheAnimals); * } * - * @param [mrb_state *] mrb The current mruby state. - * @param [const char *] name The name of the defined class. - * @param [struct RClass *] super The new class parent. + * @param mrb The current mruby state. + * @param name The name of the defined class. + * @param super The new class parent. * @return [struct RClass *] Reference to the newly defined class. * @see mrb_define_class_under */ MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super); +MRB_API struct RClass *mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super); /** * Defines a new module. * - * @param [mrb_state *] mrb_state* The current mruby state. - * @param [const char *] char* The name of the module. + * @param mrb The current mruby state. + * @param name The name of the module. * @return [struct RClass *] Reference to the newly defined module. */ -MRB_API struct RClass *mrb_define_module(mrb_state *, const char*); -MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value); +MRB_API struct RClass *mrb_define_module(mrb_state *mrb, const char *name); +MRB_API struct RClass *mrb_define_module_id(mrb_state *mrb, mrb_sym name); + +MRB_API mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value val); +MRB_API struct RClass *mrb_singleton_class_ptr(mrb_state *mrb, mrb_value val); /** * Include a module in another class or module. @@ -310,11 +343,11 @@ MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value); * module B * include A * end - * @param [mrb_state *] mrb_state* The current mruby state. - * @param [struct RClass *] RClass* A reference to module or a class. - * @param [struct RClass *] RClass* A reference to the module to be included. + * @param mrb The current mruby state. + * @param cla A reference to module or a class. + * @param included A reference to the module to be included. */ -MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); +MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *cla, struct RClass *included); /** * Prepends a module in another class or module. @@ -323,11 +356,11 @@ MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); * module B * prepend A * end - * @param [mrb_state *] mrb_state* The current mruby state. - * @param [struct RClass *] RClass* A reference to module or a class. - * @param [struct RClass *] RClass* A reference to the module to be prepended. + * @param mrb The current mruby state. + * @param cla A reference to module or a class. + * @param prepended A reference to the module to be prepended. */ -MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*); +MRB_API void mrb_prepend_module(mrb_state *mrb, struct RClass *cla, struct RClass *prepended); /** * Defines a global function in ruby. @@ -336,7 +369,6 @@ MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*); * * Example: * - * !!!c * mrb_value example_method(mrb_state* mrb, mrb_value self) * { * puts("Executing example command!"); @@ -348,13 +380,14 @@ MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*); * mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE()); * } * - * @param [mrb_state *] mrb The MRuby state reference. - * @param [struct RClass *] cla The class pointer where the method will be defined. - * @param [const char *] name The name of the method being defined. - * @param [mrb_func_t] func The function pointer to the method definition. - * @param [mrb_aspec] aspec The method parameters declaration. + * @param mrb The MRuby state reference. + * @param cla The class pointer where the method will be defined. + * @param name The name of the method being defined. + * @param func The function pointer to the method definition. + * @param aspec The method parameters declaration. */ MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t func, mrb_aspec aspec); +MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec); /** * Defines a class method. @@ -375,14 +408,22 @@ MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *n * foo = mrb_define_class(mrb, "Foo", mrb->object_class); * mrb_define_class_method(mrb, foo, "bar", bar_method, MRB_ARGS_NONE()); * } - * @param [mrb_state *] mrb_state* The MRuby state reference. - * @param [struct RClass *] RClass* The class where the class method will be defined. - * @param [const char *] char* The name of the class method being defined. - * @param [mrb_func_t] mrb_func_t The function pointer to the class method definition. - * @param [mrb_aspec] mrb_aspec The method parameters declaration. + * @param mrb The MRuby state reference. + * @param cla The class where the class method will be defined. + * @param name The name of the class method being defined. + * @param fun The function pointer to the class method definition. + * @param aspec The method parameters declaration. + */ +MRB_API void mrb_define_class_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t fun, mrb_aspec aspec); +MRB_API void mrb_define_class_method_id(mrb_state *mrb, struct RClass *cla, mrb_sym name, mrb_func_t fun, mrb_aspec aspec); + +/** + * Defines a singleton method + * + * @see mrb_define_class_method */ -MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec); -MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec); +MRB_API void mrb_define_singleton_method(mrb_state *mrb, struct RObject *cla, const char *name, mrb_func_t fun, mrb_aspec aspec); +MRB_API void mrb_define_singleton_method_id(mrb_state *mrb, struct RObject *cla, mrb_sym name, mrb_func_t fun, mrb_aspec aspec); /** * Defines a module function. @@ -403,13 +444,14 @@ MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char * foo = mrb_define_module(mrb, "Foo"); * mrb_define_module_function(mrb, foo, "bar", bar_method, MRB_ARGS_NONE()); * } - * @param [mrb_state *] mrb_state* The MRuby state reference. - * @param [struct RClass *] RClass* The module where the module function will be defined. - * @param [const char *] char* The name of the module function being defined. - * @param [mrb_func_t] mrb_func_t The function pointer to the module function definition. - * @param [mrb_aspec] mrb_aspec The method parameters declaration. + * @param mrb The MRuby state reference. + * @param cla The module where the module function will be defined. + * @param name The name of the module function being defined. + * @param fun The function pointer to the module function definition. + * @param aspec The method parameters declaration. */ -MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); +MRB_API void mrb_define_module_function(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t fun, mrb_aspec aspec); +MRB_API void mrb_define_module_function_id(mrb_state *mrb, struct RClass *cla, mrb_sym name, mrb_func_t fun, mrb_aspec aspec); /** * Defines a constant. @@ -432,12 +474,13 @@ MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, * mrb_value * mrb_example_gem_final(mrb_state* mrb){ * } - * @param [mrb_state *] mrb_state* The MRuby state reference. - * @param [struct RClass *] RClass* A class or module the constant is defined in. - * @param [const char *] name The name of the constant being defined. - * @param [mrb_value] mrb_value The value for the constant. + * @param mrb The MRuby state reference. + * @param cla A class or module the constant is defined in. + * @param name The name of the constant being defined. + * @param val The value for the constant. */ -MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); +MRB_API void mrb_define_const(mrb_state* mrb, struct RClass* cla, const char *name, mrb_value val); +MRB_API void mrb_define_const_id(mrb_state* mrb, struct RClass* cla, mrb_sym name, mrb_value val); /** * Undefines a method. @@ -483,11 +526,11 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_ * * mrb_example_gem_final(mrb_state* mrb){ * } - * @param [mrb_state*] mrb_state* The mruby state reference. - * @param [struct RClass*] RClass* A class the method will be undefined from. - * @param [const char] const char* The name of the method to be undefined. + * @param mrb The mruby state reference. + * @param cla The class the method will be undefined from. + * @param name The name of the method to be undefined. */ -MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*); +MRB_API void mrb_undef_method(mrb_state *mrb, struct RClass *cla, const char *name); MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym); /** @@ -523,11 +566,12 @@ MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym); * void * mrb_example_gem_final(mrb_state* mrb){ * } - * @param [mrb_state*] mrb_state* The mruby state reference. - * @param [RClass*] RClass* A class the class method will be undefined from. - * @param [constchar*] constchar* The name of the class method to be undefined. + * @param mrb The mruby state reference. + * @param cls A class the class method will be undefined from. + * @param name The name of the class method to be undefined. */ -MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); +MRB_API void mrb_undef_class_method(mrb_state *mrb, struct RClass *cls, const char *name); +MRB_API void mrb_undef_class_method_id(mrb_state *mrb, struct RClass *cls, mrb_sym name); /** * Initialize a new object instance of c class. @@ -551,10 +595,10 @@ MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); * obj = mrb_obj_new(mrb, example_class, 0, NULL); # => ExampleClass.new * mrb_p(mrb, obj); // => Kernel#p * } - * @param [mrb_state*] mrb The current mruby state. - * @param [RClass*] c Reference to the class of the new object. - * @param [mrb_int] argc Number of arguments in argv - * @param [const mrb_value *] argv Array of mrb_value to initialize the object + * @param mrb The current mruby state. + * @param c Reference to the class of the new object. + * @param argc Number of arguments in argv + * @param argv Array of mrb_value to initialize the object * @return [mrb_value] The newly initialized object */ MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv); @@ -565,8 +609,6 @@ MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const return mrb_obj_new(mrb,c,argc,argv); } -MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); - /** * Creates a new instance of Class, Class. * @@ -582,8 +624,8 @@ MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); * mrb_p(mrb, obj); // => Kernel#p * } * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] super The super class or parent. + * @param mrb The current mruby state. + * @param super The super class or parent. * @return [struct RClass *] Reference to the new class. */ MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); @@ -599,7 +641,7 @@ MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); * example_module = mrb_module_new(mrb); * } * - * @param [mrb_state*] mrb The current mruby state. + * @param mrb The current mruby state. * @return [struct RClass *] Reference to the new module. */ MRB_API struct RClass * mrb_module_new(mrb_state *mrb); @@ -626,27 +668,30 @@ MRB_API struct RClass * mrb_module_new(mrb_state *mrb); * } * } * - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name A string representing the name of the class. + * @param mrb The current mruby state. + * @param name A string representing the name of the class. * @return [mrb_bool] A boolean value. */ MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); +MRB_API mrb_bool mrb_class_defined_id(mrb_state *mrb, mrb_sym name); /** * Gets a class. - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name The name of the class. + * @param mrb The current mruby state. + * @param name The name of the class. * @return [struct RClass *] A reference to the class. */ -MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); +MRB_API struct RClass* mrb_class_get(mrb_state *mrb, const char *name); +MRB_API struct RClass* mrb_class_get_id(mrb_state *mrb, mrb_sym name); /** * Gets a exception class. - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name The name of the class. + * @param mrb The current mruby state. + * @param name The name of the class. * @return [struct RClass *] A reference to the class. */ -MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name); +MRB_API struct RClass* mrb_exc_get_id(mrb_state *mrb, mrb_sym name); +#define mrb_exc_get(mrb, name) mrb_exc_get_id(mrb, mrb_intern_cstr(mrb, name)) /** * Returns an mrb_bool. True if inner class was defined, and false if the inner class was not defined. @@ -672,38 +717,46 @@ MRB_API struct RClass * mrb_exc_get(mrb_state *mrb, const char *name); * } * } * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer The name of the outer class. - * @param [const char *] name A string representing the name of the inner class. + * @param mrb The current mruby state. + * @param outer The name of the outer class. + * @param name A string representing the name of the inner class. * @return [mrb_bool] A boolean value. */ MRB_API mrb_bool mrb_class_defined_under(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API mrb_bool mrb_class_defined_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name); /** * Gets a child class. - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer The name of the parent class. - * @param [const char *] name The name of the class. + * @param mrb The current mruby state. + * @param outer The name of the parent class. + * @param name The name of the class. * @return [struct RClass *] A reference to the class. */ MRB_API struct RClass * mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API struct RClass * mrb_class_get_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name); /** * Gets a module. - * @param [mrb_state*] mrb The current mruby state. - * @param [const char *] name The name of the module. + * @param mrb The current mruby state. + * @param name The name of the module. * @return [struct RClass *] A reference to the module. */ MRB_API struct RClass * mrb_module_get(mrb_state *mrb, const char *name); +MRB_API struct RClass * mrb_module_get_id(mrb_state *mrb, mrb_sym name); /** * Gets a module defined under another module. - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer The name of the outer module. - * @param [const char *] name The name of the module. + * @param mrb The current mruby state. + * @param outer The name of the outer module. + * @param name The name of the module. * @return [struct RClass *] A reference to the module. */ MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API struct RClass * mrb_module_get_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name); + +/* a function to raise NotImplementedError with current method name */ +MRB_API void mrb_notimplement(mrb_state*); +/* a function to be replacement of unimplemented method */ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value); /** @@ -711,12 +764,11 @@ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value); * * Equivalent to: * Object#dup - * @param [mrb_state*] mrb The current mruby state. - * @param [mrb_value] obj Object to be duplicate. + * @param mrb The current mruby state. + * @param obj Object to be duplicate. * @return [mrb_value] The newly duplicated object. */ MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj); -MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method); /** * Returns true if obj responds to the given method. If the method was defined for that @@ -753,9 +805,9 @@ MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char * } * } * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] c A reference to a class. - * @param [mrb_sym] mid A symbol referencing a method id. + * @param mrb The current mruby state. + * @param c A reference to a class. + * @param mid A symbol referencing a method id. * @return [mrb_bool] A boolean value. */ MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid); @@ -763,16 +815,18 @@ MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mi /** * Defines a new class under a given module * - * @param [mrb_state*] mrb The current mruby state. - * @param [struct RClass *] outer Reference to the module under which the new class will be defined - * @param [const char *] name The name of the defined class - * @param [struct RClass *] super The new class parent + * @param mrb The current mruby state. + * @param outer Reference to the module under which the new class will be defined + * @param name The name of the defined class + * @param super The new class parent * @return [struct RClass *] Reference to the newly defined class * @see mrb_define_class */ -MRB_API struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super); +MRB_API struct RClass* mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super); +MRB_API struct RClass* mrb_define_class_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name, struct RClass *super); -MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API struct RClass* mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name); +MRB_API struct RClass* mrb_define_module_under_id(mrb_state *mrb, struct RClass *outer, mrb_sym name); /** * Function requires n arguments. @@ -836,38 +890,93 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o * | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` | * | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` | * | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` | - * | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` | - * | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` | - * | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` | - * | `f` | {Float} | {mrb_float} | | - * | `i` | {Integer} | {mrb_int} | | + * | `s` | {String} | const char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` | + * | `z` | {String} | const char * | `NULL` terminated string; `z!` gives `NULL` for `nil` | + * | `a` | {Array} | const {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` | + * | `f` | {Integer}/{Float} | {mrb_float} | | + * | `i` | {Integer}/{Float} | {mrb_int} | | * | `b` | boolean | {mrb_bool} | | - * | `n` | {Symbol} | {mrb_sym} | | + * | `n` | {String}/{Symbol} | {mrb_sym} | | + * | `d` | data | void *, {mrb_data_type} const | 2nd argument will be used to check data type so it won't be modified; when `!` follows, the value may be `nil` | + * | `I` | inline struct | void * | | * | `&` | block | {mrb_value} | &! raises exception if no block given. | - * | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; *! avoid copy of the stack. | - * | | | optional | | After this spec following specs would be optional. | + * | `*` | rest arguments | const {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; `*!` avoid copy of the stack. | + * | <code>\|</code> | optional | | After this spec following specs would be optional. | * | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. | + * | `:` | keyword args | {mrb_kwargs} const | Get keyword arguments. @see mrb_kwargs | * * @see mrb_get_args */ typedef const char *mrb_args_format; /** - * Retrieve arguments from mrb_state. + * Get keyword arguments by `mrb_get_args()` with `:` specifier. + * + * `mrb_kwargs::num` indicates that the number of keyword values. + * + * `mrb_kwargs::values` is an object array, and the keyword argument corresponding to the string array is assigned. + * Note that `undef` is assigned if there is no keyword argument corresponding to `mrb_kwargs::optional`. + * + * `mrb_kwargs::table` accepts a string array. + * + * `mrb_kwargs::required` indicates that the specified number of keywords starting from the beginning of the string array are required. * - * When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are - * applied to received arguments. - * Used inside a function of mrb_func_t type. + * `mrb_kwargs::rest` is the remaining keyword argument that can be accepted as `**rest` in Ruby. + * If `NULL` is specified, `ArgumentError` is raised when there is an undefined keyword. + * + * Examples: + * + * // def method(a: 1, b: 2) + * + * uint32_t kw_num = 2; + * const char *kw_names[kw_num] = { "a", "b" }; + * uint32_t kw_required = 0; + * mrb_value kw_values[kw_num]; + * const mrb_kwargs kwargs = { kw_num, kw_required, kw_names, kw_values, NULL }; + * + * mrb_get_args(mrb, ":", &kwargs); + * if (mrb_undef_p(kw_values[0])) { kw_values[0] = mrb_fixnum_value(1); } + * if (mrb_undef_p(kw_values[1])) { kw_values[1] = mrb_fixnum_value(2); } + * + * + * // def method(str, x:, y: 2, z: "default string", **opts) + * + * mrb_value str, kw_rest; + * uint32_t kw_num = 3; + * const mrb_sym kw_names[kw_num] = { MRB_SYM(x), MRB_SYM(y), MRB_SYM(z) }; + * uint32_t kw_required = 1; + * mrb_value kw_values[kw_num]; + * const mrb_kwargs kwargs = { kw_num, kw_required, kw_names, kw_values, &kw_rest }; + * + * mrb_get_args(mrb, "S:", &str, &kwargs); + * // or: mrb_get_args(mrb, ":S", &kwargs, &str); + * if (mrb_undef_p(kw_values[1])) { kw_values[1] = mrb_fixnum_value(2); } + * if (mrb_undef_p(kw_values[2])) { kw_values[2] = mrb_str_new_cstr(mrb, "default string"); } + */ +typedef struct mrb_kwargs mrb_kwargs; + +struct mrb_kwargs +{ + uint32_t num; /* number of keyword arguments */ + uint32_t required; /* number of required keyword arguments */ + const mrb_sym *table; /* C array of symbols for keyword names */ + mrb_value *values; /* keyword argument values */ + mrb_value *rest; /* keyword rest (dict) */ +}; + +/** + * Retrieve arguments from mrb_state. * * @param mrb The current MRuby state. - * @param format [mrb_args_format] is a list of format specifiers + * @param format is a list of format specifiers * @param ... The passing variadic arguments must be a pointer of retrieving type. * @return the number of arguments retrieved. * @see mrb_args_format + * @see mrb_kwargs */ MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...); -static inline mrb_sym +MRB_INLINE mrb_sym mrb_get_mid(mrb_state *mrb) /* get method symbol */ { return mrb->c->ci->mid; @@ -880,7 +989,25 @@ mrb_get_mid(mrb_state *mrb) /* get method symbol */ */ MRB_API mrb_int mrb_get_argc(mrb_state *mrb); -MRB_API mrb_value* mrb_get_argv(mrb_state *mrb); +/** + * Retrieve an array of arguments from mrb_state. + * + * Correctly handles *splat arguments. + */ +MRB_API const mrb_value *mrb_get_argv(mrb_state *mrb); + +/** + * Retrieve the first and only argument from mrb_state. + * Raises ArgumentError unless the number of arguments is exactly one. + * + * Correctly handles *splat arguments. + */ +MRB_API mrb_value mrb_get_arg1(mrb_state *mrb); + +/** + * Check if a block argument is given from mrb_state. + */ +MRB_API mrb_bool mrb_block_given_p(mrb_state *mrb); /* `strlen` for character string literals (use with caution or `strlen` instead) Adjacent string literals are concatenated in C/C++ in translation phase 6. @@ -893,6 +1020,8 @@ MRB_API mrb_value* mrb_get_argv(mrb_state *mrb); /** * Call existing ruby functions. * + * Example: + * * #include <stdio.h> * #include <mruby.h> * #include "mruby/compile.h" @@ -907,17 +1036,20 @@ MRB_API mrb_value* mrb_get_argv(mrb_state *mrb); * FILE *fp = fopen("test.rb","r"); * mrb_value obj = mrb_load_file(mrb,fp); * mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i)); + * mrb_funcall_id(mrb, obj, MRB_SYM(method_name), 1, mrb_fixnum_value(i)); * fclose(fp); * mrb_close(mrb); - * } - * @param [mrb_state*] mrb_state* The current mruby state. - * @param [mrb_value] mrb_value A reference to an mruby value. - * @param [const char*] const char* The name of the method. - * @param [mrb_int] mrb_int The number of arguments the method has. - * @param [...] ... Variadic values(not type safe!). - * @return [mrb_value] mrb_value mruby function value. + * } + * + * @param mrb The current mruby state. + * @param val A reference to an mruby value. + * @param name The name of the method. + * @param argc The number of arguments the method has. + * @param ... Variadic values(not type safe!). + * @return [mrb_value] mruby function value. */ -MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); +MRB_API mrb_value mrb_funcall(mrb_state *mrb, mrb_value val, const char *name, mrb_int argc, ...); +MRB_API mrb_value mrb_funcall_id(mrb_state *mrb, mrb_value val, mrb_sym mid, mrb_int argc, ...); /** * Call existing ruby functions. This is basically the type safe version of mrb_funcall. * @@ -927,54 +1059,69 @@ MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); * int * main() * { - * mrb_int i = 99; * mrb_state *mrb = mrb_open(); + * mrb_value obj = mrb_fixnum_value(1); * * if (!mrb) { } - * mrb_sym m_sym = mrb_intern_lit(mrb, "method_name"); // Symbol for method. * * FILE *fp = fopen("test.rb","r"); * mrb_value obj = mrb_load_file(mrb,fp); - * mrb_funcall_argv(mrb, obj, m_sym, 1, &obj); // Calling ruby function from test.rb. + * mrb_funcall_argv(mrb, obj, MRB_SYM(method_name), 1, &obj); // Calling ruby function from test.rb. * fclose(fp); * mrb_close(mrb); * } - * @param [mrb_state*] mrb_state* The current mruby state. - * @param [mrb_value] mrb_value A reference to an mruby value. - * @param [mrb_sym] mrb_sym The symbol representing the method. - * @param [mrb_int] mrb_int The number of arguments the method has. - * @param [const mrb_value*] mrb_value* Pointer to the object. + * @param mrb The current mruby state. + * @param val A reference to an mruby value. + * @param name_sym The symbol representing the method. + * @param argc The number of arguments the method has. + * @param obj Pointer to the object. * @return [mrb_value] mrb_value mruby function value. * @see mrb_funcall */ -MRB_API mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*); +MRB_API mrb_value mrb_funcall_argv(mrb_state *mrb, mrb_value val, mrb_sym name, mrb_int argc, const mrb_value *argv); /** * Call existing ruby functions with a block. */ -MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value); +MRB_API mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value val, mrb_sym name, mrb_int argc, const mrb_value *argv, mrb_value block); /** - * Create a symbol + * Create a symbol from C string. But usually it's better to use MRB_SYM, + * MRB_OPSYM, MRB_CVSYM, MRB_IVSYM, MRB_SYM_B, MRB_SYM_Q, MRB_SYM_E macros. + * + * Example: * * # Ruby style: * :pizza # => :pizza * * // C style: - * mrb_sym m_sym = mrb_intern_lit(mrb, "pizza"); // => :pizza - * @param [mrb_state*] mrb_state* The current mruby state. - * @param [const char*] const char* The name of the method. + * mrb_sym sym1 = mrb_intern_lit(mrb, "pizza"); // => :pizza + * mrb_sym sym2 = MRB_SYM(pizza); // => :pizza + * mrb_sym sym3 = MRB_SYM_Q(pizza); // => :pizza? + * + * @param mrb The current mruby state. + * @param str The string to be symbolized * @return [mrb_sym] mrb_sym A symbol. */ -MRB_API mrb_sym mrb_intern_cstr(mrb_state*,const char*); +MRB_API mrb_sym mrb_intern_cstr(mrb_state *mrb, const char* str); MRB_API mrb_sym mrb_intern(mrb_state*,const char*,size_t); MRB_API mrb_sym mrb_intern_static(mrb_state*,const char*,size_t); -#define mrb_intern_lit(mrb, lit) mrb_intern_static(mrb, lit, mrb_strlen_lit(lit)) +#define mrb_intern_lit(mrb, lit) mrb_intern_static(mrb, (lit ""), mrb_strlen_lit(lit)) MRB_API mrb_sym mrb_intern_str(mrb_state*,mrb_value); +/* mrb_intern_check series functions returns 0 if the symbol is not defined */ +MRB_API mrb_sym mrb_intern_check_cstr(mrb_state*,const char*); +MRB_API mrb_sym mrb_intern_check(mrb_state*,const char*,size_t); +MRB_API mrb_sym mrb_intern_check_str(mrb_state*,mrb_value); +/* mrb_check_intern series functions returns nil if the symbol is not defined */ +/* otherwise returns mrb_value */ MRB_API mrb_value mrb_check_intern_cstr(mrb_state*,const char*); MRB_API mrb_value mrb_check_intern(mrb_state*,const char*,size_t); MRB_API mrb_value mrb_check_intern_str(mrb_state*,mrb_value); -MRB_API const char *mrb_sym2name(mrb_state*,mrb_sym); -MRB_API const char *mrb_sym2name_len(mrb_state*,mrb_sym,mrb_int*); -MRB_API mrb_value mrb_sym2str(mrb_state*,mrb_sym); +MRB_API const char *mrb_sym_name(mrb_state*,mrb_sym); +MRB_API const char *mrb_sym_name_len(mrb_state*,mrb_sym,mrb_int*); +MRB_API const char *mrb_sym_dump(mrb_state*,mrb_sym); +MRB_API mrb_value mrb_sym_str(mrb_state*,mrb_sym); +#define mrb_sym2name(mrb,sym) mrb_sym_name(mrb,sym) +#define mrb_sym2name_len(mrb,sym,len) mrb_sym_name_len(mrb,sym,len) +#define mrb_sym2str(mrb,sym) mrb_sym_str(mrb,sym) MRB_API void *mrb_malloc(mrb_state*, size_t); /* raise RuntimeError if no mem */ MRB_API void *mrb_calloc(mrb_state*, size_t, size_t); /* ditto */ @@ -984,6 +1131,17 @@ MRB_API void *mrb_malloc_simple(mrb_state*, size_t); /* return NULL if no memor MRB_API struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*); MRB_API void mrb_free(mrb_state*, void*); +/** + * Allocates a Ruby object that matches the constant literal defined in + * `enum mrb_vtype` and returns a pointer to the corresponding C type. + * + * @param mrb The current mruby state + * @param tt The constant literal of `enum mrb_vtype` + * @param klass A Class object + * @return Reference to the newly created object + */ +#define MRB_OBJ_ALLOC(mrb, tt, klass) ((MRB_VTYPE_TYPEOF(tt)*)mrb_obj_alloc(mrb, tt, klass)) + MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); /** @@ -993,14 +1151,20 @@ MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*); MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len); #define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit)) +MRB_API mrb_value mrb_obj_freeze(mrb_state*, mrb_value); +#define mrb_str_new_frozen(mrb,p,len) mrb_obj_freeze(mrb,mrb_str_new(mrb,p,len)) +#define mrb_str_new_cstr_frozen(mrb,p) mrb_obj_freeze(mrb,mrb_str_new_cstr(mrb,p)) +#define mrb_str_new_static_frozen(mrb,p,len) mrb_obj_freeze(mrb,mrb_str_new_static(mrb,p,len)) +#define mrb_str_new_lit_frozen(mrb,lit) mrb_obj_freeze(mrb,mrb_str_new_lit(mrb,lit)) + #ifdef _WIN32 MRB_API char* mrb_utf8_from_locale(const char *p, int len); MRB_API char* mrb_locale_from_utf8(const char *p, int len); #define mrb_locale_free(p) free(p) #define mrb_utf8_free(p) free(p) #else -#define mrb_utf8_from_locale(p, l) ((char*)p) -#define mrb_locale_from_utf8(p, l) ((char*)p) +#define mrb_utf8_from_locale(p, l) ((char*)(p)) +#define mrb_locale_from_utf8(p, l) ((char*)(p)) #define mrb_locale_free(p) #define mrb_utf8_free(p) #endif @@ -1055,11 +1219,10 @@ MRB_API void mrb_close(mrb_state *mrb); */ MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*); -MRB_API mrb_value mrb_top_self(mrb_state *); -MRB_API mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value); -MRB_API mrb_value mrb_top_run(mrb_state*, struct RProc*, mrb_value, unsigned int); -MRB_API mrb_value mrb_vm_run(mrb_state*, struct RProc*, mrb_value, unsigned int); -MRB_API mrb_value mrb_vm_exec(mrb_state*, struct RProc*, mrb_code*); +MRB_API mrb_value mrb_top_self(mrb_state *mrb); +MRB_API mrb_value mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep); +MRB_API mrb_value mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int stack_keep); +MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *iseq); /* compatibility macros */ #define mrb_toplevel_run_keep(m,p,k) mrb_top_run((m),(p),mrb_top_self(m),(k)) #define mrb_toplevel_run(m,p) mrb_toplevel_run_keep((m),(p),0) @@ -1069,27 +1232,25 @@ MRB_API void mrb_p(mrb_state*, mrb_value); MRB_API mrb_int mrb_obj_id(mrb_value obj); MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name); -MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value); -MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value); +MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value a, mrb_value b); +MRB_API mrb_bool mrb_obj_equal(mrb_state *mrb, mrb_value a, mrb_value b); MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2); MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base); -MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val); -#ifndef MRB_WITHOUT_FLOAT -MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val); +#ifndef MRB_NO_FLOAT +MRB_API mrb_value mrb_to_float(mrb_state *mrb, mrb_value val); #endif MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj); MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2); +/* mrb_cmp(mrb, obj1, obj2): 1:0:-1; -2 for error */ +MRB_API mrb_int mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2); -static inline int mrb_gc_arena_save(mrb_state*); -static inline void mrb_gc_arena_restore(mrb_state*,int); - -static inline int +MRB_INLINE int mrb_gc_arena_save(mrb_state *mrb) { return mrb->gc.arena_idx; } -static inline void +MRB_INLINE void mrb_gc_arena_restore(mrb_state *mrb, int idx) { mrb->gc.arena_idx = idx; @@ -1108,12 +1269,15 @@ MRB_API void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic* } while (0) MRB_API void mrb_write_barrier(mrb_state *, struct RBasic*); -MRB_API mrb_value mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method); +MRB_API mrb_value mrb_type_convert(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym method); +#define mrb_convert_type(mrb, val, type, tname, method) mrb_type_convert(mrb, val, type, mrb_intern_lit(mrb, method)) +MRB_API mrb_value mrb_type_convert_check(mrb_state *mrb, mrb_value val, enum mrb_vtype type, mrb_sym method); +#define mrb_check_convert_type(mrb, val, type, tname, method) mrb_type_convert_check(mrb, val, type, mrb_intern_lit(mrb, method)) + MRB_API mrb_value mrb_any_to_s(mrb_state *mrb, mrb_value obj); MRB_API const char * mrb_obj_classname(mrb_state *mrb, mrb_value obj); MRB_API struct RClass* mrb_obj_class(mrb_state *mrb, mrb_value obj); MRB_API mrb_value mrb_class_path(mrb_state *mrb, struct RClass *c); -MRB_API mrb_value mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method); MRB_API mrb_bool mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c); MRB_API mrb_value mrb_obj_inspect(mrb_state *mrb, mrb_value self); MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self); @@ -1140,36 +1304,40 @@ MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc); MRB_API mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg); MRB_API mrb_noreturn void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...); MRB_API mrb_noreturn void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); +MRB_API mrb_noreturn void mrb_frozen_error(mrb_state *mrb, void *frozen_obj); +MRB_API mrb_noreturn void mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max); MRB_API void mrb_warn(mrb_state *mrb, const char *fmt, ...); MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...); MRB_API void mrb_print_backtrace(mrb_state *mrb); MRB_API void mrb_print_error(mrb_state *mrb); +/* function for `raisef` formatting */ +MRB_API mrb_value mrb_vformat(mrb_state *mrb, const char *format, va_list ap); /* macros to get typical exception objects note: + those E_* macros requires mrb_state* variable named mrb. + exception objects obtained from those macros are local to mrb */ -#define E_RUNTIME_ERROR (mrb_exc_get(mrb, "RuntimeError")) -#define E_TYPE_ERROR (mrb_exc_get(mrb, "TypeError")) -#define E_ARGUMENT_ERROR (mrb_exc_get(mrb, "ArgumentError")) -#define E_INDEX_ERROR (mrb_exc_get(mrb, "IndexError")) -#define E_RANGE_ERROR (mrb_exc_get(mrb, "RangeError")) -#define E_NAME_ERROR (mrb_exc_get(mrb, "NameError")) -#define E_NOMETHOD_ERROR (mrb_exc_get(mrb, "NoMethodError")) -#define E_SCRIPT_ERROR (mrb_exc_get(mrb, "ScriptError")) -#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError")) -#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError")) -#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError")) -#define E_FROZEN_ERROR (mrb_exc_get(mrb, "FrozenError")) - -#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError")) -#ifndef MRB_WITHOUT_FLOAT -#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError")) +#define MRB_ERROR_SYM(sym) mrb_intern_lit(mrb, #sym) +#define E_RUNTIME_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(RuntimeError)) +#define E_TYPE_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(TypeError)) +#define E_ZERODIV_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(ZeroDivisionError)) +#define E_ARGUMENT_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(ArgumentError)) +#define E_INDEX_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(IndexError)) +#define E_RANGE_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(RangeError)) +#define E_NAME_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(NameError)) +#define E_NOMETHOD_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(NoMethodError)) +#define E_SCRIPT_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(ScriptError)) +#define E_SYNTAX_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(SyntaxError)) +#define E_LOCALJUMP_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(LocalJumpError)) +#define E_REGEXP_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(RegexpError)) +#define E_FROZEN_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(FrozenError)) +#define E_NOTIMP_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(NotImplementedError)) +#define E_KEY_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(KeyError)) +#ifndef MRB_NO_FLOAT +# define E_FLOATDOMAIN_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(FloatDomainError)) #endif -#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError")) - MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg); MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c); @@ -1187,17 +1355,19 @@ MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj); MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj); MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val); -#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val)) +#define mrb_as_int(mrb, val) mrb_integer(mrb_to_int(mrb, val)) + +/* string type checking (contrary to the name, it doesn't convert) */ +MRB_API mrb_value mrb_to_str(mrb_state *mrb, mrb_value val); MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); -typedef enum call_type { - CALL_PUBLIC, - CALL_FCALL, - CALL_VCALL, - CALL_TYPE_MAX -} call_type; +MRB_INLINE void mrb_check_frozen(mrb_state *mrb, void *o) +{ + if (mrb_frozen_p((struct RBasic*)o)) mrb_frozen_error(mrb, o); +} MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *c, const char *a, const char *b); +MRB_API void mrb_define_alias_id(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b); MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass); MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val); @@ -1207,34 +1377,36 @@ MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func); +/* obsolete function(s); will be removed */ +#define mrb_int(mrb, val) mrb_as_int(mrb, val) -/* +/** * Resume a Fiber * - * @mrbgem mruby-fiber + * Implemented in mruby-fiber */ MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv); -/* +/** * Yield a Fiber * - * @mrbgem mruby-fiber + * Implemented in mruby-fiber */ MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv); -/* +/** * Check if a Fiber is alive * - * @mrbgem mruby-fiber + * Implemented in mruby-fiber */ MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib); -/* +/** * FiberError reference * - * @mrbgem mruby-fiber + * Implemented in mruby-fiber */ -#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError")) +#define E_FIBER_ERROR mrb_exc_get_id(mrb, MRB_ERROR_SYM(FiberError)) MRB_API void mrb_stack_extend(mrb_state*, mrb_int); /* memory pool implementation */ @@ -1244,6 +1416,7 @@ MRB_API void mrb_pool_close(struct mrb_pool*); MRB_API void* mrb_pool_alloc(struct mrb_pool*, size_t); MRB_API void* mrb_pool_realloc(struct mrb_pool*, void*, size_t oldlen, size_t newlen); MRB_API mrb_bool mrb_pool_can_realloc(struct mrb_pool*, void*, size_t); +/* temporary memory allocation, only effective while GC arena is kept */ MRB_API void* mrb_alloca(mrb_state *mrb, size_t); MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func); @@ -1253,6 +1426,10 @@ MRB_API void mrb_show_copyright(mrb_state *mrb); MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...); +#ifdef MRB_PRESYM_SCANNING +# include <mruby/presym/scanning.h> +#endif + #if 0 /* memcpy and memset does not work with gdb reverse-next on my box */ /* use naive memcpy and memset instead */ diff --git a/include/mruby/array.h b/include/mruby/array.h index 6fffe4512..105e825ea 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -1,5 +1,5 @@ -/* -** mruby/array.h - Array class +/** +** @file mruby/array.h - Array class ** ** See Copyright Notice in mruby.h */ @@ -17,23 +17,32 @@ MRB_BEGIN_DECL typedef struct mrb_shared_array { int refcnt; - mrb_int len; + mrb_ssize len; mrb_value *ptr; } mrb_shared_array; -#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value))) +#if defined(MRB_32BIT) && defined(MRB_NO_BOXING) && !defined(MRB_USE_FLOAT32) +# define MRB_ARY_NO_EMBED +# define MRB_ARY_EMBED_LEN_MAX 0 +#else +# define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value))) +mrb_static_assert(MRB_ARY_EMBED_LEN_MAX > 0, "MRB_ARY_EMBED_LEN_MAX > 0"); +#endif + struct RArray { MRB_OBJECT_HEADER; union { struct { - mrb_int len; + mrb_ssize len; union { - mrb_int capa; + mrb_ssize capa; mrb_shared_array *shared; } aux; mrb_value *ptr; } heap; - mrb_value embed[MRB_ARY_EMBED_LEN_MAX]; +#ifndef MRB_ARY_NO_EMBED + mrb_value ary[MRB_ARY_EMBED_LEN_MAX]; +#endif } as; }; @@ -41,14 +50,22 @@ struct RArray { #define mrb_ary_value(p) mrb_obj_value((void*)(p)) #define RARRAY(v) ((struct RArray*)(mrb_ptr(v))) +#ifdef MRB_ARY_NO_EMBED +#define ARY_EMBED_P(a) 0 +#define ARY_UNSET_EMBED_FLAG(a) (void)0 +#define ARY_EMBED_LEN(a) 0 +#define ARY_SET_EMBED_LEN(a,len) (void)0 +#define ARY_EMBED_PTR(a) 0 +#else #define MRB_ARY_EMBED_MASK 7 #define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK) #define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK)) #define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1)) #define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1)) -#define ARY_EMBED_PTR(a) (&((a)->as.embed[0])) +#define ARY_EMBED_PTR(a) ((a)->as.ary) +#endif -#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len) +#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(mrb_int)(a)->as.heap.len) #define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr) #define RARRAY_LEN(a) ARY_LEN(RARRAY(a)) #define RARRAY_PTR(a) ARY_PTR(RARRAY(a)) @@ -90,7 +107,7 @@ MRB_API mrb_value mrb_ary_new(mrb_state *mrb); * Array[value1, value2, ...] * * @param mrb The mruby state reference. - * @param size The numer of values. + * @param size The number of values. * @param vals The actual values. * @return The initialized array. */ @@ -160,20 +177,6 @@ MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value); MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); /* - * Returns a reference to an element of the array on the given index. - * - * Equivalent to: - * - * ary[n] - * - * @param mrb The mruby state reference. - * @param ary The target array. - * @param n The array index being referenced - * @return The referenced value. - */ -MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); - -/* * Sets a value on an array at the given index * * Equivalent to: @@ -183,7 +186,7 @@ MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); * @param mrb The mruby state reference. * @param ary The target array. * @param n The array index being referenced. - * @param val The value being setted. + * @param val The value being set. */ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); @@ -199,6 +202,7 @@ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val * @param other The array to replace it with. */ MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other); +MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self); MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); /* @@ -225,6 +229,24 @@ MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item * @param offset The element position (negative counts from the tail). */ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset); +#define mrb_ary_ref(mrb, ary, n) mrb_ary_entry(ary, n) + +/* + * Replace subsequence of an array. + * + * Equivalent to: + * + * ary[head, len] = rpl + * + * @param mrb The mruby state reference. + * @param self The array from which the value will be partiality replaced. + * @param head Beginning position of a replacement subsequence. + * @param len Length of a replacement subsequence. + * @param rpl The array of replacement elements. + * It is possible to pass `mrb_undef_value()` instead of an empty array. + * @return The receiver array. + */ +MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl); /* * Shifts the first element from the array. @@ -261,7 +283,7 @@ MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self); * * @param mrb The mruby state reference. * @param ary The target array - * @param sep The separater, can be NULL + * @param sep The separator, can be NULL */ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep); @@ -274,6 +296,9 @@ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep); */ MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len); +/* helper functions */ +mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len); + MRB_END_DECL #endif /* MRUBY_ARRAY_H */ diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h index 3d9bbdc69..05f1d953c 100644 --- a/include/mruby/boxing_nan.h +++ b/include/mruby/boxing_nan.h @@ -1,5 +1,5 @@ -/* -** mruby/boxing_nan.h - nan boxing mrb_value definition +/** +** @file mruby/boxing_nan.h - nan boxing mrb_value definition ** ** See Copyright Notice in mruby.h */ @@ -7,12 +7,12 @@ #ifndef MRUBY_BOXING_NAN_H #define MRUBY_BOXING_NAN_H -#ifdef MRB_USE_FLOAT -# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<---- +#ifdef MRB_USE_FLOAT32 +# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT32 conflict <<---- #endif -#ifdef MRB_WITHOUT_FLOAT -# error ---->> MRB_NAN_BOXING and MRB_WITHOUT_FLOAT conflict <<---- +#ifdef MRB_NO_FLOAT +# error ---->> MRB_NAN_BOXING and MRB_NO_FLOAT conflict <<---- #endif #ifdef MRB_INT64 @@ -20,13 +20,9 @@ #endif #define MRB_FIXNUM_SHIFT 0 -#define MRB_TT_HAS_BASIC MRB_TT_OBJECT - -#ifdef MRB_ENDIAN_BIG -#define MRB_ENDIAN_LOHI(a,b) a b -#else -#define MRB_ENDIAN_LOHI(a,b) b a -#endif +#define MRB_SYMBOL_SHIFT 0 +#define MRB_FIXNUM_MIN INT32_MIN +#define MRB_FIXNUM_MAX INT32_MAX /* value representation by nan-boxing: * float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF @@ -37,66 +33,98 @@ * in the right direction. Also, TTTTTT is the mrb_vtype + 1; */ typedef struct mrb_value { - union { - mrb_float f; - union { - void *p; - struct { - MRB_ENDIAN_LOHI( - uint32_t ttt; - ,union { - mrb_int i; - mrb_sym sym; - }; - ) - }; - } value; - }; + uint64_t u; } mrb_value; -#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) +union mrb_value_ { + mrb_float f; + uint64_t u; +#ifdef MRB_64BIT + void *p; +# define BOXNAN_IMMEDIATE_VALUE uint32_t i +#else +# define BOXNAN_IMMEDIATE_VALUE union { uint32_t i; void *p; } +#endif + struct { + MRB_ENDIAN_LOHI( + uint32_t ttt; + ,BOXNAN_IMMEDIATE_VALUE; + ) + }; + mrb_value value; +}; + +mrb_static_assert1(sizeof(mrb_value) == sizeof(union mrb_value_)); -#define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)-1) -#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT) -#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2)) -#define mrb_float(o) (o).f -#define mrb_cptr(o) mrb_ptr(o) -#define mrb_fixnum(o) (o).value.i -#define mrb_symbol(o) (o).value.sym +static inline union mrb_value_ +mrb_val_union(mrb_value v) +{ + union mrb_value_ x; + x.value = v; + return x; +} + +#define mrb_tt(o) ((enum mrb_vtype)((mrb_val_union(o).ttt & 0xfc000)>>14)-1) +#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < mrb_val_union(o).ttt ? mrb_tt(o) : MRB_TT_FLOAT) +#define mrb_float(o) mrb_val_union(o).f +#define mrb_fixnum(o) ((mrb_int)mrb_val_union(o).i) +#define mrb_integer(o) mrb_fixnum(o) +#define mrb_symbol(o) ((mrb_sym)mrb_val_union(o).i) #ifdef MRB_64BIT +#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)(mrb_val_union(o).p)))<<2)) +#define mrb_cptr(o) (((struct RCptr*)mrb_ptr(o))->p) #define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff) #else +#define mrb_ptr(o) ((void*)mrb_val_union(o).i) +#define mrb_cptr(o) mrb_ptr(o) #define BOXNAN_SHIFT_LONG_POINTER(v) 0 #endif -#define BOXNAN_SET_VALUE(o, tt, attr, v) do {\ - (o).attr = (v);\ - (o).value.ttt = 0xfff00000 | (((tt)+1)<<14);\ +#define BOXNAN_SET_VALUE(o, tt, attr, v) do { \ + union mrb_value_ mrb_value_union_variable; \ + mrb_value_union_variable.attr = (v);\ + mrb_value_union_variable.ttt = 0xfff00000 | (((tt)+1)<<14);\ + o = mrb_value_union_variable.value;\ } while (0) +#ifdef MRB_64BIT #define BOXNAN_SET_OBJ_VALUE(o, tt, v) do {\ - (o).value.p = (void*)((uintptr_t)(v)>>2);\ - (o).value.ttt = (0xfff00000|(((tt)+1)<<14)|BOXNAN_SHIFT_LONG_POINTER(v));\ + union mrb_value_ mrb_value_union_variable;\ + mrb_value_union_variable.p = (void*)((uintptr_t)(v)>>2);\ + mrb_value_union_variable.ttt = (0xfff00000|(((tt)+1)<<14)|BOXNAN_SHIFT_LONG_POINTER(v));\ + o = mrb_value_union_variable.value;\ } while (0) +#else +#define BOXNAN_SET_OBJ_VALUE(o, tt, v) BOXNAN_SET_VALUE(o, tt, i, (uint32_t)v) +#endif #define SET_FLOAT_VALUE(mrb,r,v) do { \ - if (v != v) { \ - (r).value.ttt = 0x7ff80000; \ - (r).value.i = 0; \ + union mrb_value_ mrb_value_union_variable; \ + if ((v) != (v)) { /* NaN */ \ + mrb_value_union_variable.ttt = 0x7ff80000; \ + mrb_value_union_variable.i = 0; \ } \ else { \ - (r).f = v; \ - }} while(0) - -#define SET_NIL_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) -#define SET_FALSE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) -#define SET_TRUE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) -#define SET_BOOL_VALUE(r,b) BOXNAN_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) -#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) + mrb_value_union_variable.f = (v); \ + } \ + r = mrb_value_union_variable.value; \ +} while(0) + +#define SET_NIL_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, i, 0) +#define SET_FALSE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_FALSE, i, 1) +#define SET_TRUE_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_TRUE, i, 1) +#define SET_BOOL_VALUE(r,b) BOXNAN_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, i, 1) +#define SET_INT_VALUE(mrb, r,n) BOXNAN_SET_VALUE(r, MRB_TT_INTEGER, i, (uint32_t)(n)) +#define SET_FIXNUM_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_INTEGER, i, (uint32_t)(n)) +#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, i, (uint32_t)(v)) #define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v)) -#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_OBJ_VALUE(r, MRB_TT_CPTR, v) -#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) +#ifdef MRB_64BIT +MRB_API mrb_value mrb_nan_boxing_cptr_value(struct mrb_state*, void*); +#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_nan_boxing_cptr_value(mrb, v)) +#else +#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, p, v) +#endif +#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, i, 0) #endif /* MRUBY_BOXING_NAN_H */ diff --git a/include/mruby/boxing_no.h b/include/mruby/boxing_no.h index 86ce64555..84908a0d8 100644 --- a/include/mruby/boxing_no.h +++ b/include/mruby/boxing_no.h @@ -1,5 +1,5 @@ -/* -** mruby/boxing_no.h - unboxed mrb_value definition +/** +** @file mruby/boxing_no.h - unboxed mrb_value definition ** ** See Copyright Notice in mruby.h */ @@ -8,30 +8,31 @@ #define MRUBY_BOXING_NO_H #define MRB_FIXNUM_SHIFT 0 -#define MRB_TT_HAS_BASIC MRB_TT_OBJECT +#define MRB_SYMBOL_SHIFT 0 +#define MRB_FIXNUM_MIN MRB_INT_MIN +#define MRB_FIXNUM_MAX MRB_INT_MAX -typedef struct mrb_value { - union { -#ifndef MRB_WITHOUT_FLOAT - mrb_float f; +union mrb_value_union { +#ifndef MRB_NO_FLOAT + mrb_float f; #endif - void *p; - mrb_int i; - mrb_sym sym; - } value; + void *p; + mrb_int i; + mrb_sym sym; +}; + +typedef struct mrb_value { + union mrb_value_union value; enum mrb_vtype tt; } mrb_value; -#ifndef MRB_WITHOUT_FLOAT -#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) -#endif - #define mrb_ptr(o) (o).value.p #define mrb_cptr(o) mrb_ptr(o) -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT #define mrb_float(o) (o).value.f #endif #define mrb_fixnum(o) (o).value.i +#define mrb_integer(o) mrb_fixnum(o) #define mrb_symbol(o) (o).value.sym #define mrb_type(o) (o).tt @@ -44,8 +45,9 @@ typedef struct mrb_value { #define SET_FALSE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) #define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) #define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) -#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#ifndef MRB_WITHOUT_FLOAT +#define SET_INT_VALUE(mrb,r,n) BOXNIX_SET_VALUE(r, MRB_TT_INTEGER, value.i, (n)) +#define SET_FIXNUM_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_INTEGER, value.i, (n)) +#ifndef MRB_NO_FLOAT #define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v)) #endif #define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index 2ff314144..beab8681e 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -1,5 +1,5 @@ -/* -** mruby/boxing_word.h - word boxing mrb_value definition +/** +** @file mruby/boxing_word.h - word boxing mrb_value definition ** ** See Copyright Notice in mruby.h */ @@ -7,138 +7,199 @@ #ifndef MRUBY_BOXING_WORD_H #define MRUBY_BOXING_WORD_H -#if defined(MRB_INT16) -# error MRB_INT16 is too small for MRB_WORD_BOXING. -#endif - -#if defined(MRB_INT64) && !defined(MRB_64BIT) -#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode. -#endif - -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT struct RFloat { MRB_OBJECT_HEADER; mrb_float f; }; #endif -struct RCptr { +struct RInteger { MRB_OBJECT_HEADER; - void *p; + mrb_int i; }; -#define MRB_FIXNUM_SHIFT 1 -#ifdef MRB_WITHOUT_FLOAT -#define MRB_TT_HAS_BASIC MRB_TT_CPTR -#else -#define MRB_TT_HAS_BASIC MRB_TT_FLOAT -#endif - enum mrb_special_consts { - MRB_Qnil = 0, - MRB_Qfalse = 2, - MRB_Qtrue = 4, - MRB_Qundef = 6, + MRB_Qnil = 0, + MRB_Qfalse = 4, + MRB_Qtrue = 12, + MRB_Qundef = 20, }; -#define MRB_FIXNUM_FLAG 0x01 -#define MRB_SYMBOL_FLAG 0x0e -#define MRB_SPECIAL_SHIFT 8 +#if defined(MRB_64BIT) && defined(MRB_INT32) +#define MRB_FIXNUM_SHIFT 0 +#else +#define MRB_FIXNUM_SHIFT BOXWORD_FIXNUM_SHIFT +#endif +#define MRB_SYMBOL_SHIFT BOXWORD_SYMBOL_SHIFT -#if defined(MRB_64BIT) -#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT) -#define MRB_SYMBOL_MAX UINT32_MAX +#if defined(MRB_64BIT) && defined(MRB_INT64) +# define MRB_FIXNUM_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT) +# define MRB_FIXNUM_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT) #else -#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT - MRB_SPECIAL_SHIFT) -#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SPECIAL_SHIFT) +# define MRB_FIXNUM_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT) +# define MRB_FIXNUM_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT) #endif -typedef union mrb_value { - union { - void *p; - struct { - unsigned int i_flag : MRB_FIXNUM_SHIFT; - mrb_int i : (MRB_INT_BIT - MRB_FIXNUM_SHIFT); - }; - struct { - unsigned int sym_flag : MRB_SPECIAL_SHIFT; - mrb_sym sym : MRB_SYMBOL_BITSIZE; - }; - struct RBasic *bp; -#ifndef MRB_WITHOUT_FLOAT - struct RFloat *fp; +#define BOXWORD_FIXNUM_BIT_POS 1 +#define BOXWORD_SYMBOL_BIT_POS 2 +#define BOXWORD_FIXNUM_SHIFT BOXWORD_FIXNUM_BIT_POS +#ifdef MRB_64BIT +#define BOXWORD_SYMBOL_SHIFT 0 +#else +#define BOXWORD_SYMBOL_SHIFT BOXWORD_SYMBOL_BIT_POS #endif - struct RCptr *vp; - } value; - unsigned long w; +#define BOXWORD_FIXNUM_FLAG (1 << (BOXWORD_FIXNUM_BIT_POS - 1)) +#define BOXWORD_SYMBOL_FLAG (1 << (BOXWORD_SYMBOL_BIT_POS - 1)) +#define BOXWORD_FIXNUM_MASK ((1 << BOXWORD_FIXNUM_BIT_POS) - 1) +#define BOXWORD_SYMBOL_MASK ((1 << BOXWORD_SYMBOL_BIT_POS) - 1) +#define BOXWORD_IMMEDIATE_MASK 0x07 + +#define BOXWORD_SET_SHIFT_VALUE(o,n,v) \ + ((o).w = (((uintptr_t)(v)) << BOXWORD_##n##_SHIFT) | BOXWORD_##n##_FLAG) +#define BOXWORD_SHIFT_VALUE_P(o,n) \ + (((o).w & BOXWORD_##n##_MASK) == BOXWORD_##n##_FLAG) +#define BOXWORD_OBJ_TYPE_P(o,n) \ + (!mrb_immediate_p(o) && mrb_val_union(o).bp->tt == MRB_TT_##n) + +/* + * mrb_value representation: + * + * nil : ...0000 0000 (all bits are 0) + * false : ...0000 0100 (mrb_fixnum(v) != 0) + * true : ...0000 1100 + * undef : ...0001 0100 + * fixnum: ...IIII III1 + * symbol: ...SSSS SS10 (use only upper 32-bit as symbol value on 64-bit CPU) + * object: ...PPPP P000 (any bits are 1) + */ +typedef struct mrb_value { + uintptr_t w; } mrb_value; +union mrb_value_ { + void *p; +#ifdef MRB_64BIT + /* use struct to avoid bit shift. */ + struct { + MRB_ENDIAN_LOHI( + mrb_sym sym; + ,uint32_t flag; + ) + } sym; +#endif + struct RBasic *bp; +#ifndef MRB_NO_FLOAT + struct RFloat *fp; +#endif + struct RInteger *ip; + struct RCptr *vp; + uintptr_t w; + mrb_value value; +}; + +mrb_static_assert1(sizeof(mrb_value) == sizeof(union mrb_value_)); + +static inline union mrb_value_ +mrb_val_union(mrb_value v) +{ + union mrb_value_ x; + x.value = v; + return x; +} + MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*); -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float); -MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float); #endif +MRB_API mrb_value mrb_word_boxing_int_value(struct mrb_state*, mrb_int); -#ifndef MRB_WITHOUT_FLOAT -#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f) -#endif +#define mrb_immediate_p(o) ((o).w & BOXWORD_IMMEDIATE_MASK || (o).w == MRB_Qnil) -#define mrb_ptr(o) (o).value.p -#define mrb_cptr(o) (o).value.vp->p -#ifndef MRB_WITHOUT_FLOAT -#define mrb_float(o) (o).value.fp->f +#define mrb_ptr(o) mrb_val_union(o).p +#define mrb_cptr(o) mrb_val_union(o).vp->p +#ifndef MRB_NO_FLOAT +#define mrb_float(o) mrb_val_union(o).fp->f #endif -#define mrb_fixnum(o) ((mrb_int)(o).value.i) -#define mrb_symbol(o) (o).value.sym - -static inline enum mrb_vtype -mrb_type(mrb_value o) -{ - switch (o.w) { - case MRB_Qfalse: - case MRB_Qnil: - return MRB_TT_FALSE; - case MRB_Qtrue: - return MRB_TT_TRUE; - case MRB_Qundef: - return MRB_TT_UNDEF; - } - if (o.value.i_flag == MRB_FIXNUM_FLAG) { - return MRB_TT_FIXNUM; - } - if (o.value.sym_flag == MRB_SYMBOL_FLAG) { - return MRB_TT_SYMBOL; - } - return o.value.bp->tt; +#define mrb_fixnum(o) (mrb_int)(((intptr_t)(o).w) >> BOXWORD_FIXNUM_SHIFT) +MRB_INLINE mrb_int +mrb_integer_func(mrb_value o) { + if (mrb_immediate_p(o)) return mrb_fixnum(o); + return mrb_val_union(o).ip->i; } +#define mrb_integer(o) mrb_integer_func(o) +#ifdef MRB_64BIT +#define mrb_symbol(o) mrb_val_union(o).sym.sym +#else +#define mrb_symbol(o) (mrb_sym)(((o).w) >> BOXWORD_SYMBOL_SHIFT) +#endif +#define mrb_bool(o) (((o).w & ~(uintptr_t)MRB_Qfalse) != 0) -#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse) -#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG) +#define mrb_fixnum_p(o) BOXWORD_SHIFT_VALUE_P(o, FIXNUM) +#define mrb_integer_p(o) (BOXWORD_SHIFT_VALUE_P(o, FIXNUM)||BOXWORD_OBJ_TYPE_P(o, INTEGER)) +#ifdef MRB_64BIT +#define mrb_symbol_p(o) (mrb_val_union(o).sym.flag == BOXWORD_SYMBOL_FLAG) +#else +#define mrb_symbol_p(o) BOXWORD_SHIFT_VALUE_P(o, SYMBOL) +#endif #define mrb_undef_p(o) ((o).w == MRB_Qundef) #define mrb_nil_p(o) ((o).w == MRB_Qnil) - -#define BOXWORD_SET_VALUE(o, ttt, attr, v) do { \ - switch (ttt) {\ - case MRB_TT_FALSE: (o).w = (v) ? MRB_Qfalse : MRB_Qnil; break;\ - case MRB_TT_TRUE: (o).w = MRB_Qtrue; break;\ - case MRB_TT_UNDEF: (o).w = MRB_Qundef; break;\ - case MRB_TT_FIXNUM: (o).w = 0;(o).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\ - case MRB_TT_SYMBOL: (o).w = 0;(o).value.sym_flag = MRB_SYMBOL_FLAG; (o).attr = (v); break;\ - default: (o).w = 0; (o).attr = (v); if ((o).value.bp) (o).value.bp->tt = ttt; break;\ - }\ +#define mrb_false_p(o) ((o).w == MRB_Qfalse) +#define mrb_true_p(o) ((o).w == MRB_Qtrue) +#ifndef MRB_NO_FLOAT +#define mrb_float_p(o) BOXWORD_OBJ_TYPE_P(o, FLOAT) +#endif +#define mrb_array_p(o) BOXWORD_OBJ_TYPE_P(o, ARRAY) +#define mrb_string_p(o) BOXWORD_OBJ_TYPE_P(o, STRING) +#define mrb_hash_p(o) BOXWORD_OBJ_TYPE_P(o, HASH) +#define mrb_cptr_p(o) BOXWORD_OBJ_TYPE_P(o, CPTR) +#define mrb_exception_p(o) BOXWORD_OBJ_TYPE_P(o, EXCEPTION) +#define mrb_free_p(o) BOXWORD_OBJ_TYPE_P(o, FREE) +#define mrb_object_p(o) BOXWORD_OBJ_TYPE_P(o, OBJECT) +#define mrb_class_p(o) BOXWORD_OBJ_TYPE_P(o, CLASS) +#define mrb_module_p(o) BOXWORD_OBJ_TYPE_P(o, MODULE) +#define mrb_iclass_p(o) BOXWORD_OBJ_TYPE_P(o, ICLASS) +#define mrb_sclass_p(o) BOXWORD_OBJ_TYPE_P(o, SCLASS) +#define mrb_proc_p(o) BOXWORD_OBJ_TYPE_P(o, PROC) +#define mrb_range_p(o) BOXWORD_OBJ_TYPE_P(o, RANGE) +#define mrb_env_p(o) BOXWORD_OBJ_TYPE_P(o, ENV) +#define mrb_data_p(o) BOXWORD_OBJ_TYPE_P(o, DATA) +#define mrb_fiber_p(o) BOXWORD_OBJ_TYPE_P(o, FIBER) +#define mrb_istruct_p(o) BOXWORD_OBJ_TYPE_P(o, ISTRUCT) +#define mrb_break_p(o) BOXWORD_OBJ_TYPE_P(o, BREAK) + +#ifndef MRB_NO_FLOAT +#define SET_FLOAT_VALUE(mrb,r,v) ((r) = mrb_word_boxing_float_value(mrb, v)) +#endif +#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_word_boxing_cptr_value(mrb, v)) +#define SET_UNDEF_VALUE(r) ((r).w = MRB_Qundef) +#define SET_NIL_VALUE(r) ((r).w = MRB_Qnil) +#define SET_FALSE_VALUE(r) ((r).w = MRB_Qfalse) +#define SET_TRUE_VALUE(r) ((r).w = MRB_Qtrue) +#define SET_BOOL_VALUE(r,b) ((b) ? SET_TRUE_VALUE(r) : SET_FALSE_VALUE(r)) +#define SET_INT_VALUE(mrb,r,n) ((r) = mrb_word_boxing_int_value(mrb, n)) +#define SET_FIXNUM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, FIXNUM, n) +#ifdef MRB_64BIT +#define SET_SYM_VALUE(r,v) do {\ + union mrb_value_ mrb_value_union_variable;\ + mrb_value_union_variable.sym.sym = v;\ + mrb_value_union_variable.sym.flag = BOXWORD_SYMBOL_FLAG;\ + (r) = mrb_value_union_variable.value;\ } while (0) - -#ifndef MRB_WITHOUT_FLOAT -#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v) +#else +#define SET_SYM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, SYMBOL, n) #endif -#define SET_CPTR_VALUE(mrb,r,v) r = mrb_word_boxing_cptr_value(mrb, v) -#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) -#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) -#define SET_TRUE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) -#define SET_BOOL_VALUE(r,b) BOXWORD_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1) -#define SET_INT_VALUE(r,n) BOXWORD_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#define SET_SYM_VALUE(r,v) BOXWORD_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) -#define SET_OBJ_VALUE(r,v) BOXWORD_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) -#define SET_UNDEF_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) +#define SET_OBJ_VALUE(r,v) ((r).w = (uintptr_t)(v)) + +MRB_INLINE enum mrb_vtype +mrb_type(mrb_value o) +{ + return !mrb_bool(o) ? MRB_TT_FALSE : + mrb_true_p(o) ? MRB_TT_TRUE : + mrb_fixnum_p(o) ? MRB_TT_INTEGER : + mrb_symbol_p(o) ? MRB_TT_SYMBOL : + mrb_undef_p(o) ? MRB_TT_UNDEF : + mrb_val_union(o).bp->tt; +} #endif /* MRUBY_BOXING_WORD_H */ diff --git a/include/mruby/class.h b/include/mruby/class.h index 97b1df58a..b97bc3991 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -1,5 +1,5 @@ -/* -** mruby/class.h - Class class +/** +** @file mruby/class.h - Class class ** ** See Copyright Notice in mruby.h */ @@ -17,13 +17,13 @@ MRB_BEGIN_DECL struct RClass { MRB_OBJECT_HEADER; struct iv_tbl *iv; - struct kh_mt *mt; + struct mt_tbl *mt; struct RClass *super; }; #define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v))) -static inline struct RClass* +MRB_INLINE struct RClass* mrb_class(mrb_state *mrb, mrb_value v) { switch (mrb_type(v)) { @@ -35,9 +35,9 @@ mrb_class(mrb_state *mrb, mrb_value v) return mrb->true_class; case MRB_TT_SYMBOL: return mrb->symbol_class; - case MRB_TT_FIXNUM: - return mrb->fixnum_class; -#ifndef MRB_WITHOUT_FLOAT + case MRB_TT_INTEGER: + return mrb->integer_class; +#ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: return mrb->float_class; #endif @@ -61,37 +61,48 @@ mrb_class(mrb_state *mrb, mrb_value v) #define MRB_FL_CLASS_IS_PREPENDED (1 << 19) #define MRB_FL_CLASS_IS_ORIGIN (1 << 18) #define MRB_CLASS_ORIGIN(c) do {\ - if (c->flags & MRB_FL_CLASS_IS_PREPENDED) {\ - c = c->super;\ - while (!(c->flags & MRB_FL_CLASS_IS_ORIGIN)) {\ - c = c->super;\ + if ((c)->flags & MRB_FL_CLASS_IS_PREPENDED) {\ + (c) = (c)->super;\ + while (!((c)->flags & MRB_FL_CLASS_IS_ORIGIN)) {\ + (c) = (c)->super;\ }\ }\ } while (0) #define MRB_FL_CLASS_IS_INHERITED (1 << 17) #define MRB_INSTANCE_TT_MASK (0xFF) -#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt) -#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK) +#define MRB_SET_INSTANCE_TT(c, tt) ((c)->flags = (((c)->flags & ~MRB_INSTANCE_TT_MASK) | (char)(tt))) +#define MRB_INSTANCE_TT(c) (enum mrb_vtype)((c)->flags & MRB_INSTANCE_TT_MASK) -MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*); -MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym); -MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym); -MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym); +struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym); +struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym); MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t); -MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec); MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b); +MRB_API void mrb_remove_method(mrb_state *mrb, struct RClass *c, mrb_sym sym); MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym); MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym); MRB_API struct RClass* mrb_class_real(struct RClass* cl); +mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym); +mrb_bool mrb_const_name_p(mrb_state*, const char*, mrb_int); mrb_value mrb_class_find_path(mrb_state*, struct RClass*); +mrb_value mrb_mod_to_s(mrb_state*, mrb_value); void mrb_gc_mark_mt(mrb_state*, struct RClass*); size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*); void mrb_gc_free_mt(mrb_state*, struct RClass*); +#ifndef MRB_NO_METHOD_CACHE +void mrb_mc_clear_by_class(mrb_state *mrb, struct RClass* c); +#else +#define mrb_mc_clear_by_class(mrb,c) +#endif + +/* return non zero to break the loop */ +typedef int (mrb_mt_foreach_func)(mrb_state*,mrb_sym,mrb_method_t,void*); +MRB_API void mrb_mt_foreach(mrb_state*, struct RClass*, mrb_mt_foreach_func*, void*); + MRB_END_DECL #endif /* MRUBY_CLASS_H */ diff --git a/include/mruby/common.h b/include/mruby/common.h index 4c7d9384a..90c97cf65 100644 --- a/include/mruby/common.h +++ b/include/mruby/common.h @@ -1,5 +1,5 @@ -/* -**"common.h - mruby common platform definition" +/** +** @file common.h - mruby common platform definition" ** ** See Copyright Notice in mruby.h */ @@ -14,7 +14,7 @@ #endif #ifdef __cplusplus -#ifdef MRB_ENABLE_CXX_ABI +#ifdef MRB_USE_CXX_ABI #define MRB_BEGIN_DECL #define MRB_END_DECL #else @@ -34,7 +34,7 @@ MRB_BEGIN_DECL /** Declare a function that never returns. */ -#if __STDC_VERSION__ >= 201112L +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L # define mrb_noreturn _Noreturn #elif defined __GNUC__ && !defined __STRICT_ANSI__ # define mrb_noreturn __attribute__((noreturn)) @@ -54,14 +54,15 @@ MRB_BEGIN_DECL #endif /** Declare a function as always inlined. */ -#if defined(_MSC_VER) -# define MRB_INLINE static __inline -#else -# define MRB_INLINE static inline +#if defined _MSC_VER && _MSC_VER < 1900 +# ifndef __cplusplus +# define inline __inline +# endif #endif - +#define MRB_INLINE static inline /** Declare a public MRuby API function. */ +#ifndef MRB_API #if defined(MRB_BUILD_AS_DLL) #if defined(MRB_CORE) || defined(MRB_LIB) # define MRB_API __declspec(dllexport) @@ -71,6 +72,20 @@ MRB_BEGIN_DECL #else # define MRB_API extern #endif +#endif + +/** Declare mingw versions */ +#if defined(__MINGW32__) || defined(__MINGW64__) +# include <_mingw.h> +# if defined(__MINGW64_VERSION_MAJOR) +# define MRB_MINGW64_VERSION (__MINGW64_VERSION_MAJOR * 1000 + __MINGW64_VERSION_MINOR) +# elif defined(__MINGW32_MAJOR_VERSION) +# define MRB_MINGW32_VERSION (__MINGW32_MAJOR_VERSION * 1000 + __MINGW32_MINOR_VERSION) +# endif +# if defined(__MINGW32__) && !defined(__MINGW64__) +# define MRB_MINGW32_LEGACY +# endif +#endif MRB_END_DECL diff --git a/include/mruby/compile.h b/include/mruby/compile.h index a85460415..8159cd696 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -1,5 +1,5 @@ -/* -** mruby/compile.h - mruby parser +/** +** @file mruby/compile.h - mruby parser ** ** See Copyright Notice in mruby.h */ @@ -24,7 +24,7 @@ typedef struct mrbc_context { mrb_sym *syms; int slen; char *filename; - short lineno; + uint16_t lineno; int (*partial_hook)(struct mrb_parser_state*); void *partial_data; struct RClass *target_class; @@ -33,7 +33,7 @@ typedef struct mrbc_context { mrb_bool no_exec:1; mrb_bool keep_lv:1; mrb_bool no_optimize:1; - mrb_bool on_eval:1; + const struct RProc *upper; size_t parser_nerr; } mrbc_context; @@ -42,6 +42,7 @@ MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb); MRB_API void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt); MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data); +MRB_API void mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c); /* AST node structure */ typedef struct mrb_ast_node { @@ -67,7 +68,7 @@ enum mrb_lex_state_enum { /* saved error message */ struct mrb_parser_message { - int lineno; + uint16_t lineno; int column; char* message; }; @@ -98,6 +99,9 @@ enum mrb_string_type { /* heredoc structure */ struct mrb_parser_heredoc_info { mrb_bool allow_indent:1; + mrb_bool remove_indent:1; + size_t indent; + mrb_ast_node *indented; mrb_bool line_head:1; enum mrb_string_type type; const char *term; @@ -105,7 +109,7 @@ struct mrb_parser_heredoc_info { mrb_ast_node *doc; }; -#define MRB_PARSER_TOKBUF_MAX 65536 +#define MRB_PARSER_TOKBUF_MAX (UINT16_MAX-1) #define MRB_PARSER_TOKBUF_SIZE 256 /* parser structure */ @@ -114,12 +118,13 @@ struct mrb_parser_state { struct mrb_pool *pool; mrb_ast_node *cells; const char *s, *send; -#ifndef MRB_DISABLE_STDIO +#ifndef MRB_NO_STDIO + /* If both f and s are non-null, it will be taken preferentially from s until s < send. */ FILE *f; #endif mrbc_context *cxt; - char const *filename; - int lineno; + mrb_sym filename_sym; + uint16_t lineno; int column; enum mrb_lex_state_enum lstate; @@ -143,7 +148,6 @@ struct mrb_parser_state { mrb_ast_node *heredocs_from_nextline; mrb_ast_node *parsing_heredoc; mrb_ast_node *lex_strterm_before_heredoc; - mrb_bool heredoc_end_now:1; /* for mirb */ void *ylval; @@ -152,16 +156,17 @@ struct mrb_parser_state { mrb_ast_node *tree; mrb_bool no_optimize:1; - mrb_bool on_eval:1; mrb_bool capture_errors:1; + const struct RProc *upper; struct mrb_parser_message error_buffer[10]; struct mrb_parser_message warn_buffer[10]; mrb_sym* filename_table; - size_t filename_table_length; - int current_filename_index; + uint16_t filename_table_length; + uint16_t current_filename_index; struct mrb_jmpbuf* jmp; + mrb_ast_node *nvars; }; MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*); @@ -169,10 +174,10 @@ MRB_API void mrb_parser_free(struct mrb_parser_state*); MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*); -MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); +MRB_API mrb_sym mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); /* utility functions */ -#ifndef MRB_DISABLE_STDIO +#ifndef MRB_NO_STDIO MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); #endif MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); @@ -180,10 +185,19 @@ MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c); -/* program load functions */ -#ifndef MRB_DISABLE_STDIO +/** program load functions +* Please note! Currently due to interactions with the GC calling these functions will +* leak one RProc object per function call. +* To prevent this save the current memory arena before calling and restore the arena +* right after, like so +* int ai = mrb_gc_arena_save(mrb); +* mrb_value status = mrb_load_string(mrb, buffer); +* mrb_gc_arena_restore(mrb, ai); +*/ +#ifndef MRB_NO_STDIO MRB_API mrb_value mrb_load_file(mrb_state*,FILE*); MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); +MRB_API mrb_value mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c); #endif MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s); MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len); diff --git a/include/mruby/data.h b/include/mruby/data.h index 590470528..7bdf1c34e 100644 --- a/include/mruby/data.h +++ b/include/mruby/data.h @@ -1,5 +1,5 @@ -/* -** mruby/data.h - Data class +/** +** @file mruby/data.h - Data class ** ** See Copyright Notice in mruby.h */ @@ -39,10 +39,11 @@ MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass #define Data_Wrap_Struct(mrb,klass,type,ptr)\ mrb_data_object_alloc(mrb,klass,ptr,type) -#define Data_Make_Struct(mrb,klass,strct,type,sval,data) do { \ - sval = mrb_malloc(mrb, sizeof(strct)); \ - { static const strct zero = { 0 }; *sval = zero; };\ - data = Data_Wrap_Struct(mrb,klass,type,sval);\ +#define Data_Make_Struct(mrb,klass,strct,type,sval,data_obj) do { \ + (data_obj) = Data_Wrap_Struct(mrb,klass,type,NULL);\ + (sval) = (strct *)mrb_malloc(mrb, sizeof(strct)); \ + { static const strct zero = { 0 }; *(sval) = zero; };\ + (data_obj)->data = (sval);\ } while (0) #define RDATA(obj) ((struct RData *)(mrb_ptr(obj))) @@ -62,10 +63,10 @@ MRB_API void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_t *(void**)&sval = mrb_data_get_ptr(mrb, obj, type); \ } while (0) -static inline void +MRB_INLINE void mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type) { - mrb_assert(mrb_type(v) == MRB_TT_DATA); + mrb_assert(mrb_data_p(v)); DATA_PTR(v) = ptr; DATA_TYPE(v) = type; } diff --git a/include/mruby/debug.h b/include/mruby/debug.h index d1de34882..7319ccb3f 100644 --- a/include/mruby/debug.h +++ b/include/mruby/debug.h @@ -1,5 +1,5 @@ -/* -** mruby/debug.h - mruby debug info +/** +** @file mruby/debug.h - mruby debug info ** ** See Copyright Notice in mruby.h */ @@ -16,7 +16,8 @@ MRB_BEGIN_DECL typedef enum mrb_debug_line_type { mrb_debug_line_ary = 0, - mrb_debug_line_flat_map = 1 + mrb_debug_line_flat_map, + mrb_debug_line_packed_map } mrb_debug_line_type; typedef struct mrb_irep_debug_info_line { @@ -26,14 +27,14 @@ typedef struct mrb_irep_debug_info_line { typedef struct mrb_irep_debug_info_file { uint32_t start_pos; - const char *filename; mrb_sym filename_sym; uint32_t line_entry_count; mrb_debug_line_type line_type; union { void *ptr; - mrb_irep_debug_info_line *flat_map; uint16_t *ary; + mrb_irep_debug_info_line *flat_map; + uint8_t *packed_map; } lines; } mrb_irep_debug_info_file; @@ -47,18 +48,19 @@ typedef struct mrb_irep_debug_info { * get line from irep's debug info and program counter * @return returns NULL if not found */ -MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc); +MRB_API const char *mrb_debug_get_filename(mrb_state *mrb, const mrb_irep *irep, uint32_t pc); /* * get line from irep's debug info and program counter * @return returns -1 if not found */ -MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc); +MRB_API int32_t mrb_debug_get_line(mrb_state *mrb, const mrb_irep *irep, uint32_t pc); +MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file( - mrb_state *mrb, mrb_irep *irep, + mrb_state *mrb, mrb_irep_debug_info *info, + const char *filename, uint16_t *lines, uint32_t start_pos, uint32_t end_pos); -MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d); MRB_END_DECL diff --git a/include/mruby/dump.h b/include/mruby/dump.h index bff838484..3c48866d9 100644 --- a/include/mruby/dump.h +++ b/include/mruby/dump.h @@ -1,5 +1,5 @@ -/* -** mruby/dump.h - mruby binary dumper (mrbc binary format) +/** +** @file mruby/dump.h - mruby binary dumper (mrbc binary format) ** ** See Copyright Notice in mruby.h */ @@ -16,21 +16,22 @@ */ MRB_BEGIN_DECL -#define DUMP_DEBUG_INFO 1 -#define DUMP_ENDIAN_BIG 2 -#define DUMP_ENDIAN_LIL 4 -#define DUMP_ENDIAN_NAT 6 -#define DUMP_ENDIAN_MASK 6 +/* flags for mrb_dump_irep{,_binary,_cfunc,_cstruct} */ +#define MRB_DUMP_DEBUG_INFO 1 +#define MRB_DUMP_STATIC 2 +#define DUMP_DEBUG_INFO MRB_DUMP_DEBUG_INFO /* deprecated */ -int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size); -#ifndef MRB_DISABLE_STDIO -int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*); -int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname); +int mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size); +#ifndef MRB_NO_STDIO +int mrb_dump_irep_binary(mrb_state*, const mrb_irep*, uint8_t, FILE*); +int mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname); +int mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname); mrb_irep *mrb_read_irep_file(mrb_state*, FILE*); MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*); MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*); #endif MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*); +MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t); /* dump/load error code * @@ -41,26 +42,28 @@ MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*); #define MRB_DUMP_GENERAL_FAILURE (-1) #define MRB_DUMP_WRITE_FAULT (-2) #define MRB_DUMP_READ_FAULT (-3) -#define MRB_DUMP_CRC_ERROR (-4) -#define MRB_DUMP_INVALID_FILE_HEADER (-5) -#define MRB_DUMP_INVALID_IREP (-6) -#define MRB_DUMP_INVALID_ARGUMENT (-7) +#define MRB_DUMP_INVALID_FILE_HEADER (-4) +#define MRB_DUMP_INVALID_IREP (-5) +#define MRB_DUMP_INVALID_ARGUMENT (-6) /* null symbol length */ #define MRB_DUMP_NULL_SYM_LEN 0xFFFF /* Rite Binary File header */ #define RITE_BINARY_IDENT "RITE" -#define RITE_BINARY_IDENT_LIL "ETIR" -#define RITE_BINARY_FORMAT_VER "0005" +/* Binary Format Version Major:Minor */ +/* Major: Incompatible to prior versions */ +/* Minor: Upper-compatible to prior versions */ +#define RITE_BINARY_MAJOR_VER "02" +#define RITE_BINARY_MINOR_VER "00" +#define RITE_BINARY_FORMAT_VER RITE_BINARY_MAJOR_VER RITE_BINARY_MINOR_VER #define RITE_COMPILER_NAME "MATZ" #define RITE_COMPILER_VERSION "0000" -#define RITE_VM_VER "0002" +#define RITE_VM_VER "0300" #define RITE_BINARY_EOF "END\0" #define RITE_SECTION_IREP_IDENT "IREP" -#define RITE_SECTION_LINENO_IDENT "LINE" #define RITE_SECTION_DEBUG_IDENT "DBG\0" #define RITE_SECTION_LV_IDENT "LVAR" @@ -70,8 +73,8 @@ MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*); /* binary header */ struct rite_binary_header { uint8_t binary_ident[4]; /* Binary Identifier */ - uint8_t binary_version[4]; /* Binary Format Version */ - uint8_t binary_crc[2]; /* Binary CRC */ + uint8_t major_version[2]; /* Binary Format Major Version */ + uint8_t minor_version[2]; /* Binary Format Minor Version */ uint8_t binary_size[4]; /* Binary Size */ uint8_t compiler_name[4]; /* Compiler name */ uint8_t compiler_version[4]; @@ -92,10 +95,6 @@ struct rite_section_irep_header { uint8_t rite_version[4]; /* Rite Instruction Specification Version */ }; -struct rite_section_lineno_header { - RITE_SECTION_HEADER; -}; - struct rite_section_debug_header { RITE_SECTION_HEADER; }; @@ -110,17 +109,6 @@ struct rite_binary_footer { RITE_SECTION_HEADER; }; -static inline int -bigendian_p() -{ - int i; - char *p; - - i = 1; - p = (char*)&i; - return p[0]?0:1; -} - static inline size_t uint8_to_bin(uint8_t s, uint8_t *bin) { @@ -146,16 +134,6 @@ uint32_to_bin(uint32_t l, uint8_t *bin) return sizeof(uint32_t); } -static inline size_t -uint32l_to_bin(uint32_t l, uint8_t *bin) -{ - bin[3] = (l >> 24) & 0xff; - bin[2] = (l >> 16) & 0xff; - bin[1] = (l >> 8) & 0xff; - bin[0] = l & 0xff; - return sizeof(uint32_t); -} - static inline uint32_t bin_to_uint32(const uint8_t *bin) { @@ -165,15 +143,6 @@ bin_to_uint32(const uint8_t *bin) (uint32_t)bin[3]; } -static inline uint32_t -bin_to_uint32l(const uint8_t *bin) -{ - return (uint32_t)bin[3] << 24 | - (uint32_t)bin[2] << 16 | - (uint32_t)bin[1] << 8 | - (uint32_t)bin[0]; -} - static inline uint16_t bin_to_uint16(const uint8_t *bin) { @@ -189,8 +158,4 @@ bin_to_uint8(const uint8_t *bin) MRB_END_DECL -/** @internal crc.c */ -uint16_t -calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc); - #endif /* MRUBY_DUMP_H */ diff --git a/include/mruby/endian.h b/include/mruby/endian.h new file mode 100644 index 000000000..477f3bc94 --- /dev/null +++ b/include/mruby/endian.h @@ -0,0 +1,44 @@ +/** +** @file mruby/endian.h - detect endian-ness +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_ENDIAN_H +#define MRUBY_ENDIAN_H + +#include <limits.h> + +MRB_BEGIN_DECL + +#if !defined(BYTE_ORDER) && defined(__BYTE_ORDER__) +# define BYTE_ORDER __BYTE_ORDER__ +#endif +#if !defined(BIG_ENDIAN) && defined(__ORDER_BIG_ENDIAN__) +# define BIG_ENDIAN __ORDER_BIG_ENDIAN__ +#endif +#if !defined(LITTLE_ENDIAN) && defined(__ORDER_LITTLE_ENDIAN__) +# define LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +#endif + +#ifdef BYTE_ORDER +# if BYTE_ORDER == BIG_ENDIAN +# define littleendian 0 +# elif BYTE_ORDER == LITTLE_ENDIAN +# define littleendian 1 +# endif +#endif +#ifndef littleendian +/* can't distinguish endian in compile time */ +static inline int +check_little_endian(void) +{ + unsigned int n = 1; + return (*(unsigned char *)&n == 1); +} +# define littleendian check_little_endian() +#endif + +MRB_END_DECL + +#endif /* MRUBY_ENDIAN_H */ diff --git a/include/mruby/error.h b/include/mruby/error.h index 1587795fc..20ca38586 100644 --- a/include/mruby/error.h +++ b/include/mruby/error.h @@ -1,5 +1,5 @@ -/* -** mruby/error.h - Exception class +/** +** @file mruby/error.h - Exception class ** ** See Copyright Notice in mruby.h */ @@ -23,32 +23,102 @@ struct RException { MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg); MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str); -#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit)) +#define mrb_exc_new_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit)) +#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_lit(mrb, c, lit) MRB_API mrb_value mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv); -MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); -MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb); +mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); +mrb_value mrb_get_backtrace(mrb_state *mrb); + MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...); -/* declaration for fail method */ +/* declaration for `fail` method */ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value); +#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT32) || defined(MRB_NAN_BOXING) || defined(MRB_WORD_BOXING) +struct RBreak { + MRB_OBJECT_HEADER; + const struct RProc *proc; + mrb_value val; +}; +#define mrb_break_value_get(brk) ((brk)->val) +#define mrb_break_value_set(brk, v) ((brk)->val = v) +#else struct RBreak { MRB_OBJECT_HEADER; - struct RProc *proc; + const struct RProc *proc; + union mrb_value_union value; +}; +#define RBREAK_VALUE_TT_MASK ((1 << 8) - 1) +static inline mrb_value +mrb_break_value_get(struct RBreak *brk) +{ mrb_value val; + val.value = brk->value; + val.tt = (enum mrb_vtype)(brk->flags & RBREAK_VALUE_TT_MASK); + return val; +} +static inline void +mrb_break_value_set(struct RBreak *brk, mrb_value val) +{ + brk->value = val.value; + brk->flags &= ~RBREAK_VALUE_TT_MASK; + brk->flags |= val.tt; +} +#endif /* MRB_64BIT || MRB_USE_FLOAT32 || MRB_NAN_BOXING || MRB_WORD_BOXING */ +#define mrb_break_proc_get(brk) ((brk)->proc) +#define mrb_break_proc_set(brk, p) ((brk)->proc = p) + +#define RBREAK_TAG_FOREACH(f) \ + f(RBREAK_TAG_BREAK, 0) \ + f(RBREAK_TAG_BREAK_UPPER, 1) \ + f(RBREAK_TAG_BREAK_INTARGET, 2) \ + f(RBREAK_TAG_RETURN_BLOCK, 3) \ + f(RBREAK_TAG_RETURN, 4) \ + f(RBREAK_TAG_RETURN_TOPLEVEL, 5) \ + f(RBREAK_TAG_JUMP, 6) \ + f(RBREAK_TAG_STOP, 7) + +#define RBREAK_TAG_DEFINE(tag, i) tag = i, +enum { + RBREAK_TAG_FOREACH(RBREAK_TAG_DEFINE) }; +#undef RBREAK_TAG_DEFINE + +#define RBREAK_TAG_BIT 3 +#define RBREAK_TAG_BIT_OFF 8 +#define RBREAK_TAG_MASK (~(~UINT32_C(0) << RBREAK_TAG_BIT)) + +static inline uint32_t +mrb_break_tag_get(struct RBreak *brk) +{ + return (brk->flags >> RBREAK_TAG_BIT_OFF) & RBREAK_TAG_MASK; +} + +static inline void +mrb_break_tag_set(struct RBreak *brk, uint32_t tag) +{ + brk->flags &= ~(RBREAK_TAG_MASK << RBREAK_TAG_BIT_OFF); + brk->flags |= (tag & RBREAK_TAG_MASK) << RBREAK_TAG_BIT_OFF; +} /** * Protect * - * @mrbgem mruby-error + */ +typedef mrb_value mrb_protect_error_func(mrb_state *mrb, void *userdata); +MRB_API mrb_value mrb_protect_error(mrb_state *mrb, mrb_protect_error_func *body, void *userdata, mrb_bool *error); + +/** + * Protect (takes mrb_value for body argument) + * + * Implemented in the mruby-error mrbgem */ MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state); /** * Ensure * - * @mrbgem mruby-error + * Implemented in the mruby-error mrbgem */ MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data); @@ -56,7 +126,7 @@ MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, /** * Rescue * - * @mrbgem mruby-error + * Implemented in the mruby-error mrbgem */ MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data); @@ -64,7 +134,7 @@ MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, /** * Rescue exception * - * @mrbgem mruby-error + * Implemented in the mruby-error mrbgem */ MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data, diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 2a3ff4182..9f9bba410 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -1,5 +1,5 @@ -/* -** mruby/gc.h - garbage collector for mruby +/** +** @file mruby/gc.h - garbage collector for mruby ** ** See Copyright Notice in mruby.h */ @@ -21,6 +21,7 @@ struct mrb_state; #define MRB_EACH_OBJ_BREAK 1 typedef int (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data); void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data); +size_t mrb_objspace_page_slot_size(void); MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); #ifndef MRB_GC_ARENA_SIZE @@ -86,6 +87,8 @@ typedef struct mrb_gc { MRB_API mrb_bool mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object); +#define MRB_GC_RED 7 + MRB_END_DECL #endif /* MRUBY_GC_H */ diff --git a/include/mruby/hash.h b/include/mruby/hash.h index dacdd9376..749ea3869 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -1,5 +1,5 @@ -/* -** mruby/hash.h - Hash class +/** +** @file mruby/hash.h - Hash class ** ** See Copyright Notice in mruby.h */ @@ -8,23 +8,35 @@ #define MRUBY_HASH_H #include "common.h" -#include <mruby/khash.h> /** * Hash class */ MRB_BEGIN_DECL +/* offset of `iv` must be 3 words */ struct RHash { MRB_OBJECT_HEADER; +#ifdef MRB_64BIT + uint32_t size; struct iv_tbl *iv; - struct seglist *ht; + uint32_t ea_capa; + uint32_t ea_n_used; +#else + struct iv_tbl *iv; + uint32_t size; +#endif + union { + struct hash_entry *ea; + struct hash_table *ht; + } hsh; }; #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_value(p) mrb_obj_value((void*)(p)) -MRB_API mrb_value mrb_hash_new_capa(mrb_state*, mrb_int); +size_t mrb_hash_memsize(mrb_value obj); +MRB_API mrb_value mrb_hash_new_capa(mrb_state *mrb, mrb_int capa); MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); @@ -96,7 +108,7 @@ MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, * @param mrb The mruby state reference. * @param hash The target hash. * @param key The key to delete. - * @return The deleted value. + * @return The deleted value. This value is not protected from GC. Use `mrb_gc_protect()` if necessary. */ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); @@ -166,8 +178,22 @@ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash); /* - * Copies the hash. + * Get hash size. + * + * Equivalent to: * + * hash.size + * + * @param mrb The mruby state reference. + * @param hash The target hash. + * @return The hash size. + */ +MRB_API mrb_int mrb_hash_size(mrb_state *mrb, mrb_value hash); + +/* + * Copies the hash. This function does NOT copy the instance variables + * (except for the default value). Use mrb_obj_dup() to copy the instance + * variables as well. * * @param mrb The mruby state reference. * @param hash The target hash. @@ -185,31 +211,32 @@ MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash); */ MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2); -/* declaration of struct kh_ht */ -/* be careful when you touch the internal */ -typedef struct { - mrb_value v; - mrb_int n; -} mrb_hash_value; - -KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE) - -/* RHASH_TBL allocates st_table if not available. */ -#define RHASH(obj) ((struct RHash*)(mrb_ptr(obj))) -#define RHASH_TBL(h) (RHASH(h)->ht) -#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone")) -#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h) - -#define MRB_HASH_DEFAULT 1 -#define MRB_HASH_PROC_DEFAULT 2 -#define MRB_RHASH_DEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_DEFAULT) -#define MRB_RHASH_PROCDEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_PROC_DEFAULT) +#define RHASH(hash) ((struct RHash*)(mrb_ptr(hash))) + +#define MRB_HASH_IB_BIT_BIT 5 +#define MRB_HASH_AR_EA_CAPA_BIT 5 +#define MRB_HASH_IB_BIT_SHIFT 0 +#define MRB_HASH_AR_EA_CAPA_SHIFT 0 +#define MRB_HASH_AR_EA_N_USED_SHIFT MRB_HASH_AR_EA_CAPA_BIT +#define MRB_HASH_SIZE_FLAGS_SHIFT (MRB_HASH_AR_EA_CAPA_BIT * 2) +#define MRB_HASH_IB_BIT_MASK ((1 << MRB_HASH_IB_BIT_BIT) - 1) +#define MRB_HASH_AR_EA_CAPA_MASK ((1 << MRB_HASH_AR_EA_CAPA_BIT) - 1) +#define MRB_HASH_AR_EA_N_USED_MASK (MRB_HASH_AR_EA_CAPA_MASK << MRB_HASH_AR_EA_N_USED_SHIFT) +#define MRB_HASH_DEFAULT (1 << (MRB_HASH_SIZE_FLAGS_SHIFT + 0)) +#define MRB_HASH_PROC_DEFAULT (1 << (MRB_HASH_SIZE_FLAGS_SHIFT + 1)) +#define MRB_HASH_HT (1 << (MRB_HASH_SIZE_FLAGS_SHIFT + 2)) +#define MRB_RHASH_DEFAULT_P(hash) (RHASH(hash)->flags & MRB_HASH_DEFAULT) +#define MRB_RHASH_PROCDEFAULT_P(hash) (RHASH(hash)->flags & MRB_HASH_PROC_DEFAULT) /* GC functions */ void mrb_gc_mark_hash(mrb_state*, struct RHash*); size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*); void mrb_gc_free_hash(mrb_state*, struct RHash*); +/* return non zero to break the loop */ +typedef int (mrb_hash_foreach_func)(mrb_state *mrb, mrb_value key, mrb_value val, void *data); +MRB_API void mrb_hash_foreach(mrb_state *mrb, struct RHash *hash, mrb_hash_foreach_func *func, void *p); + MRB_END_DECL #endif /* MRUBY_HASH_H */ diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 76bafb25c..6a3b4bd10 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -1,5 +1,5 @@ -/* -** mruby/irep.h - mrb_irep structure +/** +** @file mruby/irep.h - mrb_irep structure ** ** See Copyright Notice in mruby.h */ @@ -16,43 +16,102 @@ MRB_BEGIN_DECL enum irep_pool_type { - IREP_TT_STRING, - IREP_TT_FIXNUM, - IREP_TT_FLOAT, + IREP_TT_STR = 0, /* string (need free) */ + IREP_TT_SSTR = 2, /* string (static) */ + IREP_TT_INT32 = 1, /* 32bit integer */ + IREP_TT_INT64 = 3, /* 64bit integer */ + IREP_TT_BIGINT = 7, /* big integer (not yet supported) */ + IREP_TT_FLOAT = 5, /* float (double/float) */ +}; + +#define IREP_TT_NFLAG 1 /* number (non string) flag */ +#define IREP_TT_SFLAG 2 /* static string flag */ + +typedef struct mrb_pool_value { + uint32_t tt; /* packed type and length (for string) */ + union { + const char *str; + int32_t i32; + int64_t i64; +#ifndef MRB_NO_FLOAT + mrb_float f; +#endif + } u; +} mrb_pool_value; + +enum mrb_catch_type { + MRB_CATCH_RESCUE = 0, + MRB_CATCH_ENSURE = 1, }; -struct mrb_locals { - mrb_sym name; - uint16_t r; +struct mrb_irep_catch_handler { + uint8_t type; /* enum mrb_catch_type */ + uint8_t begin[4]; /* The starting address to match the handler. Includes this. */ + uint8_t end[4]; /* The endpoint address that matches the handler. Not Includes this. */ + uint8_t target[4]; /* The address to jump to if a match is made. */ }; /* Program data array struct */ typedef struct mrb_irep { uint16_t nlocals; /* Number of local variables */ uint16_t nregs; /* Number of register variables */ + uint16_t clen; /* Number of catch handlers */ uint8_t flags; - mrb_code *iseq; - mrb_value *pool; - mrb_sym *syms; - struct mrb_irep **reps; + const mrb_code *iseq; + /* + * A catch handler table is placed after the iseq entity. + * The reason it doesn't add fields to the structure is to keep the mrb_irep structure from bloating. + * The catch handler table can be obtained with `mrb_irep_catch_handler_table(irep)`. + */ + const mrb_pool_value *pool; + const mrb_sym *syms; + const struct mrb_irep * const *reps; - struct mrb_locals *lv; + const mrb_sym *lv; /* debug info */ - mrb_bool own_filename; - const char *filename; - uint16_t *lines; struct mrb_irep_debug_info* debug_info; - uint16_t ilen, plen, slen, rlen; - uint32_t refcnt; + uint32_t ilen; + uint16_t plen, slen; + uint16_t rlen; + uint16_t refcnt; } mrb_irep; #define MRB_ISEQ_NO_FREE 1 +#define MRB_IREP_NO_FREE 2 +#define MRB_IREP_STATIC (MRB_ISEQ_NO_FREE | MRB_IREP_NO_FREE) MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb); + +/** load mruby bytecode functions +* Please note! Currently due to interactions with the GC calling these functions will +* leak one RProc object per function call. +* To prevent this save the current memory arena before calling and restore the arena +* right after, like so +* int ai = mrb_gc_arena_save(mrb); +* mrb_value status = mrb_load_irep(mrb, buffer); +* mrb_gc_arena_restore(mrb, ai); +*/ + +/* @param [const uint8_t*] irep code, expected as a literal */ MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*); + +/* + * @param [const void*] irep code + * @param [size_t] size of irep buffer. If -1 is given, it is considered unrestricted. + */ +MRB_API mrb_value mrb_load_irep_buf(mrb_state*, const void*, size_t); + +/* @param [const uint8_t*] irep code, expected as a literal */ MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*); + +/* + * @param [const void*] irep code + * @param [size_t] size of irep buffer. If -1 is given, it is considered unrestricted. + */ +MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state*, const void*, size_t, mrbc_context*); + void mrb_irep_free(mrb_state*, struct mrb_irep*); void mrb_irep_incref(mrb_state*, struct mrb_irep*); void mrb_irep_decref(mrb_state*, struct mrb_irep*); @@ -63,10 +122,24 @@ struct mrb_insn_data { uint8_t insn; uint16_t a; uint16_t b; - uint8_t c; + uint16_t c; }; -struct mrb_insn_data mrb_decode_insn(mrb_code *pc); +struct mrb_insn_data mrb_decode_insn(const mrb_code *pc); + +static inline const struct mrb_irep_catch_handler * +mrb_irep_catch_handler_table(const struct mrb_irep *irep) +{ + if (irep->clen > 0) { + return (const struct mrb_irep_catch_handler*)(irep->iseq + irep->ilen); + } + else { + return (const struct mrb_irep_catch_handler*)NULL; + } +} + +#define mrb_irep_catch_handler_pack(n, v) uint32_to_bin(n, v) +#define mrb_irep_catch_handler_unpack(v) bin_to_uint32(v) MRB_END_DECL diff --git a/include/mruby/istruct.h b/include/mruby/istruct.h index 4d2393ccd..d6b6116a7 100644 --- a/include/mruby/istruct.h +++ b/include/mruby/istruct.h @@ -1,5 +1,5 @@ -/* -** mruby/istruct.h - Inline structures +/** +** @file mruby/istruct.h - Inline structures ** ** See Copyright Notice in mruby.h */ @@ -19,12 +19,15 @@ MRB_BEGIN_DECL #define ISTRUCT_DATA_SIZE (sizeof(void*) * 3) -struct RIstruct { +struct RIStruct { MRB_OBJECT_HEADER; - char inline_data[ISTRUCT_DATA_SIZE]; + union { + intptr_t inline_alignment[3]; + char inline_data[ISTRUCT_DATA_SIZE]; + }; }; -#define RISTRUCT(obj) ((struct RIstruct*)(mrb_ptr(obj))) +#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj))) #define ISTRUCT_PTR(obj) (RISTRUCT(obj)->inline_data) MRB_INLINE mrb_int mrb_istruct_size() diff --git a/include/mruby/khash.h b/include/mruby/khash.h index 9c40c6b80..1fb6eecbb 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -1,5 +1,5 @@ -/* -** mruby/khash.c - Hash for mruby +/** +** @file mruby/khash.h - Hash for mruby ** ** See Copyright Notice in mruby.h */ @@ -61,7 +61,6 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0}; typedef struct kh_##name { \ khint_t n_buckets; \ khint_t size; \ - khint_t n_occupied; \ uint8_t *ed_flags; \ khkey_t *keys; \ khval_t *vals; \ @@ -92,19 +91,28 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) khval_t: value data type kh_is_map: (0: hash set / 1: hash map) __hash_func: hash function - __hash_equal: hash comparation function + __hash_equal: hash comparison function */ #define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \ + mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \ + int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \ { \ khint_t sz = h->n_buckets; \ size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \ - uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \ - h->size = h->n_occupied = 0; \ + uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \ + if (!p) { return 1; } \ + h->size = 0; \ h->keys = (khkey_t *)p; \ h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \ h->ed_flags = p+len*sz; \ kh_fill_flags(h->ed_flags, 0xaa, sz/4); \ + return 0; \ + } \ + void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \ + { \ + if (kh_alloc_simple_##name(mrb, h)) { \ + mrb_raise_nomemory(mrb); \ + } \ } \ kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \ kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \ @@ -112,7 +120,10 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) size = KHASH_MIN_SIZE; \ khash_power2(size); \ h->n_buckets = size; \ - kh_alloc_##name(mrb, h); \ + if (kh_alloc_simple_##name(mrb, h)) { \ + mrb_free(mrb, h); \ + mrb_raise_nomemory(mrb); \ + } \ return h; \ } \ kh_##name##_t *kh_init_##name(mrb_state *mrb) { \ @@ -130,7 +141,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) (void)mrb; \ if (h && h->ed_flags) { \ kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \ - h->size = h->n_occupied = 0; \ + h->size = 0; \ } \ } \ khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key) \ @@ -174,7 +185,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \ { \ khint_t k, del_k, step = 0; \ - if (h->n_occupied >= khash_upper_bound(h)) { \ + if (h->size >= khash_upper_bound(h)) { \ kh_resize_##name(mrb, h, h->n_buckets*2); \ } \ k = __hash_func(mrb,key) & khash_mask(h); \ @@ -204,7 +215,6 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) h->keys[k] = key; \ h->ed_flags[k/4] &= ~__m_empty[k%4]; \ h->size++; \ - h->n_occupied++; \ if (ret) *ret = 1; \ return k; \ } \ diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index da9225aaa..e09a797ed 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -1,5 +1,5 @@ -/* -** mruby/numeric.h - Numeric, Integer, Float, Fixnum class +/** +** @file mruby/numeric.h - Numeric, Integer, Float class ** ** See Copyright Notice in mruby.h */ @@ -12,34 +12,36 @@ /** * Numeric class and it's sub-classes. * - * Integer, Float and Fixnum + * Integer and Float */ MRB_BEGIN_DECL -#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX) -#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN) +#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_FIXNUM_MAX) +#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_FIXNUM_MIN) #define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t)) #define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int) #define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int) #define FIXABLE(f) TYPED_FIXABLE(f,mrb_int) -#ifndef MRB_WITHOUT_FLOAT -#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,double) -#endif - -#ifndef MRB_WITHOUT_FLOAT -MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); +#ifndef MRB_NO_FLOAT +#ifdef MRB_INT64 +#define FIXABLE_FLOAT(f) ((f)>=-9223372036854775808.0 && (f)<9223372036854775808.0) +#else +#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,mrb_float) #endif -MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base); -/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */ -#ifndef MRB_WITHOUT_FLOAT -MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt); -MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); #endif -mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y); +MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y); +MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y); +MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y); + +MRB_API mrb_value mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base); +MRB_API char *mrb_int_to_cstr(char *buf, size_t len, mrb_int n, mrb_int base); + +/* internal function(s) */ +mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y); + +/* obsolete function(s); will be removed */ +#define mrb_fixnum_to_str(mrb, x, base) mrb_integer_to_str(mrb, x, base) #ifndef __has_builtin #define __has_builtin(x) 0 @@ -66,96 +68,113 @@ mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y); #ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS -#ifndef MRB_WORD_BOXING -# define WBCHK(x) 0 -#else -# define WBCHK(x) !FIXABLE(x) -#endif - static inline mrb_bool mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) { - return __builtin_add_overflow(augend, addend, sum) || WBCHK(*sum); + return __builtin_add_overflow(augend, addend, sum); } static inline mrb_bool mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) { - return __builtin_sub_overflow(minuend, subtrahend, difference) || WBCHK(*difference); + return __builtin_sub_overflow(minuend, subtrahend, difference); } static inline mrb_bool mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product) { - return __builtin_mul_overflow(multiplier, multiplicand, product) || WBCHK(*product); + return __builtin_mul_overflow(multiplier, multiplicand, product); } -#undef WBCHK - #else -#define MRB_UINT_MAKE2(n) uint ## n ## _t -#define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n) -#define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT) - -#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT)) +#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1)) static inline mrb_bool -mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) +mrb_int_add_overflow(mrb_int a, mrb_int b, mrb_int *c) { - mrb_uint x = (mrb_uint)augend; - mrb_uint y = (mrb_uint)addend; + mrb_uint x = (mrb_uint)a; + mrb_uint y = (mrb_uint)b; mrb_uint z = (mrb_uint)(x + y); - *sum = (mrb_int)z; + *c = (mrb_int)z; return !!(((x ^ z) & (y ^ z)) & MRB_INT_OVERFLOW_MASK); } static inline mrb_bool -mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) +mrb_int_sub_overflow(mrb_int a, mrb_int b, mrb_int *c) { - mrb_uint x = (mrb_uint)minuend; - mrb_uint y = (mrb_uint)subtrahend; + mrb_uint x = (mrb_uint)a; + mrb_uint y = (mrb_uint)b; mrb_uint z = (mrb_uint)(x - y); - *difference = (mrb_int)z; + *c = (mrb_int)z; return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK); } static inline mrb_bool -mrb_int_mul_overflow(mrb_int multiplier, mrb_int multiplicand, mrb_int *product) +mrb_int_mul_overflow(mrb_int a, mrb_int b, mrb_int *c) { -#if MRB_INT_BIT == 32 - int64_t n = (int64_t)multiplier * multiplicand; - *product = (mrb_int)n; - return !FIXABLE(n); -#else - if (multiplier > 0) { - if (multiplicand > 0) { - if (multiplier > MRB_INT_MAX / multiplicand) return TRUE; - } - else { - if (multiplicand < MRB_INT_MAX / multiplier) return TRUE; - } - } - else { - if (multiplicand > 0) { - if (multiplier < MRB_INT_MAX / multiplicand) return TRUE; - } - else { - if (multiplier != 0 && multiplicand < MRB_INT_MAX / multiplier) return TRUE; - } - } - *product = multiplier * multiplicand; +#ifdef MRB_INT32 + int64_t n = (int64_t)a * b; + *c = (mrb_int)n; + return n > MRB_INT_MAX || n < MRB_INT_MIN; +#else /* MRB_INT64 */ + if (a > 0 && b > 0 && a > MRB_INT_MAX / b) return TRUE; + if (a < 0 && b > 0 && a < MRB_INT_MIN / b) return TRUE; + if (a > 0 && b < 0 && b < MRB_INT_MIN / a) return TRUE; + if (a < 0 && b < 0 && (a <= MRB_INT_MIN || b <= MRB_INT_MIN || -a > MRB_INT_MAX / -b)) + return TRUE; + *c = a * b; return FALSE; #endif } #undef MRB_INT_OVERFLOW_MASK -#undef mrb_uint -#undef MRB_UINT_MAKE -#undef MRB_UINT_MAKE2 #endif +#ifndef MRB_NO_FLOAT +# include <stdint.h> +# include <float.h> + +# define MRB_FLT_RADIX FLT_RADIX + +# ifdef MRB_USE_FLOAT32 +# define MRB_FLT_MANT_DIG FLT_MANT_DIG +# define MRB_FLT_EPSILON FLT_EPSILON +# define MRB_FLT_DIG FLT_DIG +# define MRB_FLT_MIN_EXP FLT_MIN_EXP +# define MRB_FLT_MIN FLT_MIN +# define MRB_FLT_MIN_10_EXP FLT_MIN_10_EXP +# define MRB_FLT_MAX_EXP FLT_MAX_EXP +# define MRB_FLT_MAX FLT_MAX +# define MRB_FLT_MAX_10_EXP FLT_MAX_10_EXP + +# else /* not MRB_USE_FLOAT32 */ +# define MRB_FLT_MANT_DIG DBL_MANT_DIG +# define MRB_FLT_EPSILON DBL_EPSILON +# define MRB_FLT_DIG DBL_DIG +# define MRB_FLT_MIN_EXP DBL_MIN_EXP +# define MRB_FLT_MIN DBL_MIN +# define MRB_FLT_MIN_10_EXP DBL_MIN_10_EXP +# define MRB_FLT_MAX_EXP DBL_MAX_EXP +# define MRB_FLT_MAX DBL_MAX +# define MRB_FLT_MAX_10_EXP DBL_MAX_10_EXP +# endif /* MRB_USE_FLOAT32 */ + +MRB_API mrb_value mrb_float_to_integer(mrb_state *mrb, mrb_value val); +MRB_API mrb_float mrb_as_float(mrb_state *mrb, mrb_value x); + +/* internal functions */ +mrb_float mrb_div_float(mrb_float x, mrb_float y); +mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt); +int mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec, char sign); + +/* obsolete functions; will be removed */ +#define mrb_flo_to_fixnum(mrb, val) mrb_float_to_integer(mrb, val) +#define mrb_to_flo(mrb, x) mrb_as_float(mrb, x) + +#endif /* MRB_NO_FLOAT */ + MRB_END_DECL #endif /* MRUBY_NUMERIC_H */ diff --git a/include/mruby/object.h b/include/mruby/object.h index 25584a1d4..f75e99f1b 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -1,5 +1,5 @@ -/* -** mruby/object.h - mruby object definition +/** +** @file mruby/object.h - mruby object definition ** ** See Copyright Notice in mruby.h */ @@ -8,14 +8,13 @@ #define MRUBY_OBJECT_H #define MRB_OBJECT_HEADER \ - enum mrb_vtype tt:8;\ - uint32_t color:3;\ - uint32_t flags:21;\ - struct RClass *c;\ - struct RBasic *gcnext - -#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & flag) + struct RClass *c; \ + struct RBasic *gcnext; \ + enum mrb_vtype tt:8; \ + uint32_t color:3; \ + uint32_t flags:21 +#define MRB_FLAG_TEST(obj, flag) ((obj)->flags & (flag)) struct RBasic { MRB_OBJECT_HEADER; @@ -26,6 +25,7 @@ struct RBasic { #define MRB_FROZEN_P(o) ((o)->flags & MRB_FL_OBJ_IS_FROZEN) #define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FL_OBJ_IS_FROZEN) #define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FL_OBJ_IS_FROZEN) +#define mrb_frozen_p(o) MRB_FROZEN_P(o) struct RObject { MRB_OBJECT_HEADER; @@ -33,7 +33,6 @@ struct RObject { }; #define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v))) -#define mrb_immediate_p(x) (mrb_type(x) < MRB_TT_HAS_BASIC) #define mrb_special_const_p(x) mrb_immediate_p(x) struct RFiber { diff --git a/include/mruby/opcode.h b/include/mruby/opcode.h index d513ca472..249598161 100644 --- a/include/mruby/opcode.h +++ b/include/mruby/opcode.h @@ -1,5 +1,5 @@ -/* -** mruby/opcode.h - RiteVM operation codes +/** +** @file mruby/opcode.h - RiteVM operation codes ** ** See Copyright Notice in mruby.h */ @@ -36,6 +36,7 @@ enum mrb_insn { #define FETCH_BB() do {a=READ_B(); b=READ_B();} while (0) #define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0) #define FETCH_BS() do {a=READ_B(); b=READ_S();} while (0) +#define FETCH_BSS() do {a=READ_B(); b=READ_S(); c=READ_S();} while (0) #define FETCH_S() do {a=READ_S();} while (0) #define FETCH_W() do {a=READ_W();} while (0) @@ -45,6 +46,7 @@ enum mrb_insn { #define FETCH_BB_1() do {a=READ_S(); b=READ_B();} while (0) #define FETCH_BBB_1() do {a=READ_S(); b=READ_B(); c=READ_B();} while (0) #define FETCH_BS_1() do {a=READ_S(); b=READ_S();} while (0) +#define FETCH_BSS_1() do {a=READ_S(); b=READ_S();c=READ_S();} while (0) #define FETCH_S_1() FETCH_S() #define FETCH_W_1() FETCH_W() @@ -54,6 +56,7 @@ enum mrb_insn { #define FETCH_BB_2() do {a=READ_B(); b=READ_S();} while (0) #define FETCH_BBB_2() do {a=READ_B(); b=READ_S(); c=READ_B();} while (0) #define FETCH_BS_2() FETCH_BS() +#define FETCH_BSS_2() FETCH_BSS() #define FETCH_S_2() FETCH_S() #define FETCH_W_2() FETCH_W() @@ -63,6 +66,7 @@ enum mrb_insn { #define FETCH_BB_3() do {a=READ_S(); b=READ_S();} while (0) #define FETCH_BBB_3() do {a=READ_S(); b=READ_S(); c=READ_B();} while (0) #define FETCH_BS_3() do {a=READ_S(); b=READ_S();} while (0) +#define FETCH_BSS_3() FETCH_BSS_1() #define FETCH_S_3() FETCH_S() #define FETCH_W_3() FETCH_W() diff --git a/include/mruby/ops.h b/include/mruby/ops.h index f23bb1b0b..fae6872cc 100644 --- a/include/mruby/ops.h +++ b/include/mruby/ops.h @@ -1,11 +1,12 @@ /* operand types: - + Z: no operand (Z,Z,Z,Z) - + B: 8bit (B,S,B,B) - + BB: 8+8bit (BB,SB,BS,SS) - + BBB: 8+8+8bit (BBB,SBB,BSB,SSB) - + BS: 8+16bit (BS,SS,BS,BS) - + S: 16bit (S,S,S,S) - + W: 24bit (W,W,W,W) + + Z: no operand + + B: 8bit + + BB: 8+8bit + + BBB: 8+8+8bit + + BS: 8+16bit + + BSS: 8+16+16bit + + S: 16bit + + W: 24bit */ /*----------------------------------------------------------------------- @@ -25,6 +26,8 @@ OPCODE(LOADI_4, B) /* R(a) = mrb_int(4) */ OPCODE(LOADI_5, B) /* R(a) = mrb_int(5) */ OPCODE(LOADI_6, B) /* R(a) = mrb_int(6) */ OPCODE(LOADI_7, B) /* R(a) = mrb_int(7) */ +OPCODE(LOADI16, BS) /* R(a) = mrb_int(b) */ +OPCODE(LOADI32, BSS) /* R(a) = mrb_int((b<<16)+c) */ OPCODE(LOADSYM, BB) /* R(a) = Syms(b) */ OPCODE(LOADNIL, B) /* R(a) = nil */ OPCODE(LOADSELF, B) /* R(a) = self */ @@ -44,43 +47,41 @@ OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */ OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */ OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */ OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */ -OPCODE(JMP, S) /* pc=a */ -OPCODE(JMPIF, BS) /* if R(b) pc=a */ -OPCODE(JMPNOT, BS) /* if !R(b) pc=a */ -OPCODE(JMPNIL, BS) /* if R(b)==nil pc=a */ -OPCODE(ONERR, S) /* rescue_push(a) */ +OPCODE(JMP, S) /* pc+=a */ +OPCODE(JMPIF, BS) /* if R(a) pc+=b */ +OPCODE(JMPNOT, BS) /* if !R(a) pc+=b */ +OPCODE(JMPNIL, BS) /* if R(a)==nil pc+=b */ +OPCODE(JMPUW, S) /* unwind_and_jump_to(a) */ OPCODE(EXCEPT, B) /* R(a) = exc */ OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */ -OPCODE(POPERR, B) /* a.times{rescue_pop()} */ -OPCODE(RAISE, B) /* raise(R(a)) */ -OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */ -OPCODE(EPOP, B) /* A.times{ensure_pop().call} */ +OPCODE(RAISEIF, B) /* raise(R(a)) if R(a) */ OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */ OPCODE(SENDVB, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) */ OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */ -OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */ +OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1)) */ +OPCODE(SENDVK, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),**(a+2),&R(a+3)) # todo */ OPCODE(CALL, Z) /* R(0) = self.call(frame.argc, frame.argv) */ OPCODE(SUPER, BB) /* R(a) = super(R(a+1),... ,R(a+b+1)) */ OPCODE(ARGARY, BS) /* R(a) = argument array (16=m5:r1:m5:d1:lv4) */ OPCODE(ENTER, W) /* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */ -OPCODE(KEY_P, BB) /* R(a) = kdict.key?(Syms(b)) # todo */ -OPCODE(KEYEND, Z) /* raise unless kdict.empty? # todo */ -OPCODE(KARG, BB) /* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) # todo */ +OPCODE(KEY_P, BB) /* R(a) = kdict.key?(Syms(b)) */ +OPCODE(KEYEND, Z) /* raise unless kdict.empty? */ +OPCODE(KARG, BB) /* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) */ OPCODE(RETURN, B) /* return R(a) (normal) */ OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */ OPCODE(BREAK, B) /* break R(a) */ OPCODE(BLKPUSH, BS) /* R(a) = block (16=m5:r1:m5:d1:lv4) */ -OPCODE(ADD, BB) /* R(a) = R(a)+R(a+1) (Syms[b]=:+) */ -OPCODE(ADDI, BBB) /* R(a) = R(a)+mrb_int(c) (Syms[b]=:+) */ -OPCODE(SUB, BB) /* R(a) = R(a)-R(a+1) (Syms[b]=:-) */ -OPCODE(SUBI, BBB) /* R(a) = R(a)-C (Syms[b]=:-) */ -OPCODE(MUL, BB) /* R(a) = R(a)*R(a+1) (Syms[b]=:*) */ -OPCODE(DIV, BB) /* R(a) = R(a)/R(a+1) (Syms[b]=:/) */ -OPCODE(EQ, BB) /* R(a) = R(a)==R(a+1) (Syms[b]=:==) */ -OPCODE(LT, BB) /* R(a) = R(a)<R(a+1) (Syms[b]=:<) */ -OPCODE(LE, BB) /* R(a) = R(a)<=R(a+1) (Syms[b]=:<=) */ -OPCODE(GT, BB) /* R(a) = R(a)>R(a+1) (Syms[b]=:>) */ -OPCODE(GE, BB) /* R(a) = R(a)>=R(a+1) (Syms[b]=:>=) */ +OPCODE(ADD, B) /* R(a) = R(a)+R(a+1) */ +OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(b) */ +OPCODE(SUB, B) /* R(a) = R(a)-R(a+1) */ +OPCODE(SUBI, BB) /* R(a) = R(a)-mrb_int(b) */ +OPCODE(MUL, B) /* R(a) = R(a)*R(a+1) */ +OPCODE(DIV, B) /* R(a) = R(a)/R(a+1) */ +OPCODE(EQ, B) /* R(a) = R(a)==R(a+1) */ +OPCODE(LT, B) /* R(a) = R(a)<R(a+1) */ +OPCODE(LE, B) /* R(a) = R(a)<=R(a+1) */ +OPCODE(GT, B) /* R(a) = R(a)>R(a+1) */ +OPCODE(GE, B) /* R(a) = R(a)>=R(a+1) */ OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */ OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */ OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */ @@ -88,30 +89,30 @@ OPCODE(ARYPUSH, B) /* ary_push(R(a),R(a+1)) */ OPCODE(ARYDUP, B) /* R(a) = ary_dup(R(a)) */ OPCODE(AREF, BBB) /* R(a) = R(b)[c] */ OPCODE(ASET, BBB) /* R(a)[c] = R(b) */ -OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+C) = R(a)[b..] */ +OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+c) = R(a)[b..] */ OPCODE(INTERN, B) /* R(a) = intern(R(a)) */ -OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */ +OPCODE(STRING, BB) /* R(a) = str_dup(Pool(b)) */ OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */ -OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */ -OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */ +OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */ +OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */ OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */ -OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */ -OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */ -OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */ +OPCODE(LAMBDA, BB) /* R(a) = lambda(Irep(b),L_LAMBDA) */ +OPCODE(BLOCK, BB) /* R(a) = lambda(Irep(b),L_BLOCK) */ +OPCODE(METHOD, BB) /* R(a) = lambda(Irep(b),L_METHOD) */ OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */ OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */ OPCODE(OCLASS, B) /* R(a) = ::Object */ OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */ OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */ -OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */ -OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */ +OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),Irep(b)) */ +OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)); R(a) = Syms(b) */ OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */ OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */ OPCODE(SCLASS, B) /* R(a) = R(a).singleton_class */ OPCODE(TCLASS, B) /* R(a) = target_class */ OPCODE(DEBUG, BBB) /* print a,b,c */ -OPCODE(ERR, B) /* raise(LocalJumpError, Lit(a)) */ -OPCODE(EXT1, Z) /* make 1st operand 16bit */ -OPCODE(EXT2, Z) /* make 2nd operand 16bit */ +OPCODE(ERR, B) /* raise(LocalJumpError, Pool(a)) */ +OPCODE(EXT1, Z) /* make 1st operand (a) 16bit */ +OPCODE(EXT2, Z) /* make 2nd operand (b) 16bit */ OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */ OPCODE(STOP, Z) /* stop VM */ diff --git a/include/mruby/presym.h b/include/mruby/presym.h new file mode 100644 index 000000000..066b675e7 --- /dev/null +++ b/include/mruby/presym.h @@ -0,0 +1,40 @@ +/** +** @file mruby/presym.h - Preallocated Symbols +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_PRESYM_H +#define MRUBY_PRESYM_H + +#if defined(MRB_NO_PRESYM) +# include <mruby/presym/disable.h> +#elif !defined(MRB_PRESYM_SCANNING) +# include <mruby/presym/enable.h> +#endif + +/* + * Where `mrb_intern_lit` is allowed for symbol interning, it is directly + * replaced by the symbol ID if presym is enabled by using the following + * macros. + * + * MRB_OPSYM(xor) //=> ^ (Operator) + * MRB_CVSYM(xor) //=> @@xor (Class Variable) + * MRB_IVSYM(xor) //=> @xor (Instance Variable) + * MRB_SYM_B(xor) //=> xor! (Method with Bang) + * MRB_SYM_Q(xor) //=> xor? (Method with Question mark) + * MRB_SYM_E(xor) //=> xor= (Method with Equal) + * MRB_SYM(xor) //=> xor (Word characters) + * + * For `MRB_OPSYM`, specify the names corresponding to operators (see + * `MRuby::Presym::OPERATORS` in `lib/mruby/presym.rb` for the names that + * can be specified for it). Other than that, describe only word characters + * excluding leading and ending punctuations. + * + * These macros are expanded to `mrb_intern_lit` if presym is disabled, + * therefore the mruby state variable is required. The above macros can be + * used when the variable name is `mrb`. If you want to use other variable + * names, you need to use macros with `_2` suffix, such as `MRB_SYM_2`. + */ + +#endif /* MRUBY_PRESYM_H */ diff --git a/include/mruby/presym/disable.h b/include/mruby/presym/disable.h new file mode 100644 index 000000000..45843fbf8 --- /dev/null +++ b/include/mruby/presym/disable.h @@ -0,0 +1,70 @@ +/** +** @file mruby/presym/disable.h - Disable Preallocated Symbols +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_PRESYM_DISABLE_H +#define MRUBY_PRESYM_DISABLE_H + +#include <string.h> + +#define MRB_PRESYM_MAX 0 + +#define MRB_OPSYM(name) MRB_OPSYM__##name(mrb) +#define MRB_CVSYM(name) mrb_intern_lit(mrb, "@@" #name) +#define MRB_IVSYM(name) mrb_intern_lit(mrb, "@" #name) +#define MRB_SYM_B(name) mrb_intern_lit(mrb, #name "!") +#define MRB_SYM_Q(name) mrb_intern_lit(mrb, #name "?") +#define MRB_SYM_E(name) mrb_intern_lit(mrb, #name "=") +#define MRB_SYM(name) mrb_intern_lit(mrb, #name) + +#define MRB_OPSYM_2(mrb, name) MRB_OPSYM__##name(mrb) +#define MRB_CVSYM_2(mrb, name) mrb_intern_lit(mrb, "@@" #name) +#define MRB_IVSYM_2(mrb, name) mrb_intern_lit(mrb, "@" #name) +#define MRB_SYM_B_2(mrb, name) mrb_intern_lit(mrb, #name "!") +#define MRB_SYM_Q_2(mrb, name) mrb_intern_lit(mrb, #name "?") +#define MRB_SYM_E_2(mrb, name) mrb_intern_lit(mrb, #name "=") +#define MRB_SYM_2(mrb, name) mrb_intern_lit(mrb, #name) + +#define MRB_OPSYM__not(mrb) mrb_intern_lit(mrb, "!") +#define MRB_OPSYM__mod(mrb) mrb_intern_lit(mrb, "%") +#define MRB_OPSYM__and(mrb) mrb_intern_lit(mrb, "&") +#define MRB_OPSYM__mul(mrb) mrb_intern_lit(mrb, "*") +#define MRB_OPSYM__add(mrb) mrb_intern_lit(mrb, "+") +#define MRB_OPSYM__sub(mrb) mrb_intern_lit(mrb, "-") +#define MRB_OPSYM__div(mrb) mrb_intern_lit(mrb, "/") +#define MRB_OPSYM__lt(mrb) mrb_intern_lit(mrb, "<") +#define MRB_OPSYM__gt(mrb) mrb_intern_lit(mrb, ">") +#define MRB_OPSYM__xor(mrb) mrb_intern_lit(mrb, "^") +#define MRB_OPSYM__tick(mrb) mrb_intern_lit(mrb, "`") +#define MRB_OPSYM__or(mrb) mrb_intern_lit(mrb, "|") +#define MRB_OPSYM__neg(mrb) mrb_intern_lit(mrb, "~") +#define MRB_OPSYM__neq(mrb) mrb_intern_lit(mrb, "!=") +#define MRB_OPSYM__nmatch(mrb) mrb_intern_lit(mrb, "!~") +#define MRB_OPSYM__andand(mrb) mrb_intern_lit(mrb, "&&") +#define MRB_OPSYM__pow(mrb) mrb_intern_lit(mrb, "**") +#define MRB_OPSYM__plus(mrb) mrb_intern_lit(mrb, "+@") +#define MRB_OPSYM__minus(mrb) mrb_intern_lit(mrb, "-@") +#define MRB_OPSYM__lshift(mrb) mrb_intern_lit(mrb, "<<") +#define MRB_OPSYM__le(mrb) mrb_intern_lit(mrb, "<=") +#define MRB_OPSYM__eq(mrb) mrb_intern_lit(mrb, "==") +#define MRB_OPSYM__match(mrb) mrb_intern_lit(mrb, "=~") +#define MRB_OPSYM__ge(mrb) mrb_intern_lit(mrb, ">=") +#define MRB_OPSYM__rshift(mrb) mrb_intern_lit(mrb, ">>") +#define MRB_OPSYM__aref(mrb) mrb_intern_lit(mrb, "[]") +#define MRB_OPSYM__oror(mrb) mrb_intern_lit(mrb, "||") +#define MRB_OPSYM__cmp(mrb) mrb_intern_lit(mrb, "<=>") +#define MRB_OPSYM__eqq(mrb) mrb_intern_lit(mrb, "===") +#define MRB_OPSYM__aset(mrb) mrb_intern_lit(mrb, "[]=") + +#define MRB_PRESYM_DEFINE_VAR_AND_INITER(name, size, ...) \ + static mrb_sym name[size]; \ + static void presym_init_##name(mrb_state *mrb) { \ + mrb_sym name__[] = {__VA_ARGS__}; \ + memcpy(name, name__, sizeof(name)); \ + } + +#define MRB_PRESYM_INIT_SYMBOLS(mrb, name) presym_init_##name(mrb) + +#endif /* MRUBY_PRESYM_DISABLE_H */ diff --git a/include/mruby/presym/enable.h b/include/mruby/presym/enable.h new file mode 100644 index 000000000..8ca0c3cc6 --- /dev/null +++ b/include/mruby/presym/enable.h @@ -0,0 +1,37 @@ +/** +** @file mruby/presym/enable.h - Enable Preallocated Symbols +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_PRESYM_ENABLE_H +#define MRUBY_PRESYM_ENABLE_H + +#include <mruby/presym/id.h> + +#define MRB_OPSYM(name) MRB_OPSYM__##name +#define MRB_CVSYM(name) MRB_CVSYM__##name +#define MRB_IVSYM(name) MRB_IVSYM__##name +#define MRB_SYM_B(name) MRB_SYM_B__##name +#define MRB_SYM_Q(name) MRB_SYM_Q__##name +#define MRB_SYM_E(name) MRB_SYM_E__##name +#define MRB_SYM(name) MRB_SYM__##name + +#define MRB_OPSYM_2(mrb, name) MRB_OPSYM__##name +#define MRB_CVSYM_2(mrb, name) MRB_CVSYM__##name +#define MRB_IVSYM_2(mrb, name) MRB_IVSYM__##name +#define MRB_SYM_B_2(mrb, name) MRB_SYM_B__##name +#define MRB_SYM_Q_2(mrb, name) MRB_SYM_Q__##name +#define MRB_SYM_E_2(mrb, name) MRB_SYM_E__##name +#define MRB_SYM_2(mrb, name) MRB_SYM__##name + +#define MRB_PRESYM_DEFINE_VAR_AND_INITER(name, size, ...) \ + static const mrb_sym name[] = {__VA_ARGS__}; + +#define MRB_PRESYM_INIT_SYMBOLS(mrb, name) (void)(mrb) + +/* use MRB_SYM() for E_RUNTIME_ERROR etc. */ +#undef MRB_ERROR_SYM +#define MRB_ERROR_SYM(sym) MRB_SYM(sym) + +#endif /* MRUBY_PRESYM_ENABLE_H */ diff --git a/include/mruby/presym/scanning.h b/include/mruby/presym/scanning.h new file mode 100644 index 000000000..fab0743f7 --- /dev/null +++ b/include/mruby/presym/scanning.h @@ -0,0 +1,73 @@ +/** +** @file mruby/presym/scanning.h - Scanning Preallocated Symbols +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_PRESYM_SCANNING_H +#define MRUBY_PRESYM_SCANNING_H + +#define MRB_PRESYM_SCANNING_TAGGED(arg) <@! arg !@> + +#undef mrb_intern_lit +#define mrb_intern_lit(mrb, name) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_intern_cstr(mrb, name) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_method(mrb, c, name, f, a) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_class_method(mrb, c, name, f, a) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_singleton_method(mrb, c, name, f, a) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_class(mrb, name, s) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_class_under(mrb, o, name, s) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_module(mrb, name) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_module_under(mrb, o, name) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_module_function(mrb, c, name, f, s) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_const(mrb, c, name, v) MRB_PRESYM_SCANNING_TAGGED(name) +#define mrb_define_global_const(mrb, name, v) MRB_PRESYM_SCANNING_TAGGED(name) + +#define MRB_OPSYM(name) MRB_OPSYM__##name(mrb) +#define MRB_CVSYM(name) MRB_PRESYM_SCANNING_TAGGED("@@" #name) +#define MRB_IVSYM(name) MRB_PRESYM_SCANNING_TAGGED("@" #name) +#define MRB_SYM_B(name) MRB_PRESYM_SCANNING_TAGGED(#name "!") +#define MRB_SYM_Q(name) MRB_PRESYM_SCANNING_TAGGED(#name "?") +#define MRB_SYM_E(name) MRB_PRESYM_SCANNING_TAGGED(#name "=") +#define MRB_SYM(name) MRB_PRESYM_SCANNING_TAGGED(#name) + +#define MRB_OPSYM_2(mrb, name) MRB_OPSYM__##name(mrb) +#define MRB_CVSYM_2(mrb, name) MRB_PRESYM_SCANNING_TAGGED("@@" #name) +#define MRB_IVSYM_2(mrb, name) MRB_PRESYM_SCANNING_TAGGED("@" #name) +#define MRB_SYM_B_2(mrb, name) MRB_PRESYM_SCANNING_TAGGED(#name "!") +#define MRB_SYM_Q_2(mrb, name) MRB_PRESYM_SCANNING_TAGGED(#name "?") +#define MRB_SYM_E_2(mrb, name) MRB_PRESYM_SCANNING_TAGGED(#name "=") +#define MRB_SYM_2(mrb, name) MRB_PRESYM_SCANNING_TAGGED(#name) + +#define MRB_OPSYM__not(mrb) MRB_PRESYM_SCANNING_TAGGED("!") +#define MRB_OPSYM__mod(mrb) MRB_PRESYM_SCANNING_TAGGED("%") +#define MRB_OPSYM__and(mrb) MRB_PRESYM_SCANNING_TAGGED("&") +#define MRB_OPSYM__mul(mrb) MRB_PRESYM_SCANNING_TAGGED("*") +#define MRB_OPSYM__add(mrb) MRB_PRESYM_SCANNING_TAGGED("+") +#define MRB_OPSYM__sub(mrb) MRB_PRESYM_SCANNING_TAGGED("-") +#define MRB_OPSYM__div(mrb) MRB_PRESYM_SCANNING_TAGGED("/") +#define MRB_OPSYM__lt(mrb) MRB_PRESYM_SCANNING_TAGGED("<") +#define MRB_OPSYM__gt(mrb) MRB_PRESYM_SCANNING_TAGGED(">") +#define MRB_OPSYM__xor(mrb) MRB_PRESYM_SCANNING_TAGGED("^") +#define MRB_OPSYM__tick(mrb) MRB_PRESYM_SCANNING_TAGGED("`") +#define MRB_OPSYM__or(mrb) MRB_PRESYM_SCANNING_TAGGED("|") +#define MRB_OPSYM__neg(mrb) MRB_PRESYM_SCANNING_TAGGED("~") +#define MRB_OPSYM__neq(mrb) MRB_PRESYM_SCANNING_TAGGED("!=") +#define MRB_OPSYM__nmatch(mrb) MRB_PRESYM_SCANNING_TAGGED("!~") +#define MRB_OPSYM__andand(mrb) MRB_PRESYM_SCANNING_TAGGED("&&") +#define MRB_OPSYM__pow(mrb) MRB_PRESYM_SCANNING_TAGGED("**") +#define MRB_OPSYM__plus(mrb) MRB_PRESYM_SCANNING_TAGGED("+@") +#define MRB_OPSYM__minus(mrb) MRB_PRESYM_SCANNING_TAGGED("-@") +#define MRB_OPSYM__lshift(mrb) MRB_PRESYM_SCANNING_TAGGED("<<") +#define MRB_OPSYM__le(mrb) MRB_PRESYM_SCANNING_TAGGED("<=") +#define MRB_OPSYM__eq(mrb) MRB_PRESYM_SCANNING_TAGGED("==") +#define MRB_OPSYM__match(mrb) MRB_PRESYM_SCANNING_TAGGED("=~") +#define MRB_OPSYM__ge(mrb) MRB_PRESYM_SCANNING_TAGGED(">=") +#define MRB_OPSYM__rshift(mrb) MRB_PRESYM_SCANNING_TAGGED(">>") +#define MRB_OPSYM__aref(mrb) MRB_PRESYM_SCANNING_TAGGED("[]") +#define MRB_OPSYM__oror(mrb) MRB_PRESYM_SCANNING_TAGGED("||") +#define MRB_OPSYM__cmp(mrb) MRB_PRESYM_SCANNING_TAGGED("<=>") +#define MRB_OPSYM__eqq(mrb) MRB_PRESYM_SCANNING_TAGGED("===") +#define MRB_OPSYM__aset(mrb) MRB_PRESYM_SCANNING_TAGGED("[]=") + +#endif /* MRUBY_PRESYM_SCANNING_H */ diff --git a/include/mruby/proc.h b/include/mruby/proc.h index f428e6666..31f40d379 100644 --- a/include/mruby/proc.h +++ b/include/mruby/proc.h @@ -1,5 +1,5 @@ -/* -** mruby/proc.h - Proc class +/** +** @file mruby/proc.h - Proc class ** ** See Copyright Notice in mruby.h */ @@ -22,24 +22,29 @@ struct REnv { mrb_sym mid; }; -/* flags (21bits): 1(shared flag):10(cioff/bidx):10(stack_len) */ -#define MRB_ENV_SET_STACK_LEN(e,len) (e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff)) -#define MRB_ENV_STACK_LEN(e) ((mrb_int)((e)->flags & 0x3ff)) -#define MRB_ENV_STACK_UNSHARED (1<<20) -#define MRB_ENV_UNSHARE_STACK(e) (e)->flags |= MRB_ENV_STACK_UNSHARED -#define MRB_ENV_STACK_SHARED_P(e) (((e)->flags & MRB_ENV_STACK_UNSHARED) == 0) -#define MRB_ENV_BIDX(e) (((e)->flags >> 10) & 0x3ff) -#define MRB_ENV_SET_BIDX(e,idx) (e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10) +/* flags (21bits): 1(close):1(touched):1(heap):8(cioff/bidx):8(stack_len) */ +#define MRB_ENV_SET_LEN(e,len) ((e)->flags = (((e)->flags & ~0xff)|((unsigned int)(len) & 0xff))) +#define MRB_ENV_LEN(e) ((mrb_int)((e)->flags & 0xff)) +#define MRB_ENV_CLOSED (1<<20) +#define MRB_ENV_TOUCHED (1<<19) +#define MRB_ENV_HEAPED (1<<18) +#define MRB_ENV_CLOSE(e) ((e)->flags |= MRB_ENV_CLOSED) +#define MRB_ENV_TOUCH(e) ((e)->flags |= MRB_ENV_TOUCHED) +#define MRB_ENV_HEAP(e) ((e)->flags |= MRB_ENV_HEAPED) +#define MRB_ENV_HEAP_P(e) ((e)->flags & MRB_ENV_HEAPED) +#define MRB_ENV_ONSTACK_P(e) (((e)->flags & MRB_ENV_CLOSED) == 0) +#define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff) +#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8)) void mrb_env_unshare(mrb_state*, struct REnv*); struct RProc { MRB_OBJECT_HEADER; union { - mrb_irep *irep; + const mrb_irep *irep; mrb_func_t func; } body; - struct RProc *upper; + const struct RProc *upper; union { struct RClass *target_class; struct REnv *env; @@ -52,7 +57,7 @@ struct RProc { #define MRB_ASPEC_REST(a) (((a) >> 12) & 0x1) #define MRB_ASPEC_POST(a) (((a) >> 7) & 0x1f) #define MRB_ASPEC_KEY(a) (((a) >> 2) & 0x1f) -#define MRB_ASPEC_KDICT(a) ((a) & (1<<1)) +#define MRB_ASPEC_KDICT(a) (((a) >> 1) & 0x1) #define MRB_ASPEC_BLOCK(a) ((a) & 1) #define MRB_PROC_CFUNC_FL 128 @@ -69,11 +74,11 @@ struct RProc { #define MRB_PROC_SET_TARGET_CLASS(p,tc) do {\ if (MRB_PROC_ENV_P(p)) {\ (p)->e.env->c = (tc);\ - mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)tc);\ + mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)(tc));\ }\ else {\ (p)->e.target_class = (tc);\ - mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)tc);\ + mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)(tc));\ }\ } while (0) #define MRB_PROC_SCOPE 2048 @@ -81,50 +86,123 @@ struct RProc { #define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v))) -struct RProc *mrb_proc_new(mrb_state*, mrb_irep*); -struct RProc *mrb_closure_new(mrb_state*, mrb_irep*); +struct RProc *mrb_proc_new(mrb_state*, const mrb_irep*); +struct RProc *mrb_closure_new(mrb_state*, const mrb_irep*); MRB_API struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t); MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals); void mrb_proc_copy(struct RProc *a, struct RProc *b); - -/* implementation of #send method */ -mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); +mrb_int mrb_proc_arity(const struct RProc *p); /* following functions are defined in mruby-proc-ext so please include it when using */ -MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*); -MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int); +MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv); +MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx); /* old name */ #define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx) -#ifdef MRB_METHOD_TABLE_INLINE +#define MRB_METHOD_FUNC_FL 1 +#define MRB_METHOD_NOARG_FL 2 + +#ifndef MRB_USE_METHOD_T_STRUCT -#define MRB_METHOD_FUNC_FL ((uintptr_t)1) #define MRB_METHOD_FUNC_P(m) (((uintptr_t)(m))&MRB_METHOD_FUNC_FL) -#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)&(~MRB_METHOD_FUNC_FL))) -#define MRB_METHOD_FROM_FUNC(m,fn) m=(mrb_method_t)((struct RProc*)((uintptr_t)(fn)|MRB_METHOD_FUNC_FL)) -#define MRB_METHOD_FROM_PROC(m,pr) m=(mrb_method_t)(struct RProc*)(pr) +#define MRB_METHOD_NOARG_P(m) ((((uintptr_t)(m))&MRB_METHOD_NOARG_FL)?1:0) +#define MRB_METHOD_NOARG_SET(m) ((m)=(mrb_method_t)(((uintptr_t)(m))|MRB_METHOD_NOARG_FL)) +#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)>>2)) +#define MRB_METHOD_FROM_FUNC(m,fn) ((m)=(mrb_method_t)((((uintptr_t)(fn))<<2)|MRB_METHOD_FUNC_FL)) +#define MRB_METHOD_FROM_PROC(m,pr) ((m)=(mrb_method_t)(pr)) #define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m)) #define MRB_METHOD_PROC(m) ((struct RProc*)(m)) #define MRB_METHOD_UNDEF_P(m) ((m)==0) #else -#define MRB_METHOD_FUNC_P(m) ((m).func_p) +#define MRB_METHOD_FUNC_P(m) ((m).flags&MRB_METHOD_FUNC_FL) +#define MRB_METHOD_NOARG_P(m) (((m).flags&MRB_METHOD_NOARG_FL)?1:0) #define MRB_METHOD_FUNC(m) ((m).func) -#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).func_p=TRUE;(m).func=(fn);}while(0) -#define MRB_METHOD_FROM_PROC(m,pr) do{(m).func_p=FALSE;(m).proc=(pr);}while(0) +#define MRB_METHOD_NOARG_SET(m) do{(m).flags|=MRB_METHOD_NOARG_FL;}while(0) +#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).flags=MRB_METHOD_FUNC_FL;(m).func=(fn);}while(0) +#define MRB_METHOD_FROM_PROC(m,pr) do{(m).flags=0;(m).proc=(struct RProc*)(pr);}while(0) #define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m)) #define MRB_METHOD_PROC(m) ((m).proc) #define MRB_METHOD_UNDEF_P(m) ((m).proc==NULL) -#endif /* MRB_METHOD_TABLE_INLINE */ +#endif /* MRB_USE_METHOD_T_STRUCT */ #define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m)?TRUE:(MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE)) #define MRB_METHOD_CFUNC(m) (MRB_METHOD_FUNC_P(m)?MRB_METHOD_FUNC(m):((MRB_METHOD_PROC(m)&&MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m)))?MRB_PROC_CFUNC(MRB_METHOD_PROC(m)):NULL)) #include <mruby/khash.h> -KHASH_DECLARE(mt, mrb_sym, mrb_method_t, TRUE) + +MRB_API mrb_value mrb_load_proc(mrb_state *mrb, const struct RProc *proc); + +static inline void +mrb_vm_ci_proc_set(mrb_callinfo *ci, const struct RProc *p) +{ + ci->proc = p; + ci->pc = (p && !MRB_PROC_CFUNC_P(p)) ? p->body.irep->iseq : NULL; +} + +static inline struct RClass * +mrb_vm_ci_target_class(const mrb_callinfo *ci) +{ + if (ci->u.env && ci->u.env->tt == MRB_TT_ENV) { + return ci->u.env->c; + } + else { + return ci->u.target_class; + } +} + +static inline void +mrb_vm_ci_target_class_set(mrb_callinfo *ci, struct RClass *tc) +{ + struct REnv *e = ci->u.env; + if (e) { + if (e->tt == MRB_TT_ENV) { + e->c = tc; + } + else { + ci->u.target_class = tc; + } + } +} + +static inline struct REnv * +mrb_vm_ci_env(const mrb_callinfo *ci) +{ + if (ci->u.env && ci->u.env->tt == MRB_TT_ENV) { + return ci->u.env; + } + else { + return NULL; + } +} + +static inline void +mrb_vm_ci_env_set(mrb_callinfo *ci, struct REnv *e) +{ + if (ci->u.env) { + if (ci->u.env->tt == MRB_TT_ENV) { + if (e) { + e->c = ci->u.env->c; + ci->u.env = e; + } + else { + ci->u.target_class = ci->u.env->c; + } + } + else { + if (e) { + e->c = ci->u.target_class; + ci->u.env = e; + } + } + } + else { + ci->u.env = e; + } +} MRB_END_DECL diff --git a/include/mruby/range.h b/include/mruby/range.h index b166e586b..fea700c24 100644 --- a/include/mruby/range.h +++ b/include/mruby/range.h @@ -1,5 +1,5 @@ -/* -** mruby/range.h - Range class +/** +** @file mruby/range.h - Range class ** ** See Copyright Notice in mruby.h */ @@ -14,20 +14,43 @@ */ MRB_BEGIN_DECL +#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT) || defined(MRB_WORD_BOXING) +# define MRB_RANGE_EMBED +#endif + +#ifdef MRB_RANGE_EMBED +struct RRange { + MRB_OBJECT_HEADER; + mrb_value beg; + mrb_value end; + mrb_bool excl; +}; +# define mrb_gc_free_range(mrb, p) ((void)0) +# define RANGE_BEG(p) ((p)->beg) +# define RANGE_END(p) ((p)->end) +#else typedef struct mrb_range_edges { mrb_value beg; mrb_value end; } mrb_range_edges; - struct RRange { MRB_OBJECT_HEADER; mrb_range_edges *edges; - mrb_bool excl : 1; + mrb_bool excl; }; +# define mrb_gc_free_range(mrb, p) mrb_free(mrb, (p)->edges) +# define RANGE_BEG(p) ((p)->edges->beg) +# define RANGE_END(p) ((p)->edges->end) +#endif -MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v); -#define mrb_range_raw_ptr(v) ((struct RRange*)mrb_ptr(v)) -#define mrb_range_value(p) mrb_obj_value((void*)(p)) +#define mrb_range_beg(mrb, r) RANGE_BEG(mrb_range_ptr(mrb, r)) +#define mrb_range_end(mrb, r) RANGE_END(mrb_range_ptr(mrb, r)) +#define mrb_range_excl_p(mrb, r) RANGE_EXCL(mrb_range_ptr(mrb, r)) +#define mrb_range_raw_ptr(r) ((struct RRange*)mrb_ptr(r)) +#define mrb_range_value(p) mrb_obj_value((void*)(p)) +#define RANGE_EXCL(p) ((p)->excl) + +MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value range); /* * Initializes a Range. @@ -41,8 +64,15 @@ MRB_API struct RRange* mrb_range_ptr(mrb_state *mrb, mrb_value v); */ MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude); -MRB_API mrb_int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc); +enum mrb_range_beg_len { + MRB_RANGE_TYPE_MISMATCH = 0, /* (failure) not range */ + MRB_RANGE_OK = 1, /* (success) range */ + MRB_RANGE_OUT = 2 /* (failure) out of range */ +}; + +MRB_API enum mrb_range_beg_len mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_bool trunc); mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int)); +void mrb_gc_mark_range(mrb_state *mrb, struct RRange *r); MRB_END_DECL diff --git a/include/mruby/re.h b/include/mruby/re.h index 1d09d06c9..2d48019cf 100644 --- a/include/mruby/re.h +++ b/include/mruby/re.h @@ -1,5 +1,5 @@ -/* -** mruby/re.h - Regexp class +/** +** @file mruby/re.h - Regexp class ** ** See Copyright Notice in mruby.h */ diff --git a/include/mruby/string.h b/include/mruby/string.h index 481b2fb38..9c88a0856 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -1,5 +1,5 @@ -/* -** mruby/string.h - String class +/** +** @file mruby/string.h - String class ** ** See Copyright Notice in mruby.h */ @@ -16,43 +16,53 @@ MRB_BEGIN_DECL extern const char mrb_digitmap[]; -#define RSTRING_EMBED_LEN_MAX ((mrb_int)(sizeof(void*) * 3 - 1)) +#define RSTRING_EMBED_LEN_MAX \ + ((mrb_int)(sizeof(void*) * 3 + sizeof(void*) - 32 / CHAR_BIT - 1)) struct RString { MRB_OBJECT_HEADER; union { struct { - mrb_int len; + mrb_ssize len; union { - mrb_int capa; + mrb_ssize capa; struct mrb_shared_string *shared; struct RString *fshared; } aux; char *ptr; } heap; - char ary[RSTRING_EMBED_LEN_MAX + 1]; } as; }; +struct RStringEmbed { + MRB_OBJECT_HEADER; + char ary[RSTRING_EMBED_LEN_MAX+1]; +}; + +#define RSTR_SET_TYPE_FLAG(s, type) (RSTR_UNSET_TYPE_FLAG(s), (s)->flags |= MRB_STR_##type) +#define RSTR_UNSET_TYPE_FLAG(s) ((s)->flags &= ~(MRB_STR_TYPE_MASK|MRB_STR_EMBED_LEN_MASK)) #define RSTR_EMBED_P(s) ((s)->flags & MRB_STR_EMBED) #define RSTR_SET_EMBED_FLAG(s) ((s)->flags |= MRB_STR_EMBED) #define RSTR_UNSET_EMBED_FLAG(s) ((s)->flags &= ~(MRB_STR_EMBED|MRB_STR_EMBED_LEN_MASK)) #define RSTR_SET_EMBED_LEN(s, n) do {\ size_t tmp_n = (n);\ - s->flags &= ~MRB_STR_EMBED_LEN_MASK;\ - s->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\ + (s)->flags &= ~MRB_STR_EMBED_LEN_MASK;\ + (s)->flags |= (tmp_n) << MRB_STR_EMBED_LEN_SHIFT;\ } while (0) #define RSTR_SET_LEN(s, n) do {\ if (RSTR_EMBED_P(s)) {\ RSTR_SET_EMBED_LEN((s),(n));\ }\ else {\ - s->as.heap.len = (mrb_int)(n);\ + (s)->as.heap.len = (mrb_ssize)(n);\ }\ } while (0) +#define RSTR_EMBED_PTR(s) (((struct RStringEmbed*)(s))->ary) #define RSTR_EMBED_LEN(s)\ (mrb_int)(((s)->flags & MRB_STR_EMBED_LEN_MASK) >> MRB_STR_EMBED_LEN_SHIFT) -#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? (s)->as.ary : (s)->as.heap.ptr) +#define RSTR_EMBEDDABLE_P(len) ((len) <= RSTRING_EMBED_LEN_MAX) + +#define RSTR_PTR(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_PTR(s) : (s)->as.heap.ptr) #define RSTR_LEN(s) ((RSTR_EMBED_P(s)) ? RSTR_EMBED_LEN(s) : (s)->as.heap.len) #define RSTR_CAPA(s) (RSTR_EMBED_P(s) ? RSTRING_EMBED_LEN_MAX : (s)->as.heap.aux.capa) @@ -68,10 +78,21 @@ struct RString { #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) -#define RSTR_POOL_P(s) ((s)->flags & MRB_STR_POOL) -#define RSTR_SET_POOL_FLAG(s) ((s)->flags |= MRB_STR_POOL) +#ifdef MRB_UTF8_STRING +# define RSTR_ASCII_P(s) ((s)->flags & MRB_STR_ASCII) +# define RSTR_SET_ASCII_FLAG(s) ((s)->flags |= MRB_STR_ASCII) +# define RSTR_UNSET_ASCII_FLAG(s) ((s)->flags &= ~MRB_STR_ASCII) +# define RSTR_WRITE_ASCII_FLAG(s, v) (RSTR_UNSET_ASCII_FLAG(s), (s)->flags |= v) +# define RSTR_COPY_ASCII_FLAG(dst, src) RSTR_WRITE_ASCII_FLAG(dst, RSTR_ASCII_P(src)) +#else +# define RSTR_ASCII_P(s) (void)0 +# define RSTR_SET_ASCII_FLAG(s) (void)0 +# define RSTR_UNSET_ASCII_FLAG(s) (void)0 +# define RSTR_WRITE_ASCII_FLAG(s, v) (void)0 +# define RSTR_COPY_ASCII_FLAG(dst, src) (void)0 +#endif -/* +/** * Returns a pointer from a Ruby string */ #define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) @@ -82,32 +103,36 @@ struct RString { #define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s)) #define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*); +#define RSTRING_CSTR(mrb,s) mrb_string_cstr(mrb, s) #define MRB_STR_SHARED 1 #define MRB_STR_FSHARED 2 #define MRB_STR_NOFREE 4 -#define MRB_STR_POOL 8 -#define MRB_STR_NO_UTF 16 -#define MRB_STR_EMBED 32 -#define MRB_STR_EMBED_LEN_MASK 0x7c0 +#define MRB_STR_EMBED 8 /* type flags up to here */ +#define MRB_STR_ASCII 16 #define MRB_STR_EMBED_LEN_SHIFT 6 +#define MRB_STR_EMBED_LEN_BIT 5 +#define MRB_STR_EMBED_LEN_MASK (((1 << MRB_STR_EMBED_LEN_BIT) - 1) << MRB_STR_EMBED_LEN_SHIFT) +#define MRB_STR_TYPE_MASK 15 void mrb_gc_free_str(mrb_state*, struct RString*); -MRB_API void mrb_str_modify(mrb_state*, struct RString*); -/* +MRB_API void mrb_str_modify(mrb_state *mrb, struct RString *s); +/* mrb_str_modify() with keeping ASCII flag if set */ +MRB_API void mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s); + +/** * Finds the index of a substring in a string */ -MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int); +MRB_API mrb_int mrb_str_index(mrb_state *mrb, mrb_value str, const char *p, mrb_int len, mrb_int offset); #define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off); -/* +/** * Appends self to other. Returns self as a concatenated string. * * - * Example: + * Example: * - * !!!c * int * main(int argc, * char **argv) @@ -129,32 +154,30 @@ MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_i * // Concatenates str2 to str1. * mrb_str_concat(mrb, str1, str2); * - * // Prints new Concatenated Ruby string. - * mrb_p(mrb, str1); - * - * mrb_close(mrb); - * return 0; - * } + * // Prints new Concatenated Ruby string. + * mrb_p(mrb, str1); * + * mrb_close(mrb); + * return 0; + * } * - * Result: + * Result: * * => "abcdef" * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] self String to concatenate. - * @param [mrb_value] other String to append to self. + * @param mrb The current mruby state. + * @param self String to concatenate. + * @param other String to append to self. * @return [mrb_value] Returns a new String appending other to self. */ -MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value); +MRB_API void mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other); -/* +/** * Adds two strings together. * * - * Example: + * Example: * - * !!!c * int * main(int argc, * char **argv) @@ -181,52 +204,51 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value); * // Concatenates both Ruby strings. * c = mrb_str_plus(mrb, a, b); * - * // Prints new Concatenated Ruby string. - * mrb_p(mrb, c); + * // Prints new Concatenated Ruby string. + * mrb_p(mrb, c); * - * mrb_close(mrb); - * return 0; - * } + * mrb_close(mrb); + * return 0; + * } * * - * Result: + * Result: * * => "abc" # First string * => "def" # Second string * => "abcdef" # First & Second concatenated. * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] a First string to concatenate. - * @param [mrb_value] b Second string to concatenate. + * @param mrb The current mruby state. + * @param a First string to concatenate. + * @param b Second string to concatenate. * @return [mrb_value] Returns a new String containing a concatenated to b. */ -MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); +MRB_API mrb_value mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b); -/* +/** * Converts pointer into a Ruby string. * - * @param [mrb_state] mrb The current mruby state. - * @param [void*] p The pointer to convert to Ruby string. + * @param mrb The current mruby state. + * @param p The pointer to convert to Ruby string. * @return [mrb_value] Returns a new Ruby String. */ -MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*); +MRB_API mrb_value mrb_ptr_to_str(mrb_state *mrb, void *p); -/* +/** * Returns an object as a Ruby string. * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] obj An object to return as a Ruby string. + * @param mrb The current mruby state. + * @param obj An object to return as a Ruby string. * @return [mrb_value] An object as a Ruby string. */ MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); -/* +/** * Resizes the string's length. Returns the amount of characters * in the specified by len. * * Example: * - * !!!c * int * main(int argc, * char **argv) @@ -251,21 +273,20 @@ MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); * * Result: * - * => "Hello" + * => "Hello" * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str The Ruby string to resize. - * @param [mrb_value] len The length. + * @param mrb The current mruby state. + * @param str The Ruby string to resize. + * @param len The length. * @return [mrb_value] An object as a Ruby string. */ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); -/* +/** * Returns a sub string. * - * Example: + * Example: * - * !!!c * int * main(int argc, * char const **argv) @@ -291,59 +312,59 @@ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); * return 0; * } * - * Result: + * Result: * * => "He" * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str Ruby string. - * @param [mrb_int] beg The beginning point of the sub-string. - * @param [mrb_int] len The end point of the sub-string. + * @param mrb The current mruby state. + * @param str Ruby string. + * @param beg The beginning point of the sub-string. + * @param len The end point of the sub-string. * @return [mrb_value] An object as a Ruby sub-string. */ MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); -/* +/** * Returns a Ruby string type. * * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str Ruby string. + * @param mrb The current mruby state. + * @param str Ruby string. * @return [mrb_value] A Ruby string. */ +MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str); +MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); +/* obsolete: use mrb_ensure_string_type() instead */ MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str); -MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); + MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa); -MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa); +#define mrb_str_buf_new(mrb, capa) mrb_str_new_capa(mrb, (capa)) -MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); +/* NULL terminated C string from mrb_value */ +MRB_API const char *mrb_string_cstr(mrb_state *mrb, mrb_value str); +/* NULL terminated C string from mrb_value; `str` will be updated */ +MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *str); +/* obsolete: use RSTRING_PTR() */ MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str); -/* - * Returns the length of the Ruby string. - * - * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str Ruby string. - * @return [mrb_int] The length of the passed in Ruby string. - */ +/* obsolete: use RSTRING_LEN() */ MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str); -/* +/** * Duplicates a string object. * * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str Ruby string. + * @param mrb The current mruby state. + * @param str Ruby string. * @return [mrb_value] Duplicated Ruby string. */ MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); -/* +/** * Returns a symbol from a passed in Ruby string. * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] self Ruby string. + * @param mrb The current mruby state. + * @param self Ruby string. * @return [mrb_value] A symbol. */ MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); @@ -351,39 +372,41 @@ MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck); MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck); -/* +/** * Returns a converted string type. + * For type checking, non converting `mrb_to_str` is recommended. + * obsolete: use `mrb_obj_as_string()` instead. */ -MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); +#define mrb_str_to_str(mrb, str) mrb_obj_as_string(mrb, str) -/* +/** * Returns true if the strings match and false if the strings don't match. * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str1 Ruby string to compare. - * @param [mrb_value] str2 Ruby string to compare. + * @param mrb The current mruby state. + * @param str1 Ruby string to compare. + * @param str2 Ruby string to compare. * @return [mrb_value] boolean value. */ MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); -/* - * Returns a concated string comprised of a Ruby string and a C string. +/** + * Returns a concatenated string comprised of a Ruby string and a C string. * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str Ruby string. - * @param [const char *] ptr A C string. - * @param [size_t] len length of C string. + * @param mrb The current mruby state. + * @param str Ruby string. + * @param ptr A C string. + * @param len length of C string. * @return [mrb_value] A Ruby string. * @see mrb_str_cat_cstr */ MRB_API mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len); -/* - * Returns a concated string comprised of a Ruby string and a C string. +/** + * Returns a concatenated string comprised of a Ruby string and a C string. * - * @param [mrb_state] mrb The current mruby state. - * @param [mrb_value] str Ruby string. - * @param [const char *] ptr A C string. + * @param mrb The current mruby state. + * @param str Ruby string. + * @param ptr A C string. * @return [mrb_value] A Ruby string. * @see mrb_str_cat */ @@ -391,50 +414,54 @@ MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *pt MRB_API mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2); #define mrb_str_cat_lit(mrb, str, lit) mrb_str_cat(mrb, str, lit, mrb_strlen_lit(lit)) -/* +/** * Adds str2 to the end of str1. */ MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2); -/* +/** * Returns 0 if both Ruby strings are equal. Returns a value < 0 if Ruby str1 is less than Ruby str2. Returns a value > 0 if Ruby str2 is greater than Ruby str1. */ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2); -/* +/** * Returns a newly allocated C string from a Ruby string. * This is an utility function to pass a Ruby string to C library functions. * * - Returned string does not contain any NUL characters (but terminator). * - It raises an ArgumentError exception if Ruby string contains * NUL characters. - * - Retured string will be freed automatically on next GC. + * - Returned string will be freed automatically on next GC. * - Caller can modify returned string without affecting Ruby string * (e.g. it can be used for mkstemp(3)). * - * @param [mrb_state *] mrb The current mruby state. - * @param [mrb_value] str Ruby string. Must be an instance of String. + * @param mrb The current mruby state. + * @param str Ruby string. Must be an instance of String. * @return [char *] A newly allocated C string. */ MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str); uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str); mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str); -/* +/** * Returns a printable version of str, surrounded by quote marks, with special characters escaped. */ mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str); -void mrb_noregexp(mrb_state *mrb, mrb_value self); -void mrb_regexp_check(mrb_state *mrb, mrb_value obj); - /* For backward compatibility */ #define mrb_str_cat2(mrb, str, ptr) mrb_str_cat_cstr(mrb, str, ptr) #define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len) #define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2) +mrb_bool mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp); +mrb_value mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); + +#ifdef MRB_UTF8_STRING +mrb_int mrb_utf8len(const char *str, const char *end); +mrb_int mrb_utf8_strlen(const char *str, mrb_int byte_len); +#endif + MRB_END_DECL #endif /* MRUBY_STRING_H */ diff --git a/include/mruby/throw.h b/include/mruby/throw.h index 5d3d214e7..52171e9b0 100644 --- a/include/mruby/throw.h +++ b/include/mruby/throw.h @@ -1,5 +1,5 @@ -/* -** mruby/throw.h - mruby exception throwing handler +/** +** @file mruby/throw.h - mruby exception throwing handler ** ** See Copyright Notice in mruby.h */ @@ -7,21 +7,27 @@ #ifndef MRB_THROW_H #define MRB_THROW_H -#if defined(MRB_ENABLE_CXX_ABI) +#if defined(MRB_USE_CXX_ABI) # if !defined(__cplusplus) # error Trying to use C++ exception handling in C code # endif #endif -#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus) +#if defined(MRB_USE_CXX_EXCEPTION) -#define MRB_TRY(buf) do { try { +# if defined(__cplusplus) + +#define MRB_TRY(buf) try { #define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; } -#define MRB_END_EXC(buf) } } while(0) +#define MRB_END_EXC(buf) } #define MRB_THROW(buf) throw((buf)->impl) typedef mrb_int mrb_jmpbuf_impl; +# else +# error "need to be compiled with C++ compiler" +# endif /* __cplusplus */ + #else #include <setjmp.h> @@ -29,14 +35,17 @@ typedef mrb_int mrb_jmpbuf_impl; #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #define MRB_SETJMP _setjmp #define MRB_LONGJMP _longjmp +#elif defined(__MINGW64__) && defined(__GNUC__) && __GNUC__ >= 4 +#define MRB_SETJMP __builtin_setjmp +#define MRB_LONGJMP __builtin_longjmp #else #define MRB_SETJMP setjmp #define MRB_LONGJMP longjmp #endif -#define MRB_TRY(buf) do { if (MRB_SETJMP((buf)->impl) == 0) { +#define MRB_TRY(buf) if (MRB_SETJMP((buf)->impl) == 0) { #define MRB_CATCH(buf) } else { -#define MRB_END_EXC(buf) } } while(0) +#define MRB_END_EXC(buf) } #define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1); #define mrb_jmpbuf_impl jmp_buf @@ -46,9 +55,11 @@ typedef mrb_int mrb_jmpbuf_impl; struct mrb_jmpbuf { mrb_jmpbuf_impl impl; -#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus) +#if defined(MRB_USE_CXX_EXCEPTION) static mrb_int jmpbuf_id; +# if defined(__cplusplus) mrb_jmpbuf() : impl(jmpbuf_id++) {} +# endif #endif }; diff --git a/include/mruby/value.h b/include/mruby/value.h index f988826ca..d65da30fb 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -1,5 +1,5 @@ -/* -** mruby/value.h - mruby value definitions +/** +** @file mruby/value.h - mruby value definitions ** ** See Copyright Notice in mruby.h */ @@ -9,28 +9,66 @@ #include "common.h" -/** +/* * MRuby Value definition functions and macros. */ MRB_BEGIN_DECL +/** + * mruby Symbol. + * @class mrb_sym + * + * You can create an mrb_sym by simply using mrb_str_intern() or mrb_intern_cstr() + */ typedef uint32_t mrb_sym; + +/** + * mruby Boolean. + * @class mrb_bool + * + * + * Used internally to represent boolean. Can be TRUE or FALSE. + * Not to be confused with Ruby's boolean classes, which can be + * obtained using mrb_false_value() and mrb_true_value() + */ +#if defined(__cplusplus) || (defined(__bool_true_false_are_defined) && __bool_true_false_are_defined) +typedef bool mrb_bool; + +# ifndef FALSE +# define FALSE false +# endif +# ifndef TRUE +# define TRUE true +# endif +#else +# if __STDC_VERSION__ >= 199901L +typedef _Bool mrb_bool; +# else typedef uint8_t mrb_bool; -struct mrb_state; +# endif -#if defined(MRB_INT16) && defined(MRB_INT64) -# error "You can't define MRB_INT16 and MRB_INT64 at the same time." +# ifndef FALSE +# define FALSE 0 +# endif +# ifndef TRUE +# define TRUE 1 +# endif #endif +struct mrb_state; + #if defined _MSC_VER && _MSC_VER < 1800 # define PRIo64 "llo" # define PRId64 "lld" +# define PRIu64 "llu" # define PRIx64 "llx" # define PRIo16 "ho" # define PRId16 "hd" +# define PRIu16 "hu" # define PRIx16 "hx" # define PRIo32 "o" # define PRId32 "d" +# define PRIu32 "u" # define PRIx32 "x" #else # include <inttypes.h> @@ -38,34 +76,34 @@ struct mrb_state; #if defined(MRB_INT64) typedef int64_t mrb_int; + typedef uint64_t mrb_uint; # define MRB_INT_BIT 64 -# define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT) +# define MRB_INT_MIN INT64_MIN +# define MRB_INT_MAX INT64_MAX # define MRB_PRIo PRIo64 # define MRB_PRId PRId64 # define MRB_PRIx PRIx64 -#elif defined(MRB_INT16) - typedef int16_t mrb_int; -# define MRB_INT_BIT 16 -# define MRB_INT_MIN (INT16_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT16_MAX>>MRB_FIXNUM_SHIFT) -# define MRB_PRIo PRIo16 -# define MRB_PRId PRId16 -# define MRB_PRIx PRIx16 #else typedef int32_t mrb_int; + typedef uint32_t mrb_uint; # define MRB_INT_BIT 32 -# define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT) +# define MRB_INT_MIN INT32_MIN +# define MRB_INT_MAX INT32_MAX # define MRB_PRIo PRIo32 # define MRB_PRId PRId32 # define MRB_PRIx PRIx32 #endif +#ifdef MRB_ENDIAN_BIG +# define MRB_ENDIAN_LOHI(a,b) a b +#else +# define MRB_ENDIAN_LOHI(a,b) b a +#endif -#ifndef MRB_WITHOUT_FLOAT +MRB_API mrb_int mrb_int_read(const char *p, const char *e, char **endp); +#ifndef MRB_NO_FLOAT MRB_API double mrb_float_read(const char*, char**); -#ifdef MRB_USE_FLOAT +#ifdef MRB_USE_FLOAT32 typedef float mrb_float; #else typedef double mrb_float; @@ -73,15 +111,12 @@ MRB_API double mrb_float_read(const char*, char**); #endif #if defined _MSC_VER && _MSC_VER < 1900 -# ifndef __cplusplus -# define inline __inline -# endif # include <stdarg.h> MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list arg); MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...); # define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg) # define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__) -# if _MSC_VER < 1800 && !defined MRB_WITHOUT_FLOAT +# if _MSC_VER < 1800 && !defined MRB_NO_FLOAT # include <float.h> # define isfinite(n) _finite(n) # define isnan _isnan @@ -93,35 +128,51 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000; # endif #endif +#define MRB_VTYPE_FOREACH(f) \ + /* mrb_vtype */ /* c type */ /* ruby class */ \ + f(MRB_TT_FALSE, void, "false") \ + f(MRB_TT_TRUE, void, "true") \ + f(MRB_TT_SYMBOL, void, "Symbol") \ + f(MRB_TT_UNDEF, void, "undefined") \ + f(MRB_TT_FREE, void, "free") \ + f(MRB_TT_FLOAT, struct RFloat, "Float") \ + f(MRB_TT_INTEGER, struct RInteger, "Integer") \ + f(MRB_TT_CPTR, struct RCptr, "cptr") \ + f(MRB_TT_OBJECT, struct RObject, "Object") \ + f(MRB_TT_CLASS, struct RClass, "Class") \ + f(MRB_TT_MODULE, struct RClass, "Module") \ + f(MRB_TT_ICLASS, struct RClass, "iClass") \ + f(MRB_TT_SCLASS, struct RClass, "SClass") \ + f(MRB_TT_PROC, struct RProc, "Proc") \ + f(MRB_TT_ARRAY, struct RArray, "Array") \ + f(MRB_TT_HASH, struct RHash, "Hash") \ + f(MRB_TT_STRING, struct RString, "String") \ + f(MRB_TT_RANGE, struct RRange, "Range") \ + f(MRB_TT_EXCEPTION, struct RException, "Exception") \ + f(MRB_TT_ENV, struct REnv, "env") \ + f(MRB_TT_DATA, struct RData, "Data") \ + f(MRB_TT_FIBER, struct RFiber, "Fiber") \ + f(MRB_TT_ISTRUCT, struct RIStruct, "istruct") \ + f(MRB_TT_BREAK, struct RBreak, "break") \ + f(MRB_TT_COMPLEX, struct RComplex, "Complex") \ + f(MRB_TT_RATIONAL, struct RRational, "Rational") + enum mrb_vtype { - MRB_TT_FALSE = 0, /* 0 */ - MRB_TT_FREE, /* 1 */ - MRB_TT_TRUE, /* 2 */ - MRB_TT_FIXNUM, /* 3 */ - MRB_TT_SYMBOL, /* 4 */ - MRB_TT_UNDEF, /* 5 */ - MRB_TT_FLOAT, /* 6 */ - MRB_TT_CPTR, /* 7 */ - MRB_TT_OBJECT, /* 8 */ - MRB_TT_CLASS, /* 9 */ - MRB_TT_MODULE, /* 10 */ - MRB_TT_ICLASS, /* 11 */ - MRB_TT_SCLASS, /* 12 */ - MRB_TT_PROC, /* 13 */ - MRB_TT_ARRAY, /* 14 */ - MRB_TT_HASH, /* 15 */ - MRB_TT_STRING, /* 16 */ - MRB_TT_RANGE, /* 17 */ - MRB_TT_EXCEPTION, /* 18 */ - MRB_TT_FILE, /* 19 */ - MRB_TT_ENV, /* 20 */ - MRB_TT_DATA, /* 21 */ - MRB_TT_FIBER, /* 22 */ - MRB_TT_ISTRUCT, /* 23 */ - MRB_TT_BREAK, /* 24 */ - MRB_TT_MAXDEFINE /* 25 */ +#define MRB_VTYPE_DEFINE(tt, type, name) tt, + MRB_VTYPE_FOREACH(MRB_VTYPE_DEFINE) +#undef MRB_VTYPE_DEFINE + MRB_TT_MAXDEFINE }; +#define MRB_VTYPE_TYPEOF(tt) MRB_TYPEOF_##tt + +#define MRB_VTYPE_TYPEDEF(tt, type, name) typedef type MRB_VTYPE_TYPEOF(tt); +MRB_VTYPE_FOREACH(MRB_VTYPE_TYPEDEF) +#undef MRB_VTYPE_TYPEDEF + +/* for compatibility */ +#define MRB_TT_FIXNUM MRB_TT_INTEGER + #include <mruby/object.h> #ifdef MRB_DOCUMENTATION_BLOCK @@ -140,6 +191,13 @@ typedef void mrb_value; #endif +#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT)) +struct RCptr { + MRB_OBJECT_HEADER; + void *p; +}; +#endif + #if defined(MRB_NAN_BOXING) #include "boxing_nan.h" #elif defined(MRB_WORD_BOXING) @@ -148,8 +206,25 @@ typedef void mrb_value; #include "boxing_no.h" #endif +#if INTPTR_MAX < MRB_INT_MAX + typedef intptr_t mrb_ssize; +# define MRB_SSIZE_MAX INTPTR_MAX +#else + typedef mrb_int mrb_ssize; +# define MRB_SSIZE_MAX MRB_INT_MAX +#endif + +#ifndef mrb_immediate_p +#define mrb_immediate_p(o) (mrb_type(o) <= MRB_TT_CPTR) +#endif +#ifndef mrb_integer_p +#define mrb_integer_p(o) (mrb_type(o) == MRB_TT_INTEGER) +#endif #ifndef mrb_fixnum_p -#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM) +#define mrb_fixnum_p(o) mrb_integer_p(o) +#endif +#ifndef mrb_symbol_p +#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL) #endif #ifndef mrb_undef_p #define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF) @@ -157,25 +232,82 @@ typedef void mrb_value; #ifndef mrb_nil_p #define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !mrb_fixnum(o)) #endif -#ifndef mrb_bool -#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE) +#ifndef mrb_false_p +#define mrb_false_p(o) (mrb_type(o) == MRB_TT_FALSE && !!mrb_fixnum(o)) +#endif +#ifndef mrb_true_p +#define mrb_true_p(o) (mrb_type(o) == MRB_TT_TRUE) #endif -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT +#ifndef mrb_float_p #define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT) #endif -#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL) +#endif +#ifndef mrb_array_p #define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY) +#endif +#ifndef mrb_string_p #define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING) +#endif +#ifndef mrb_hash_p #define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH) +#endif +#ifndef mrb_cptr_p #define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR) +#endif +#ifndef mrb_exception_p #define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION) +#endif +#ifndef mrb_free_p +#define mrb_free_p(o) (mrb_type(o) == MRB_TT_FREE) +#endif +#ifndef mrb_object_p +#define mrb_object_p(o) (mrb_type(o) == MRB_TT_OBJECT) +#endif +#ifndef mrb_class_p +#define mrb_class_p(o) (mrb_type(o) == MRB_TT_CLASS) +#endif +#ifndef mrb_module_p +#define mrb_module_p(o) (mrb_type(o) == MRB_TT_MODULE) +#endif +#ifndef mrb_iclass_p +#define mrb_iclass_p(o) (mrb_type(o) == MRB_TT_ICLASS) +#endif +#ifndef mrb_sclass_p +#define mrb_sclass_p(o) (mrb_type(o) == MRB_TT_SCLASS) +#endif +#ifndef mrb_proc_p +#define mrb_proc_p(o) (mrb_type(o) == MRB_TT_PROC) +#endif +#ifndef mrb_range_p +#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE) +#endif +#ifndef mrb_env_p +#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV) +#endif +#ifndef mrb_data_p +#define mrb_data_p(o) (mrb_type(o) == MRB_TT_DATA) +#endif +#ifndef mrb_fiber_p +#define mrb_fiber_p(o) (mrb_type(o) == MRB_TT_FIBER) +#endif +#ifndef mrb_istruct_p +#define mrb_istruct_p(o) (mrb_type(o) == MRB_TT_ISTRUCT) +#endif +#ifndef mrb_break_p +#define mrb_break_p(o) (mrb_type(o) == MRB_TT_BREAK) +#endif +#ifndef mrb_bool +#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE) +#endif #define mrb_test(o) mrb_bool(o) -MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value); -/* +/** * Returns a float in Ruby. + * + * Takes a float and boxes it into an mrb_value */ -#ifndef MRB_WITHOUT_FLOAT +#ifndef MRB_NO_FLOAT MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f) { mrb_value v; @@ -185,7 +317,7 @@ MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f) } #endif -static inline mrb_value +MRB_INLINE mrb_value mrb_cptr_value(struct mrb_state *mrb, void *p) { mrb_value v; @@ -194,17 +326,24 @@ mrb_cptr_value(struct mrb_state *mrb, void *p) return v; } -/* - * Returns a fixnum in Ruby. +/** + * Returns an integer in Ruby. */ +MRB_INLINE mrb_value mrb_int_value(struct mrb_state *mrb, mrb_int i) +{ + mrb_value v; + SET_INT_VALUE(mrb, v, i); + return v; +} + MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i) { mrb_value v; - SET_INT_VALUE(v, i); + SET_FIXNUM_VALUE(v, i); return v; } -static inline mrb_value +MRB_INLINE mrb_value mrb_symbol_value(mrb_sym i) { mrb_value v; @@ -212,7 +351,7 @@ mrb_symbol_value(mrb_sym i) return v; } -static inline mrb_value +MRB_INLINE mrb_value mrb_obj_value(void *p) { mrb_value v; @@ -222,8 +361,7 @@ mrb_obj_value(void *p) return v; } - -/* +/** * Get a nil mrb_value object. * * @return @@ -236,7 +374,7 @@ MRB_INLINE mrb_value mrb_nil_value(void) return v; } -/* +/** * Returns false in Ruby. */ MRB_INLINE mrb_value mrb_false_value(void) @@ -246,7 +384,7 @@ MRB_INLINE mrb_value mrb_false_value(void) return v; } -/* +/** * Returns true in Ruby. */ MRB_INLINE mrb_value mrb_true_value(void) @@ -256,7 +394,7 @@ MRB_INLINE mrb_value mrb_true_value(void) return v; } -static inline mrb_value +MRB_INLINE mrb_value mrb_bool_value(mrb_bool boolean) { mrb_value v; @@ -264,7 +402,7 @@ mrb_bool_value(mrb_bool boolean) return v; } -static inline mrb_value +MRB_INLINE mrb_value mrb_undef_value(void) { mrb_value v; @@ -272,34 +410,25 @@ mrb_undef_value(void) return v; } -#ifdef MRB_USE_ETEXT_EDATA -#if (defined(__APPLE__) && defined(__MACH__)) -#include <mach-o/getsect.h> -static inline mrb_bool -mrb_ro_data_p(const char *p) -{ - return (const char*)get_etext() < p && p < (const char*)get_edata(); -} -#else -extern char _etext[]; -#ifdef MRB_NO_INIT_ARRAY_START -extern char _edata[]; +#if defined(MRB_USE_ETEXT_EDATA) && !defined(MRB_USE_LINK_TIME_RO_DATA_P) +# ifdef __GNUC__ +# warning MRB_USE_ETEXT_EDATA is deprecated. Define MRB_USE_LINK_TIME_RO_DATA_P instead. +# endif +# define MRB_USE_LINK_TIME_RO_DATA_P +#endif -static inline mrb_bool -mrb_ro_data_p(const char *p) -{ - return _etext < p && p < _edata; -} -#else +#if defined(MRB_USE_CUSTOM_RO_DATA_P) +/* If you define `MRB_USE_CUSTOM_RO_DATA_P`, you must implement `mrb_ro_data_p()`. */ +mrb_bool mrb_ro_data_p(const char *p); +#elif defined(MRB_USE_LINK_TIME_RO_DATA_P) +extern char __ehdr_start[]; extern char __init_array_start[]; static inline mrb_bool mrb_ro_data_p(const char *p) { - return _etext < p && p < (char*)&__init_array_start; + return __ehdr_start < p && p < __init_array_start; } -#endif -#endif #else # define mrb_ro_data_p(p) FALSE #endif diff --git a/include/mruby/variable.h b/include/mruby/variable.h index a0fbca1f9..3dc2c9a6d 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -1,5 +1,5 @@ -/* -** mruby/variable.h - mruby variables +/** +** @file mruby/variable.h - mruby variables ** ** See Copyright Notice in mruby.h */ @@ -14,27 +14,13 @@ */ MRB_BEGIN_DECL -typedef struct global_variable { - int counter; - mrb_value *data; - mrb_value (*getter)(void); - void (*setter)(void); - /* void (*marker)(); */ - /* int block_trace; */ - /* struct trace_var *trace; */ -} global_variable; - -struct global_entry { - global_variable *var; - mrb_sym id; -}; - mrb_value mrb_vm_special_get(mrb_state*, mrb_sym); void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value); mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym); void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value); mrb_value mrb_vm_const_get(mrb_state*, mrb_sym); void mrb_vm_const_set(mrb_state*, mrb_sym, mrb_value); +size_t mrb_obj_iv_tbl_memsize(mrb_value); MRB_API mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym); @@ -97,18 +83,15 @@ MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); * * Example: * - * !!!ruby * # Ruby style * $value = nil * - * !!!c * // C style * mrb_sym sym = mrb_intern_lit(mrb, "$value"); * mrb_gv_remove(mrb, sym); * * @param mrb The mruby state reference * @param sym The name of the global variable - * @param val The value of the global variable */ MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym); @@ -117,12 +100,14 @@ MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_ MRB_API void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v); MRB_API mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym); mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*); +void mrb_obj_iv_set_force(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); mrb_value mrb_mod_constants(mrb_state *mrb, mrb_value mod); mrb_value mrb_f_global_variables(mrb_state *mrb, mrb_value self); mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value); mrb_value mrb_mod_class_variables(mrb_state*, mrb_value); mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym); mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym); +mrb_bool mrb_ident_p(const char *s, mrb_int len); /* GC functions */ void mrb_gc_mark_gv(mrb_state*); @@ -131,6 +116,10 @@ void mrb_gc_mark_iv(mrb_state*, struct RObject*); size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*); void mrb_gc_free_iv(mrb_state*, struct RObject*); +/* return non zero to break the loop */ +typedef int (mrb_iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); +MRB_API void mrb_iv_foreach(mrb_state *mrb, mrb_value obj, mrb_iv_foreach_func *func, void *p); + MRB_END_DECL #endif /* MRUBY_VARIABLE_H */ diff --git a/include/mruby/version.h b/include/mruby/version.h index 43d6461ea..185263f32 100644 --- a/include/mruby/version.h +++ b/include/mruby/version.h @@ -1,5 +1,5 @@ -/* -** mruby/version.h - mruby version definition +/** +** @file mruby/version.h - mruby version definition ** ** See Copyright Notice in mruby.h */ @@ -27,7 +27,7 @@ MRB_BEGIN_DECL /* * The version of Ruby used by mruby. */ -#define MRUBY_RUBY_VERSION "1.9" +#define MRUBY_RUBY_VERSION "3.0" /* * Ruby engine. @@ -37,17 +37,35 @@ MRB_BEGIN_DECL /* * Major release version number. */ -#define MRUBY_RELEASE_MAJOR 1 +#define MRUBY_RELEASE_MAJOR 3 /* * Minor release version number. */ -#define MRUBY_RELEASE_MINOR 4 +#define MRUBY_RELEASE_MINOR 0 /* * Tiny release version number. */ -#define MRUBY_RELEASE_TEENY 1 +#define MRUBY_RELEASE_TEENY 0 + +/* + * Patch level. + */ +#define MRUBY_PATCHLEVEL -1 + +/* + * Patch level string. (optional) + */ +#define MRUBY_PATCHLEVEL_STR "" + +#ifndef MRUBY_PATCHLEVEL_STR +# if MRUBY_PATCHLEVEL < 0 +# define MRUBY_PATCHLEVEL_STR "dev" +# else +# define MRUBY_PATCHLEVEL_STR "p"MRB_STRINGIZE(MRUBY_PATCHLEVEL) +# endif +#endif /* * The mruby version. @@ -62,22 +80,36 @@ MRB_BEGIN_DECL /* * Release year. */ -#define MRUBY_RELEASE_YEAR 2018 +#define MRUBY_RELEASE_YEAR 2021 /* * Release month. */ -#define MRUBY_RELEASE_MONTH 4 +#define MRUBY_RELEASE_MONTH 3 /* * Release day. */ -#define MRUBY_RELEASE_DAY 27 +#define MRUBY_RELEASE_DAY 5 /* * Release date as a string. */ -#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY) +#define MRUBY_RELEASE_DATE \ + MRUBY_RELEASE_YEAR_STR "-" \ + MRUBY_RELEASE_MONTH_STR "-" \ + MRUBY_RELEASE_DAY_STR +#define MRUBY_RELEASE_YEAR_STR MRB_STRINGIZE(MRUBY_RELEASE_YEAR) +#if MRUBY_RELEASE_MONTH < 10 +#define MRUBY_RELEASE_MONTH_STR "0" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) +#else +#define MRUBY_RELEASE_MONTH_STR MRB_STRINGIZE(MRUBY_RELEASE_MONTH) +#endif +#if MRUBY_RELEASE_DAY < 10 +#define MRUBY_RELEASE_DAY_STR "0" MRB_STRINGIZE(MRUBY_RELEASE_DAY) +#else +#define MRUBY_RELEASE_DAY_STR MRB_STRINGIZE(MRUBY_RELEASE_DAY) +#endif /* * The year mruby was first created. @@ -92,9 +124,10 @@ MRB_BEGIN_DECL /* * mruby's version, and release date. */ -#define MRUBY_DESCRIPTION \ - "mruby " MRUBY_VERSION \ - " (" MRUBY_RELEASE_DATE ") " \ +#define MRUBY_DESCRIPTION \ + "mruby " MRUBY_VERSION \ + MRUBY_PATCHLEVEL_STR \ + " (" MRUBY_RELEASE_DATE ")" \ /* * mruby's copyright information. |
