summaryrefslogtreecommitdiff
path: root/include/mruby.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/mruby.h')
-rw-r--r--include/mruby.h159
1 files changed, 114 insertions, 45 deletions
diff --git a/include/mruby.h b/include/mruby.h
index fe29b1e..1c6e838 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -155,18 +155,8 @@ typedef uint8_t mrb_code;
typedef uint32_t mrb_aspec;
typedef struct mrb_irep mrb_irep;
-struct mrb_state;
-/**
- * Function pointer type of custom allocator used in @see mrb_open_allocf.
- *
- * The function pointing it must behave similarly as realloc except:
- * - If ptr is NULL it must allocate new space.
- * - If size is zero, ptr must be freed.
- *
- * See @see mrb_default_allocf for the default implementation.
- */
-typedef void* (*mrb_allocf) (struct mrb_state *mrb, void *ptr, size_t size, void *ud);
+struct mrb_state;
#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE
#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5
@@ -176,7 +166,8 @@ typedef struct {
uint8_t n:4; /* (15=*) c=n|nk<<4 */
uint8_t nk:4; /* (15=*) */
uint8_t cci; /* called from C function */
- uint8_t vis; /* visibility in the current scope */
+ uint8_t vis; /* 5(ZERO):1(separate module):2(method visibility) */
+ /* under 3-bit flags are copied to env, and after that, env takes precedence */
mrb_sym mid;
const struct RProc *proc;
struct RProc *blk;
@@ -198,6 +189,10 @@ enum mrb_fiber_state {
MRB_FIBER_TERMINATED,
};
+/* Task context status aliases */
+#define MRB_TASK_CREATED MRB_FIBER_CREATED
+#define MRB_TASK_STOPPED MRB_FIBER_TERMINATED
+
struct mrb_context {
struct mrb_context *prev;
@@ -232,7 +227,7 @@ mrb_static_assert_powerof2(MRB_METHOD_CACHE_SIZE);
typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value self);
typedef struct {
- uint32_t flags; /* compatible with mt keys in class.c */
+ uint32_t flags; /* method flags (no symbol packed) */
union {
const struct RProc *proc;
@@ -243,7 +238,7 @@ typedef struct {
#ifndef MRB_NO_METHOD_CACHE
struct mrb_cache_entry {
struct RClass *c, *c0;
- /* mrb_sym mid; // mid is stored in mrb_method_t::flags */
+ mrb_sym mid;
mrb_method_t m;
};
#endif
@@ -252,12 +247,22 @@ struct mrb_jmpbuf;
typedef void (*mrb_atexit_func)(struct mrb_state*);
+#ifdef MRB_USE_TASK_SCHEDULER
+struct mrb_task;
+
+typedef struct mrb_task_state {
+ struct mrb_task *queues[4]; /* Task queues (dormant, ready, waiting, suspended) */
+ volatile uint32_t tick; /* Current tick count */
+ volatile uint32_t wakeup_tick; /* Next wakeup tick */
+ volatile mrb_bool switching; /* Context switch pending flag */
+ struct mrb_task *main_task; /* Main task wrapper for root context */
+ uint8_t scheduler_lock; /* Lock counter for synchronous execution */
+} mrb_task_state;
+#endif
+
typedef struct mrb_state {
struct mrb_jmpbuf *jmp;
- 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 */
@@ -286,16 +291,17 @@ typedef struct mrb_state {
mrb_gc gc;
+ mrb_bool bootstrapping;
+
#ifndef MRB_NO_METHOD_CACHE
struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE];
#endif
mrb_sym symidx;
const char **symtbl;
- uint8_t *symlink;
- uint8_t *symflags;
- mrb_sym symhash[256];
size_t symcapa;
+ struct mrb_sym_hash_table *symhash;
+ void *sym_pool;
#ifndef MRB_USE_ALL_SYMBOLS
char symbuf[8]; /* buffer for small symbol names */
#endif
@@ -317,6 +323,10 @@ typedef struct mrb_state {
struct RObject *arena_err; /* pre-allocated arena overflow error */
#endif
+ struct mrb_mt_rom_list *rom_mt; /* heap-allocated ROM wrappers (freed at close) */
+
+ struct mrb_iv_shape *root_shape; /* root of IV shape tree */
+
void *ud; /* auxiliary data */
#ifdef MRB_FIXED_STATE_ATEXIT_STACK
@@ -325,6 +335,10 @@ typedef struct mrb_state {
mrb_atexit_func *atexit_stack;
#endif
uint16_t atexit_stack_len;
+
+#ifdef MRB_USE_TASK_SCHEDULER
+ mrb_task_state task; /* Task scheduler state */
+#endif
} mrb_state;
/**
@@ -402,7 +416,7 @@ MRB_API void mrb_include_module(mrb_state *mrb, struct RClass *cla, struct RClas
MRB_API void mrb_prepend_module(mrb_state *mrb, struct RClass *cla, struct RClass *prepended);
/**
- * Defines a global function in ruby.
+ * Defines a global function in Ruby.
*
* If you're creating a gem it may look something like this
*
@@ -913,6 +927,11 @@ MRB_API struct RClass* mrb_define_module_under_id(mrb_state *mrb, struct RClass
#define MRB_ARGS_BLOCK() ((mrb_aspec)1)
/**
+ * Function does not accept a block (&nil)
+ */
+#define MRB_ARGS_NOBLOCK() ((mrb_aspec)(1 << 23))
+
+/**
* Function accepts any number of arguments
*/
#define MRB_ARGS_ANY() MRB_ARGS_REST()
@@ -946,7 +965,7 @@ MRB_API struct RClass* mrb_define_module_under_id(mrb_state *mrb, struct RClass
* | `I` | inline struct | void *, struct RClass | `I!` gives `NULL` for `nil` |
* | `&` | 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 | | 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 |
*
@@ -996,7 +1015,7 @@ typedef const char *mrb_args_format;
* mrb_value str, kw_rest;
* uint32_t kw_num = 3;
* uint32_t kw_required = 1;
- * // Note that `#include <mruby/presym.h>` is required beforehand because `MRB_SYM()` is used.
+ * // `MRB_SYM()` is available via `mruby.h` (which includes `mruby/presym.h`).
* // If the usage of `MRB_SYM()` is not desired, replace it with `mrb_intern_lit()`.
* mrb_sym kw_names[] = { MRB_SYM(x), MRB_SYM(y), MRB_SYM(z) };
* mrb_value kw_values[kw_num];
@@ -1079,7 +1098,7 @@ MRB_API mrb_bool mrb_block_given_p(mrb_state *mrb);
#define mrb_strlen_lit(lit) (sizeof(lit "") - 1)
/**
- * Call existing ruby functions.
+ * Call existing Ruby functions.
*
* Example:
*
@@ -1112,7 +1131,7 @@ MRB_API mrb_bool mrb_block_given_p(mrb_state *mrb);
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.
+ * Call existing Ruby functions. This is basically the type safe version of mrb_funcall.
*
* #include <stdio.h>
* #include <mruby.h>
@@ -1127,7 +1146,7 @@ MRB_API mrb_value mrb_funcall_id(mrb_state *mrb, mrb_value val, mrb_sym mid, mrb
*
* FILE *fp = fopen("test.rb","r");
* mrb_value obj = mrb_load_file(mrb,fp);
- * mrb_funcall_argv(mrb, obj, MRB_SYM(method_name), 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);
* }
@@ -1141,7 +1160,7 @@ MRB_API mrb_value mrb_funcall_id(mrb_state *mrb, mrb_value val, mrb_sym mid, mrb
*/
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.
+ * Call existing Ruby functions with a block.
*/
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);
/**
@@ -1240,46 +1259,70 @@ MRB_API char* mrb_locale_from_utf8(const char *p, int len);
MRB_API mrb_state* mrb_open(void);
/**
- * Create new mrb_state with custom allocators.
+ * Create new mrb_state with just the mruby core
*
* @param f
* Reference to the allocation function.
+ * Use mrb_basic_alloc_func for the default
* @param ud
* User data will be passed to custom allocator f.
* If user data isn't required just pass NULL.
* @return
* Pointer to the newly created mrb_state.
*/
-MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud);
+MRB_API mrb_state* mrb_open_core(void);
/**
- * Create new mrb_state with just the mruby core
+ * Closes and frees a mrb_state.
*
- * @param f
- * Reference to the allocation function.
- * Use mrb_default_allocf for the default
- * @param ud
- * User data will be passed to custom allocator f.
- * If user data isn't required just pass NULL.
+ * @param mrb
+ * Pointer to the mrb_state to be closed.
+ */
+MRB_API void mrb_close(mrb_state *mrb);
+#ifndef MRB_NO_METHOD_CACHE
+MRB_API void mrb_method_cache_clear(mrb_state *mrb);
+#else
+#define mrb_method_cache_clear(mrb) ((void)0)
+#endif
+
+/**
+ * Check if mrb_open() failed
+ *
+ * @param mrb
+ * Pointer returned from mrb_open() or mrb_open_core().
* @return
- * Pointer to the newly created mrb_state.
+ * Non-zero if initialization failed, 0 if succeeded.
+ * @note
+ * mrb_open() may return non-NULL even on failure (with mrb->exc set).
+ * Use this macro to check for failure:
+ * @code
+ * mrb_state *mrb = mrb_open();
+ * if (MRB_OPEN_FAILURE(mrb)) {
+ * if (mrb) {
+ * // Inspect mrb->exc for error details
+ * mrb_close(mrb);
+ * }
+ * return EXIT_FAILURE;
+ * }
+ * @endcode
*/
-MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud);
+#define MRB_OPEN_FAILURE(mrb) (!(mrb) || (mrb)->exc)
/**
- * Closes and frees a mrb_state.
+ * Check if mrb_open() succeeded
*
* @param mrb
- * Pointer to the mrb_state to be closed.
+ * Pointer returned from mrb_open() or mrb_open_core().
+ * @return
+ * Non-zero if initialization succeeded, 0 if failed.
*/
-MRB_API void mrb_close(mrb_state *mrb);
+#define MRB_OPEN_SUCCESS(mrb) (!MRB_OPEN_FAILURE(mrb))
/**
- * The default allocation function.
+ * The memory allocation function. You can redefine this function for your own allocator.
*
- * @see mrb_allocf
*/
-MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
+MRB_API void* mrb_basic_alloc_func(void*, size_t);
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
@@ -1330,6 +1373,25 @@ 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);
+/* recursion detection */
+MRB_API mrb_bool mrb_recursive_method_p(mrb_state *mrb, mrb_sym mid, mrb_value obj1, mrb_value obj2);
+MRB_API mrb_bool mrb_recursive_func_p(mrb_state *mrb, mrb_sym mid, mrb_value obj1, mrb_value obj2);
+
+#define MRB_RECURSIVE_P(mrb, mid, obj1, obj2) \
+ mrb_recursive_method_p(mrb, mid, obj1, obj2)
+
+#define MRB_RECURSIVE_UNARY_P(mrb, mid, obj) \
+ mrb_recursive_method_p(mrb, mid, obj, mrb_nil_value())
+
+#define MRB_RECURSIVE_BINARY_P(mrb, mid, obj1, obj2) \
+ mrb_recursive_method_p(mrb, mid, obj1, obj2)
+
+#define MRB_RECURSIVE_FUNC_P(mrb, mid, obj) \
+ mrb_recursive_func_p(mrb, mid, obj, mrb_nil_value())
+
+#define MRB_RECURSIVE_BINARY_FUNC_P(mrb, mid, obj1, obj2) \
+ mrb_recursive_func_p(mrb, mid, obj1, obj2)
+
#define mrb_gc_arena_save(mrb) ((mrb)->gc.arena_idx)
#define mrb_gc_arena_restore(mrb, idx) ((mrb)->gc.arena_idx = (idx))
@@ -1520,7 +1582,8 @@ MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib);
MRB_API void mrb_stack_extend(mrb_state*, mrb_int);
/* temporary memory allocation, only effective while GC arena is kept */
-MRB_API void* mrb_alloca(mrb_state *mrb, size_t);
+MRB_API void* mrb_temp_alloc(mrb_state *mrb, size_t);
+#define mrb_alloca(mrb, size) mrb_temp_alloc(mrb, size) /* for compatibility */
MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func);
@@ -1531,6 +1594,8 @@ MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
#ifdef MRB_PRESYM_SCANNING
# include <mruby/presym/scanning.h>
+#else
+# include <mruby/presym.h>
#endif
#if 0
@@ -1562,6 +1627,10 @@ mrbmemset(void *s, int c, size_t n)
#define mrb_int_hash_func(mrb,key) (uint32_t)((key)^((key)<<2)^((key)>>2))
+#define MRB_UNIQNAME(name) MRB_UNIQNAME_1(name, __LINE__)
+#define MRB_UNIQNAME_1(name, line) MRB_UNIQNAME_2(name, line)
+#define MRB_UNIQNAME_2(name, line) name##line
+
MRB_END_DECL
#endif /* MRUBY_H */