summaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/mrbconf.h185
-rw-r--r--include/mruby.h750
-rw-r--r--include/mruby/array.h116
-rw-r--r--include/mruby/boxing_nan.h141
-rw-r--r--include/mruby/boxing_no.h34
-rw-r--r--include/mruby/boxing_word.h263
-rw-r--r--include/mruby/class.h76
-rw-r--r--include/mruby/common.h40
-rw-r--r--include/mruby/compile.h57
-rw-r--r--include/mruby/data.h17
-rw-r--r--include/mruby/debug.h14
-rw-r--r--include/mruby/dump.h83
-rw-r--r--include/mruby/endian.h44
-rw-r--r--include/mruby/error.h86
-rw-r--r--include/mruby/gc.h21
-rw-r--r--include/mruby/hash.h114
-rw-r--r--include/mruby/irep.h120
-rw-r--r--include/mruby/istruct.h13
-rw-r--r--include/mruby/khash.h32
-rw-r--r--include/mruby/numeric.h142
-rw-r--r--include/mruby/object.h26
-rw-r--r--include/mruby/opcode.h163
-rw-r--r--include/mruby/ops.h122
-rw-r--r--include/mruby/presym.h40
-rw-r--r--include/mruby/presym/disable.h70
-rw-r--r--include/mruby/presym/enable.h37
-rw-r--r--include/mruby/presym/scanning.h73
-rw-r--r--include/mruby/proc.h177
-rw-r--r--include/mruby/range.h46
-rw-r--r--include/mruby/re.h4
-rw-r--r--include/mruby/string.h286
-rw-r--r--include/mruby/throw.h33
-rw-r--r--include/mruby/value.h265
-rw-r--r--include/mruby/variable.h22
-rw-r--r--include/mruby/version.h57
35 files changed, 2614 insertions, 1155 deletions
diff --git a/include/mrbconf.h b/include/mrbconf.h
index 4796919c2..347f6786e 100644
--- a/include/mrbconf.h
+++ b/include/mrbconf.h
@@ -25,24 +25,85 @@
#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
-/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
-//#define MRB_INT16
+/* exclude floating point numbers */
+//#define MRB_NO_FLOAT
-/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */
-//#define MRB_INT64
+/* obsolete configuration */
+#if defined(MRB_USE_FLOAT)
+# define MRB_USE_FLOAT32
+#endif
-/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT */
-//#define MRB_NAN_BOXING
+/* 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<<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
+
+/* 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
-/* define on big endian machines; used by MRB_NAN_BOXING */
-//#define MRB_ENDIAN_BIG
+/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT32 and MRB_NO_FLOAT */
+//#define MRB_NAN_BOXING
/* 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_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
+# else
+/* Otherwise use 32bit integers */
+# define MRB_INT32
+# endif
+#endif
+
+/* call malloc_trim(0) from mrb_full_gc() */
+//#define MRB_USE_MALLOC_TRIM
+
/* string class to handle UTF-8 encoding */
//#define MRB_UTF8_STRING
@@ -52,18 +113,13 @@
/* number of object per heap page */
//#define MRB_HEAP_PAGE_SIZE 1024
-/* use segmented list for IV table */
-//#define MRB_USE_IV_SEGLIST
-
-/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */
-//#define MRB_IVHASH_INIT_SIZE 8
+/* if __ehdr_start is available, mruby can reduce memory used by symbols */
+//#define MRB_USE_LINK_TIME_RO_DATA_P
-/* if _etext and _edata available, mruby can reduce memory used by symbols */
-//#define MRB_USE_ETEXT_EDATA
-
-/* 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
@@ -77,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
@@ -92,25 +145,39 @@
/* 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_NO_XXXX to drop following features */
+//#define MRB_NO_STDIO /* use of stdio */
-/* -DMRB_ENABLE_XXXX to enable following features */
-//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
+/* -DMRB_USE_XXXX to enable following features */
+//#define MRB_USE_DEBUG_HOOK /* hooks for debugger */
+//#define MRB_USE_ALL_SYMBOLS /* Symbol.all_symbols */
-/* end of configuration */
-
-/* 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
@@ -122,4 +189,46 @@
# define TRUE 1
#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 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 8adce289b..d421dc58c 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -1,7 +1,7 @@
/*
** mruby - An embeddable Ruby implementation
**
-** Copyright (c) mruby developers 2010-2017
+** 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,38 +66,70 @@
#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"
-#ifdef MRB_USE_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
+#ifndef DBL_EPSILON
+#define DBL_EPSILON ((double)2.22044604925031308085e-16L)
+#endif
+#ifndef LDBL_EPSILON
+#define LDBL_EPSILON (1.08420217248550443401e-19L)
+#endif
+
+#ifdef MRB_USE_FLOAT32
#define MRB_FLOAT_EPSILON FLT_EPSILON
#else
#define MRB_FLOAT_EPSILON DBL_EPSILON
#endif
-
-#include "mruby/common.h"
-#include <mruby/value.h>
-#include <mruby/gc.h>
-#include <mruby/version.h>
+#endif
/**
* MRuby C API entry point
*/
MRB_BEGIN_DECL
-typedef uint32_t mrb_code;
+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;
@@ -109,17 +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;
- int nregs;
- int ridx;
- int eidx;
- 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 {
@@ -134,55 +173,70 @@ 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;
- mrb_code **rescue; /* exception handler stack */
- int rsize;
- struct RProc **ensure; /* ensure handler stack */
- int esize;
-
- enum mrb_fiber_state status;
- mrb_bool vmexec;
+ enum mrb_fiber_state status : 4;
+ mrb_bool vmexec : 1;
struct RFiber *fib;
};
-struct mrb_jmpbuf;
+#ifdef MRB_METHOD_CACHE_SIZE
+# undef MRB_NO_METHOD_CACHE
+#else
+/* default method cache size: 256 */
+/* cache size needs to be power of 2 */
+# define MRB_METHOD_CACHE_SIZE (1<<8)
+#endif
+/**
+ * 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);
+
+#ifndef MRB_USE_METHOD_T_STRUCT
+typedef uintptr_t mrb_method_t;
+#else
typedef struct {
- const char *filename;
- int lineno;
- struct RClass *klass;
- char sep;
- mrb_sym method_id;
-} mrb_backtrace_entry;
+ uint8_t flags;
+ union {
+ struct RProc *proc;
+ mrb_func_t func;
+ };
+} mrb_method_t;
+#endif
-typedef void (*mrb_atexit_func)(struct mrb_state*);
+#ifndef MRB_NO_METHOD_CACHE
+struct mrb_cache_entry {
+ struct RClass *c, *c0;
+ mrb_sym mid;
+ mrb_method_t m;
+};
+#endif
+
+struct mrb_jmpbuf;
-#define MRB_STATE_NO_REGEXP 1
-#define MRB_STATE_REGEXP 2
+typedef void (*mrb_atexit_func)(struct mrb_state*);
typedef struct mrb_state {
struct mrb_jmpbuf *jmp;
- uint32_t flags;
mrb_allocf allocf; /* memory allocation function */
void *allocf_ud; /* auxiliary data of allocf */
struct mrb_context *c;
struct mrb_context *root_c;
+ struct iv_tbl *globals; /* global variable table */
struct RObject *exc; /* exception */
- struct {
- struct RObject *exc;
- int n;
- int n_allocated;
- mrb_backtrace_entry *entries;
- } backtrace;
- struct iv_tbl *globals; /* global variable table */
struct RObject *top_self;
struct RClass *object_class; /* Object class */
@@ -192,26 +246,35 @@ typedef struct mrb_state {
struct RClass *string_class;
struct RClass *array_class;
struct RClass *hash_class;
+ struct RClass *range_class;
+#ifndef MRB_NO_FLOAT
struct RClass *float_class;
- struct RClass *fixnum_class;
+#endif
+ 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;
+#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
@@ -223,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 */
@@ -233,12 +296,9 @@ typedef struct mrb_state {
#else
mrb_atexit_func *atexit_stack;
#endif
- mrb_int atexit_stack_len;
+ uint16_t atexit_stack_len;
} mrb_state;
-
-typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
-
/**
* Defines a new class.
*
@@ -254,23 +314,27 @@ typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
* //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.
@@ -279,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.
@@ -292,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.
@@ -305,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!");
@@ -317,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.
@@ -344,17 +408,25 @@ 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 fuction.
+ * Defines a module function.
*
* Example:
*
@@ -372,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.
@@ -401,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.
@@ -452,11 +526,12 @@ 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*] constchar* 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);
/**
* Undefine a class method.
@@ -491,14 +566,15 @@ MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
* 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 instace of c class.
+ * Initialize a new object instance of c class.
*
* Example:
*
@@ -519,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);
@@ -533,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.
*
@@ -550,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);
@@ -567,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);
@@ -594,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.
@@ -640,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);
/**
@@ -679,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
@@ -721,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);
@@ -731,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.
@@ -751,7 +837,7 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18)
/**
- * Funtion takes n optional arguments
+ * Function takes n optional arguments
*
* @param n
* The number of optional arguments.
@@ -759,7 +845,7 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13)
/**
- * Funtion takes n1 mandatory arguments and n2 optional arguments
+ * Function takes n1 mandatory arguments and n2 optional arguments
*
* @param n1
* The number of required arguments.
@@ -797,55 +883,126 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
*
* Must be a C string composed of the following format specifiers:
*
- * | char | Ruby type | C types | Notes |
+ * | char | Ruby type | C types | Notes |
* |:----:|----------------|-------------------|----------------------------------------------------|
* | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument |
* | `C` | {Class}/{Module} | {mrb_value} | |
* | `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} | |
- * | `&` | block | {mrb_value} | |
- * | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. |
- * | &vert; | optional | | After this spec following specs would be optional. |
+ * | `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 | 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.
+ *
+ * `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); }
+ *
*
- * 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.
+ * // 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;
}
-static inline int
-mrb_get_argc(mrb_state *mrb) /* get argc */
-{
- return mrb->c->ci->argc;
-}
+/**
+ * Retrieve number of arguments from mrb_state.
+ *
+ * Correctly handles *splat arguments.
+ */
+MRB_API mrb_int mrb_get_argc(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);
/* `strlen` for character string literals (use with caution or `strlen` instead)
Adjacent string literals are concatenated in C/C++ in translation phase 6.
@@ -858,6 +1015,8 @@ mrb_get_argc(mrb_state *mrb) /* get argc */
/**
* Call existing ruby functions.
*
+ * Example:
+ *
* #include <stdio.h>
* #include <mruby.h>
* #include "mruby/compile.h"
@@ -872,17 +1031,20 @@ mrb_get_argc(mrb_state *mrb) /* get argc */
* 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.
*
@@ -892,54 +1054,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 */
@@ -958,14 +1135,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
-char* mrb_utf8_from_locale(const char *p, size_t len);
-char* mrb_locale_from_utf8(const char *p, size_t len);
+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) (p)
-#define mrb_locale_from_utf8(p, l) (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
@@ -1020,11 +1203,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)
@@ -1034,20 +1216,34 @@ 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, int base);
+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_NO_FLOAT
MRB_API mrb_value mrb_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);
+
+MRB_INLINE int
+mrb_gc_arena_save(mrb_state *mrb)
+{
+ return mrb->gc.arena_idx;
+}
+
+MRB_INLINE void
+mrb_gc_arena_restore(mrb_state *mrb, int idx)
+{
+ mrb->gc.arena_idx = idx;
+}
MRB_API void mrb_garbage_collect(mrb_state*);
MRB_API void mrb_full_gc(mrb_state*);
MRB_API void mrb_incremental_gc(mrb_state *);
-MRB_API int mrb_gc_arena_save(mrb_state*);
-MRB_API void mrb_gc_arena_restore(mrb_state*,int);
MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*);
#define mrb_gc_mark_value(mrb,val) do {\
if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \
@@ -1058,12 +1254,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);
@@ -1090,37 +1289,49 @@ 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_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError"))
-#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError"))
-
-#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError"))
+#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
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);
+/* continue execution to the proc */
+/* this function should always be called as the last function of a method */
+/* e.g. return mrb_yield_cont(mrb, proc, self, argc, argv); */
+mrb_value mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb_value *argv);
+
/* mrb_gc_protect() leaves the object in the arena */
MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj);
/* mrb_gc_register() keeps the object from GC. */
@@ -1129,17 +1340,18 @@ 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_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 *klass, const char *name1, const char *name2);
+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);
@@ -1150,26 +1362,34 @@ MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RC
MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func);
-/*
+/**
* 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
+ *
+ * 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 */
typedef struct mrb_pool mrb_pool;
@@ -1178,6 +1398,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);
@@ -1187,6 +1408,37 @@ 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 */
+#undef memcpy
+#undef memset
+static void*
+mrbmemcpy(void *dst, const void *src, size_t n)
+{
+ char *d = (char*)dst;
+ const char *s = (const char*)src;
+ while (n--)
+ *d++ = *s++;
+ return d;
+}
+#define memcpy(a,b,c) mrbmemcpy(a,b,c)
+
+static void*
+mrbmemset(void *s, int c, size_t n)
+{
+ char *t = (char*)s;
+ while (n--)
+ *t++ = c;
+ return s;
+}
+#define memset(a,b,c) mrbmemset(a,b,c)
+#endif
+
MRB_END_DECL
#endif /* MRUBY_H */
diff --git a/include/mruby/array.h b/include/mruby/array.h
index e553faf92..16f78f773 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,26 +17,67 @@ MRB_BEGIN_DECL
typedef struct mrb_shared_array {
int refcnt;
- mrb_int len;
+ mrb_ssize len;
mrb_value *ptr;
} mrb_shared_array;
+#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;
- mrb_int len;
union {
- mrb_int capa;
- mrb_shared_array *shared;
- } aux;
- mrb_value *ptr;
+ struct {
+ mrb_ssize len;
+ union {
+ mrb_ssize capa;
+ mrb_shared_array *shared;
+ } aux;
+ mrb_value *ptr;
+ } heap;
+#ifndef MRB_ARY_NO_EMBED
+ mrb_value ary[MRB_ARY_EMBED_LEN_MAX];
+#endif
+ } as;
};
#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
-#define RARRAY_LEN(a) (RARRAY(a)->len)
-#define RARRAY_PTR(a) ((const mrb_value*)RARRAY(a)->ptr)
+#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.ary)
+#endif
+
+#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))
+#define ARY_SET_LEN(a,n) do {\
+ if (ARY_EMBED_P(a)) {\
+ mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
+ ARY_SET_EMBED_LEN(a,n);\
+ }\
+ else\
+ (a)->as.heap.len = (n);\
+} while (0)
+#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
#define MRB_ARY_SHARED 256
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
@@ -66,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.
*/
@@ -175,10 +216,11 @@ 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);
/*
- * Unshift an element into an array
+ * Unshift an element into the array
*
* Equivalent to:
*
@@ -189,9 +231,37 @@ MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
* @param item The item to unshift.
*/
MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
+
+/*
+ * Get nth element in the array
+ *
+ * Equivalent to:
+ *
+ * ary[offset]
+ *
+ * @param ary The target array.
+ * @param offset The element position (negative counts from the tail).
+ */
MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
/*
+ * 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.
*
* Equivalent to:
@@ -205,7 +275,7 @@ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
/*
- * Removes all elements from this array
+ * Removes all elements from the array
*
* Equivalent to:
*
@@ -226,7 +296,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);
@@ -239,22 +309,8 @@ 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);
-static inline mrb_int
-mrb_ary_len(mrb_state *mrb, mrb_value ary)
-{
- (void)mrb;
- mrb_assert(mrb_array_p(ary));
- return RARRAY_LEN(ary);
-}
-
-static inline mrb_value
-ary_elt(mrb_value ary, mrb_int offset)
-{
- if (offset < 0 || RARRAY_LEN(ary) <= offset) {
- return mrb_nil_value();
- }
- return RARRAY_PTR(ary)[offset];
-}
+/* helper functions */
+mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
MRB_END_DECL
diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h
index 4cb82bf14..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,8 +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_NO_FLOAT
+# error ---->> MRB_NAN_BOXING and MRB_NO_FLOAT conflict <<----
#endif
#ifdef MRB_INT64
@@ -16,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
@@ -33,65 +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;
+};
-#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
+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;
+}
+
+#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; \
- } 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))
+ union mrb_value_ mrb_value_union_variable; \
+ if ((v) != (v)) { /* NaN */ \
+ mrb_value_union_variable.ttt = 0x7ff80000; \
+ mrb_value_union_variable.i = 0; \
+ } \
+ else { \
+ 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 7ee44a934..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,24 +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
+
+union mrb_value_union {
+#ifndef MRB_NO_FLOAT
+ mrb_float f;
+#endif
+ void *p;
+ mrb_int i;
+ mrb_sym sym;
+};
typedef struct mrb_value {
- union {
- mrb_float f;
- void *p;
- mrb_int i;
- mrb_sym sym;
- } value;
+ union mrb_value_union value;
enum mrb_vtype tt;
} mrb_value;
-#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
-
#define mrb_ptr(o) (o).value.p
#define mrb_cptr(o) mrb_ptr(o)
+#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
@@ -38,8 +45,11 @@ 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))
+#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))
#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h
index 6ca491585..86a04368f 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,114 +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_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
-#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
-
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
-
-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 : (sizeof(mrb_sym) * CHAR_BIT);
- };
- struct RBasic *bp;
- struct RFloat *fp;
- struct RCptr *vp;
- } value;
- unsigned long w;
-} mrb_value;
+#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) && defined(MRB_INT64)
+# define MRB_FIXNUM_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT)
+# define MRB_FIXNUM_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT)
+#else
+# define MRB_FIXNUM_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT)
+# define MRB_FIXNUM_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT)
+#endif
-MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
-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);
+#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
+#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)
-#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f)
+/*
+ * 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 sym_flag;
+ )
+ };
+#endif
+ struct RBasic *bp;
+#ifndef MRB_NO_FLOAT
+ struct RFloat *fp;
+#endif
+ struct RInteger *ip;
+ struct RCptr *vp;
+ uintptr_t w;
+ mrb_value value;
+};
-#define mrb_ptr(o) (o).value.p
-#define mrb_cptr(o) (o).value.vp->p
-#define mrb_float(o) (o).value.fp->f
-#define mrb_fixnum(o) (o).value.i
-#define mrb_symbol(o) (o).value.sym
+mrb_static_assert1(sizeof(mrb_value) == sizeof(union mrb_value_));
-static inline enum mrb_vtype
-mrb_type(mrb_value o)
+static inline union mrb_value_
+mrb_val_union(mrb_value v)
{
- 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;
+ union mrb_value_ x;
+ x.value = v;
+ return x;
}
-#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse)
-#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG)
+MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
+#ifndef MRB_NO_FLOAT
+MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
+#endif
+MRB_API mrb_value mrb_word_boxing_int_value(struct mrb_state*, mrb_int);
+
+#define mrb_immediate_p(o) ((o).w & BOXWORD_IMMEDIATE_MASK || (o).w == MRB_Qnil)
+
+#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)(((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
+#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_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 = v;\
+ mrb_value_union_variable.sym_flag = BOXWORD_SYMBOL_FLAG;\
+ (r) = mrb_value_union_variable.value;\
} while (0)
+#else
+#define SET_SYM_VALUE(r,n) BOXWORD_SET_SHIFT_VALUE(r, SYMBOL, n)
+#endif
+#define SET_OBJ_VALUE(r,v) ((r).w = (uintptr_t)(v))
-#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v)
-#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)
+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 ce953af3b..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,16 +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)))
-#define RCLASS_SUPER(v) (((struct RClass*)(mrb_ptr(v)))->super)
-#define RCLASS_IV_TBL(v) (((struct RClass*)(mrb_ptr(v)))->iv)
-#define RCLASS_M_TBL(v) (((struct RClass*)(mrb_ptr(v)))->mt)
-static inline struct RClass*
+MRB_INLINE struct RClass*
mrb_class(mrb_state *mrb, mrb_value v)
{
switch (mrb_type(v)) {
@@ -38,10 +35,12 @@ 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;
+ case MRB_TT_INTEGER:
+ return mrb->integer_class;
+#ifndef MRB_NO_FLOAT
case MRB_TT_FLOAT:
return mrb->float_class;
+#endif
case MRB_TT_CPTR:
return mrb->object_class;
case MRB_TT_ENV:
@@ -51,40 +50,59 @@ mrb_class(mrb_state *mrb, mrb_value v)
}
}
-// TODO: figure out where to put user flags
-#define MRB_FLAG_IS_FROZEN (1 << 18)
-#define MRB_FLAG_IS_PREPENDED (1 << 19)
-#define MRB_FLAG_IS_ORIGIN (1 << 20)
+/* flags:
+ 20: frozen
+ 19: is_prepended
+ 18: is_origin
+ 17: is_inherited (used by method cache)
+ 16: unused
+ 0-15: instance type
+*/
+#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_FLAG_IS_PREPENDED) {\
- c = c->super;\
- while (!(c->flags & MRB_FLAG_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);
-MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
-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 *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
+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_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 struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
-MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
-MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_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 338044c2f..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
*/
@@ -7,14 +7,19 @@
#ifndef MRUBY_COMMON_H
#define MRUBY_COMMON_H
+#ifdef __APPLE__
+ #ifndef __TARGETCONDITIONALS__
+ #include "TargetConditionals.h"
+ #endif
+#endif
#ifdef __cplusplus
-#ifdef MRB_ENABLE_CXX_EXCEPTION
+#ifdef MRB_USE_CXX_ABI
#define MRB_BEGIN_DECL
#define MRB_END_DECL
#else
# define MRB_BEGIN_DECL extern "C" {
-# define MRB_END_DECL }
+# define MRB_END_DECL }
#endif
#else
/** Start declarations in C mode */
@@ -29,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))
@@ -49,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)
@@ -66,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 ad3f19db1..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,12 +33,16 @@ typedef struct mrbc_context {
mrb_bool no_exec:1;
mrb_bool keep_lv:1;
mrb_bool no_optimize:1;
+ const struct RProc *upper;
+
+ size_t parser_nerr;
} mrbc_context;
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 {
@@ -64,7 +68,7 @@ enum mrb_lex_state_enum {
/* saved error message */
struct mrb_parser_message {
- int lineno;
+ uint16_t lineno;
int column;
char* message;
};
@@ -95,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;
@@ -102,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 */
@@ -111,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;
@@ -136,11 +144,10 @@ struct mrb_parser_state {
int tidx;
int tsiz;
- mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
+ mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
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;
@@ -150,42 +157,52 @@ struct mrb_parser_state {
mrb_bool no_optimize: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*);
MRB_API void mrb_parser_free(struct mrb_parser_state*);
MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
-MRB_API double mrb_float_read(const char*, char**);
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*);
-MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*);
+MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrbc_context*);
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, int len);
+MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len);
MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
-MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt);
+MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *cxt);
/** @} */
MRB_END_DECL
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 44f84e49c..2062a9308 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
*/
@@ -26,7 +26,6 @@ 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;
@@ -47,18 +46,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, uint32_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, uint32_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 165a20b3f..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 "0003"
+/* 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 "0000"
+#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 bb67e7bd8..1d550e415 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,26 +23,94 @@ 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))
-MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
+#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_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;
+ 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
+ * 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);
@@ -50,7 +118,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);
@@ -58,7 +126,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 81950f169..98236a219 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
*/
@@ -17,8 +17,11 @@ MRB_BEGIN_DECL
struct mrb_state;
-typedef void (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data);
+#define MRB_EACH_OBJ_OK 0
+#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
@@ -31,6 +34,13 @@ typedef enum {
MRB_GC_STATE_SWEEP
} mrb_gc_state;
+/* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
+ * in struct/union" when in C++ mode */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4200)
+#endif
+
typedef struct mrb_heap_page {
struct RBasic *freelist;
struct mrb_heap_page *prev;
@@ -41,6 +51,10 @@ typedef struct mrb_heap_page {
void *objects[];
} mrb_heap_page;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
typedef struct mrb_gc {
mrb_heap_page *heaps; /* heaps for GC */
mrb_heap_page *sweeps;
@@ -62,6 +76,7 @@ typedef struct mrb_gc {
size_t threshold;
int interval_ratio;
int step_ratio;
+ mrb_bool iterating :1;
mrb_bool disabled :1;
mrb_bool full :1;
mrb_bool generational :1;
diff --git a/include/mruby/hash.h b/include/mruby/hash.h
index 55ad6a921..a16df2f75 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,37 @@
#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 kh_ht *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;
+ };
};
#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*, 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);
/*
* Initializes a new hash.
@@ -74,7 +88,7 @@ MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
*
* Equivalent to:
*
- * hash.hash_key?(key) ? hash[key] : def
+ * hash.key?(key) ? hash[key] : def
*
* @param mrb The mruby state reference.
* @param hash The target hash.
@@ -94,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);
@@ -110,7 +124,19 @@ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value
* @return An array with the keys of the hash.
*/
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
-MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
+/*
+ * Check if the hash has the key.
+ *
+ * Equivalent to:
+ *
+ * hash.key?(key)
+ *
+ * @param mrb The mruby state reference.
+ * @param hash The target hash.
+ * @param key The key to check existence.
+ * @return True if the hash has the key
+ */
+MRB_API mrb_bool mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key);
/*
* Check if the hash is empty
@@ -123,7 +149,7 @@ MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
* @param self The target hash.
* @return True if the hash is empty, false otherwise.
*/
-MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
+MRB_API mrb_bool mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
/*
* Gets an array of values.
@@ -151,32 +177,66 @@ 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);
-/* 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)
+/*
+ * 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);
-/* 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)
-MRB_API struct kh_ht * mrb_hash_tbl(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.
+ * @return The copy of the hash
+ */
+MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash);
-#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)
+/*
+ * Merges two hashes. The first hash will be modified by the
+ * second hash.
+ *
+ * @param mrb The mruby state reference.
+ * @param hash1 The target hash.
+ * @param hash2 Updating hash
+ */
+MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2);
+
+#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 35ae2bbaa..8d1648e13 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,45 +16,131 @@
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_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;
+#if defined(MRB_64BIT) || defined(MRB_INT64)
+ int64_t i64;
+#endif
+#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 hander. Includes this. */
+ uint8_t end[4]; /* The endpoint address that matches the hander. 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;
- size_t ilen, plen, slen, rlen, 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*);
+void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
+void mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep);
+
+struct mrb_insn_data {
+ uint8_t insn;
+ uint16_t a;
+ uint16_t b;
+ uint16_t c;
+};
+
+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 36489b1ce..fc6cacfda 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,24 +12,38 @@
/**
* Numeric class and it's sub-classes.
*
- * Integer, Float and Fixnum
+ * Integer and Float
*/
MRB_BEGIN_DECL
-#define POSFIXABLE(f) ((f) <= MRB_INT_MAX)
-#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
-#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
+#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_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
+#endif
+#ifndef MRB_NO_FLOAT
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
-MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
+#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_NO_FLOAT
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
+MRB_API int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f);
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);
#ifndef __has_builtin
#define __has_builtin(x) 0
@@ -42,9 +56,11 @@ mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y);
# define MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
#endif
+/*
// Clang 3.8 and 3.9 have problem compiling mruby in 32-bit mode, when MRB_INT64 is set
// because of missing __mulodi4 and similar functions in its runtime. We need to use custom
// implementation for them.
+*/
#ifdef MRB_HAVE_TYPE_GENERIC_CHECKED_ARITHMETIC_BUILTINS
#if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ >= 8) && \
defined(MRB_32BIT) && defined(MRB_INT64)
@@ -54,96 +70,100 @@ 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 */
+#endif /* MRB_NO_FLOAT */
+
MRB_END_DECL
#endif /* MRUBY_NUMERIC_H */
diff --git a/include/mruby/object.h b/include/mruby/object.h
index 9347981d4..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,23 +8,24 @@
#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;
};
#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
-#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN)
-#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN)
-#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN)
+#define MRB_FL_OBJ_IS_FROZEN (1 << 20)
+#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;
@@ -32,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 9dfa7f75d..987c5ad8f 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
*/
@@ -7,144 +7,10 @@
#ifndef MRUBY_OPCODE_H
#define MRUBY_OPCODE_H
-#define MAXARG_Bx (0xffff)
-#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
-
-/* instructions: packed 32 bit */
-/* ------------------------------- */
-/* A:B:C:OP = 9: 9: 7: 7 */
-/* A:Bx:OP = 9:16: 7 */
-/* Ax:OP = 25: 7 */
-/* A:Bz:Cz:OP = 9:14: 2: 7 */
-
-#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
-#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
-#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff))
-#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
-#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
-#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
-#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
-#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
-#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
-#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
-#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
-
-#define MKOPCODE(op) ((op) & 0x7f)
-#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
-#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
-#define MKARG_C(c) (((c) & 0x7f) << 7)
-#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
-#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
-#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
-#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
-#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
-
-#define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a))
-#define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b))
-#define MKOP_ABC(op,a,b,c) (MKOP_AB(op,a,b)|MKARG_C(c))
-#define MKOP_ABx(op,a,bx) (MKOP_A(op,a)|MKARG_Bx(bx))
-#define MKOP_Bx(op,bx) (MKOPCODE(op)|MKARG_Bx(bx))
-#define MKOP_sBx(op,sbx) (MKOPCODE(op)|MKARG_sBx(sbx))
-#define MKOP_AsBx(op,a,sbx) (MKOP_A(op,a)|MKARG_sBx(sbx))
-#define MKOP_Ax(op,ax) (MKOPCODE(op)|MKARG_Ax(ax))
-#define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c))
-
-enum {
- /*-----------------------------------------------------------------------
- operation code operand description
- ------------------------------------------------------------------------*/
- OP_NOP=0,/* */
- OP_MOVE,/* A B R(A) := R(B) */
- OP_LOADL,/* A Bx R(A) := Pool(Bx) */
- OP_LOADI,/* A sBx R(A) := sBx */
- OP_LOADSYM,/* A Bx R(A) := Syms(Bx) */
- OP_LOADNIL,/* A R(A) := nil */
- OP_LOADSELF,/* A R(A) := self */
- OP_LOADT,/* A R(A) := true */
- OP_LOADF,/* A R(A) := false */
-
- OP_GETGLOBAL,/* A Bx R(A) := getglobal(Syms(Bx)) */
- OP_SETGLOBAL,/* A Bx setglobal(Syms(Bx), R(A)) */
- OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */
- OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */
- OP_GETIV,/* A Bx R(A) := ivget(Syms(Bx)) */
- OP_SETIV,/* A Bx ivset(Syms(Bx),R(A)) */
- OP_GETCV,/* A Bx R(A) := cvget(Syms(Bx)) */
- OP_SETCV,/* A Bx cvset(Syms(Bx),R(A)) */
- OP_GETCONST,/* A Bx R(A) := constget(Syms(Bx)) */
- OP_SETCONST,/* A Bx constset(Syms(Bx),R(A)) */
- OP_GETMCNST,/* A Bx R(A) := R(A)::Syms(Bx) */
- OP_SETMCNST,/* A Bx R(A+1)::Syms(Bx) := R(A) */
- OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */
- OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */
-
- OP_JMP,/* sBx pc+=sBx */
- OP_JMPIF,/* A sBx if R(A) pc+=sBx */
- OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */
- OP_ONERR,/* sBx rescue_push(pc+sBx) */
- OP_RESCUE,/* A clear(exc); R(A) := exception (ignore when A=0) */
- OP_POPERR,/* A A.times{rescue_pop()} */
- OP_RAISE,/* A raise(R(A)) */
- OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */
- OP_EPOP,/* A A.times{ensure_pop().call} */
-
- OP_SEND,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
- OP_SENDB,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
- OP_FSEND,/* A B C R(A) := fcall(R(A),Syms(B),R(A+1),...,R(A+C-1)) */
- OP_CALL,/* A R(A) := self.call(frame.argc, frame.argv) */
- OP_SUPER,/* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
- OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */
- OP_ENTER,/* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
- OP_KARG,/* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
- OP_KDICT,/* A C R(A) := kdict */
-
- OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */
- OP_TAILCALL,/* A B C return call(R(A),Syms(B),*R(C)) */
- OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */
-
- OP_ADD,/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1) */
- OP_ADDI,/* A B C R(A) := R(A)+C (Syms[B]=:+) */
- OP_SUB,/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1) */
- OP_SUBI,/* A B C R(A) := R(A)-C (Syms[B]=:-) */
- OP_MUL,/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1) */
- OP_DIV,/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1) */
- OP_EQ,/* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1) */
- OP_LT,/* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1) */
- OP_LE,/* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1) */
- OP_GT,/* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1) */
- OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */
-
- OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
- OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */
- OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */
- OP_AREF,/* A B C R(A) := R(B)[C] */
- OP_ASET,/* A B C R(B)[C] := R(A) */
- OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A) */
-
- OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */
- OP_STRCAT,/* A B str_cat(R(A),R(B)) */
-
- OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
- OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */
- OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */
-
- OP_OCLASS,/* A R(A) := ::Object */
- OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
- OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */
- OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
- OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */
- OP_SCLASS,/* A B R(A) := R(B).singleton_class */
- OP_TCLASS,/* A R(A) := target_class */
-
- OP_DEBUG,/* A B C print R(A),R(B),R(C) */
- OP_STOP,/* stop VM */
- OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */
-
- OP_RSVD1,/* reserved instruction #1 */
- OP_RSVD2,/* reserved instruction #2 */
- OP_RSVD3,/* reserved instruction #3 */
- OP_RSVD4,/* reserved instruction #4 */
- OP_RSVD5,/* reserved instruction #5 */
+enum mrb_insn {
+#define OPCODE(x,_) OP_ ## x,
+#include "mruby/ops.h"
+#undef OPCODE
};
#define OP_L_STRICT 1
@@ -157,4 +23,21 @@ enum {
#define OP_R_BREAK 1
#define OP_R_RETURN 2
+#define PEEK_B(pc) (*(pc))
+#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
+#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
+
+#define READ_B() PEEK_B(pc++)
+#define READ_S() (pc+=2, PEEK_S(pc-2))
+#define READ_W() (pc+=3, PEEK_W(pc-3))
+
+#define FETCH_Z() /* nothing */
+#define FETCH_B() do {a=READ_B();} while (0)
+#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)
+
#endif /* MRUBY_OPCODE_H */
diff --git a/include/mruby/ops.h b/include/mruby/ops.h
new file mode 100644
index 000000000..d5d8fb077
--- /dev/null
+++ b/include/mruby/ops.h
@@ -0,0 +1,122 @@
+/* operand types:
+ + Z: no operand
+ + B: 8bit
+ + BB: 8+8bit
+ + BBB: 8+8+8bit
+ + BS: 8+16bit
+ + BSS: 8+16+16bit
+ + S: 16bit
+ + W: 24bit
+*/
+
+/*-----------------------------------------------------------------------
+operation code operands semantics
+------------------------------------------------------------------------*/
+OPCODE(NOP, Z) /* no operation */
+OPCODE(MOVE, BB) /* R(a) = R(b) */
+OPCODE(LOADL, BB) /* R(a) = Pool(b) */
+OPCODE(LOADL16, BS) /* R(a) = Pool(b) */
+OPCODE(LOADI, BB) /* R(a) = mrb_int(b) */
+OPCODE(LOADINEG, BB) /* R(a) = mrb_int(-b) */
+OPCODE(LOADI__1, B) /* R(a) = mrb_int(-1) */
+OPCODE(LOADI_0, B) /* R(a) = mrb_int(0) */
+OPCODE(LOADI_1, B) /* R(a) = mrb_int(1) */
+OPCODE(LOADI_2, B) /* R(a) = mrb_int(2) */
+OPCODE(LOADI_3, B) /* R(a) = mrb_int(3) */
+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(LOADSYM16, BS) /* R(a) = Syms(b) */
+OPCODE(LOADNIL, B) /* R(a) = nil */
+OPCODE(LOADSELF, B) /* R(a) = self */
+OPCODE(LOADT, B) /* R(a) = true */
+OPCODE(LOADF, B) /* R(a) = false */
+OPCODE(GETGV, BB) /* R(a) = getglobal(Syms(b)) */
+OPCODE(SETGV, BB) /* setglobal(Syms(b), R(a)) */
+OPCODE(GETSV, BB) /* R(a) = Special[Syms(b)] */
+OPCODE(SETSV, BB) /* Special[Syms(b)] = R(a) */
+OPCODE(GETIV, BB) /* R(a) = ivget(Syms(b)) */
+OPCODE(SETIV, BB) /* ivset(Syms(b),R(a)) */
+OPCODE(GETCV, BB) /* R(a) = cvget(Syms(b)) */
+OPCODE(SETCV, BB) /* cvset(Syms(b),R(a)) */
+OPCODE(GETCONST, BB) /* R(a) = constget(Syms(b)) */
+OPCODE(SETCONST, BB) /* constset(Syms(b),R(a)) */
+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(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(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(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)) */
+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, 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)) */
+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(INTERN, B) /* R(a) = intern(R(a)) */
+OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
+OPCODE(STRING16, BS) /* R(a) = str_dup(Lit(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*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(LAMBDA16, BS) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
+OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
+OPCODE(BLOCK16, BS) /* R(a) = lambda(SEQ[b],L_BLOCK) */
+OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
+OPCODE(METHOD16, BS) /* R(a) = lambda(SEQ[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(EXEC16, BS) /* R(a) = blockexec(R(a),SEQ[b]) */
+OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
+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(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 5965a2b39..0edd3e1f1 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
*/
@@ -18,25 +18,37 @@ MRB_BEGIN_DECL
struct REnv {
MRB_OBJECT_HEADER;
mrb_value *stack;
+ struct mrb_context *cxt;
mrb_sym mid;
- ptrdiff_t cioff;
};
-#define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len)
-#define MRB_ENV_STACK_LEN(e) ((mrb_int)(e)->flags)
-#define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1)
-#define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0)
-
-MRB_API void mrb_env_unshare(mrb_state*, struct REnv*);
+/* 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 RClass *target_class;
- struct REnv *env;
+ const struct RProc *upper;
+ union {
+ struct RClass *target_class;
+ struct REnv *env;
+ } e;
};
/* aspec access */
@@ -45,33 +57,152 @@ 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 128
-#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC) != 0)
+#define MRB_PROC_CFUNC_FL 128
+#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC_FL) != 0)
+#define MRB_PROC_CFUNC(p) (p)->body.func
#define MRB_PROC_STRICT 256
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
+#define MRB_PROC_ORPHAN 512
+#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
+#define MRB_PROC_ENVSET 1024
+#define MRB_PROC_ENV_P(p) (((p)->flags & MRB_PROC_ENVSET) != 0)
+#define MRB_PROC_ENV(p) (MRB_PROC_ENV_P(p) ? (p)->e.env : NULL)
+#define MRB_PROC_TARGET_CLASS(p) (MRB_PROC_ENV_P(p) ? (p)->e.env->c : (p)->e.target_class)
+#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));\
+ }\
+ else {\
+ (p)->e.target_class = (tc);\
+ mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)(tc));\
+ }\
+} while (0)
+#define MRB_PROC_SCOPE 2048
+#define MRB_PROC_SCOPE_P(p) (((p)->flags & MRB_PROC_SCOPE) != 0)
#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_API 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)
+#define MRB_METHOD_FUNC_FL 1
+#define MRB_METHOD_NOARG_FL 2
+
+#ifndef MRB_USE_METHOD_T_STRUCT
+
+#define MRB_METHOD_FUNC_P(m) (((uintptr_t)(m))&MRB_METHOD_FUNC_FL)
+#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).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_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=(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_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, struct RProc*, 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 5a5a6ffd2..4410accd5 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,41 +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);\
+ }\
+ else {\
+ (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)
@@ -58,11 +70,29 @@ struct RString {
#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
+#define RSTR_FSHARED_P(s) ((s)->flags & MRB_STR_FSHARED)
+#define RSTR_SET_FSHARED_FLAG(s) ((s)->flags |= MRB_STR_FSHARED)
+#define RSTR_UNSET_FSHARED_FLAG(s) ((s)->flags &= ~MRB_STR_FSHARED)
+
#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
-/*
+#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)))
@@ -73,23 +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_NOFREE 2
-#define MRB_STR_NO_UTF 8
-#define MRB_STR_EMBED 16
-#define MRB_STR_EMBED_LEN_MASK 0x3e0
-#define MRB_STR_EMBED_LEN_SHIFT 5
+#define MRB_STR_FSHARED 2
+#define MRB_STR_NOFREE 4
+#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*);
-/*
- * Appends self to other. Returns self as a concatnated string.
+
+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, 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)
@@ -108,35 +151,33 @@ MRB_API void mrb_str_modify(mrb_state*, struct RString*);
* str1 = mrb_str_new_lit(mrb, "abc");
* str2 = mrb_str_new_lit(mrb, "def");
*
- * // Concatnates str2 to str1.
+ * // Concatenates str2 to str1.
* mrb_str_concat(mrb, str1, str2);
*
- * // Prints new Concatnated 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)
@@ -160,55 +201,54 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
* mrb_p(mrb, a);
* mrb_p(mrb, b);
*
- * // Concatnates both Ruby strings.
+ * // Concatenates both Ruby strings.
* c = mrb_str_plus(mrb, a, b);
*
- * // Prints new Concatnated 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 concatnated.
+ * => "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)
@@ -233,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)
@@ -273,98 +312,103 @@ 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_buf_new(mrb_state *mrb, size_t capa);
-MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
+MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
+#define mrb_str_buf_new(mrb, capa) mrb_str_new_capa(mrb, (capa))
+
+/* 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);
MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck);
+MRB_API mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *s, mrb_int base, mrb_bool badcheck);
MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck);
+MRB_API double mrb_cstr_to_dbl(mrb_state *mrb, const char *s, 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
*/
@@ -372,50 +416,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);
-mrb_int mrb_str_hash(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 010793027..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,19 +7,27 @@
#ifndef MRB_THROW_H
#define MRB_THROW_H
-#if defined(MRB_ENABLE_CXX_EXCEPTION) && !defined(__cplusplus)
-#error Trying to use C++ exception handling in C code
+#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>
@@ -27,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
@@ -44,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 54d197f8f..4831b55af 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,43 @@
#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()
+ */
typedef uint8_t mrb_bool;
struct mrb_state;
-#if defined(MRB_INT16) && defined(MRB_INT64)
-# error "You can't define MRB_INT16 and MRB_INT64 at the same time."
-#endif
-
#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,48 +53,46 @@ 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_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;
#endif
+#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
+# if _MSC_VER < 1800 && !defined MRB_NO_FLOAT
# include <float.h>
# define isfinite(n) _finite(n)
# define isnan _isnan
@@ -92,33 +105,36 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
#endif
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_MAXDEFINE /* 24 */
+ MRB_TT_FALSE = 0,
+ MRB_TT_TRUE,
+ MRB_TT_SYMBOL,
+ MRB_TT_UNDEF,
+ MRB_TT_FREE,
+ MRB_TT_FLOAT,
+ MRB_TT_INTEGER,
+ MRB_TT_CPTR,
+ MRB_TT_OBJECT,
+ MRB_TT_CLASS,
+ MRB_TT_MODULE,
+ MRB_TT_ICLASS,
+ MRB_TT_SCLASS,
+ MRB_TT_PROC,
+ MRB_TT_ARRAY,
+ MRB_TT_HASH,
+ MRB_TT_STRING,
+ MRB_TT_RANGE,
+ MRB_TT_EXCEPTION,
+ MRB_TT_ENV,
+ MRB_TT_DATA,
+ MRB_TT_FIBER,
+ MRB_TT_ISTRUCT,
+ MRB_TT_BREAK,
+ MRB_TT_MAXDEFINE
};
+/* for compatibility */
+#define MRB_TT_FIXNUM MRB_TT_INTEGER
+
#include <mruby/object.h>
#ifdef MRB_DOCUMENTATION_BLOCK
@@ -137,6 +153,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)
@@ -145,8 +168,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)
@@ -154,22 +194,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_NO_FLOAT
+#ifndef mrb_float_p
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
-#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
+#endif
+#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_NO_FLOAT
MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
{
mrb_value v;
@@ -177,8 +277,9 @@ MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
SET_FLOAT_VALUE(mrb, v, f);
return v;
}
+#endif
-static inline mrb_value
+MRB_INLINE mrb_value
mrb_cptr_value(struct mrb_state *mrb, void *p)
{
mrb_value v;
@@ -187,17 +288,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;
@@ -205,7 +313,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;
@@ -215,8 +323,7 @@ mrb_obj_value(void *p)
return v;
}
-
-/*
+/**
* Get a nil mrb_value object.
*
* @return
@@ -229,7 +336,7 @@ MRB_INLINE mrb_value mrb_nil_value(void)
return v;
}
-/*
+/**
* Returns false in Ruby.
*/
MRB_INLINE mrb_value mrb_false_value(void)
@@ -239,7 +346,7 @@ MRB_INLINE mrb_value mrb_false_value(void)
return v;
}
-/*
+/**
* Returns true in Ruby.
*/
MRB_INLINE mrb_value mrb_true_value(void)
@@ -249,7 +356,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;
@@ -257,7 +364,7 @@ mrb_bool_value(mrb_bool boolean)
return v;
}
-static inline mrb_value
+MRB_INLINE mrb_value
mrb_undef_value(void)
{
mrb_value v;
@@ -265,25 +372,25 @@ mrb_undef_value(void)
return v;
}
-#ifdef MRB_USE_ETEXT_EDATA
-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
#else
# define mrb_ro_data_p(p) FALSE
#endif
diff --git a/include/mruby/variable.h b/include/mruby/variable.h
index 2f2bbbf98..01a44fff9 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
*/
@@ -31,23 +31,21 @@ struct global_entry {
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_iv_get(mrb_state*, mrb_sym);
-void mrb_vm_iv_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);
MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
-MRB_API mrb_bool mrb_iv_p(mrb_state *mrb, mrb_sym sym);
-MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym sym);
+MRB_API mrb_bool mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym sym);
+MRB_API void mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym sym);
MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
-MRB_API void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
@@ -100,18 +98,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);
@@ -120,13 +115,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_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer);
+mrb_bool mrb_ident_p(const char *s, mrb_int len);
/* GC functions */
void mrb_gc_mark_gv(mrb_state*);
@@ -135,6 +131,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 20c39ec79..3385fce4e 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,12 +37,12 @@ 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 2
+#define MRUBY_RELEASE_MINOR 0
/*
* Tiny release version number.
@@ -50,6 +50,24 @@ MRB_BEGIN_DECL
#define MRUBY_RELEASE_TEENY 0
/*
+ * Patch level.
+ */
+#define MRUBY_PATCHLEVEL -1
+
+/*
+ * Patch level string. (optional)
+ */
+#define MRUBY_PATCHLEVEL_STR "preview"
+
+#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.
*/
#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY)
@@ -62,22 +80,36 @@ MRB_BEGIN_DECL
/*
* Release year.
*/
-#define MRUBY_RELEASE_YEAR 2015
+#define MRUBY_RELEASE_YEAR 2020
/*
* Release month.
*/
-#define MRUBY_RELEASE_MONTH 11
+#define MRUBY_RELEASE_MONTH 10
/*
* Release day.
*/
-#define MRUBY_RELEASE_DAY 17
+#define MRUBY_RELEASE_DAY 16
/*
* 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.