diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/mrbconf.h | 32 | ||||
| -rw-r--r-- | include/mruby.h | 1076 | ||||
| -rw-r--r-- | include/mruby/array.h | 119 | ||||
| -rw-r--r-- | include/mruby/boxing_nan.h | 93 | ||||
| -rw-r--r-- | include/mruby/boxing_no.h | 48 | ||||
| -rw-r--r-- | include/mruby/boxing_word.h | 116 | ||||
| -rw-r--r-- | include/mruby/class.h | 54 | ||||
| -rw-r--r-- | include/mruby/common.h | 67 | ||||
| -rw-r--r-- | include/mruby/compile.h | 71 | ||||
| -rw-r--r-- | include/mruby/data.h | 37 | ||||
| -rw-r--r-- | include/mruby/debug.h | 23 | ||||
| -rw-r--r-- | include/mruby/dump.h | 88 | ||||
| -rw-r--r-- | include/mruby/error.h | 70 | ||||
| -rw-r--r-- | include/mruby/gc.h | 71 | ||||
| -rw-r--r-- | include/mruby/hash.h | 59 | ||||
| -rw-r--r-- | include/mruby/irep.h | 20 | ||||
| -rw-r--r-- | include/mruby/khash.h | 34 | ||||
| -rw-r--r-- | include/mruby/numeric.h | 69 | ||||
| -rw-r--r-- | include/mruby/object.h | 39 | ||||
| -rw-r--r-- | include/mruby/opcode.h | 10 | ||||
| -rw-r--r-- | include/mruby/proc.h | 33 | ||||
| -rw-r--r-- | include/mruby/range.h | 28 | ||||
| -rw-r--r-- | include/mruby/string.h | 192 | ||||
| -rw-r--r-- | include/mruby/throw.h | 41 | ||||
| -rw-r--r-- | include/mruby/value.h | 527 | ||||
| -rw-r--r-- | include/mruby/variable.h | 61 | ||||
| -rw-r--r-- | include/mruby/version.h | 98 |
27 files changed, 2225 insertions, 951 deletions
diff --git a/include/mrbconf.h b/include/mrbconf.h index ac33ff0bf..ab5dd1a03 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -26,6 +26,9 @@ /* represent mrb_value as a word (natural unit of data for the processor) */ //#define MRB_WORD_BOXING +/* string class to handle UTF-8 encoding */ +//#define MRB_UTF8_STRING + /* argv max size in mrb_funcall */ //#define MRB_FUNCALL_ARGC_MAX 16 @@ -38,6 +41,13 @@ /* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */ //#define MRB_IVHASH_INIT_SIZE 8 +/* 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 + /* turn off generational GC by default */ //#define MRB_GC_TURN_OFF_GENERATIONAL @@ -65,23 +75,25 @@ /* fixed size state atexit stack */ //#define MRB_FIXED_STATE_ATEXIT_STACK -/* -DDISABLE_XXXX to drop following features */ -//#define DISABLE_STDIO /* use of stdio */ +/* -DMRB_DISABLE_XXXX to drop following features */ +//#define MRB_DISABLE_STDIO /* use of stdio */ -/* -DENABLE_XXXX to enable following features */ -//#define ENABLE_DEBUG /* hooks for debugger */ +/* -DMRB_ENABLE_XXXX to enable following features */ +//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */ /* end of configuration */ -/* define ENABLE_XXXX from DISABLE_XXX */ -#ifndef DISABLE_STDIO -#define ENABLE_STDIO +/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */ +#ifdef DISABLE_STDIO +#define MRB_DISABLE_STDIO #endif -#ifndef ENABLE_DEBUG -#define DISABLE_DEBUG + +/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */ +#ifdef ENABLE_DEBUG +#define MRB_ENABLE_DEBUG_HOOK #endif -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO # include <stdio.h> #endif diff --git a/include/mruby.h b/include/mruby.h index 7b9f1b428..1ea0156e8 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1,7 +1,7 @@ /* ** mruby - An embeddable Ruby implementation ** -** Copyright (c) mruby developers 2010-2014 +** Copyright (c) mruby developers 2010-2015 ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the @@ -28,30 +28,43 @@ #ifndef MRUBY_H #define MRUBY_H -#if defined(__cplusplus) -extern "C" { -#endif - #include <stdint.h> #include <stddef.h> #include <limits.h> #include "mrbconf.h" -#include "mruby/value.h" -#include "mruby/version.h" +#include "mruby/common.h" +#include <mruby/value.h> +#include <mruby/gc.h> +#include <mruby/version.h> + +/** + * MRuby C API entry point + */ +MRB_BEGIN_DECL typedef uint32_t mrb_code; + +/** + * Required arguments signature type. + */ typedef uint32_t mrb_aspec; + struct 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 s is NULL, ptr must be freed. + * + * See @see mrb_default_allocf for the default implementation. + */ typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud); -#ifndef MRB_GC_ARENA_SIZE -#define MRB_GC_ARENA_SIZE 100 -#endif - #ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE #define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5 #endif @@ -98,12 +111,6 @@ struct mrb_context { struct RFiber *fib; }; -enum gc_state { - GC_STATE_NONE = 0, - GC_STATE_MARK, - GC_STATE_SWEEP -}; - struct mrb_jmpbuf; typedef void (*mrb_atexit_func)(struct mrb_state*); @@ -112,6 +119,7 @@ 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; @@ -136,37 +144,15 @@ typedef struct mrb_state { struct RClass *symbol_class; struct RClass *kernel_module; - struct heap_page *heaps; /* heaps for GC */ - struct heap_page *sweeps; - struct heap_page *free_heaps; - size_t live; /* count of live objects */ -#ifdef MRB_GC_FIXED_ARENA - struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */ -#else - struct RBasic **arena; /* GC protection array */ - int arena_capa; -#endif - int arena_idx; - - enum gc_state gc_state; /* state of gc */ - int current_white_part; /* make white object by white_part */ - struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */ - struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */ - size_t gc_live_after_mark; - size_t gc_threshold; - int gc_interval_ratio; - int gc_step_ratio; - mrb_bool gc_disabled:1; - mrb_bool gc_full:1; - mrb_bool is_generational_gc_mode:1; - mrb_bool out_of_memory:1; - size_t majorgc_old_threshold; struct alloca_header *mems; + mrb_gc gc; mrb_sym symidx; - struct kh_n2s *name2sym; /* symbol table */ + struct kh_n2s *name2sym; /* symbol hash */ + struct symbol_name *symtbl; /* symbol table */ + size_t symcapa; -#ifdef ENABLE_DEBUG +#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); #endif @@ -185,78 +171,577 @@ typedef struct mrb_state { mrb_int atexit_stack_len; } mrb_state; -#if __STDC_VERSION__ >= 201112L -# define mrb_noreturn _Noreturn -#elif defined __GNUC__ && !defined __STRICT_ANSI__ -# define mrb_noreturn __attribute__((noreturn)) -#elif defined _MSC_VER -# define mrb_noreturn __declspec(noreturn) -#else -# define mrb_noreturn -#endif typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value); -struct RClass *mrb_define_class(mrb_state *, const char*, struct RClass*); -struct RClass *mrb_define_module(mrb_state *, const char*); -mrb_value mrb_singleton_class(mrb_state*, mrb_value); -void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); - -void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); -void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec); -void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec); -void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); -void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); -void mrb_undef_method(mrb_state*, struct RClass*, const char*); -void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); -mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv); -#define mrb_class_new_instance(mrb,argc,argv,c) mrb_obj_new(mrb,c,argc,argv) -mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); -struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); -struct RClass * mrb_module_new(mrb_state *mrb); -mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); -struct RClass * mrb_class_get(mrb_state *mrb, const char *name); -struct RClass * mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name); -struct RClass * mrb_module_get(mrb_state *mrb, const char *name); -struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name); - -mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj); -mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method); -mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid); -struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super); -struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name); - -/* required arguments */ + +/** + * Defines a new class. + * + * If you're creating a gem it may look something like this: + * + * !!!c + * void mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class); + * } + * + * void mrb_example_gem_final(mrb_state* mrb) { + * //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. + * @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); + +/** + * Defines a new module. + * + * @param [mrb_state *] mrb_state* The current mruby state. + * @param [const char *] char* 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); + +/** + * Include a module in another class or module. + * Equivalent to: + * + * 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. + */ +MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); + +/** + * Prepends a module in another class or module. + * + * Equivalent to: + * 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. + */ +MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*); + +/** + * Defines a global function in ruby. + * + * If you're creating a gem it may look something like this + * + * Example: + * + * !!!c + * mrb_value example_method(mrb_state* mrb, mrb_value self) + * { + * puts("Executing example command!"); + * return self; + * } + * + * void mrb_example_gem_init(mrb_state* mrb) + * { + * 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. + */ +MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t func, mrb_aspec aspec); + +/** + * Defines a class method. + * + * Example: + * + * # Ruby style + * class Foo + * def Foo.bar + * end + * end + * // C style + * mrb_value bar_method(mrb_state* mrb, mrb_value self){ + * return mrb_nil_value(); + * } + * void mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *foo; + * 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. + */ +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); + +/** + * Defines a module fuction. + * + * Example: + * + * # Ruby style + * module Foo + * def Foo.bar + * end + * end + * // C style + * mrb_value bar_method(mrb_state* mrb, mrb_value self){ + * return mrb_nil_value(); + * } + * void mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *foo; + * 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. + */ +MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); + +/** + * Defines a constant. + * + * Example: + * + * # Ruby style + * class ExampleClass + * AGE = 22 + * end + * // C style + * #include <stdio.h> + * #include <mruby.h> + * + * void + * mrb_example_gem_init(mrb_state* mrb){ + * mrb_define_const(mrb, mrb->kernel_module, "AGE", mrb_fixnum_value(22)); + * } + * + * 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. + */ +MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); + +/** + * Undefines a method. + * + * Example: + * + * # Ruby style + * + * class ExampleClassA + * def example_method + * "example" + * end + * end + * ExampleClassA.new.example_method # => example + * + * class ExampleClassB < ExampleClassA + * undef_method :example_method + * end + * + * ExampleClassB.new.example_method # => undefined method 'example_method' for ExampleClassB (NoMethodError) + * + * // C style + * #include <stdio.h> + * #include <mruby.h> + * + * mrb_value + * mrb_example_method(mrb_state *mrb){ + * return mrb_str_new_cstr(mrb, "example"); + * } + * + * void + * mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *example_class_a; + * struct RClass *example_class_b; + * struct RClass *example_class_c; + * + * example_class_a = mrb_define_class(mrb, "ExampleClassA", mrb->object_class); + * mrb_define_method(mrb, example_class_a, "example_method", mrb_example_method, MRB_ARGS_NONE()); + * example_class_b = mrb_define_class(mrb, "ExampleClassB", example_class_a); + * example_class_c = mrb_define_class(mrb, "ExampleClassC", example_class_b); + * mrb_undef_method(mrb, example_class_c, "example_method"); + * } + * + * 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. + */ +MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*); + +/** + * Undefine a class method. + * Example: + * + * # Ruby style + * class ExampleClass + * def self.example_method + * "example" + * end + * end + * + * ExampleClass.example_method + * + * // C style + * #include <stdio.h> + * #include <mruby.h> + * + * mrb_value + * mrb_example_method(mrb_state *mrb){ + * return mrb_str_new_cstr(mrb, "example"); + * } + * + * void + * mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *example_class; + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); + * mrb_define_class_method(mrb, example_class, "example_method", mrb_example_method, MRB_ARGS_NONE()); + * mrb_undef_class_method(mrb, example_class, "example_method"); + * } + * + * 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. + */ +MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); + +/** + * Initialize a new object instace of c class. + * + * Example: + * + * # Ruby style + * class ExampleClass + * end + * + * p ExampleClass # => #<ExampleClass:0x9958588> + * // C style + * #include <stdio.h> + * #include <mruby.h> + * + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * mrb_value obj; + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); # => class ExampleClass; end + * 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 + * @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); + +/** @see mrb_obj_new */ +MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const mrb_value *argv, struct RClass *c) +{ + 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. + * + * Example: + * + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * + * mrb_value obj; + * example_class = mrb_class_new(mrb, mrb->object_class); + * obj = mrb_obj_new(mrb, example_class, 0, NULL); // => #<#<Class:0x9a945b8>:0x9a94588> + * mrb_p(mrb, obj); // => Kernel#p + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @param [struct RClass *] 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); + +/** + * Creates a new module, Module. + * + * Example: + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_module; + * + * example_module = mrb_module_new(mrb); + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @return [struct RClass *] Reference to the new module. + */ +MRB_API struct RClass * mrb_module_new(mrb_state *mrb); + +/** + * Returns an mrb_bool. True if class was defined, and false if the class was not defined. + * + * Example: + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * mrb_bool cd; + * + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); + * cd = mrb_class_defined(mrb, "ExampleClass"); + * + * // If mrb_class_defined returns 1 then puts "True" + * // If mrb_class_defined returns 0 then puts "False" + * if (cd == 1){ + * puts("True"); + * } + * else { + * puts("False"); + * } + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] 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); + +/** + * Gets a class. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] 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); + +/** + * 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. + * @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); + +/** + * Gets a module. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] 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); + +/** + * 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. + * @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 mrb_value mrb_notimplement_m(mrb_state*, mrb_value); + +/** + * Duplicate an object. + * + * Equivalent to: + * Object#dup + * @param [mrb_state*] mrb The current mruby state. + * @param [mrb_value] 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 + * class it returns true, it returns false otherwise. + * + * Example: + * # Ruby style + * class ExampleClass + * def example_method + * end + * end + * + * ExampleClass.new.respond_to?(:example_method) # => true + * + * // C style + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * mrb_sym mid; + * mrb_bool obj_resp; + * + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); + * mrb_define_method(mrb, example_class, "example_method", exampleMethod, MRB_ARGS_NONE()); + * mid = mrb_intern_str(mrb, mrb_str_new_cstr(mrb, "example_method" )); + * obj_resp = mrb_obj_respond_to(mrb, example_class, mid); // => 1(true in Ruby world) + * + * // If mrb_obj_respond_to returns 1 then puts "True" + * // If mrb_obj_respond_to returns 0 then puts "False" + * if (obj_resp == 1) { + * puts("True"); + * } + * else if (obj_resp == 0) { + * puts("False"); + * } + * } + * + * @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. + * @return [mrb_bool] A boolean value. + */ +MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid); + +/** + * 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 + * @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_module_under(mrb_state *mrb, struct RClass *outer, const char *name); + +/** + * Function requires n arguments. + * + * @param n + * The number of required arguments. + */ #define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18) -/* optional arguments */ + +/** + * Funtion takes n optional arguments + * + * @param n + * The number of optional arguments. + */ #define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13) -/* mandatory and optinal arguments */ + +/** + * Funtion takes n1 mandatory arguments and n2 optional arguments + * + * @param n1 + * The number of required arguments. + * @param n2 + * The number of optional arguments. + */ #define MRB_ARGS_ARG(n1,n2) (MRB_ARGS_REQ(n1)|MRB_ARGS_OPT(n2)) -/* rest argument */ +/** rest argument */ #define MRB_ARGS_REST() ((mrb_aspec)(1 << 12)) -/* required arguments after rest */ + +/** required arguments after rest */ #define MRB_ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 7) -/* keyword arguments (n of keys, kdict) */ + +/** keyword arguments (n of keys, kdict) */ #define MRB_ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 2) | ((n2)?(1<<1):0))) -/* block argument */ + +/** + * Function takes a block argument + */ #define MRB_ARGS_BLOCK() ((mrb_aspec)1) -/* accept any number of arguments */ +/** + * Function accepts any number of arguments + */ #define MRB_ARGS_ANY() MRB_ARGS_REST() -/* accept no arguments */ -#define MRB_ARGS_NONE() ((mrb_aspec)0) -/* compatibility macros; will be removed */ -#define ARGS_REQ(n) MRB_ARGS_REQ(n) -#define ARGS_OPT(n) MRB_ARGS_OPT(n) -#define ARGS_REST() MRB_ARGS_REST() -#define ARGS_POST(n) MRB_ARGS_POST() -#define ARGS_KEY(n1,n2) MRB_ARGS_KEY(n1,n2) -#define ARGS_BLOCK() MRB_ARGS_BLOCK() -#define ARGS_ANY() MRB_ARGS_ANY() -#define ARGS_NONE() MRB_ARGS_NONE() +/** + * Function accepts no arguments + */ +#define MRB_ARGS_NONE() ((mrb_aspec)0) -mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...); +/** + * Format specifiers for {mrb_get_args} function + * + * Must be a C string composed of the following format specifiers: + * + * | 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} | | + * | `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. | + * | | | 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. | + * + * @see mrb_get_args + */ +typedef const char *mrb_args_format; + +/** + * Retrieve arguments from mrb_state. + * + * 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. + * + * @param mrb The current MRuby state. + * @param format [mrb_args_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 + */ +MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...); + +static 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; +} /* `strlen` for character string literals (use with caution or `strlen` instead) Adjacent string literals are concatenated in C/C++ in translation phase 6. @@ -266,105 +751,240 @@ mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...); */ #define mrb_strlen_lit(lit) (sizeof(lit "") - 1) -mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); -mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*); -mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value); -mrb_sym mrb_intern_cstr(mrb_state*,const char*); -mrb_sym mrb_intern(mrb_state*,const char*,size_t); -mrb_sym mrb_intern_static(mrb_state*,const char*,size_t); +/** + * Call existing ruby functions. + * + * #include <stdio.h> + * #include <mruby.h> + * #include "mruby/compile.h" + * + * int + * main() + * { + * mrb_int i = 99; + * mrb_state *mrb = mrb_open(); + * + * if (!mrb) { } + * FILE *fp = fopen("test.rb","r"); + * mrb_value obj = mrb_load_file(mrb,fp); + * mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i)); + * 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. + */ +MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); +/** + * Call existing ruby functions. This is basically the type safe version of mrb_funcall. + * + * #include <stdio.h> + * #include <mruby.h> + * #include "mruby/compile.h" + * int + * main() + * { + * mrb_int i = 99; + * mrb_state *mrb = mrb_open(); + * + * if (!mrb) { } + * mrb_sym m_sym = mrb_intern_cstr(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. + * 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. + * @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*); +/** + * 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); +/** + * Create a symbol + * + * # Ruby style: + * :pizza # => :pizza + * + * // C style: + * mrb_sym m_sym = mrb_intern_cstr(mrb, "pizza"); // => :pizza + * @param [mrb_state*] mrb_state* The current mruby state. + * @param [const char*] const char* The name of the method. + * @return [mrb_sym] mrb_sym A symbol. + */ +MRB_API mrb_sym mrb_intern_cstr(mrb_state*,const char*); +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)) -mrb_sym mrb_intern_str(mrb_state*,mrb_value); -mrb_value mrb_check_intern_cstr(mrb_state*,const char*); -mrb_value mrb_check_intern(mrb_state*,const char*,size_t); -mrb_value mrb_check_intern_str(mrb_state*,mrb_value); -const char *mrb_sym2name(mrb_state*,mrb_sym); -const char *mrb_sym2name_len(mrb_state*,mrb_sym,mrb_int*); -mrb_value mrb_sym2str(mrb_state*,mrb_sym); - -void *mrb_malloc(mrb_state*, size_t); /* raise RuntimeError if no mem */ -void *mrb_calloc(mrb_state*, size_t, size_t); /* ditto */ -void *mrb_realloc(mrb_state*, void*, size_t); /* ditto */ -void *mrb_realloc_simple(mrb_state*, void*, size_t); /* return NULL if no memory available */ -void *mrb_malloc_simple(mrb_state*, size_t); /* return NULL if no memory available */ -struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*); -void mrb_free(mrb_state*, void*); - -mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); -mrb_value mrb_str_new_cstr(mrb_state*, const char*); -mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len); +MRB_API mrb_sym mrb_intern_str(mrb_state*,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 void *mrb_malloc(mrb_state*, size_t); /* raise RuntimeError if no mem */ +MRB_API void *mrb_calloc(mrb_state*, size_t, size_t); /* ditto */ +MRB_API void *mrb_realloc(mrb_state*, void*, size_t); /* ditto */ +MRB_API void *mrb_realloc_simple(mrb_state*, void*, size_t); /* return NULL if no memory available */ +MRB_API void *mrb_malloc_simple(mrb_state*, size_t); /* return NULL if no memory available */ +MRB_API struct RBasic *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*); +MRB_API void mrb_free(mrb_state*, void*); + +MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); + +/** + * Turns a C string into a Ruby string value. + */ +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_state* mrb_open(void); -mrb_state* mrb_open_allocf(mrb_allocf, void *ud); -void mrb_close(mrb_state*); - -mrb_value mrb_top_self(mrb_state *); -mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value); -mrb_value mrb_toplevel_run(mrb_state*, struct RProc*); -mrb_value mrb_context_run(mrb_state*, struct RProc*, mrb_value, unsigned int); - -void mrb_p(mrb_state*, mrb_value); -mrb_int mrb_obj_id(mrb_value obj); -mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name); - -mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value); -mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value); -mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2); -mrb_value mrb_Integer(mrb_state *mrb, mrb_value val); -mrb_value mrb_Float(mrb_state *mrb, mrb_value val); -mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj); -mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2); - -void mrb_garbage_collect(mrb_state*); -void mrb_full_gc(mrb_state*); -void mrb_incremental_gc(mrb_state *); -int mrb_gc_arena_save(mrb_state*); -void mrb_gc_arena_restore(mrb_state*,int); -void mrb_gc_mark(mrb_state*,struct RBasic*); +#ifdef _WIN32 +char* mrb_utf8_from_locale(const char *p, size_t len); +char* mrb_locale_from_utf8(const char *p, size_t 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_locale_free(p) +#define mrb_utf8_free(p) +#endif + +/** + * Creates new mrb_state. + * + * @return + * Pointer to the newly created mrb_state. + */ +MRB_API mrb_state* mrb_open(void); + +/** + * Create new mrb_state with custom allocators. + * + * @param f + * Reference to the allocation function. + * @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); + +/** + * Create new mrb_state with just the MRuby core + * + * @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. + * @return + * Pointer to the newly created mrb_state. + */ +MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud); + +/** + * Closes and frees a mrb_state. + * + * @param mrb + * Pointer to the mrb_state to be closed. + */ +MRB_API void mrb_close(mrb_state *mrb); + +/** + * The default allocation function. + * + * @see mrb_allocf + */ +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_toplevel_run(mrb_state*, struct RProc*); +MRB_API mrb_value mrb_context_run(mrb_state*, struct RProc*, mrb_value, unsigned int); + +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_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_Integer(mrb_state *mrb, mrb_value val); +MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val); +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_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_TT_HAS_BASIC_P(mrb_type(val))) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \ + if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \ } while (0) -void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*); +MRB_API void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*); #define mrb_field_write_barrier_value(mrb, obj, val) do{\ - if (MRB_TT_HAS_BASIC_P(mrb_type(val))) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val)); \ + if (!mrb_immediate_p(val)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val)); \ } while (0) -void mrb_write_barrier(mrb_state *, struct RBasic*); - -mrb_value mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method); -mrb_value mrb_any_to_s(mrb_state *mrb, mrb_value obj); -const char * mrb_obj_classname(mrb_state *mrb, mrb_value obj); -struct RClass* mrb_obj_class(mrb_state *mrb, mrb_value obj); -mrb_value mrb_class_path(mrb_state *mrb, struct RClass *c); -mrb_value mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method); -mrb_bool mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c); -mrb_value mrb_obj_inspect(mrb_state *mrb, mrb_value self); -mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self); - -/* need to include <ctype.h> to use these macros */ +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_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); + #ifndef ISPRINT -#define ISASCII(c) (!(((int)(unsigned char)(c)) & ~0x7f)) -#define ISPRINT(c) (ISASCII(c) && isprint((int)(unsigned char)(c))) -#define ISSPACE(c) (ISASCII(c) && isspace((int)(unsigned char)(c))) -#define ISUPPER(c) (ISASCII(c) && isupper((int)(unsigned char)(c))) -#define ISLOWER(c) (ISASCII(c) && islower((int)(unsigned char)(c))) -#define ISALNUM(c) (ISASCII(c) && isalnum((int)(unsigned char)(c))) -#define ISALPHA(c) (ISASCII(c) && isalpha((int)(unsigned char)(c))) -#define ISDIGIT(c) (ISASCII(c) && isdigit((int)(unsigned char)(c))) -#define ISXDIGIT(c) (ISASCII(c) && isxdigit((int)(unsigned char)(c))) -#define TOUPPER(c) (ISASCII(c) ? toupper((int)(unsigned char)(c)) : (c)) -#define TOLOWER(c) (ISASCII(c) ? tolower((int)(unsigned char)(c)) : (c)) +#define ISASCII(c) ((unsigned)(c) <= 0x7f) +#define ISPRINT(c) (((unsigned)(c) - 0x20) < 0x5f) +#define ISSPACE(c) ((c) == ' ' || (unsigned)(c) - '\t' < 5) +#define ISUPPER(c) (((unsigned)(c) - 'A') < 26) +#define ISLOWER(c) (((unsigned)(c) - 'a') < 26) +#define ISALPHA(c) ((((unsigned)(c) | 0x20) - 'a') < 26) +#define ISDIGIT(c) (((unsigned)(c) - '0') < 10) +#define ISXDIGIT(c) (ISDIGIT(c) || ((unsigned)(c) | 0x20) - 'a' < 6) +#define ISALNUM(c) (ISALPHA(c) || ISDIGIT(c)) +#define ISBLANK(c) ((c) == ' ' || (c) == '\t') +#define ISCNTRL(c) ((unsigned)(c) < 0x20 || (c) == 0x7f) +#define TOUPPER(c) (ISLOWER(c) ? ((c) & 0x5f) : (c)) +#define TOLOWER(c) (ISUPPER(c) ? ((c) | 0x20) : (c)) #endif -mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len); -mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc); +MRB_API mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len); +MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc); -mrb_noreturn void mrb_raise(mrb_state *mrb, struct RClass *c, const char *msg); -mrb_noreturn void mrb_raisef(mrb_state *mrb, struct RClass *c, const char *fmt, ...); -mrb_noreturn void mrb_name_error(mrb_state *mrb, mrb_sym id, const char *fmt, ...); -void mrb_warn(mrb_state *mrb, const char *fmt, ...); -mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...); -void mrb_print_backtrace(mrb_state *mrb); -void mrb_print_error(mrb_state *mrb); +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 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); /* macros to get typical exception objects note: @@ -382,20 +1002,27 @@ void mrb_print_error(mrb_state *mrb); #define E_SYNTAX_ERROR (mrb_class_get(mrb, "SyntaxError")) #define E_LOCALJUMP_ERROR (mrb_class_get(mrb, "LocalJumpError")) #define E_REGEXP_ERROR (mrb_class_get(mrb, "RegexpError")) +#define E_SYSSTACK_ERROR (mrb_class_get(mrb, "SystemStackError")) #define E_NOTIMP_ERROR (mrb_class_get(mrb, "NotImplementedError")) #define E_FLOATDOMAIN_ERROR (mrb_class_get(mrb, "FloatDomainError")) #define E_KEY_ERROR (mrb_class_get(mrb, "KeyError")) -mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg); -mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); -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); +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); + +/* 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. */ +MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj); +/* mrb_gc_unregister() removes the object from GC root. */ +MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj); -void mrb_gc_protect(mrb_state *mrb, mrb_value obj); -mrb_value mrb_to_int(mrb_state *mrb, mrb_value val); +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)) -void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); +MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); typedef enum call_type { CALL_PUBLIC, @@ -404,29 +1031,50 @@ typedef enum call_type { CALL_TYPE_MAX } call_type; -void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2); -const char *mrb_class_name(mrb_state *mrb, struct RClass* klass); -void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val); +MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2); +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); + +MRB_API mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id); + +MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); +MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); + -mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id); +/* + * Resume a Fiber + * + * @mrbgem mruby-fiber + */ +MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv); -mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); -mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); +/* + * Yield a Fiber + * + * @mrbgem mruby-fiber + */ +MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv); -/* fiber functions (you need to link mruby-fiber mrbgem to use) */ -mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv); +/* + * FiberError reference + * + * @mrbgem mruby-fiber + */ #define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError")) /* memory pool implementation */ typedef struct mrb_pool mrb_pool; -struct mrb_pool* mrb_pool_open(mrb_state*); -void mrb_pool_close(struct mrb_pool*); -void* mrb_pool_alloc(struct mrb_pool*, size_t); -void* mrb_pool_realloc(struct mrb_pool*, void*, size_t oldlen, size_t newlen); -mrb_bool mrb_pool_can_realloc(struct mrb_pool*, void*, size_t); -void* mrb_alloca(mrb_state *mrb, size_t); +MRB_API struct mrb_pool* mrb_pool_open(mrb_state*); +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); +MRB_API void* mrb_alloca(mrb_state *mrb, size_t); -void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func); +MRB_API void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func); + +MRB_API void mrb_show_version(mrb_state *mrb); +MRB_API void mrb_show_copyright(mrb_state *mrb); #ifdef MRB_DEBUG #include <assert.h> @@ -443,10 +1091,8 @@ void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func func); #define mrb_static_assert(exp, str) mrb_assert(exp) #endif -mrb_value mrb_format(mrb_state *mrb, const char *format, ...); +MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_H */ diff --git a/include/mruby/array.h b/include/mruby/array.h index 5fbf71174..bd78db066 100644 --- a/include/mruby/array.h +++ b/include/mruby/array.h @@ -7,9 +7,13 @@ #ifndef MRUBY_ARRAY_H #define MRUBY_ARRAY_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/* + * Array class + */ +MRB_BEGIN_DECL + typedef struct mrb_shared_array { int refcnt; @@ -32,28 +36,95 @@ struct RArray { #define RARRAY(v) ((struct RArray*)(mrb_ptr(v))) #define RARRAY_LEN(a) (RARRAY(a)->len) -#define RARRAY_PTR(a) (RARRAY(a)->ptr) +#define RARRAY_PTR(a) ((const mrb_value*)RARRAY(a)->ptr) #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) +#define ARY_UNSET_SHARED_FLAG(a) ((a)->flags &= ~MRB_ARY_SHARED) -void mrb_ary_modify(mrb_state*, struct RArray*); void mrb_ary_decref(mrb_state*, mrb_shared_array*); -mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); -mrb_value mrb_ary_new(mrb_state *mrb); -mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); -mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); -void mrb_ary_concat(mrb_state*, mrb_value, mrb_value); -mrb_value mrb_ary_splat(mrb_state*, mrb_value); -void mrb_ary_push(mrb_state*, mrb_value, mrb_value); -mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); -mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); -void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); -void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b); -mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); -mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item); -mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset); -mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self); -mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self); -mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep); +MRB_API void mrb_ary_modify(mrb_state*, struct RArray*); +MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); + +/* + * Initializes a new array. + * + * Equivalent to: + * + * Array.new + * + * @param mrb The mruby state reference. + * @return The initialized array + */ +MRB_API mrb_value mrb_ary_new(mrb_state *mrb); + +MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); +MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); +MRB_API void mrb_ary_concat(mrb_state*, mrb_value, mrb_value); +MRB_API mrb_value mrb_ary_splat(mrb_state*, mrb_value); + +/* + * Pushes value into array. + * + * Equivalent to: + * + * ary << value + * + * @param mrb The mruby state reference. + * @param ary The array in which the value will be pushed + * @param value The value to be pushed into array + */ +MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value); + +/* + * Pops the last element from the array. + * + * Equivalent to: + * + * ary.pop + * + * @param mrb The mruby state reference. + * @param ary The array from which the value will be poped. + * @return The poped value. + */ +MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); + +/* + * Returns a reference to an element of the array on the given index. + * + * Equivalent to: + * + * ary[n] + * + * @param mrb The mruby state reference. + * @param ary The target array. + * @param n The array index being referenced + * @return The referenced value. + */ +MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); + +/* + * Sets a value on an array at the given index + * + * Equivalent to: + * + * ary[n] = val + * + * @param mrb The mruby state reference. + * @param ary The target array. + * @param n The array index being referenced. + * @param val The value being setted. + */ +MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); + +MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b); +MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); +MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item); +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); +MRB_API mrb_value mrb_ary_clear(mrb_state *mrb, mrb_value self); +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 len); static inline mrb_int mrb_ary_len(mrb_state *mrb, mrb_value ary) @@ -63,8 +134,6 @@ mrb_ary_len(mrb_state *mrb, mrb_value ary) return RARRAY_LEN(ary); } -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_ARRAY_H */ diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h new file mode 100644 index 000000000..b71c4b746 --- /dev/null +++ b/include/mruby/boxing_nan.h @@ -0,0 +1,93 @@ +/* +** mruby/boxing_nan.h - nan boxing mrb_value definition +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_BOXING_NAN_H +#define MRUBY_BOXING_NAN_H + +#ifdef MRB_USE_FLOAT +# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<---- +#endif + +#ifdef MRB_INT64 +# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<---- +#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 + +/* value representation by nan-boxing: + * float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF + * object: 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP + * int : 1111111111110001 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII + * sym : 1111111111110001 0100000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS + * In order to get enough bit size to save TT, all pointers are shifted 2 bits + * 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; + }; +} mrb_value; + +#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) + +#define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)-1) +#define mrb_type(o) ((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 + +#define BOXNAN_SET_VALUE(o, tt, attr, v) do {\ + switch (tt) {\ + case MRB_TT_FALSE:\ + case MRB_TT_TRUE:\ + case MRB_TT_UNDEF:\ + case MRB_TT_FIXNUM:\ + case MRB_TT_SYMBOL: (o).attr = (v); break;\ + default: (o).value.i = 0; (o).value.p = (void*)((uintptr_t)(o).value.p | (((uintptr_t)(v))>>2)); break;\ + }\ + (o).value.ttt = (0xfff00000|(((tt)+1)<<14));\ +} while (0) + +#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)) +#define SET_OBJ_VALUE(r,v) BOXNAN_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) +#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v) +#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) + +#endif /* MRUBY_BOXING_NAN_H */ diff --git a/include/mruby/boxing_no.h b/include/mruby/boxing_no.h new file mode 100644 index 000000000..7ee44a934 --- /dev/null +++ b/include/mruby/boxing_no.h @@ -0,0 +1,48 @@ +/* +** mruby/boxing_no.h - unboxed mrb_value definition +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_BOXING_NO_H +#define MRUBY_BOXING_NO_H + +#define MRB_FIXNUM_SHIFT 0 +#define MRB_TT_HAS_BASIC MRB_TT_OBJECT + +typedef struct mrb_value { + union { + mrb_float f; + void *p; + mrb_int i; + mrb_sym sym; + } 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) +#define mrb_float(o) (o).value.f +#define mrb_fixnum(o) (o).value.i +#define mrb_symbol(o) (o).value.sym +#define mrb_type(o) (o).tt + +#define BOXNIX_SET_VALUE(o, ttt, attr, v) do {\ + (o).tt = ttt;\ + (o).attr = v;\ +} while (0) + +#define SET_NIL_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) +#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_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v)) +#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) +#define SET_UNDEF_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0) + +#endif /* MRUBY_BOXING_NO_H */ diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h new file mode 100644 index 000000000..8754087a3 --- /dev/null +++ b/include/mruby/boxing_word.h @@ -0,0 +1,116 @@ +/* +** mruby/boxing_word.h - word boxing mrb_value definition +** +** See Copyright Notice in mruby.h +*/ + +#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 + +struct RFloat { + MRB_OBJECT_HEADER; + mrb_float f; +}; + +struct RCptr { + MRB_OBJECT_HEADER; + void *p; +}; + +#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, +}; + +#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; + +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 mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f) + +#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 + +static inline enum mrb_vtype +mrb_type(mrb_value o) +{ + switch (o.w) { + case MRB_Qfalse: + case MRB_Qnil: + return MRB_TT_FALSE; + case MRB_Qtrue: + return MRB_TT_TRUE; + case MRB_Qundef: + return MRB_TT_UNDEF; + } + if (o.value.i_flag == MRB_FIXNUM_FLAG) { + return MRB_TT_FIXNUM; + } + if (o.value.sym_flag == MRB_SYMBOL_FLAG) { + return MRB_TT_SYMBOL; + } + return o.value.bp->tt; +} + +#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse) +#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG) +#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).value.i_flag = MRB_FIXNUM_FLAG; (o).attr = (v); break;\ + case MRB_TT_SYMBOL: (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;\ + }\ +} while (0) + +#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) + +#endif /* MRUBY_BOXING_WORD_H */ diff --git a/include/mruby/class.h b/include/mruby/class.h index 3c4915dc4..246e82e59 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -7,9 +7,12 @@ #ifndef MRUBY_CLASS_H #define MRUBY_CLASS_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Class class + */ +MRB_BEGIN_DECL struct RClass { MRB_OBJECT_HEADER; @@ -28,7 +31,7 @@ mrb_class(mrb_state *mrb, mrb_value v) { switch (mrb_type(v)) { case MRB_TT_FALSE: - if (v.value.i) + if (mrb_fixnum(v)) return mrb->false_class; return mrb->nil_class; case MRB_TT_TRUE: @@ -48,30 +51,39 @@ mrb_class(mrb_state *mrb, mrb_value v) } } -#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~0xff) | (char)tt) -#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & 0xff) +// TODO: figure out where to put user flags +#define MRB_FLAG_IS_PREPENDED (1 << 19) +#define MRB_FLAG_IS_ORIGIN (1 << 20) +#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;\ + }\ + }\ +} while (0) +#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) -struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*); -struct RClass* mrb_define_module_id(mrb_state*, mrb_sym); -struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym); -struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym); -void mrb_define_method_vm(mrb_state*, struct RClass*, mrb_sym, mrb_value); -void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *); -void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec); -void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b); +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_class_outer_module(mrb_state*, struct RClass *); -struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym); -struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_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); -struct RClass* mrb_class_real(struct RClass* cl); +MRB_API struct RClass* mrb_class_real(struct RClass* cl); 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*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_CLASS_H */ diff --git a/include/mruby/common.h b/include/mruby/common.h new file mode 100644 index 000000000..3745c58ea --- /dev/null +++ b/include/mruby/common.h @@ -0,0 +1,67 @@ +/* +**"common.h - mruby common platform definition" +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_COMMON_H +#define MRUBY_COMMON_H + + +#ifdef __cplusplus +# define MRB_BEGIN_DECL extern "C" { +# define MRB_END_DECL } +#else +/** Start declarations in C mode */ +# define MRB_BEGIN_DECL +/** End declarations in C mode */ +# define MRB_END_DECL +#endif + +/** + * Shared compiler macros + */ +MRB_BEGIN_DECL + +/** Declare a function that never returns. */ +#if __STDC_VERSION__ >= 201112L +# define mrb_noreturn _Noreturn +#elif defined __GNUC__ && !defined __STRICT_ANSI__ +# define mrb_noreturn __attribute__((noreturn)) +#elif defined _MSC_VER +# define mrb_noreturn __declspec(noreturn) +#else +# define mrb_noreturn +#endif + +/** Mark a function as deprecated. */ +#if defined __GNUC__ && !defined __STRICT_ANSI__ +# define mrb_deprecated __attribute__((deprecated)) +#elif defined _MSC_VER +# define mrb_deprecated __declspec(deprecated) +#else +# define mrb_deprecated +#endif + +/** Declare a function as always inlined. */ +#if defined(_MSC_VER) +# define MRB_INLINE static __inline +#else +# define MRB_INLINE static inline +#endif + + +/** Declare a public MRuby API function. */ +#if defined(MRB_BUILD_AS_DLL) +#if defined(MRB_CORE) || defined(MRB_LIB) +# define MRB_API __declspec(dllexport) +#else +# define MRB_API __declspec(dllimport) +#endif +#else +# define MRB_API extern +#endif + +MRB_END_DECL + +#endif /* MRUBY_COMMON_H */ diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 7f896e1fd..8b813b1c1 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -7,11 +7,14 @@ #ifndef MRUBY_COMPILE_H #define MRUBY_COMPILE_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * MRuby Compiler + */ +MRB_BEGIN_DECL -#include "mruby.h" +#include <mruby.h> struct mrb_jmpbuf; @@ -28,14 +31,16 @@ typedef struct mrbc_context { mrb_bool capture_errors:1; mrb_bool dump_result:1; mrb_bool no_exec:1; + mrb_bool keep_lv:1; + mrb_bool no_optimize:1; } mrbc_context; -mrbc_context* mrbc_context_new(mrb_state *mrb); -void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt); -const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); -void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data); +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_value mrb_toplevel_run_keep(mrb_state*, struct RProc*, unsigned int); +MRB_API mrb_value mrb_toplevel_run_keep(mrb_state*, struct RProc*, unsigned int); /* AST node structure */ typedef struct mrb_ast_node { @@ -53,8 +58,8 @@ enum mrb_lex_state_enum { EXPR_CMDARG, /* newline significant, +/- is an operator. */ EXPR_MID, /* newline significant, +/- is an operator. */ EXPR_FNAME, /* ignore newline, no reserved words. */ - EXPR_DOT, /* right after `.' or `::', no reserved words. */ - EXPR_CLASS, /* immediate after `class', no here document. */ + EXPR_DOT, /* right after '.' or '::', no reserved words. */ + EXPR_CLASS, /* immediate after 'class', no here document. */ EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */ EXPR_MAX_STATE }; @@ -107,7 +112,7 @@ struct mrb_parser_state { struct mrb_pool *pool; mrb_ast_node *cells; const char *s, *send; -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO FILE *f; #endif mrbc_context *cxt; @@ -142,6 +147,7 @@ struct mrb_parser_state { size_t nwarn; mrb_ast_node *tree; + mrb_bool no_optimize:1; mrb_bool capture_errors:1; struct mrb_parser_message error_buffer[10]; struct mrb_parser_message warn_buffer[10]; @@ -153,35 +159,32 @@ struct mrb_parser_state { struct mrb_jmpbuf* jmp; }; -struct mrb_parser_state* mrb_parser_new(mrb_state*); -void mrb_parser_free(struct mrb_parser_state*); -void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); +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*); -void mrb_parser_set_filename(struct mrb_parser_state*, char const*); -char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); +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); /* utility functions */ -#ifdef ENABLE_STDIO -struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); +#ifndef MRB_DISABLE_STDIO +MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); #endif -struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); -struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*); -struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); +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 RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); /* program load functions */ -#ifdef ENABLE_STDIO -mrb_value mrb_load_file(mrb_state*,FILE*); +#ifndef MRB_DISABLE_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); #endif -mrb_value mrb_load_string(mrb_state *mrb, const char *s); -mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len); -#ifdef ENABLE_STDIO -mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); -#endif -mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt); -mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt); +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_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); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +/** @} */ +MRB_END_DECL #endif /* MRUBY_COMPILE_H */ diff --git a/include/mruby/data.h b/include/mruby/data.h index 8b1b5edb7..590470528 100644 --- a/include/mruby/data.h +++ b/include/mruby/data.h @@ -7,12 +7,23 @@ #ifndef MRUBY_DATA_H #define MRUBY_DATA_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" +/** + * Custom C wrapped data. + * + * Defining Ruby wrappers around native objects. + */ +MRB_BEGIN_DECL + +/** + * Custom data type description. + */ typedef struct mrb_data_type { + /** data type name */ const char *struct_name; + + /** data type release function pointer */ void (*dfree)(mrb_state *mrb, void*); } mrb_data_type; @@ -23,7 +34,7 @@ struct RData { void *data; }; -struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void *datap, const mrb_data_type *type); +MRB_API struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void *datap, const mrb_data_type *type); #define Data_Wrap_Struct(mrb,klass,type,ptr)\ mrb_data_object_alloc(mrb,klass,ptr,type) @@ -37,10 +48,10 @@ struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void * #define RDATA(obj) ((struct RData *)(mrb_ptr(obj))) #define DATA_PTR(d) (RDATA(d)->data) #define DATA_TYPE(d) (RDATA(d)->type) -void mrb_data_check_type(mrb_state *mrb, mrb_value, const mrb_data_type*); -void *mrb_data_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); +MRB_API void mrb_data_check_type(mrb_state *mrb, mrb_value, const mrb_data_type*); +MRB_API void *mrb_data_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); #define DATA_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_get_ptr(mrb,obj,dtype) -void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); +MRB_API void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); #define DATA_CHECK_GET_PTR(mrb,obj,dtype,type) (type*)mrb_data_check_get_ptr(mrb,obj,dtype) /* obsolete functions and macros */ @@ -51,8 +62,14 @@ void *mrb_data_check_get_ptr(mrb_state *mrb, mrb_value, const mrb_data_type*); *(void**)&sval = mrb_data_get_ptr(mrb, obj, type); \ } while (0) -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +static inline void +mrb_data_init(mrb_value v, void *ptr, const mrb_data_type *type) +{ + mrb_assert(mrb_type(v) == MRB_TT_DATA); + DATA_PTR(v) = ptr; + DATA_TYPE(v) = type; +} + +MRB_END_DECL #endif /* MRUBY_DATA_H */ diff --git a/include/mruby/debug.h b/include/mruby/debug.h index a56321d42..44f84e49c 100644 --- a/include/mruby/debug.h +++ b/include/mruby/debug.h @@ -7,9 +7,12 @@ #ifndef MRUBY_DEBUG_H #define MRUBY_DEBUG_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * MRuby Debugging. + */ +MRB_BEGIN_DECL typedef enum mrb_debug_line_type { mrb_debug_line_ary = 0, @@ -44,22 +47,20 @@ typedef struct mrb_irep_debug_info { * get line from irep's debug info and program counter * @return returns NULL if not found */ -const char *mrb_debug_get_filename(mrb_irep *irep, uint32_t pc); +MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, uint32_t pc); /* * get line from irep's debug info and program counter * @return returns -1 if not found */ -int32_t mrb_debug_get_line(mrb_irep *irep, uint32_t pc); +MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, uint32_t pc); -mrb_irep_debug_info_file *mrb_debug_info_append_file( +MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file( mrb_state *mrb, mrb_irep *irep, uint32_t start_pos, uint32_t end_pos); -mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); -void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d); +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); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_DEBUG_H */ diff --git a/include/mruby/dump.h b/include/mruby/dump.h index fc79f1f4b..165a20b3f 100644 --- a/include/mruby/dump.h +++ b/include/mruby/dump.h @@ -7,22 +7,30 @@ #ifndef MRUBY_DUMP_H #define MRUBY_DUMP_H -#if defined(__cplusplus) -extern "C" { -#endif - -#include "mruby.h" -#include "mruby/irep.h" +#include <mruby.h> +#include <mruby/irep.h> +#include "common.h" -int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size); -#ifdef ENABLE_STDIO -int mrb_dump_irep_binary(mrb_state*, mrb_irep*, int, FILE*); -int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, int, FILE *f, const char *initname); +/** + * Dumping compiled mruby script. + */ +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 + +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); mrb_irep *mrb_read_irep_file(mrb_state*, FILE*); -mrb_value mrb_load_irep_file(mrb_state*,FILE*); -mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*); +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_irep *mrb_read_irep(mrb_state*, const uint8_t*); +MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*); /* dump/load error code * @@ -42,24 +50,26 @@ mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*); #define MRB_DUMP_NULL_SYM_LEN 0xFFFF /* Rite Binary File header */ -#define RITE_BINARY_IDENTIFIER "RITE" -#define RITE_BINARY_FORMAT_VER "0002" +#define RITE_BINARY_IDENT "RITE" +#define RITE_BINARY_IDENT_LIL "ETIR" +#define RITE_BINARY_FORMAT_VER "0003" #define RITE_COMPILER_NAME "MATZ" #define RITE_COMPILER_VERSION "0000" #define RITE_VM_VER "0000" #define RITE_BINARY_EOF "END\0" -#define RITE_SECTION_IREP_IDENTIFIER "IREP" -#define RITE_SECTION_LINENO_IDENTIFIER "LINE" -#define RITE_SECTION_DEBUG_IDENTIFIER "DBG\0" -#define RITE_SECTION_LV_IDENTIFIER "LVAR" +#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" #define MRB_DUMP_DEFAULT_STR_LEN 128 +#define MRB_DUMP_ALIGNMENT sizeof(uint32_t) /* binary header */ struct rite_binary_header { - uint8_t binary_identify[4]; /* Binary Identifier */ + uint8_t binary_ident[4]; /* Binary Identifier */ uint8_t binary_version[4]; /* Binary Format Version */ uint8_t binary_crc[2]; /* Binary CRC */ uint8_t binary_size[4]; /* Binary Size */ @@ -69,7 +79,7 @@ struct rite_binary_header { /* section header */ #define RITE_SECTION_HEADER \ - uint8_t section_identify[4]; \ + uint8_t section_ident[4]; \ uint8_t section_size[4] struct rite_section_header { @@ -100,6 +110,17 @@ 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) { @@ -125,6 +146,16 @@ 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) { @@ -134,6 +165,15 @@ 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) { @@ -147,11 +187,9 @@ bin_to_uint8(const uint8_t *bin) return (uint8_t)bin[0]; } -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL -/* crc.c */ +/** @internal crc.c */ uint16_t calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc); diff --git a/include/mruby/error.h b/include/mruby/error.h index 4d37f1701..bb67e7bd8 100644 --- a/include/mruby/error.h +++ b/include/mruby/error.h @@ -1,5 +1,5 @@ /* -** error.h - Exception class +** mruby/error.h - Exception class ** ** See Copyright Notice in mruby.h */ @@ -7,25 +7,63 @@ #ifndef MRUBY_ERROR_H #define MRUBY_ERROR_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" -void mrb_sys_fail(mrb_state *mrb, const char *mesg); -mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str); +/** + * MRuby error handling. + */ +MRB_BEGIN_DECL + +struct RException { + MRB_OBJECT_HEADER; + struct iv_tbl *iv; +}; + +#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v)) + +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_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv); -void mrb_exc_print(mrb_state *mrb, struct RObject *exc); -void mrb_print_backtrace(mrb_state *mrb); -mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); -mrb_value mrb_get_backtrace(mrb_state *mrb); -mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, const char *fmt, ...); +MRB_API mrb_value mrb_make_exception(mrb_state *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 */ -mrb_value mrb_f_raise(mrb_state*, mrb_value); +MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value); + +/** + * Protect + * + * @mrbgem mruby-error + */ +MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state); + +/** + * Ensure + * + * @mrbgem mruby-error + */ +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); + +/** + * Rescue + * + * @mrbgem mruby-error + */ +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); + +/** + * Rescue exception + * + * @mrbgem mruby-error + */ +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, + mrb_int len, struct RClass **classes); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_ERROR_H */ diff --git a/include/mruby/gc.h b/include/mruby/gc.h index 02714be8e..81950f169 100644 --- a/include/mruby/gc.h +++ b/include/mruby/gc.h @@ -1,5 +1,5 @@ /* -** gc.h - garbage collector for mruby +** mruby/gc.h - garbage collector for mruby ** ** See Copyright Notice in mruby.h */ @@ -7,16 +7,71 @@ #ifndef MRUBY_GC_H #define MRUBY_GC_H -#if defined(__cplusplus) -extern "C" { +#include "common.h" + +/** + * Uncommon memory management stuffs. + */ +MRB_BEGIN_DECL + + +struct mrb_state; + +typedef void (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); +MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); + +#ifndef MRB_GC_ARENA_SIZE +#define MRB_GC_ARENA_SIZE 100 #endif -typedef void (mrb_each_object_callback)(mrb_state *mrb, struct RBasic *obj, void *data); -void mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data); -void mrb_free_context(mrb_state *mrb, struct mrb_context *c); +typedef enum { + MRB_GC_STATE_ROOT = 0, + MRB_GC_STATE_MARK, + MRB_GC_STATE_SWEEP +} mrb_gc_state; -#if defined(__cplusplus) -} /* extern "C" { */ +typedef struct mrb_heap_page { + struct RBasic *freelist; + struct mrb_heap_page *prev; + struct mrb_heap_page *next; + struct mrb_heap_page *free_next; + struct mrb_heap_page *free_prev; + mrb_bool old:1; + void *objects[]; +} mrb_heap_page; + +typedef struct mrb_gc { + mrb_heap_page *heaps; /* heaps for GC */ + mrb_heap_page *sweeps; + mrb_heap_page *free_heaps; + size_t live; /* count of live objects */ +#ifdef MRB_GC_FIXED_ARENA + struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */ +#else + struct RBasic **arena; /* GC protection array */ + int arena_capa; #endif + int arena_idx; + + mrb_gc_state state; /* state of gc */ + int current_white_part; /* make white object by white_part */ + struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */ + struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */ + size_t live_after_mark; + size_t threshold; + int interval_ratio; + int step_ratio; + mrb_bool disabled :1; + mrb_bool full :1; + mrb_bool generational :1; + mrb_bool out_of_memory :1; + size_t majorgc_old_threshold; +} mrb_gc; + +MRB_API mrb_bool +mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object); + +MRB_END_DECL #endif /* MRUBY_GC_H */ diff --git a/include/mruby/hash.h b/include/mruby/hash.h index 6a8b11373..1d00a33ab 100644 --- a/include/mruby/hash.h +++ b/include/mruby/hash.h @@ -7,9 +7,12 @@ #ifndef MRUBY_HASH_H #define MRUBY_HASH_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Hash class + */ +MRB_BEGIN_DECL struct RHash { MRB_OBJECT_HEADER; @@ -20,24 +23,48 @@ struct RHash { #define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v))) #define mrb_hash_value(p) mrb_obj_value((void*)(p)) -mrb_value mrb_hash_new_capa(mrb_state*, int); -mrb_value mrb_hash_new(mrb_state *mrb); +MRB_API mrb_value mrb_hash_new_capa(mrb_state*, int); + +/* + * Initializes a new hash. + */ +MRB_API mrb_value mrb_hash_new(mrb_state *mrb); + +/* + * Sets a keys and values to hashes. + */ +MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val); + +/* + * Gets a value from a key. + */ +MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key); -void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val); -mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key); -mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def); -mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); -mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash); -mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); -mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self); -mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash); +MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def); + +/* + * Deletes hash key and value pair. + */ +MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); + +/* + * Gets an array of keys. + */ +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); +MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self); + +/* + * Clears the hash. + */ +MRB_API mrb_value mrb_hash_clear(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) -struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash); +MRB_API struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash); #define MRB_HASH_PROC_DEFAULT 256 #define MRB_RHASH_PROCDEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_PROC_DEFAULT) @@ -47,8 +74,6 @@ 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*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_HASH_H */ diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 3d6b5efc7..8922f4b76 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -7,11 +7,13 @@ #ifndef MRUBY_IREP_H #define MRUBY_IREP_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" +#include <mruby/compile.h> -#include "mruby/compile.h" +/** + * Compiled mruby scripts. + */ +MRB_BEGIN_DECL enum irep_pool_type { IREP_TT_STRING, @@ -46,15 +48,13 @@ typedef struct mrb_irep { #define MRB_ISEQ_NO_FREE 1 -mrb_irep *mrb_add_irep(mrb_state *mrb); -mrb_value mrb_load_irep(mrb_state*, const uint8_t*); -mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*); +MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb); +MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*); +MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_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*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_IREP_H */ diff --git a/include/mruby/khash.h b/include/mruby/khash.h index d2501dd52..9c40c6b80 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -4,16 +4,19 @@ ** See Copyright Notice in mruby.h */ -#ifndef KHASH_H -#define KHASH_H +#ifndef MRUBY_KHASH_H +#define MRUBY_KHASH_H -#if defined(__cplusplus) -extern "C" { -#endif - -#include "mruby.h" #include <string.h> +#include <mruby.h> +#include "common.h" + +/** + * khash definitions used in mruby's hash table. + */ +MRB_BEGIN_DECL + typedef uint32_t khint_t; typedef khint_t khiter_t; @@ -148,20 +151,23 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) new_n_buckets = KHASH_MIN_SIZE; \ khash_power2(new_n_buckets); \ { \ + kh_##name##_t hh; \ uint8_t *old_ed_flags = h->ed_flags; \ khkey_t *old_keys = h->keys; \ khval_t *old_vals = h->vals; \ khint_t old_n_buckets = h->n_buckets; \ khint_t i; \ - h->n_buckets = new_n_buckets; \ - kh_alloc_##name(mrb, h); \ + hh.n_buckets = new_n_buckets; \ + kh_alloc_##name(mrb, &hh); \ /* relocate */ \ for (i=0 ; i<old_n_buckets ; i++) { \ if (!__ac_iseither(old_ed_flags, i)) { \ - khint_t k = kh_put_##name(mrb, h, old_keys[i], NULL); \ - if (kh_is_map) kh_value(h,k) = old_vals[i]; \ + khint_t k = kh_put_##name(mrb, &hh, old_keys[i], NULL); \ + if (kh_is_map) kh_value(&hh,k) = old_vals[i]; \ } \ } \ + /* copy hh to h */ \ + *h = hh; \ mrb_free(mrb, old_keys); \ } \ } \ @@ -263,8 +269,6 @@ static inline khint_t __ac_X31_hash_string(const char *s) typedef const char *kh_cstr_t; -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL -#endif /* KHASH_H */ +#endif /* MRUBY_KHASH_H */ diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index fe4f3b264..6a7c172a6 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -7,33 +7,76 @@ #ifndef MRUBY_NUMERIC_H #define MRUBY_NUMERIC_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Numeric class and it's sub-classes. + * + * Integer, Float and Fixnum + */ +MRB_BEGIN_DECL #define POSFIXABLE(f) ((f) <= MRB_INT_MAX) #define NEGFIXABLE(f) ((f) >= MRB_INT_MIN) #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) -mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); - -mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base); +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); +/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */ +MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt); +MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); 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_float mrb_to_flo(mrb_state *mrb, mrb_value x); #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) -#ifdef MRB_WORD_BOXING -# 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 - MRB_FIXNUM_SHIFT)) + +/* Idea from Potion: https://github.com/perl11/potion (MIT) */ +#if (defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 4))) \ + || (defined(__GNUC__) && __GNUC__ >= 5) + +static inline mrb_bool +mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) +{ + mrb_bool of; + +#ifdef MRB_INT64 + long long val; + of = __builtin_saddll_overflow(augend, addend, &val) || +#else + int val; + of = __builtin_sadd_overflow(augend, addend, &val) || +#endif + (val > MRB_INT_MAX) || (val < MRB_INT_MIN); + + *sum = (mrb_int) val; + return of; +} + +static inline mrb_bool +mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) +{ + mrb_bool of; + +#ifdef MRB_INT64 + long long val; + of = __builtin_ssubll_overflow(minuend, subtrahend, &val) || #else -# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1)) + int val; + of = __builtin_ssub_overflow(minuend, subtrahend, &val) || #endif + (val > MRB_INT_MAX) || (val < MRB_INT_MIN); + + *difference = (mrb_int) val; + return of; +} +#else static inline mrb_bool mrb_int_add_overflow(mrb_int augend, mrb_int addend, mrb_int *sum) @@ -55,13 +98,13 @@ mrb_int_sub_overflow(mrb_int minuend, mrb_int subtrahend, mrb_int *difference) return !!(((x ^ z) & (~y ^ z)) & MRB_INT_OVERFLOW_MASK); } +#endif + #undef MRB_INT_OVERFLOW_MASK #undef mrb_uint #undef MRB_UINT_MAKE #undef MRB_UINT_MAKE2 -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_NUMERIC_H */ diff --git a/include/mruby/object.h b/include/mruby/object.h new file mode 100644 index 000000000..9fbfe34f3 --- /dev/null +++ b/include/mruby/object.h @@ -0,0 +1,39 @@ +/* +** mruby/object.h - mruby object definition +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_OBJECT_H +#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 RBasic { + MRB_OBJECT_HEADER; +}; +#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) + +struct RObject { + MRB_OBJECT_HEADER; + struct iv_tbl *iv; +}; +#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 { + MRB_OBJECT_HEADER; + struct mrb_context *cxt; +}; + +#endif /* MRUBY_OBJECT_H */ diff --git a/include/mruby/opcode.h b/include/mruby/opcode.h index c8a47c273..9dfa7f75d 100644 --- a/include/mruby/opcode.h +++ b/include/mruby/opcode.h @@ -1,14 +1,14 @@ /* -** opcode.h - RiteVM operation codes +** mruby/opcode.h - RiteVM operation codes ** ** See Copyright Notice in mruby.h */ -#ifndef OPCODE_H -#define OPCODE_H +#ifndef MRUBY_OPCODE_H +#define MRUBY_OPCODE_H #define MAXARG_Bx (0xffff) -#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ +#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */ /* instructions: packed 32 bit */ /* ------------------------------- */ @@ -157,4 +157,4 @@ enum { #define OP_R_BREAK 1 #define OP_R_RETURN 2 -#endif /* OPCODE_H */ +#endif /* MRUBY_OPCODE_H */ diff --git a/include/mruby/proc.h b/include/mruby/proc.h index 39f5eca22..24f0f319f 100644 --- a/include/mruby/proc.h +++ b/include/mruby/proc.h @@ -7,11 +7,13 @@ #ifndef MRUBY_PROC_H #define MRUBY_PROC_H -#include "mruby/irep.h" +#include "common.h" +#include <mruby/irep.h> -#if defined(__cplusplus) -extern "C" { -#endif +/** + * Proc class + */ +MRB_BEGIN_DECL struct REnv { MRB_OBJECT_HEADER; @@ -20,7 +22,8 @@ struct REnv { ptrdiff_t cioff; }; -#define MRB_ENV_STACK_LEN(e) ((e)->flags) +#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) @@ -37,7 +40,7 @@ struct RProc { /* aspec access */ #define MRB_ASPEC_REQ(a) (((a) >> 18) & 0x1f) #define MRB_ASPEC_OPT(a) (((a) >> 13) & 0x1f) -#define MRB_ASPEC_REST(a) ((a) & (1<<12)) +#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)) @@ -51,23 +54,23 @@ struct RProc { #define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v))) struct RProc *mrb_proc_new(mrb_state*, mrb_irep*); -struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t); struct RProc *mrb_closure_new(mrb_state*, mrb_irep*); -struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals); +MRB_API struct RProc *mrb_proc_new_cfunc(mrb_state*, mrb_func_t); +MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals); void mrb_proc_copy(struct RProc *a, struct RProc *b); /* implementation of #send method */ -mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); +MRB_API mrb_value mrb_f_send(mrb_state *mrb, mrb_value self); /* following functions are defined in mruby-proc-ext so please include it when using */ -struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*); -mrb_value mrb_cfunc_env_get(mrb_state*, mrb_int); +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); +/* old name */ +#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx) -#include "mruby/khash.h" +#include <mruby/khash.h> KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE) -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_PROC_H */ diff --git a/include/mruby/range.h b/include/mruby/range.h index 61beb2319..cf42ce133 100644 --- a/include/mruby/range.h +++ b/include/mruby/range.h @@ -7,9 +7,12 @@ #ifndef MRUBY_RANGE_H #define MRUBY_RANGE_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Range class + */ +MRB_BEGIN_DECL typedef struct mrb_range_edges { mrb_value beg; @@ -25,12 +28,21 @@ struct RRange { #define mrb_range_ptr(v) ((struct RRange*)(mrb_ptr(v))) #define mrb_range_value(p) mrb_obj_value((void*)(p)) -mrb_value mrb_range_new(mrb_state*, mrb_value, mrb_value, mrb_bool); -mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len); +/* + * Initializes a Range. + * + * If the third parameter is FALSE then it includes the last value in the range. + * If the third parameter is TRUE then it excludes the last value in the range. + * + * @param start the beginning value. + * @param end the ending value. + * @param exclude represents the inclusion or exclusion of the last value. + */ +MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude); + +MRB_API mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len); 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)); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_RANGE_H */ diff --git a/include/mruby/string.h b/include/mruby/string.h index f8a1fa7bd..a66ba70ff 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -7,9 +7,12 @@ #ifndef MRUBY_STRING_H #define MRUBY_STRING_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * String class + */ +MRB_BEGIN_DECL extern const char mrb_digitmap[]; @@ -59,74 +62,153 @@ struct RString { #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) +#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN) +#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) +#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) + +/* + * Returns a pointer from a Ruby string + */ #define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) #define RSTRING(s) mrb_str_ptr(s) #define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) #define RSTRING_EMBED_LEN(s) RSTR_ENBED_LEN(RSTRING(s)) -#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) +#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) #define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s)) #define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 -#define MRB_STR_EMBED 4 -#define MRB_STR_EMBED_LEN_MASK 0xf8 -#define MRB_STR_EMBED_LEN_SHIFT 3 +#define MRB_STR_FROZEN 4 +#define MRB_STR_EMBED 8 +#define MRB_STR_EMBED_LEN_MASK 0x1f0 +#define MRB_STR_EMBED_LEN_SHIFT 4 void mrb_gc_free_str(mrb_state*, struct RString*); -void mrb_str_modify(mrb_state*, struct RString*); -void mrb_str_concat(mrb_state*, mrb_value, mrb_value); -mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); -mrb_value mrb_ptr_to_str(mrb_state *, void*); -mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); -mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); -mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); -mrb_value mrb_string_type(mrb_state *mrb, mrb_value str); -mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa); - -char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); -char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr); -mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); -mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck); -double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck); -mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); -mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str); -mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); -mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str); -mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len); -mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr); -mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2); +MRB_API void mrb_str_modify(mrb_state*, struct RString*); +MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value); + +/* + * Adds two strings together. + */ +MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); + +/* + * Converts pointer into a Ruby string. + */ +MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*); + +/* + * Returns 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. + */ +MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); + +/* + * Returns a 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. + */ +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 const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str); +MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str); + +/* + * Duplicates a string object. + */ +MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); + +/* + * Returns a symbol from a passed in string. + */ +MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); + +MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck); +MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck); + +/* + * Returns a converted string type. + */ +MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); + +/* + * Returns true if the strings match and false if the strings don't match. + */ +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. + * + * @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. + * + * @see mrb_str_cat + */ +MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr); +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)) -mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2); -int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2); -char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str); +/* + * 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. + * - 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. + * @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); +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 */ -static inline mrb_value -mrb_str_cat2(mrb_state *mrb, mrb_value str, const char *ptr) { - return mrb_str_cat_cstr(mrb, str, ptr); -} - -static inline mrb_value -mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len) -{ - return mrb_str_cat(mrb, str, ptr, len); -} - -static inline mrb_value -mrb_str_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2) -{ - return mrb_str_cat_str(mrb, str, str2); -} - -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +#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_END_DECL #endif /* MRUBY_STRING_H */ diff --git a/include/mruby/throw.h b/include/mruby/throw.h new file mode 100644 index 000000000..7f720d512 --- /dev/null +++ b/include/mruby/throw.h @@ -0,0 +1,41 @@ +/* +** mruby/throw.h - mruby exception throwing handler +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRB_THROW_H +#define MRB_THROW_H + +#ifdef MRB_ENABLE_CXX_EXCEPTION + +#define MRB_TRY(buf) do { 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_THROW(buf) throw((buf)->impl) +typedef mrb_int mrb_jmpbuf_impl; + +#else + +#include <setjmp.h> + +#define MRB_TRY(buf) do { if (setjmp((buf)->impl) == 0) { +#define MRB_CATCH(buf) } else { +#define MRB_END_EXC(buf) } } while(0) + +#define MRB_THROW(buf) longjmp((buf)->impl, 1); +#define mrb_jmpbuf_impl jmp_buf + +#endif + +struct mrb_jmpbuf { + mrb_jmpbuf_impl impl; + +#ifdef MRB_ENABLE_CXX_EXCEPTION + static mrb_int jmpbuf_id; + mrb_jmpbuf() : impl(jmpbuf_id++) {} +#endif +}; + +#endif /* MRB_THROW_H */ diff --git a/include/mruby/value.h b/include/mruby/value.h index 98af9626d..04e5644d2 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -1,5 +1,5 @@ /* -** mruby/value.h - mrb_value definition +** mruby/value.h - mruby value definitions ** ** See Copyright Notice in mruby.h */ @@ -7,209 +7,68 @@ #ifndef MRUBY_VALUE_H #define MRUBY_VALUE_H -#ifdef MRB_USE_FLOAT - typedef float mrb_float; -# define mrb_float_to_str(buf, i) sprintf(buf, "%.7e", i) -# define str_to_mrb_float(buf) strtof(buf, NULL) -#else - typedef double mrb_float; -# define mrb_float_to_str(buf, i) sprintf(buf, "%.16e", i) -# define str_to_mrb_float(buf) strtod(buf, NULL) -#endif +#include "common.h" + +/** + * MRuby Value definition functions and macros. + */ +MRB_BEGIN_DECL + +typedef uint32_t mrb_sym; +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(MRB_INT64) -# ifdef MRB_NAN_BOXING -# error Cannot use NaN boxing when mrb_int is 64bit -# else - typedef int64_t mrb_int; -# define MRB_INT_BIT 64 -# ifdef MRB_WORD_BOXING -# define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT) -# else -# define MRB_INT_MIN INT64_MIN -# define MRB_INT_MAX INT64_MAX -# endif -# define PRIdMRB_INT PRId64 -# define PRIiMRB_INT PRIi64 -# define PRIoMRB_INT PRIo64 -# define PRIxMRB_INT PRIx64 -# define PRIXMRB_INT PRIX64 -# endif + typedef int64_t mrb_int; +# define MRB_INT_BIT 64 +# define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT) +# define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT) #elif defined(MRB_INT16) -# ifdef MRB_WORD_BOXING -# error "MRB_INT16 is too small for MRB_WORD_BOXING." -# endif typedef int16_t mrb_int; # define MRB_INT_BIT 16 -# define MRB_INT_MIN INT16_MIN -# define MRB_INT_MAX INT16_MAX +# define MRB_INT_MIN (INT16_MIN>>MRB_FIXNUM_SHIFT) +# define MRB_INT_MAX (INT16_MAX>>MRB_FIXNUM_SHIFT) #else typedef int32_t mrb_int; # define MRB_INT_BIT 32 -# ifdef MRB_WORD_BOXING -# define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT) -# define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT) -# else -# define MRB_INT_MIN INT32_MIN -# define MRB_INT_MAX INT32_MAX -# endif -# define PRIdMRB_INT PRId32 -# define PRIiMRB_INT PRIi32 -# define PRIoMRB_INT PRIo32 -# define PRIxMRB_INT PRIx32 -# define PRIXMRB_INT PRIX32 +# define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT) +# define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT) #endif -typedef short mrb_sym; -#ifdef _MSC_VER +#ifdef MRB_USE_FLOAT + typedef float mrb_float; +# define str_to_mrb_float(buf) strtof(buf, NULL) +#else + typedef double mrb_float; +# define str_to_mrb_float(buf) strtod(buf, NULL) +#endif + +#if defined _MSC_VER && _MSC_VER < 1900 # ifndef __cplusplus # define inline __inline # endif -# if _MSC_VER < 1900 -# define snprintf _snprintf -# 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 # include <float.h> # define isfinite(n) _finite(n) # define isnan _isnan # define isinf(n) (!_finite(n) && !_isnan(n)) # define signbit(n) (_copysign(1.0, (n)) < 0.0) -# define strtoll _strtoi64 # define strtof (float)strtod -# define PRId32 "I32d" -# define PRIi32 "I32i" -# define PRIo32 "I32o" -# define PRIx32 "I32x" -# define PRIX32 "I32X" -# define PRId64 "I64d" -# define PRIi64 "I64i" -# define PRIo64 "I64o" -# define PRIx64 "I64x" -# define PRIX64 "I64X" -static unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000; +static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000; # define INFINITY (*(float *)&IEEE754_INFINITY_BITS_SINGLE) # define NAN ((float)(INFINITY - INFINITY)) -# else -# include <inttypes.h> # endif -#else -# include <inttypes.h> -#endif - -typedef uint8_t mrb_bool; -struct mrb_state; - -#if defined(MRB_NAN_BOXING) - -#ifdef MRB_USE_FLOAT -# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<---- -#endif - -#ifdef MRB_INT64 -# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<---- -#endif - -enum mrb_vtype { - MRB_TT_FALSE = 1, /* 1 */ - MRB_TT_FREE, /* 2 */ - MRB_TT_TRUE, /* 3 */ - MRB_TT_FIXNUM, /* 4 */ - MRB_TT_SYMBOL, /* 5 */ - MRB_TT_UNDEF, /* 6 */ - MRB_TT_FLOAT, /* 7 */ - MRB_TT_CPTR, /* 8 */ - MRB_TT_OBJECT, /* 9 */ - MRB_TT_CLASS, /* 10 */ - MRB_TT_MODULE, /* 11 */ - MRB_TT_ICLASS, /* 12 */ - MRB_TT_SCLASS, /* 13 */ - MRB_TT_PROC, /* 14 */ - MRB_TT_ARRAY, /* 15 */ - MRB_TT_HASH, /* 16 */ - MRB_TT_STRING, /* 17 */ - MRB_TT_RANGE, /* 18 */ - MRB_TT_EXCEPTION, /* 19 */ - MRB_TT_FILE, /* 20 */ - MRB_TT_ENV, /* 21 */ - MRB_TT_DATA, /* 22 */ - MRB_TT_FIBER, /* 23 */ - MRB_TT_MAXDEFINE /* 24 */ -}; - -#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 -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; - }; -} mrb_value; - -/* value representation by nan-boxing: - * float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF - * object: 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP - * int : 1111111111110001 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII - * sym : 1111111111110001 0100000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS - * In order to get enough bit size to save TT, all pointers are shifted 2 bits - * in the right direction. - */ -#define mrb_tt(o) ((enum mrb_vtype)(((o).value.ttt & 0xfc000)>>14)) -#define mrb_mktt(tt) (0xfff00000|((tt)<<14)) -#define mrb_type(o) ((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_SET_VALUE(o, tt, attr, v) do {\ - (o).value.ttt = mrb_mktt(tt);\ - switch (tt) {\ - case MRB_TT_FALSE:\ - case MRB_TT_TRUE:\ - case MRB_TT_UNDEF:\ - case MRB_TT_FIXNUM:\ - case MRB_TT_SYMBOL: (o).attr = (v); break;\ - default: (o).value.i = 0; (o).value.p = (void*)((uintptr_t)(o).value.p | (((uintptr_t)(v))>>2)); break;\ - }\ -} while (0) - -static inline mrb_value -mrb_float_value(struct mrb_state *mrb, mrb_float f) -{ - mrb_value v; - - if (f != f) { - v.value.ttt = 0x7ff80000; - v.value.i = 0; - } else { - v.f = f; - } - return v; -} -#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) - -#else - enum mrb_vtype { MRB_TT_FALSE = 0, /* 0 */ MRB_TT_FREE, /* 1 */ @@ -237,214 +96,81 @@ enum mrb_vtype { MRB_TT_MAXDEFINE /* 23 */ }; -#if defined(MRB_WORD_BOXING) +#include <mruby/object.h> -#include <limits.h> -#define MRB_TT_HAS_BASIC MRB_TT_FLOAT +#ifdef MRB_DOCUMENTATION_BLOCK -enum mrb_special_consts { - MRB_Qnil = 0, - MRB_Qfalse = 2, - MRB_Qtrue = 4, - MRB_Qundef = 6, -}; - -#define MRB_FIXNUM_FLAG 0x01 -#define MRB_FIXNUM_SHIFT 1 -#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; - int sym : (sizeof(mrb_sym) * CHAR_BIT); - }; - struct RBasic *bp; - struct RFloat *fp; - struct RCptr *vp; - } value; - unsigned long w; -} mrb_value; - -#define mrb_ptr(o) (o).value.p -#define mrb_float(o) (o).value.fp->f - -#define MRB_SET_VALUE(o, ttt, attr, v) do {\ - (o).w = 0;\ - (o).attr = (v);\ - 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).value.i_flag = MRB_FIXNUM_FLAG; break;\ - case MRB_TT_SYMBOL: (o).value.sym_flag = MRB_SYMBOL_FLAG; break;\ - default: if ((o).value.bp) (o).value.bp->tt = ttt; break;\ - }\ -} while (0) - -mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f); -mrb_value mrb_float_pool(struct mrb_state *mrb, mrb_float f); - -#else /* No MRB_xxx_BOXING */ - -#define MRB_TT_HAS_BASIC MRB_TT_OBJECT - -typedef struct mrb_value { - union { - mrb_float f; - void *p; - mrb_int i; - mrb_sym sym; - } value; - enum mrb_vtype tt; -} mrb_value; - -#define mrb_type(o) (o).tt -#define mrb_ptr(o) (o).value.p -#define mrb_float(o) (o).value.f - -#define MRB_SET_VALUE(o, ttt, attr, v) do {\ - (o).tt = ttt;\ - (o).attr = v;\ -} while (0) - -static inline mrb_value -mrb_float_value(struct mrb_state *mrb, mrb_float f) -{ - mrb_value v; - (void) mrb; - - MRB_SET_VALUE(v, MRB_TT_FLOAT, value.f, f); - return v; -} -#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f) - -#endif /* no boxing */ +/** + * @abstract + * MRuby value boxing. + * + * Actual implementation depends on configured boxing type. + * + * @see mruby/boxing_no.h Default boxing representation + * @see mruby/boxing_word.h Word representation + * @see mruby/boxing_nan.h Boxed double representation + */ +typedef void mrb_value; #endif -#ifdef MRB_WORD_BOXING - -#define mrb_cptr(o) (o).value.vp->p -#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG) -#define mrb_undef_p(o) ((o).w == MRB_Qundef) -#define mrb_nil_p(o) ((o).w == MRB_Qnil) -#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse) - +#if defined(MRB_NAN_BOXING) +#include "boxing_nan.h" +#elif defined(MRB_WORD_BOXING) +#include "boxing_word.h" #else +#include "boxing_no.h" +#endif -#define mrb_cptr(o) mrb_ptr(o) +#ifndef mrb_fixnum_p #define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM) +#endif +#ifndef mrb_undef_p #define mrb_undef_p(o) (mrb_type(o) == MRB_TT_UNDEF) -#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && !(o).value.i) +#endif +#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) - -#endif /* no boxing */ - -#define mrb_fixnum(o) (o).value.i -#define mrb_symbol(o) (o).value.sym +#endif #define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT) #define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL) #define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY) #define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING) #define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH) #define mrb_cptr_p(o) (mrb_type(o) == MRB_TT_CPTR) +#define mrb_exception_p(o) (mrb_type(o) == MRB_TT_EXCEPTION) #define mrb_test(o) mrb_bool(o) -mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value); - -#define MRB_OBJECT_HEADER \ - enum mrb_vtype tt:8;\ - uint32_t color:3;\ - uint32_t flags:21;\ - struct RClass *c;\ - struct RBasic *gcnext - -/* white: 011, black: 100, gray: 000 */ -#define MRB_GC_GRAY 0 -#define MRB_GC_WHITE_A 1 -#define MRB_GC_WHITE_B (1 << 1) -#define MRB_GC_BLACK (1 << 2) -#define MRB_GC_WHITES (MRB_GC_WHITE_A | MRB_GC_WHITE_B) -#define MRB_GC_COLOR_MASK 7 - -#define paint_gray(o) ((o)->color = MRB_GC_GRAY) -#define paint_black(o) ((o)->color = MRB_GC_BLACK) -#define paint_white(o) ((o)->color = MRB_GC_WHITES) -#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part) -#define is_gray(o) ((o)->color == MRB_GC_GRAY) -#define is_white(o) ((o)->color & MRB_GC_WHITES) -#define is_black(o) ((o)->color & MRB_GC_BLACK) -#define is_dead(s, o) (((o)->color & other_white_part(s) & MRB_GC_WHITES) || (o)->tt == MRB_TT_FREE) -#define flip_white_part(s) ((s)->current_white_part = other_white_part(s)) -#define other_white_part(s) ((s)->current_white_part ^ MRB_GC_WHITES) - -struct RBasic { - MRB_OBJECT_HEADER; -}; -#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) -/* obsolete macro mrb_basic; will be removed soon */ -#define mrb_basic(v) mrb_basic_ptr(v) - -struct RObject { - MRB_OBJECT_HEADER; - struct iv_tbl *iv; -}; -#define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v))) -/* obsolete macro mrb_object; will be removed soon */ -#define mrb_object(o) mrb_obj_ptr(o) -#define mrb_immediate_p(x) (mrb_type(x) <= MRB_TT_CPTR) -#define mrb_special_const_p(x) mrb_immediate_p(x) +MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value); -struct RFiber { - MRB_OBJECT_HEADER; - struct mrb_context *cxt; -}; - -#ifdef MRB_WORD_BOXING -struct RFloat { - MRB_OBJECT_HEADER; - mrb_float f; -}; - -struct RCptr { - MRB_OBJECT_HEADER; - void *p; -}; - -static inline enum mrb_vtype -mrb_type(mrb_value o) +/* + * Returns a float in Ruby. + */ +MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f) { - 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; + mrb_value v; + (void) mrb; + SET_FLOAT_VALUE(mrb, v, f); + return v; } -#endif /* MRB_WORD_BOXING */ static inline mrb_value -mrb_fixnum_value(mrb_int i) +mrb_cptr_value(struct mrb_state *mrb, void *p) { mrb_value v; + (void) mrb; + SET_CPTR_VALUE(mrb,v,p); + return v; +} - MRB_SET_VALUE(v, MRB_TT_FIXNUM, value.i, i); +/* + * Returns a fixnum in Ruby. + */ +MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i) +{ + mrb_value v; + SET_INT_VALUE(v, i); return v; } @@ -452,8 +178,7 @@ static inline mrb_value mrb_symbol_value(mrb_sym i) { mrb_value v; - - MRB_SET_VALUE(v, MRB_TT_SYMBOL, value.sym, i); + SET_SYM_VALUE(v, i); return v; } @@ -461,58 +186,49 @@ static inline mrb_value mrb_obj_value(void *p) { mrb_value v; - struct RBasic *b = (struct RBasic*)p; - - MRB_SET_VALUE(v, b->tt, value.p, p); + SET_OBJ_VALUE(v, (struct RBasic*)p); return v; } -#ifdef MRB_WORD_BOXING -mrb_value -mrb_cptr_value(struct mrb_state *mrb, void *p); -#else -static inline mrb_value -mrb_cptr_value(struct mrb_state *mrb, void *p) + +/* + * Get a nil mrb_value object. + * + * @return + * nil mrb_value object reference. + */ +MRB_INLINE mrb_value mrb_nil_value(void) { mrb_value v; - (void) mrb; - - MRB_SET_VALUE(v, MRB_TT_CPTR, value.p, p); + SET_NIL_VALUE(v); return v; } -#endif -/* obsolete macros; will be removed */ -#define MRB_TT_VOIDP MRB_TT_CPTR -#define mrb_voidp_value(m,p) mrb_cptr_value((m),(p)) -#define mrb_voidp(o) mrb_cptr(o) -#define mrb_voidp_p(o) mrb_cptr_p(o) -#define MRB_TT_HAS_BASIC_P(tt) ((tt) >= MRB_TT_HAS_BASIC) - -static inline mrb_value -mrb_false_value(void) +/* + * Returns false in Ruby. + */ +MRB_INLINE mrb_value mrb_false_value(void) { mrb_value v; - - MRB_SET_VALUE(v, MRB_TT_FALSE, value.i, 1); + SET_FALSE_VALUE(v); return v; } -static inline mrb_value -mrb_nil_value(void) +/* + * Returns true in Ruby. + */ +MRB_INLINE mrb_value mrb_true_value(void) { mrb_value v; - - MRB_SET_VALUE(v, MRB_TT_FALSE, value.i, 0); + SET_TRUE_VALUE(v); return v; } static inline mrb_value -mrb_true_value(void) +mrb_bool_value(mrb_bool boolean) { mrb_value v; - - MRB_SET_VALUE(v, MRB_TT_TRUE, value.i, 1); + SET_BOOL_VALUE(v, boolean); return v; } @@ -520,18 +236,33 @@ static inline mrb_value mrb_undef_value(void) { mrb_value v; - - MRB_SET_VALUE(v, MRB_TT_UNDEF, value.i, 0); + SET_UNDEF_VALUE(v); return v; } -static inline mrb_value -mrb_bool_value(mrb_bool boolean) +#ifdef MRB_USE_ETEXT_EDATA +extern char _etext[]; +#ifdef MRB_NO_INIT_ARRAY_START +extern char _edata[]; + +static inline mrb_bool +mrb_ro_data_p(const char *p) { - mrb_value v; + return _etext < p && p < _edata; +} +#else +extern char __init_array_start[]; - MRB_SET_VALUE(v, boolean ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1); - return v; +static inline mrb_bool +mrb_ro_data_p(const char *p) +{ + return _etext < p && p < (char*)&__init_array_start; } +#endif +#else +# define mrb_ro_data_p(p) FALSE +#endif + +MRB_END_DECL #endif /* MRUBY_VALUE_H */ diff --git a/include/mruby/variable.h b/include/mruby/variable.h index 68a4e5889..15068039a 100644 --- a/include/mruby/variable.h +++ b/include/mruby/variable.h @@ -7,9 +7,12 @@ #ifndef MRUBY_VARIABLE_H #define MRUBY_VARIABLE_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Functions to access mruby variables. + */ +MRB_BEGIN_DECL typedef struct global_variable { int counter; @@ -34,36 +37,38 @@ 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); -mrb_value mrb_const_get(mrb_state*, mrb_value, mrb_sym); -void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value); -mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym); -void mrb_const_remove(mrb_state*, mrb_value, mrb_sym); +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_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym); -void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); -mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym); -void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v); -mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym); -void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v); -mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym); -mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); -void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); -int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id); +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_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); +MRB_API mrb_value mrb_iv_remove(mrb_state *mrb, mrb_value obj, mrb_sym sym); +MRB_API void mrb_iv_copy(mrb_state *mrb, mrb_value dst, mrb_value src); +MRB_API mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id); +MRB_API mrb_value mrb_gv_get(mrb_state *mrb, mrb_sym sym); +MRB_API void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); +MRB_API void mrb_gv_remove(mrb_state *mrb, mrb_sym sym); +MRB_API mrb_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym); +MRB_API void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v); +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*); 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_gv_get(mrb_state *mrb, mrb_sym sym); -void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val); -void mrb_gv_remove(mrb_state *mrb, mrb_sym sym); mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value); -mrb_value mrb_obj_iv_inspect(mrb_state*, struct RObject*); -mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer); 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_value mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym); -void mrb_mod_cv_set(mrb_state *mrb, struct RClass * c, mrb_sym sym, mrb_value v); -void mrb_cv_set(mrb_state *mrb, mrb_value mod, mrb_sym sym, mrb_value v); mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym); -mrb_bool mrb_cv_defined(mrb_state *mrb, mrb_value mod, mrb_sym sym); +mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer); /* GC functions */ void mrb_gc_mark_gv(mrb_state*); @@ -72,8 +77,6 @@ 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*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_VARIABLE_H */ diff --git a/include/mruby/version.h b/include/mruby/version.h index d451dfb31..20c39ec79 100644 --- a/include/mruby/version.h +++ b/include/mruby/version.h @@ -1,34 +1,110 @@ +/* +** mruby/version.h - mruby version definition +** +** See Copyright Notice in mruby.h +*/ + #ifndef MRUBY_VERSION_H #define MRUBY_VERSION_H +#include "common.h" + +/** + * mruby version definition macros + */ +MRB_BEGIN_DECL + +/* + * A passed in expression. + */ +#define MRB_STRINGIZE0(expr) #expr + +/* + * Passes in an expression to MRB_STRINGIZE0. + */ +#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr) + +/* + * The version of Ruby used by mruby. + */ #define MRUBY_RUBY_VERSION "1.9" + +/* + * Ruby engine. + */ #define MRUBY_RUBY_ENGINE "mruby" -#define MRUBY_VERSION "1.0.0" +/* + * Major release version number. + */ #define MRUBY_RELEASE_MAJOR 1 -#define MRUBY_RELEASE_MINOR 0 -#define MRUBY_RELEASE_TEENY 1 -#define MRUBY_RELEASE_NO 10001 -#define MRUBY_RELEASE_DATE "2014-01-10" -#define MRUBY_RELEASE_YEAR 2014 -#define MRUBY_RELEASE_MONTH 1 -#define MRUBY_RELEASE_DAY 10 +/* + * Minor release version number. + */ +#define MRUBY_RELEASE_MINOR 2 + +/* + * Tiny release version number. + */ +#define MRUBY_RELEASE_TEENY 0 + +/* + * The mruby version. + */ +#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY) + +/* + * Release number. + */ +#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY) + +/* + * Release year. + */ +#define MRUBY_RELEASE_YEAR 2015 + +/* + * Release month. + */ +#define MRUBY_RELEASE_MONTH 11 + +/* + * Release day. + */ +#define MRUBY_RELEASE_DAY 17 + +/* + * Release date as a string. + */ +#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY) + +/* + * The year mruby was first created. + */ #define MRUBY_BIRTH_YEAR 2010 +/* + * MRuby's authors. + */ #define MRUBY_AUTHOR "mruby developers" -#define MRB_STRINGIZE0(expr) #expr -#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr) - +/* + * mruby's version, and release date. + */ #define MRUBY_DESCRIPTION \ "mruby " MRUBY_VERSION \ " (" MRUBY_RELEASE_DATE ") " \ +/* + * mruby's copyright information. + */ #define MRUBY_COPYRIGHT \ "mruby - Copyright (c) " \ MRB_STRINGIZE(MRUBY_BIRTH_YEAR)"-" \ MRB_STRINGIZE(MRUBY_RELEASE_YEAR)" " \ MRUBY_AUTHOR \ +MRB_END_DECL + #endif /* MRUBY_VERSION_H */ |
