diff options
| author | Daniel Bovensiepen <[email protected]> | 2013-06-15 03:53:50 +0800 |
|---|---|---|
| committer | Daniel Bovensiepen <[email protected]> | 2013-06-15 03:53:50 +0800 |
| commit | 373122a299ebec890cfaa95ee41fde221ac6a543 (patch) | |
| tree | 346e79bb8a30a4e0b4102babf7dd9407beb36979 | |
| parent | ad07d41bd1b42fe7d23e04361839f511c5f9cd7f (diff) | |
| parent | 961cd408a86580c4d428f56153da00fd46738e35 (diff) | |
| download | mruby-373122a299ebec890cfaa95ee41fde221ac6a543.tar.gz mruby-373122a299ebec890cfaa95ee41fde221ac6a543.zip | |
Merge upstream
89 files changed, 1343 insertions, 768 deletions
@@ -11,3 +11,8 @@ Original Authors "mruby developers" are: Masaki Muranaka Internet Initiative Japan Inc. Tadashi FUKUZAWA + MATSUMOTO Ryosuke + Yasuhiro Matsumoto + Koji Yoshioka + Jun Hiroe + Narihiro Nakamura @@ -2,7 +2,7 @@ This is a preliminary release for internal team review. The URLs and addresses described below are not available yet. The official release will be announced later. - Any suggestion for modification is welcome. + Any suggestions for modification are welcome. Delays in replies are to be expected. Sorry in advance. ## What's mruby @@ -113,4 +113,4 @@ Please ask us if you want to distribute your code under another license. See the [contribution guidelines](https://github.com/mruby/mruby/blob/master/CONTRIBUTING.md) then send a pull request to <http://github.com/mruby/mruby>. We consider you have granted non-exclusive right to your contributed code under MIT license. If you want to be named -as one of mruby developers, include update to the AUTHORS file in your pull request. +as one of mruby developers, please include an update to the AUTHORS file in your pull request. diff --git a/doc/compile/README.md b/doc/compile/README.md index a244d06b2..e7f382f15 100644 --- a/doc/compile/README.md +++ b/doc/compile/README.md @@ -33,7 +33,8 @@ customized path using the *$MRUBY_CONFIG* environment variable. To compile just call ```./minirake``` inside of the mruby source root. To generate and execute the test tools call ```./minirake test```. To clean -all build files call ```./minirake clean```. +all build files call ```./minirake clean```. To see full command line on +build, call ```./minirake -v```. ## Build Configuration @@ -177,6 +178,7 @@ Integrate GEMs in the build process. conf.gem 'path/to/another/gem' +See doc/mrbgems/README.md for more option about mrbgems. ### Mrbtest Configuration Mrbtest build process. diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md index e89fd1a56..881fbb228 100644 --- a/doc/mrbgems/README.md +++ b/doc/mrbgems/README.md @@ -25,6 +25,9 @@ A remote GIT repository location for a GEM is also supported: conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' +To pull all gems from remote GIT repository on build, call ```./minirake -p```, +or ```./minirake --pull-gems```. + NOTE: `:bitbucket` option supports only git. Hg is unsupported in this version. ## GemBox @@ -96,7 +99,7 @@ GEM directory. A typical GEM specification could look like this for example: MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end The mrbgems build process will use this specification to compile Object and Ruby @@ -121,7 +124,7 @@ In case your GEM is depending on other GEMs please use MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' # add GEM dependency mruby-parser. # Version has to be between 1.0.0 and 1.5.2 diff --git a/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake b/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake index 35dbe5e18..a1f964b36 100644 --- a/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake +++ b/examples/mrbgems/c_and_ruby_extension_example/mrbgem.rake @@ -1,6 +1,6 @@ MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' # Add compile flags # spec.cc.flags << '' diff --git a/examples/mrbgems/c_extension_example/mrbgem.rake b/examples/mrbgems/c_extension_example/mrbgem.rake index 8c132b233..3524e22f4 100644 --- a/examples/mrbgems/c_extension_example/mrbgem.rake +++ b/examples/mrbgems/c_extension_example/mrbgem.rake @@ -1,6 +1,6 @@ MRuby::Gem::Specification.new('c_extension_example') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' # Add compile flags # spec.cc.flags << '-g' diff --git a/examples/mrbgems/ruby_extension_example/mrbgem.rake b/examples/mrbgems/ruby_extension_example/mrbgem.rake index 3a80b5cd7..5624c33e9 100644 --- a/examples/mrbgems/ruby_extension_example/mrbgem.rake +++ b/examples/mrbgems/ruby_extension_example/mrbgem.rake @@ -1,6 +1,6 @@ MRuby::Gem::Specification.new('ruby_extension_example') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' # Add compile flags # spec.cc.flags << '' diff --git a/examples/targets/ArduinoDue.rb b/examples/targets/ArduinoDue.rb index c45efb57c..a4af4a926 100644 --- a/examples/targets/ArduinoDue.rb +++ b/examples/targets/ArduinoDue.rb @@ -5,6 +5,8 @@ MRuby::CrossBuild.new("Arduino Due") do |conf| toolchain :gcc + # Mac OS X + # ARDUINO_PATH = '/Applications/Arduino.app/Contents/Resources/Java' # GNU Linux ARDUINO_PATH = '/opt/arduino' BIN_PATH = "#{ARDUINO_PATH}/hardware/tools/g++_arm_none_eabi/bin" @@ -13,18 +15,28 @@ MRuby::CrossBuild.new("Arduino Due") do |conf| conf.cc do |cc| cc.command = "#{BIN_PATH}/arm-none-eabi-gcc" - cc.include_paths << ["#{SAM_PATH}/system/libsam -I#{SAM_PATH}/system/CMSIS/CMSIS/Include/", + cc.include_paths << ["#{SAM_PATH}/system/libsam", "#{SAM_PATH}/system/CMSIS/CMSIS/Include/", "#{SAM_PATH}/system/CMSIS/Device/ATMEL/", - "#{SAM_PATH}/cores/arduino -I#{TARGET_PATH}"] + "#{SAM_PATH}/cores/arduino", "#{SAM_PATH}/libraries","#{TARGET_PATH}"] cc.flags = %w(-g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=152 -D__SAM3X8E__ -mthumb -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON) cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" + + #configuration for low memory environment + cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) + cc.defines << %w(MRB_USE_IV_SEGLIST) + cc.defines << %w(KHASH_DEFAULT_SIZE=8) + cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) + cc.defines << %w(MRB_GC_STRESS) + #cc.defines << %w(DISABLE_STDIO) #if you dont need stdio. + #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval end conf.cxx do |cxx| cxx.command = conf.cc.command.dup cxx.include_paths = conf.cc.include_paths.dup cxx.flags = conf.cc.flags.dup + cxx.defines = conf.cc.defines.dup cxx.compile_options = conf.cc.compile_options.dup end @@ -36,4 +48,18 @@ MRuby::CrossBuild.new("Arduino Due") do |conf| #no executables conf.bins = [] + #do not build executable test + conf.build_mrbtest_lib_only + + #gems from core + conf.gem :core => "mruby-print" + conf.gem :core => "mruby-math" + conf.gem :core => "mruby-enum-ext" + + #light-weight regular expression + conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master" + + #Arduino API + #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" + end diff --git a/examples/targets/chipKitMax32.rb b/examples/targets/chipKitMax32.rb index 380a34094..5c3a30a2b 100644 --- a/examples/targets/chipKitMax32.rb +++ b/examples/targets/chipKitMax32.rb @@ -24,12 +24,22 @@ MRuby::CrossBuild.new("chipKitMax32") do |conf| -fno-short-double -mprocessor=32MX795F512L -DF_CPU=80000000L -DARDUINO=23 -D_BOARD_MEGA_ -DMPIDEVER=0x01000202 -DMPIDE=23) cc.compile_options = "%{flags} -o %{outfile} -c %{infile}" + + #configuration for low memory environment + cc.defines << %w(MRB_HEAP_PAGE_SIZE=64) + cc.defines << %w(MRB_USE_IV_SEGLIST) + cc.defines << %w(KHASH_DEFAULT_SIZE=8) + cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20) + cc.defines << %w(MRB_GC_STRESS) + #cc.defines << %w(DISABLE_STDIO) #if you dont need stdio. + #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval end conf.cxx do |cxx| cxx.command = conf.cc.command.dup cxx.include_paths = conf.cc.include_paths.dup cxx.flags = conf.cc.flags.dup + cxx.defines = conf.cc.defines.dup cxx.compile_options = conf.cc.compile_options.dup end @@ -41,4 +51,18 @@ MRuby::CrossBuild.new("chipKitMax32") do |conf| #no executables conf.bins = [] + #do not build test executable + conf.build_mrbtest_lib_only + + #gems from core + conf.gem :core => "mruby-print" + conf.gem :core => "mruby-math" + conf.gem :core => "mruby-enum-ext" + + #light-weight regular expression + conf.gem :github => "masamitsu-murase/mruby-hs-regexp", :branch => "master" + + #Arduino API + #conf.gem :github =>"kyab/mruby-arduino", :branch => "master" + end diff --git a/include/mruby.h b/include/mruby.h index 33a15de0e..dcd2aa5fc 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -73,15 +73,15 @@ enum mrb_fiber_state { struct mrb_context { struct mrb_context *prev; - mrb_value *stack; + mrb_value *stack; /* stack of virtual machine */ mrb_value *stbase, *stend; mrb_callinfo *ci; mrb_callinfo *cibase, *ciend; - mrb_code **rescue; + mrb_code **rescue; /* exception handler stack */ int rsize; - struct RProc **ensure; + struct RProc **ensure; /* ensure handler stack */ int esize; uint8_t status; @@ -97,19 +97,19 @@ enum gc_state { typedef struct mrb_state { void *jmp; - mrb_allocf allocf; + mrb_allocf allocf; /* memory allocation function */ struct mrb_context *c; struct mrb_context *root_c; - struct RObject *exc; - struct iv_tbl *globals; - struct mrb_irep **irep; + struct RObject *exc; /* exception */ + struct iv_tbl *globals; /* global variable table */ + struct mrb_irep **irep; /* program data array */ size_t irep_len, irep_capa; mrb_sym init_sym; struct RObject *top_self; - struct RClass *object_class; + struct RClass *object_class; /* Object class */ struct RClass *class_class; struct RClass *module_class; struct RClass *proc_class; @@ -125,17 +125,17 @@ typedef struct mrb_state { struct RClass *symbol_class; struct RClass *kernel_module; - struct heap_page *heaps; + struct heap_page *heaps; /* heaps for GC */ struct heap_page *sweeps; struct heap_page *free_heaps; size_t live; /* count of live objects */ - struct RBasic *arena[MRB_ARENA_SIZE]; + struct RBasic *arena[MRB_ARENA_SIZE]; /* GC protection array */ 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 */ - struct RBasic *variable_gray_list; /* list of objects to be traversed atomically */ + 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; @@ -176,12 +176,13 @@ void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); 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); -int mrb_class_defined(mrb_state *mrb, const char *name); +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); 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); -int mrb_obj_respond_to(struct RClass* c, mrb_sym mid); +mrb_bool mrb_obj_respond_to(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); @@ -239,9 +240,11 @@ mrb_sym mrb_intern(mrb_state *mrb,const char *cstr) return mrb_intern_cstr(mrb, cstr); } -void *mrb_malloc(mrb_state*, size_t); -void *mrb_calloc(mrb_state*, size_t, size_t); -void *mrb_realloc(mrb_state*, void*, size_t); +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*); @@ -261,15 +264,16 @@ 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); -int mrb_obj_eq(mrb_state*, mrb_value, mrb_value); -int mrb_obj_equal(mrb_state*, mrb_value, mrb_value); -int mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2); +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); -int mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2); +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); @@ -283,13 +287,13 @@ void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*); } while (0) void mrb_write_barrier(mrb_state *, struct RBasic*); -mrb_value mrb_check_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname, const char *method); +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, mrb_int type, const char *tname, const char *method); -int mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, 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); @@ -366,8 +370,8 @@ void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val); mrb_value mrb_block_proc(void); mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id); -int mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); -int mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); +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); /* memory pool implementation */ typedef struct mrb_pool mrb_pool; @@ -375,9 +379,16 @@ 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); -int mrb_pool_can_realloc(struct mrb_pool*, void*, size_t); +mrb_bool mrb_pool_can_realloc(struct mrb_pool*, void*, size_t); void* mrb_alloca(mrb_state *mrb, size_t); +#ifdef MRB_DEBUG +#include <assert.h> +#define mrb_assert(p) assert(p) +#else +#define mrb_assert(p) ((void)0) +#endif + #if defined(__cplusplus) } /* extern "C" { */ #endif diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 856b12099..498b58ca3 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -11,10 +11,11 @@ extern "C" { #endif +/* Program data array struct */ typedef struct mrb_irep { uint32_t idx; - uint16_t nlocals; - uint16_t nregs; + uint16_t nlocals; /* Number of local variables */ + uint16_t nregs; /* Number of register variables */ uint8_t flags; mrb_code *iseq; diff --git a/include/mruby/khash.h b/include/mruby/khash.h index db8048f5a..fb11586d2 100644 --- a/include/mruby/khash.h +++ b/include/mruby/khash.h @@ -27,12 +27,14 @@ typedef khint_t khiter_t; //extern uint8_t __m[]; /* mask for flags */ -static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; +static const uint8_t __m_empty[8] = {0x02, 0x08, 0x20, 0x80}; +static const uint8_t __m_del[8] = {0x01, 0x04, 0x10, 0x40}; +static const uint8_t __m_either[8] = {0x03, 0x0c, 0x30, 0xc0}; -#define __ac_isempty(e_flag, d_flag, i) (e_flag[(i)/8]&__m[(i)%8]) -#define __ac_isdel(e_flag, d_flag, i) (d_flag[(i)/8]&__m[(i)%8]) -#define __ac_iseither(e_flag, d_flag, i) (__ac_isempty(e_flag,d_flag,i)||__ac_isdel(e_flag,d_flag,i)) +#define __ac_isempty(ed_flag, i) (ed_flag[(i)/4]&__m_empty[(i)%4]) +#define __ac_isdel(ed_flag, i) (ed_flag[(i)/4]&__m_del[(i)%4]) +#define __ac_iseither(ed_flag, i) (ed_flag[(i)/4]&__m_either[(i)%4]) #define khash_power2(v) do { \ v--;\ v |= v >> 1;\ @@ -56,8 +58,7 @@ static const uint8_t __m[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; khint_t size; \ khint_t n_occupied; \ khint_t upper_bound; \ - uint8_t *e_flags; \ - uint8_t *d_flags; \ + uint8_t *ed_flags; \ khkey_t *keys; \ khval_t *vals; \ khint_t mask; \ @@ -96,14 +97,13 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) void kh_alloc_##name(kh_##name##_t *h) \ { \ khint_t sz = h->n_buckets; \ + uint8_t *p = mrb_malloc(h->mrb, sizeof(uint8_t)*sz/4+(sizeof(khkey_t)+sizeof(khval_t))*sz); \ h->size = h->n_occupied = 0; \ h->upper_bound = UPPER_BOUND(sz); \ - h->e_flags = (uint8_t *)mrb_malloc(h->mrb, sizeof(uint8_t)*sz/4); \ - h->d_flags = h->e_flags + sz/8; \ - kh_fill_flags(h->e_flags, 0xff, sz/8); \ - kh_fill_flags(h->d_flags, 0x00, sz/8); \ - h->keys = (khkey_t *)mrb_malloc(h->mrb, sizeof(khkey_t)*sz); \ - h->vals = (khval_t *)mrb_malloc(h->mrb, sizeof(khval_t)*sz); \ + h->keys = (khkey_t *)p; \ + h->vals = (khval_t *)(p+sizeof(khkey_t)*sz); \ + h->ed_flags = (p+sizeof(khkey_t)*sz+sizeof(khval_t)*sz); \ + kh_fill_flags(h->ed_flags, 0xaa, sz/4); \ h->mask = sz-1; \ h->inc = sz/2-1; \ } \ @@ -124,24 +124,21 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) { \ if (h) { \ mrb_free(h->mrb, h->keys); \ - mrb_free(h->mrb, h->vals); \ - mrb_free(h->mrb, h->e_flags); \ mrb_free(h->mrb, h); \ } \ } \ void kh_clear_##name(kh_##name##_t *h) \ { \ - if (h && h->e_flags) { \ - kh_fill_flags(h->e_flags, 0xff, h->n_buckets/8); \ - kh_fill_flags(h->d_flags, 0x00, h->n_buckets/8); \ + if (h && h->ed_flags) { \ + kh_fill_flags(h->ed_flags, 0xaa, h->n_buckets/4); \ h->size = h->n_occupied = 0; \ } \ } \ khint_t kh_get_##name(kh_##name##_t *h, khkey_t key) \ { \ khint_t k = __hash_func(h->mrb,key) & (h->mask); \ - while (!__ac_isempty(h->e_flags, h->d_flags, k)) { \ - if (!__ac_isdel(h->e_flags, h->d_flags, k)) { \ + while (!__ac_isempty(h->ed_flags, k)) { \ + if (!__ac_isdel(h->ed_flags, k)) { \ if (__hash_equal(h->mrb,h->keys[k], key)) return k; \ } \ k = (k+h->inc) & (h->mask); \ @@ -154,7 +151,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) new_n_buckets = KHASH_MIN_SIZE; \ khash_power2(new_n_buckets); \ { \ - uint8_t *old_e_flags = h->e_flags; \ + 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; \ @@ -163,14 +160,12 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) kh_alloc_##name(h); \ /* relocate */ \ for (i=0 ; i<old_n_buckets ; i++) { \ - if (!__ac_isempty(old_e_flags, old_d_flags, i)) { \ + if (!__ac_iseither(old_ed_flags, i)) { \ khint_t k = kh_put_##name(h, old_keys[i]); \ kh_value(h,k) = old_vals[i]; \ } \ } \ - mrb_free(h->mrb, old_e_flags); \ mrb_free(h->mrb, old_keys); \ - mrb_free(h->mrb, old_vals); \ } \ } \ khint_t kh_put_##name(kh_##name##_t *h, khkey_t key) \ @@ -180,27 +175,27 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) kh_resize_##name(h, h->n_buckets*2); \ } \ k = __hash_func(h->mrb,key) & (h->mask); \ - while (!__ac_iseither(h->e_flags, h->d_flags, k)) { \ + while (!__ac_iseither(h->ed_flags, k)) { \ if (__hash_equal(h->mrb,h->keys[k], key)) break; \ k = (k+h->inc) & (h->mask); \ } \ - if (__ac_isempty(h->e_flags, h->d_flags, k)) { \ + if (__ac_isempty(h->ed_flags, k)) { \ /* put at empty */ \ h->keys[k] = key; \ - h->e_flags[k/8] &= ~__m[k%8]; \ + h->ed_flags[k/4] &= ~__m_empty[k%4]; \ h->size++; \ h->n_occupied++; \ - } else if (__ac_isdel(h->e_flags, h->d_flags, k)) { \ + } else if (__ac_isdel(h->ed_flags, k)) { \ /* put at del */ \ h->keys[k] = key; \ - h->d_flags[k/8] &= ~__m[k%8]; \ + h->ed_flags[k/4] &= ~__m_del[k%4]; \ h->size++; \ } \ return k; \ } \ void kh_del_##name(kh_##name##_t *h, khint_t x) \ { \ - h->d_flags[x/8] |= __m[x%8]; \ + h->ed_flags[x/4] |= __m_del[x%4]; \ h->size--; \ } \ kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h) \ @@ -231,7 +226,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len) #define kh_del(name, h, k) kh_del_##name(h, k) #define kh_copy(name, mrb, h) kh_copy_##name(mrb, h) -#define kh_exist(h, x) (!__ac_iseither((h)->e_flags, (h)->d_flags, (x))) +#define kh_exist(h, x) (!__ac_iseither((h)->ed_flags, (x))) #define kh_key(h, x) ((h)->keys[x]) #define kh_val(h, x) ((h)->vals[x]) #define kh_value(h, x) ((h)->vals[x]) diff --git a/include/mruby/string.h b/include/mruby/string.h index 26d1344d8..000c80b09 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -57,7 +57,7 @@ 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_buf_append(mrb_state *mrb, mrb_value str, mrb_value str2); mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str); -int mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); +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_append(mrb_state *mrb, mrb_value str, mrb_value str2); diff --git a/include/mruby/value.h b/include/mruby/value.h index 06241ec76..e78035b5f 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -51,23 +51,29 @@ typedef short mrb_sym; #ifdef _MSC_VER -# define _ALLOW_KEYWORD_MACROS -# include <float.h> -# define inline __inline +# ifndef __cplusplus +# define inline __inline +# endif # define snprintf _snprintf -# define isnan _isnan -# define isinf(n) (!_finite(n) && !_isnan(n)) -# define strtoll _strtoi64 -# 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" +# if _MSC_VER < 1800 +# include <float.h> +# define isnan _isnan +# define isinf(n) (!_finite(n) && !_isnan(n)) +# 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" +# else +# include <inttypes.h> +# endif #else # include <inttypes.h> #endif @@ -317,6 +317,8 @@ class RakeApp "Require MODULE before executing rakefile."], ['--tasks', '-T', GetoptLong::NO_ARGUMENT, "Display the tasks and dependencies, then exit."], + ['--pull-gems','-p', GetoptLong::NO_ARGUMENT, + "Pull all git mrbgems."], ['--trace', '-t', GetoptLong::NO_ARGUMENT, "Turn on invoke/execute tracing."], ['--usage', '-h', GetoptLong::NO_ARGUMENT, @@ -401,6 +403,8 @@ class RakeApp require value when '--tasks' $show_tasks = true + when '--pull-gems' + $pull_gems = true when '--trace' $trace = true when '--usage' @@ -419,6 +423,7 @@ class RakeApp # Read and handle the command line options. def handle_options $verbose = false + $pull_gems = false opts = GetoptLong.new(*command_line_options) opts.each { |opt, value| do_option(opt, value) } end diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index 1c6732d48..33ee99be0 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -41,12 +41,18 @@ MRuby::GemBox.new do |conf| # Use Random class conf.gem :core => "mruby-random" + # Use extensional Object class + conf.gem :core => "mruby-object-ext" + # Use ObjectSpace class conf.gem :core => "mruby-objectspace" # Use Fiber class conf.gem :core => "mruby-fiber" + # Use extended toplevel object (main) methods + conf.gem :core => "mruby-toplevel-ext" + # Generate mirb command conf.gem :core => "mruby-bin-mirb" diff --git a/mrbgems/mruby-array-ext/mrbgem.rake b/mrbgems/mruby-array-ext/mrbgem.rake index 38e0ad267..18f92ad65 100644 --- a/mrbgems/mruby-array-ext/mrbgem.rake +++ b/mrbgems/mruby-array-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-array-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-bin-mirb/mrbgem.rake b/mrbgems/mruby-bin-mirb/mrbgem.rake index fd0b20254..846a3b077 100644 --- a/mrbgems/mruby-bin-mirb/mrbgem.rake +++ b/mrbgems/mruby-bin-mirb/mrbgem.rake @@ -1,5 +1,8 @@ MRuby::Gem::Specification.new('mruby-bin-mirb') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' + + spec.linker.libraries << 'readline' if spec.cc.defines.include? "ENABLE_READLINE" + spec.bins = %w(mirb) end diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 5e3e123c6..50556e092 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -15,11 +15,19 @@ #include <mruby/data.h> #include <mruby/compile.h> #ifdef ENABLE_READLINE +#include <limits.h> #include <readline/readline.h> #include <readline/history.h> #endif #include <mruby/string.h> + +#ifdef ENABLE_READLINE +static const char *history_file_name = ".mirb_history"; +char history_path[PATH_MAX]; +#endif + + static void p(mrb_state *mrb, mrb_value obj, int prompt) { @@ -38,7 +46,7 @@ p(mrb_state *mrb, mrb_value obj, int prompt) /* Guess if the user might want to enter more * or if he wants an evaluation of his code now */ -int +mrb_bool is_code_block_open(struct mrb_parser_state *parser) { int code_block_open = FALSE; @@ -236,6 +244,8 @@ main(int argc, char **argv) #ifndef ENABLE_READLINE int last_char; int char_index; +#else + char *home = NULL; #endif mrbc_context *cxt; struct mrb_parser_state *parser; @@ -268,6 +278,23 @@ main(int argc, char **argv) if (args.verbose) cxt->dump_result = 1; ai = mrb_gc_arena_save(mrb); + +#ifdef ENABLE_READLINE + using_history(); + home = getenv("HOME"); +#ifdef _WIN32 + if (!home) + home = getenv("USERPROFILE"); +#endif + if (home) { + strcpy(history_path, home); + strcat(history_path, "/"); + strcat(history_path, history_file_name); + read_history(history_path); + } +#endif + + while (TRUE) { #ifndef ENABLE_READLINE print_cmdline(code_block_open); @@ -346,7 +373,7 @@ main(int argc, char **argv) } else { /* no */ - if (!mrb_respond_to(mrb,result,mrb_intern(mrb,"inspect"))){ + if (!mrb_respond_to(mrb, result, mrb_intern2(mrb, "inspect", 7))){ result = mrb_any_to_s(mrb,result); } p(mrb, result, 1); @@ -361,5 +388,9 @@ main(int argc, char **argv) mrbc_context_free(mrb, cxt); mrb_close(mrb); +#ifdef ENABLE_READLINE + write_history(history_path); +#endif + return 0; } diff --git a/mrbgems/mruby-bin-mruby/mrbgem.rake b/mrbgems/mruby-bin-mruby/mrbgem.rake index 2e173a291..08ba89855 100644 --- a/mrbgems/mruby-bin-mruby/mrbgem.rake +++ b/mrbgems/mruby-bin-mruby/mrbgem.rake @@ -1,5 +1,5 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' spec.bins = %w(mruby) end diff --git a/mrbgems/mruby-enum-ext/mrbgem.rake b/mrbgems/mruby-enum-ext/mrbgem.rake index 758d298dc..e054f4318 100644 --- a/mrbgems/mruby-enum-ext/mrbgem.rake +++ b/mrbgems/mruby-enum-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-enum-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-eval/mrbgem.rake b/mrbgems/mruby-eval/mrbgem.rake index f80cf1b9e..217a9e604 100644 --- a/mrbgems/mruby-eval/mrbgem.rake +++ b/mrbgems/mruby-eval/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-eval') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-fiber/mrbgem.rake b/mrbgems/mruby-fiber/mrbgem.rake index cb258adcb..25009c47f 100644 --- a/mrbgems/mruby-fiber/mrbgem.rake +++ b/mrbgems/mruby-fiber/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-fiber') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-hash-ext/mrbgem.rake b/mrbgems/mruby-hash-ext/mrbgem.rake index 3163c8c88..25d4f8e61 100644 --- a/mrbgems/mruby-hash-ext/mrbgem.rake +++ b/mrbgems/mruby-hash-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-hash-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-math/mrbgem.rake b/mrbgems/mruby-math/mrbgem.rake index 4b0fa40fd..75d3d1fff 100644 --- a/mrbgems/mruby-math/mrbgem.rake +++ b/mrbgems/mruby-math/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-math') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-math/src/math.c b/mrbgems/mruby-math/src/math.c index bf3c007b4..bdc7767f7 100644 --- a/mrbgems/mruby-math/src/math.c +++ b/mrbgems/mruby-math/src/math.c @@ -12,8 +12,8 @@ #define domain_error(msg) \ mrb_raise(mrb, E_RANGE_ERROR, "Numerical argument is out of domain - " #msg) -/* math functions not provided under Microsoft Visual C++ */ -#ifdef _MSC_VER +/* math functions not provided by Microsoft Visual C++ 2012 or older */ +#if defined _MSC_VER && _MSC_VER < 1800 #define MATH_TOLERANCE 1E-12 @@ -87,6 +87,12 @@ erfc(double x) return one_sqrtpi*exp(-x*x)*q2; } +double +log2(double x) +{ + return log10(x)/log10(2.0); +} + #endif /* @@ -358,18 +364,6 @@ math_atanh(mrb_state *mrb, mrb_value obj) # define log10(x) ((x) < 0.0 ? nan("") : log10(x)) #endif -#ifndef log2 -#ifndef HAVE_LOG2 -double -log2(double x) -{ - return log10(x)/log10(2.0); -} -#else -extern double log2(double); -#endif -#endif - /* * call-seq: * Math.exp(x) -> float diff --git a/mrbgems/mruby-numeric-ext/mrbgem.rake b/mrbgems/mruby-numeric-ext/mrbgem.rake index 69c4fde4c..010804058 100644 --- a/mrbgems/mruby-numeric-ext/mrbgem.rake +++ b/mrbgems/mruby-numeric-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-numeric-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-object-ext/mrbgem.rake b/mrbgems/mruby-object-ext/mrbgem.rake new file mode 100644 index 000000000..980f1667a --- /dev/null +++ b/mrbgems/mruby-object-ext/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-object-ext') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' +end diff --git a/mrbgems/mruby-object-ext/src/object.c b/mrbgems/mruby-object-ext/src/object.c new file mode 100644 index 000000000..598ebe91d --- /dev/null +++ b/mrbgems/mruby-object-ext/src/object.c @@ -0,0 +1,108 @@ +#include "mruby.h" +#include "mruby/array.h" +#include "mruby/class.h" + +/* + * call-seq: + * nil.to_a -> [] + * + * Always returns an empty array. + */ + +static mrb_value +nil_to_a(mrb_state *mrb, mrb_value obj) +{ + return mrb_ary_new(mrb); +} + +/* + * call-seq: + * nil.to_f -> 0.0 + * + * Always returns zero. + */ + +static mrb_value +nil_to_f(mrb_state *mrb, mrb_value obj) +{ + return mrb_float_value(mrb, 0.0); +} + +/* + * call-seq: + * nil.to_i -> 0 + * + * Always returns zero. + */ + +static mrb_value +nil_to_i(mrb_state *mrb, mrb_value obj) +{ + return mrb_fixnum_value(0); +} + +/* + * call-seq: + * obj.instance_exec(arg...) {|var...| block } -> obj + * + * Executes the given block within the context of the receiver + * (_obj_). In order to set the context, the variable +self+ is set + * to _obj_ while the code is executing, giving the code access to + * _obj_'s instance variables. Arguments are passed as block parameters. + * + * class KlassWithSecret + * def initialize + * @secret = 99 + * end + * end + * k = KlassWithSecret.new + * k.instance_exec(5) {|x| @secret+x } #=> 104 + */ + +mrb_value +mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c); + +static mrb_value +mrb_obj_instance_exec(mrb_state *mrb, mrb_value self) +{ + mrb_value *argv; + int argc; + mrb_value blk; + struct RClass *c; + + mrb_get_args(mrb, "*&", &argv, &argc, &blk); + + if (mrb_nil_p(blk)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); + } + + switch (mrb_type(self)) { + case MRB_TT_SYMBOL: + case MRB_TT_FIXNUM: + case MRB_TT_FLOAT: + c = 0; + break; + default: + c = mrb_class_ptr(mrb_singleton_class(mrb, self)); + break; + } + + return mrb_yield_internal(mrb, blk, argc, argv, self, c); +} + +void +mrb_mruby_object_ext_gem_init(mrb_state* mrb) +{ + struct RClass * n = mrb->nil_class; + + mrb_define_method(mrb, n, "to_a", nil_to_a, MRB_ARGS_NONE()); + mrb_define_method(mrb, n, "to_f", nil_to_f, MRB_ARGS_NONE()); + mrb_define_method(mrb, n, "to_i", nil_to_i, MRB_ARGS_NONE()); + + mrb_define_method(mrb, mrb->object_class, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK()); +} + +void +mrb_mruby_object_ext_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-object-ext/test/nil.rb b/mrbgems/mruby-object-ext/test/nil.rb new file mode 100644 index 000000000..e385dec6a --- /dev/null +++ b/mrbgems/mruby-object-ext/test/nil.rb @@ -0,0 +1,11 @@ +assert('NilClass#to_a') do + assert_equal nil.to_a, [] +end + +assert('NilClass#to_f') do + assert_equal nil.to_f, 0.0 +end + +assert('NilClass#to_i') do + assert_equal nil.to_i, 0 +end diff --git a/mrbgems/mruby-object-ext/test/object.rb b/mrbgems/mruby-object-ext/test/object.rb new file mode 100644 index 000000000..1a75622f6 --- /dev/null +++ b/mrbgems/mruby-object-ext/test/object.rb @@ -0,0 +1,9 @@ +assert('Object#instance_exec') do + class KlassWithSecret + def initialize + @secret = 99 + end + end + k = KlassWithSecret.new + assert_equal k.instance_exec(5) {|x| @secret+x }, 104 +end diff --git a/mrbgems/mruby-objectspace/mrbgem.rake b/mrbgems/mruby-objectspace/mrbgem.rake index 100df4cdc..6a6a3e778 100644 --- a/mrbgems/mruby-objectspace/mrbgem.rake +++ b/mrbgems/mruby-objectspace/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-objectspace') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-print/mrbgem.rake b/mrbgems/mruby-print/mrbgem.rake index dc7831280..768fc2e18 100644 --- a/mrbgems/mruby-print/mrbgem.rake +++ b/mrbgems/mruby-print/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-print') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-proc-ext/mrbgem.rake b/mrbgems/mruby-proc-ext/mrbgem.rake index 7f979431d..b75fceda3 100644 --- a/mrbgems/mruby-proc-ext/mrbgem.rake +++ b/mrbgems/mruby-proc-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-proc-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-random/mrbgem.rake b/mrbgems/mruby-random/mrbgem.rake index 38e93e4b1..7ad3c855c 100644 --- a/mrbgems/mruby-random/mrbgem.rake +++ b/mrbgems/mruby-random/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-random') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 13b4fa7a3..1c89ca21d 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -11,12 +11,17 @@ #include <time.h> -#define GLOBAL_RAND_SEED_KEY "$mrb_g_rand_seed" -#define INSTANCE_RAND_SEED_KEY "$mrb_i_rand_seed" -#define MT_STATE_KEY "$mrb_i_mt_state" +#define GLOBAL_RAND_SEED_KEY "$mrb_g_rand_seed" +#define GLOBAL_RAND_SEED_KEY_CSTR_LEN 16 + +#define INSTANCE_RAND_SEED_KEY "$mrb_i_rand_seed" +#define INSTANCE_RAND_SEED_KEY_CSTR_LEN 16 + +#define MT_STATE_KEY "$mrb_i_mt_state" +#define MT_STATE_KEY_CSTR_LEN 15 static const struct mrb_data_type mt_state_type = { - MT_STATE_KEY, mrb_free, + MT_STATE_KEY, mrb_free, }; static mt_state *mrb_mt_get_context(mrb_state *mrb, mrb_value self) @@ -24,7 +29,7 @@ static mt_state *mrb_mt_get_context(mrb_state *mrb, mrb_value self) mt_state *t; mrb_value context; - context = mrb_iv_get(mrb, self, mrb_intern(mrb, MT_STATE_KEY)); + context = mrb_iv_get(mrb, self, mrb_intern2(mrb, MT_STATE_KEY, MT_STATE_KEY_CSTR_LEN)); t = (mt_state*)mrb_data_get_ptr(mrb, context, &mt_state_type); if (!t) mrb_raise(mrb, E_RUNTIME_ERROR, "mt_state get from mrb_iv_get failed"); @@ -141,7 +146,7 @@ static mrb_value mrb_random_g_rand(mrb_state *mrb, mrb_value self) mrb_value seed; max = get_opt(mrb); - seed = mrb_gv_get(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY)); + seed = mrb_gv_get(mrb, mrb_intern2(mrb, GLOBAL_RAND_SEED_KEY, GLOBAL_RAND_SEED_KEY_CSTR_LEN)); if (mrb_nil_p(seed)) { mrb_random_mt_g_srand(mrb, mrb_nil_value()); } @@ -155,8 +160,8 @@ static mrb_value mrb_random_g_srand(mrb_state *mrb, mrb_value self) seed = get_opt(mrb); seed = mrb_random_mt_g_srand(mrb, seed); - old_seed = mrb_gv_get(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY)); - mrb_gv_set(mrb, mrb_intern(mrb, GLOBAL_RAND_SEED_KEY), seed); + old_seed = mrb_gv_get(mrb, mrb_intern2(mrb, GLOBAL_RAND_SEED_KEY, GLOBAL_RAND_SEED_KEY_CSTR_LEN)); + mrb_gv_set(mrb, mrb_intern2(mrb, GLOBAL_RAND_SEED_KEY, GLOBAL_RAND_SEED_KEY_CSTR_LEN), seed); return old_seed; } @@ -170,8 +175,8 @@ static mrb_value mrb_random_init(mrb_state *mrb, mrb_value self) seed = get_opt(mrb); seed = mrb_random_mt_srand(mrb, t, seed); - mrb_iv_set(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY), seed); - mrb_iv_set(mrb, self, mrb_intern(mrb, MT_STATE_KEY), + mrb_iv_set(mrb, self, mrb_intern2(mrb, INSTANCE_RAND_SEED_KEY, INSTANCE_RAND_SEED_KEY_CSTR_LEN), seed); + mrb_iv_set(mrb, self, mrb_intern2(mrb, MT_STATE_KEY, MT_STATE_KEY_CSTR_LEN), mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &mt_state_type, (void*) t))); return self; } @@ -183,7 +188,7 @@ static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self) mt_state *t = mrb_mt_get_context(mrb, self); max = get_opt(mrb); - seed = mrb_iv_get(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY)); + seed = mrb_iv_get(mrb, self, mrb_intern2(mrb, INSTANCE_RAND_SEED_KEY, INSTANCE_RAND_SEED_KEY_CSTR_LEN)); if (mrb_nil_p(seed)) { mrb_random_mt_srand(mrb, t, mrb_nil_value()); } @@ -198,8 +203,8 @@ static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self) seed = get_opt(mrb); seed = mrb_random_mt_srand(mrb, t, seed); - old_seed = mrb_iv_get(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY)); - mrb_iv_set(mrb, self, mrb_intern(mrb, INSTANCE_RAND_SEED_KEY), seed); + old_seed = mrb_iv_get(mrb, self, mrb_intern2(mrb, INSTANCE_RAND_SEED_KEY, INSTANCE_RAND_SEED_KEY_CSTR_LEN)); + mrb_iv_set(mrb, self, mrb_intern2(mrb, INSTANCE_RAND_SEED_KEY, INSTANCE_RAND_SEED_KEY_CSTR_LEN), seed); return old_seed; } diff --git a/mrbgems/mruby-range-ext/mrbgem.rake b/mrbgems/mruby-range-ext/mrbgem.rake index 5ed521a44..a7970aa51 100644 --- a/mrbgems/mruby-range-ext/mrbgem.rake +++ b/mrbgems/mruby-range-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-range-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c index 377677ffb..4e17dac8c 100644 --- a/mrbgems/mruby-range-ext/src/range.c +++ b/mrbgems/mruby-range-ext/src/range.c @@ -1,7 +1,7 @@ #include "mruby.h" #include "mruby/range.h" -static int +static mrb_bool r_le(mrb_state *mrb, mrb_value a, mrb_value b) { mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ @@ -15,7 +15,7 @@ r_le(mrb_state *mrb, mrb_value a, mrb_value b) return FALSE; } -static int +static mrb_bool r_lt(mrb_state *mrb, mrb_value a, mrb_value b) { mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); diff --git a/mrbgems/mruby-sprintf/mrbgem.rake b/mrbgems/mruby-sprintf/mrbgem.rake index 8772a5174..3e15ee7a9 100644 --- a/mrbgems/mruby-sprintf/mrbgem.rake +++ b/mrbgems/mruby-sprintf/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-sprintf') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 55698d09f..6479b19bc 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -15,10 +15,6 @@ #include <math.h> #include <ctype.h> -#ifdef _MSC_VER -#include <float.h> -#endif - #ifdef HAVE_IEEEFP_H #include <ieeefp.h> #endif diff --git a/mrbgems/mruby-string-ext/mrbgem.rake b/mrbgems/mruby-string-ext/mrbgem.rake index 83db97eb4..4a3369998 100644 --- a/mrbgems/mruby-string-ext/mrbgem.rake +++ b/mrbgems/mruby-string-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-string-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-struct/mrbgem.rake b/mrbgems/mruby-struct/mrbgem.rake index 476e990da..3e9eab8d7 100644 --- a/mrbgems/mruby-struct/mrbgem.rake +++ b/mrbgems/mruby-struct/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-struct') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index a2731ca54..a8511fc3c 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -43,7 +43,7 @@ struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id) mrb_value mrb_struct_iv_get(mrb_state *mrb, mrb_value c, const char *name) { - return struct_ivar_get(mrb, c, mrb_intern(mrb, name)); + return struct_ivar_get(mrb, c, mrb_intern_cstr(mrb, name)); } mrb_value @@ -185,8 +185,7 @@ static mrb_value mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) { const char *name; - int i; - size_t len; + size_t i, len; mrb_sym mid; mrb_value members, slot, *ptr, *ptr_members; diff --git a/mrbgems/mruby-symbol-ext/mrbgem.rake b/mrbgems/mruby-symbol-ext/mrbgem.rake index 8e40c743b..6294e7a46 100644 --- a/mrbgems/mruby-symbol-ext/mrbgem.rake +++ b/mrbgems/mruby-symbol-ext/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-symbol-ext') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-time/mrbgem.rake b/mrbgems/mruby-time/mrbgem.rake index 0f0b4899d..edf2aa3fc 100644 --- a/mrbgems/mruby-time/mrbgem.rake +++ b/mrbgems/mruby-time/mrbgem.rake @@ -1,4 +1,4 @@ MRuby::Gem::Specification.new('mruby-time') do |spec| spec.license = 'MIT' - spec.authors = 'mruby developers' + spec.author = 'mruby developers' end diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 2a2aabe72..8b797f047 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -105,7 +105,7 @@ static const char *mon_names[] = { }; static const char *wday_names[] = { - "Sun", "Mon", "Tus", "Wed", "Thu", "Fri", "Sat", + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", }; struct mrb_time { diff --git a/mrbgems/mruby-toplevel-ext/mrbgem.rake b/mrbgems/mruby-toplevel-ext/mrbgem.rake new file mode 100644 index 000000000..78eb73a26 --- /dev/null +++ b/mrbgems/mruby-toplevel-ext/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-toplevel-ext') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' +end diff --git a/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb b/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb new file mode 100644 index 000000000..774562398 --- /dev/null +++ b/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb @@ -0,0 +1,11 @@ + +def self.include (*modules) + self.class.include(*modules) +end + +def self.private(*methods) +end +def self.protected(*methods) +end +def self.public(*methods) +end diff --git a/mrbgems/mruby-toplevel-ext/test/toplevel.rb b/mrbgems/mruby-toplevel-ext/test/toplevel.rb new file mode 100644 index 000000000..4401beba1 --- /dev/null +++ b/mrbgems/mruby-toplevel-ext/test/toplevel.rb @@ -0,0 +1,24 @@ +## +# Toplevel Self(Ext) Test + +module ToplevelTestModule1 + def method_foo + :foo + end + + CONST_BAR = :bar +end + +module ToplevelTestModule2 + CONST_BAR = :bar2 +end + +assert('Toplevel#include') do + self.include ToplevelTestModule2, ToplevelTestModule1 + + assert_true self.class.included_modules.include?( ToplevelTestModule1 ) + assert_true self.class.included_modules.include?( ToplevelTestModule2 ) + assert_equal :foo, method_foo + assert_equal :bar2, CONST_BAR +end + diff --git a/mrblib/class.rb b/mrblib/class.rb index 4f268b6c8..6d624ee83 100644 --- a/mrblib/class.rb +++ b/mrblib/class.rb @@ -1,18 +1,24 @@ class Module # 15.2.2.4.13 def attr_reader(*names) - names.each{|name| - name2 = ('@'+name.to_s).intern - define_method(name){self.instance_variable_get(name2)} - } + names.each do |name| + name = name.to_s + raise(NameError, "#{name.inspect} is not allowed as an instance variable name") if name.include?('@') || name.include?('?') || name.include?('$') + + attr_name = '@'+name + define_method(name){self.instance_variable_get(attr_name)} + end end # 15.2.2.4.14 def attr_writer(*names) - names.each{|name| - name2 = ('@'+name.to_s).intern - name = (name.to_s+"=").intern - define_method(name){|v|self.instance_variable_set(name2,v)} - } + names.each do |name| + name = name.to_s + raise(NameError, "#{name.inspect} is not allowed as an instance variable name") if name.include?('@') || name.include?('?') || name.include?('$') + + attr_name = '@'+name + name = (name+"=").intern + define_method(name){|v|self.instance_variable_set(attr_name,v)} + end end # 15.2.2.4.12 def attr_accessor(*names) diff --git a/mrblib/string.rb b/mrblib/string.rb index 131d30446..49f87be8b 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -133,6 +133,18 @@ class String a = self[pos+1..-1] self.replace([b, value, a].join('')) end + + ## + # ISO 15.2.10.5.5 + def =~(re) + re =~ self + end + + ## + # ISO 15.2.10.5.27 + def match(re, &block) + re.match(self, &block) + end end ## diff --git a/src/array.c b/src/array.c index a4a09ec0a..ceda884c0 100644 --- a/src/array.c +++ b/src/array.c @@ -19,7 +19,7 @@ #define ARY_DEFAULT_LEN 4 #define ARY_SHRINK_RATIO 5 /* must be larger than 2 */ #define ARY_C_MAX_SIZE (SIZE_MAX / sizeof(mrb_value)) -#define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX) +#define ARY_MAX_SIZE ((ARY_C_MAX_SIZE < (size_t)MRB_INT_MAX) ? (mrb_int)ARY_C_MAX_SIZE : MRB_INT_MAX-1) static inline mrb_value ary_elt(mrb_value ary, mrb_int offset) @@ -40,7 +40,7 @@ ary_new_capa(mrb_state *mrb, mrb_int capa) if (capa > ARY_MAX_SIZE) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } - blen = capa * sizeof(mrb_value) ; + blen = capa * sizeof(mrb_value); if (blen < capa) { mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } @@ -926,7 +926,8 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) } if (mrb_array_p(RARRAY_PTR(ary)[i])) { s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list); - } else { + } + else { s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]); } mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s)); @@ -1056,39 +1057,26 @@ static mrb_value mrb_ary_equal(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; - mrb_bool equal_p; + mrb_int i; mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) { - equal_p = 1; - } - else if (mrb_special_const_p(ary2)) { - equal_p = 0; - } - else if (!mrb_array_p(ary2)) { + if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); + if (mrb_special_const_p(ary2)) return mrb_false_value(); + if (!mrb_array_p(ary2)) { if (!mrb_respond_to(mrb, ary2, mrb_intern2(mrb, "to_ary", 6))) { - equal_p = 0; + return mrb_false_value(); } else { - equal_p = mrb_equal(mrb, ary2, ary1); + return mrb_bool_value(mrb_equal(mrb, ary2, ary1)); } } - else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { - equal_p = 0; - } - else { - mrb_int i; - - equal_p = 1; - for (i=0; i<RARRAY_LEN(ary1); i++) { - if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { - equal_p = 0; - break; - } + if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); + for (i=0; i<RARRAY_LEN(ary1); i++) { + if (!mrb_equal(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { + return mrb_false_value(); } } - - return mrb_bool_value(equal_p); + return mrb_true_value(); } /* 15.2.12.5.34 (x) */ @@ -1104,30 +1092,18 @@ static mrb_value mrb_ary_eql(mrb_state *mrb, mrb_value ary1) { mrb_value ary2; - mrb_bool eql_p; + mrb_int i; mrb_get_args(mrb, "o", &ary2); - if (mrb_obj_equal(mrb, ary1, ary2)) { - eql_p = 1; - } - else if (!mrb_array_p(ary2)) { - eql_p = 0; - } - else if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) { - eql_p = 0; - } - else { - mrb_int i; - eql_p = 1; - for (i=0; i<RARRAY_LEN(ary1); i++) { - if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { - eql_p = 0; - break; - } + if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value(); + if (!mrb_array_p(ary2)) return mrb_false_value(); + if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return mrb_false_value(); + for (i=0; i<RARRAY_LEN(ary1); i++) { + if (!mrb_eql(mrb, ary_elt(ary1, i), ary_elt(ary2, i))) { + return mrb_false_value(); } } - - return mrb_bool_value(eql_p); + return mrb_true_value(); } void diff --git a/src/backtrace.c b/src/backtrace.c index d5d0818ae..e05ad4326 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -18,7 +18,7 @@ mrb_print_backtrace(mrb_state *mrb) int i, line; fputs("trace:\n", stderr); - ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx"))); + ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5))); if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ @@ -41,7 +41,7 @@ mrb_print_backtrace(mrb_state *mrb) pc = mrb->c->cibase[i+1].pc; } else { - pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc"))); + pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6))); } if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { line = irep->lines[pc - irep->iseq - 1]; diff --git a/src/class.c b/src/class.c index 5fd3a4006..d67a4af3e 100644 --- a/src/class.c +++ b/src/class.c @@ -55,7 +55,7 @@ mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name) mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name)); } - + #define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c)) static void @@ -78,6 +78,8 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o) } else if (o->tt == MRB_TT_SCLASS) { c = (struct RClass*)o; + while (c->super->tt == MRB_TT_ICLASS) + c = c->super; make_metaclass(mrb, c->super); sc->super = c->super->c; } @@ -105,7 +107,7 @@ mrb_define_module_id(mrb_state *mrb, mrb_sym name) struct RClass* mrb_define_module(mrb_state *mrb, const char *name) { - return mrb_define_module_id(mrb, mrb_intern(mrb, name)); + return mrb_define_module_id(mrb, mrb_intern_cstr(mrb, name)); } static void @@ -159,9 +161,7 @@ mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super) struct RClass* mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super) { - struct RClass *c; - c = mrb_define_class_id(mrb, mrb_intern(mrb, name), super); - return c; + return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super); } struct RClass* @@ -203,7 +203,7 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id return c; } -int +mrb_bool mrb_class_defined(mrb_state *mrb, const char *name) { mrb_value sym = mrb_check_intern_cstr(mrb, name); @@ -227,7 +227,13 @@ class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id) struct RClass * mrb_class_get(mrb_state *mrb, const char *name) { - return class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name)); + return mrb_class_get_under(mrb, mrb->object_class, name); +} + +struct RClass * +mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name) +{ + return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name)); } /*! @@ -250,7 +256,7 @@ struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super) { struct RClass * c; - mrb_sym id = mrb_intern(mrb, name); + mrb_sym id = mrb_intern_cstr(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { c = class_from_sym(mrb, outer, id); @@ -272,7 +278,7 @@ struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name) { struct RClass * c; - mrb_sym id = mrb_intern(mrb, name); + mrb_sym id = mrb_intern_cstr(mrb, name); if (mrb_const_defined_at(mrb, outer, id)) { c = class_from_sym(mrb, outer, id); @@ -313,7 +319,7 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f void mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, mrb_aspec aspec) { - mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec); + mrb_define_method_id(mrb, c, mrb_intern_cstr(mrb, name), func, aspec); } void @@ -371,20 +377,22 @@ to_hash(mrb_state *mrb, mrb_value val) format specifiers: - o: Object [mrb_value] - S: String [mrb_value] - A: Array [mrb_value] - H: Hash [mrb_value] - s: String [char*,int] - z: String [char*] - a: Array [mrb_value*,mrb_int] - f: Float [mrb_float] - i: Integer [mrb_int] - b: Boolean [mrb_bool] - n: Symbol [mrb_sym] - &: Block [mrb_value] - *: rest argument [mrb_value*,int] - |: optional + string mruby type C type note + ---------------------------------------------------------------------------------------------- + o: Object [mrb_value] + S: String [mrb_value] + A: Array [mrb_value] + H: Hash [mrb_value] + s: String [char*,int] Receive two arguments. + z: String [char*] NUL terminated string. + a: Array [mrb_value*,mrb_int] Receive two arguments. + f: Float [mrb_float] + i: Integer [mrb_int] + b: Boolean [mrb_bool] + n: Symbol [mrb_sym] + &: Block [mrb_value] + *: rest argument [mrb_value*,int] Receive the rest of the arguments as an array. + |: optional Next argument of '|' and later are optional. */ int mrb_get_args(mrb_state *mrb, const char *format, ...) @@ -487,7 +495,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) if (i < argc) { ss = to_str(mrb, *sp++); s = mrb_str_ptr(ss); - if (strlen(s->ptr) != s->len) { + if (strlen(s->ptr) < s->len) { mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL"); } *ps = s->ptr; @@ -903,6 +911,12 @@ mrb_mod_module_eval(mrb_state *mrb, mrb_value mod) } mrb_value +mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod) +{ + return mod; +} + +mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value v) { struct RBasic *obj; @@ -933,7 +947,7 @@ void mrb_define_singleton_method(mrb_state *mrb, struct RObject *o, const char *name, mrb_func_t func, mrb_aspec aspec) { prepare_singleton_class(mrb, (struct RBasic*)o); - mrb_define_method_id(mrb, o->c, mrb_intern(mrb, name), func, aspec); + mrb_define_method_id(mrb, o->c, mrb_intern_cstr(mrb, name), func, aspec); } void @@ -1069,6 +1083,7 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv) super = mrb_obj_value(mrb->object_class); } new_class = mrb_class_new(mrb, mrb_class_ptr(super)); + mrb_funcall(mrb, super, "inherited", 1, mrb_obj_value(new_class)); return mrb_obj_value(new_class); } @@ -1134,16 +1149,14 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) static mrb_value mrb_bob_missing(mrb_state *mrb, mrb_value mod) { - mrb_value name, *a; + mrb_sym name; + mrb_value *a; int alen; mrb_value inspect; - mrb_get_args(mrb, "o*", &name, &a, &alen); - if (!mrb_symbol_p(name)) { - mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol"); - } + mrb_get_args(mrb, "n*", &name, &a, &alen); - if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){ + if (mrb_respond_to(mrb,mod,mrb_intern2(mrb, "inspect",7))){ inspect = mrb_funcall(mrb, mod, "inspect", 0); if (RSTRING_LEN(inspect) > 64) { inspect = mrb_any_to_s(mrb, mod); @@ -1154,12 +1167,12 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) } mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S", - mrb_sym2str(mrb, mrb_symbol(name)), inspect); + mrb_sym2str(mrb, name), inspect); /* not reached */ return mrb_nil_value(); } -int +mrb_bool mrb_obj_respond_to(struct RClass* c, mrb_sym mid) { khiter_t k; @@ -1183,7 +1196,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid) return FALSE; /* no method */ } -int +mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid) { return mrb_obj_respond_to(mrb_class(mrb, obj), mid); @@ -1338,7 +1351,7 @@ mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b) void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2) { - mrb_alias_method(mrb, klass, mrb_intern(mrb, name1), mrb_intern(mrb, name2)); + mrb_alias_method(mrb, klass, mrb_intern_cstr(mrb, name1), mrb_intern_cstr(mrb, name2)); } /* @@ -1410,10 +1423,10 @@ mrb_value mrb_mod_alias(mrb_state *mrb, mrb_value mod) { struct RClass *c = mrb_class_ptr(mod); - mrb_value new_value, old_value; + mrb_sym new_name, old_name; - mrb_get_args(mrb, "oo", &new_value, &old_value); - mrb_alias_method(mrb, c, mrb_symbol(new_value), mrb_symbol(old_value)); + mrb_get_args(mrb, "nn", &new_name, &old_name); + mrb_alias_method(mrb, c, new_name, old_name); return mrb_nil_value(); } @@ -1424,7 +1437,8 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) if (!mrb_obj_respond_to(c, a)) { mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c)); - } else { + } + else { MRB_SET_VALUE(m, MRB_TT_PROC, value.p, 0); mrb_define_method_vm(mrb, c, a, m); } @@ -1433,7 +1447,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) void mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) { - undef_method(mrb, c, mrb_intern(mrb, name)); + undef_method(mrb, c, mrb_intern_cstr(mrb, name)); } void @@ -1506,7 +1520,8 @@ get_sym_or_str_arg(mrb_state *mrb) if (mrb_symbol_p(sym_or_str) || mrb_string_p(sym_or_str)) { return sym_or_str; - } else { + } + else { mrb_value obj = mrb_funcall(mrb, sym_or_str, "inspect", 0); mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj); return mrb_nil_value(); @@ -1538,7 +1553,8 @@ mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) if (mrb_symbol_p(id)) { check_cv_name_sym(mrb, mrb_symbol(id)); defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(id)); - } else { + } + else { mrb_value sym; check_cv_name_str(mrb, id); sym = mrb_check_intern_str(mrb, id); @@ -1690,7 +1706,8 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) id = get_sym_or_str_arg(mrb); if (mrb_symbol_p(id)) { method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id)); - } else { + } + else { mrb_value sym = mrb_check_intern_str(mrb, id); if (mrb_nil_p(sym)) { method_defined_p = FALSE; @@ -1774,7 +1791,8 @@ mrb_mod_const_defined(mrb_state *mrb, mrb_value mod) if (mrb_type(id) == MRB_TT_SYMBOL) { check_const_name_sym(mrb, mrb_symbol(id)); const_defined_p = mrb_const_defined(mrb, mod, mrb_symbol(id)); - } else { + } + else { mrb_value sym; check_const_name_str(mrb, id); sym = mrb_check_intern_str(mrb, id); @@ -1874,10 +1892,10 @@ mrb_init_class(mrb_state *mrb) mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls)); /* name each classes */ - mrb_name_class(mrb, bob, mrb_intern(mrb, "BasicObject")); - mrb_name_class(mrb, obj, mrb_intern(mrb, "Object")); /* 15.2.1 */ - mrb_name_class(mrb, mod, mrb_intern(mrb, "Module")); /* 15.2.2 */ - mrb_name_class(mrb, cls, mrb_intern(mrb, "Class")); /* 15.2.3 */ + mrb_name_class(mrb, bob, mrb_intern2(mrb, "BasicObject", 11)); /* 15.2.1 */ + mrb_name_class(mrb, obj, mrb_intern2(mrb, "Object", 6)); /* 15.2.1 */ + mrb_name_class(mrb, mod, mrb_intern2(mrb, "Module", 6)); /* 15.2.2 */ + mrb_name_class(mrb, cls, mrb_intern2(mrb, "Class", 5)); /* 15.2.3 */ MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE()); @@ -1904,6 +1922,9 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "instance_methods", mrb_mod_instance_methods, MRB_ARGS_ANY()); /* 15.2.2.4.33 */ mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */ + mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */ + mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */ + mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */ mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE()); diff --git a/src/codegen.c b/src/codegen.c index cfbbe7286..5681ce03a 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -59,7 +59,7 @@ typedef struct scope { int icapa; mrb_irep *irep; - int pcapa; + size_t pcapa; int scapa; int nlocals; @@ -426,9 +426,8 @@ push_(codegen_scope *s) static inline int new_lit(codegen_scope *s, mrb_value val) { - int i; + size_t i; - switch (mrb_type(val)) { case MRB_TT_STRING: for (i=0; i<s->irep->plen; i++) { @@ -448,7 +447,7 @@ new_lit(codegen_scope *s, mrb_value val) } break; } - + if (s->irep->plen == s->pcapa) { s->pcapa *= 2; s->irep->pool = (mrb_value *)codegen_realloc(s, s->irep->pool, sizeof(mrb_value)*s->pcapa); @@ -462,7 +461,7 @@ new_lit(codegen_scope *s, mrb_value val) static inline int new_msym(codegen_scope *s, mrb_sym sym) { - int i, len; + size_t i, len; len = s->irep->slen; if (len > 256) len = 256; @@ -481,7 +480,7 @@ new_msym(codegen_scope *s, mrb_sym sym) static inline int new_sym(codegen_scope *s, mrb_sym sym) { - int i; + size_t i; for (i=0; i<s->irep->slen; i++) { if (s->irep->syms[i] == sym) return i; @@ -684,7 +683,7 @@ scope_body(codegen_scope *s, node *tree) return idx - s->idx; } -static int +static mrb_bool nosplat(node *t) { while (t) { @@ -2065,7 +2064,7 @@ codegen(codegen_scope *s, node *tree, int val) char *p1 = (char*)tree->car; char *p2 = (char*)tree->cdr; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern(s->mrb, REGEXP_CLASS)); + int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); int off = new_lit(s, mrb_str_new(s->mrb, p1, strlen(p1))); int argc = 1; @@ -2092,7 +2091,7 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { node *n = tree->car; int ai = mrb_gc_arena_save(s->mrb); - int sym = new_sym(s, mrb_intern(s->mrb, REGEXP_CLASS)); + int sym = new_sym(s, mrb_intern2(s->mrb, REGEXP_CLASS, REGEXP_CLASS_CSTR_LEN)); int argc = 1; int off; char *p; @@ -2506,7 +2505,8 @@ codedump(mrb_state *mrb, int n) { #ifdef ENABLE_STDIO mrb_irep *irep = mrb->irep[n]; - int i, ai; + uint32_t i; + int ai; mrb_code c; if (!irep) return; @@ -2842,13 +2842,15 @@ codegen_start(mrb_state *mrb, parser_state *p) if (p->filename) { scope->filename = p->filename; } - if (setjmp(scope->jmp) != 0) { + if (setjmp(scope->jmp) == 0) { + // prepare irep + codegen(scope, p->tree, NOVAL); + mrb_pool_close(scope->mpool); + return 0; + } + else { return -1; } - // prepare irep - codegen(scope, p->tree, NOVAL); - mrb_pool_close(scope->mpool); - return 0; } int @@ -6,7 +6,7 @@ #include <limits.h> #include <stdint.h> -#include <sys/types.h> +#include <stddef.h> // Calculate CRC (CRC-16-CCITT) // diff --git a/src/dump.c b/src/dump.c index c2b987bc8..72ca9e0c3 100644 --- a/src/dump.c +++ b/src/dump.c @@ -334,8 +334,7 @@ static int write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) { uint8_t *cur = bin; - size_t filename_len = 0; - int iseq_no; + size_t filename_len = 0, iseq_no; cur += sizeof(uint32_t); /* record size */ @@ -365,13 +364,13 @@ write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) } static int -mrb_write_section_lineno(mrb_state *mrb, int start_index, uint8_t *bin) +mrb_write_section_lineno(mrb_state *mrb, size_t start_index, uint8_t *bin) { - int irep_no; + size_t irep_no; uint32_t section_size = 0, rlen = 0; /* size of irep record */ uint8_t *cur = bin; - if (mrb == NULL || start_index < 0 || start_index >= mrb->irep_len || bin == NULL) { + if (mrb == NULL || start_index >= mrb->irep_len || bin == NULL) { return MRB_DUMP_INVALID_ARGUMENT; } diff --git a/src/error.c b/src/error.c index bd3afd2e1..df4bbc866 100644 --- a/src/error.c +++ b/src/error.c @@ -5,7 +5,6 @@ */ #include <errno.h> -#include <setjmp.h> #include <stdarg.h> #include <stdlib.h> #include <string.h> @@ -147,7 +146,8 @@ exc_inspect(mrb_state *mrb, mrb_value exc) if (!mrb_nil_p(mesg) && RSTRING_LEN(mesg) > 0) { mrb_str_cat(mrb, str, ": ", 2); mrb_str_append(mrb, str, mesg); - } else { + } + else { mrb_str_cat(mrb, str, ": ", 2); mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); } @@ -218,7 +218,7 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc) mrb_p(mrb, exc); abort(); } - longjmp(*(jmp_buf*)mrb->jmp, 1); + mrb_longjmp(mrb); } void @@ -425,10 +425,12 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg) sce = mrb_class_get(mrb, "SystemCallError"); if (mesg != NULL) { mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 2, mrb_fixnum_value(no), mrb_str_new_cstr(mrb, mesg)); - } else { + } + else { mrb_funcall(mrb, mrb_obj_value(sce), "_sys_fail", 1, mrb_fixnum_value(no)); } - } else { + } + else { mrb_raise(mrb, E_RUNTIME_ERROR, mesg); } } diff --git a/src/error.h b/src/error.h index 3726cb4c4..5aa4ca374 100644 --- a/src/error.h +++ b/src/error.h @@ -14,5 +14,6 @@ mrb_value make_exception(mrb_state *mrb, int argc, mrb_value *argv, int isstr); mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv); mrb_value mrb_format(mrb_state *mrb, const char *format, ...); void mrb_exc_print(mrb_state *mrb, struct RObject *exc); +void mrb_longjmp(mrb_state *mrb); #endif /* MRUBY_ERROR_H */ @@ -11,6 +11,7 @@ # include <limits.h> #endif #include <string.h> +#include <stdlib.h> #include "mruby.h" #include "mruby/array.h" #include "mruby/class.h" @@ -37,18 +38,23 @@ * Gray - Marked, But the child objects are unmarked. * Black - Marked, the child objects are also marked. - == Two white part + == Two White Types - The white has a different part of A and B. - In sweep phase, the sweep target white is either A or B. - The sweep target white is switched just before sweep phase. - e.g. A -> B -> A -> B ... + There're two white color types in a flip-flop fassion: White-A and White-B, + which respectively represent the Current White color (the newly allocated + objects in the current GC cycle) and the Sweep Target White color (the + dead objects to be swept). - All objects are painted white when allocated. - This white is another the sweep target white. - For example, if the sweep target white is A, it's B. - So objects when allocated in sweep phase will be next sweep phase target. - Therefore, these objects will not be released accidentally in sweep phase. + A and B will be switched just at the beginning of the next GC cycle. At + that time, all the dead objects have been swept, while the newly created + objects in the current GC cycle which finally remains White are now + regarded as dead objects. Instead of traversing all the White-A objects and + paint them as White-B, just switch the meaning of White-A and White-B would + be much cheaper. + + As a result, the objects we sweep in the current GC cycle are always + left from the previous GC cycle. This allows us to sweep objects + incrementally, without the disturbance of the newly created objects. == Execution Timing @@ -60,7 +66,7 @@ For details, see the comments for each function. - = Write Barrier + == Write Barrier mruby implementer, C extension library writer must write a write barrier when writing a pointer to an object on object's field. @@ -69,6 +75,20 @@ * mrb_field_write_barrier * mrb_write_barrier + == Generational Mode + + mruby's GC offers an Generational Mode while re-using the tri-color GC + infrastructure. It will treat the Black objects as Old objects after each + sweep phase, instead of paint them to White. The key idea are still same as + the traditional generational GC: + + * Minor GC - just traverse the Young objects (Gray objects) in the mark + phase, then only sweep the newly created objects, and leave + the Old objects live. + + * Major GC - same as a full regular GC cycle. + + For details, see the comments for each function. */ @@ -137,39 +157,46 @@ gettimeofday_time(void) #endif #ifdef GC_DEBUG -#include <assert.h> -#define gc_assert(expect) assert(expect) #define DEBUG(x) (x) #else -#define gc_assert(expect) ((void)0) #define DEBUG(x) #endif #define GC_STEP_SIZE 1024 + void* -mrb_realloc(mrb_state *mrb, void *p, size_t len) +mrb_realloc_simple(mrb_state *mrb, void *p, size_t len) { void *p2; p2 = (mrb->allocf)(mrb, p, len, mrb->ud); - if (!p2 && len > 0 && mrb->heaps) { - mrb_garbage_collect(mrb); + mrb_full_gc(mrb); p2 = (mrb->allocf)(mrb, p, len, mrb->ud); } + return p2; +} + + +void* +mrb_realloc(mrb_state *mrb, void *p, size_t len) +{ + void *p2; + + p2 = mrb_realloc_simple(mrb, p, len); if (!p2 && len) { if (mrb->out_of_memory) { /* mrb_panic(mrb); */ } else { - mrb->out_of_memory = 1; + mrb->out_of_memory = TRUE; mrb_raise(mrb, E_RUNTIME_ERROR, "Out of memory"); } } else { - mrb->out_of_memory = 0; + mrb->out_of_memory = FALSE; } return p2; @@ -182,6 +209,12 @@ mrb_malloc(mrb_state *mrb, size_t len) } void* +mrb_malloc_simple(mrb_state *mrb, size_t len) +{ + return mrb_realloc_simple(mrb, 0, len); +} + +void* mrb_calloc(mrb_state *mrb, size_t nelem, size_t len) { void *p; @@ -195,7 +228,8 @@ mrb_calloc(mrb_state *mrb, size_t nelem, size_t len) if (p) { memset(p, 0, size); } - } else { + } + else { p = NULL; } @@ -295,8 +329,8 @@ add_heap(mrb_state *mrb) void mrb_init_heap(mrb_state *mrb) { - mrb->heaps = 0; - mrb->free_heaps = 0; + mrb->heaps = NULL; + mrb->free_heaps = NULL; add_heap(mrb); mrb->gc_interval_ratio = DEFAULT_GC_INTERVAL_RATIO; mrb->gc_step_ratio = DEFAULT_GC_STEP_RATIO; @@ -353,7 +387,7 @@ mrb_obj_alloc(mrb_state *mrb, enum mrb_vtype ttype, struct RClass *cls) static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; #ifdef MRB_GC_STRESS - mrb_garbage_collect(mrb); + mrb_full_gc(mrb); #endif if (mrb->gc_threshold < mrb->live) { mrb_incremental_gc(mrb); @@ -391,19 +425,29 @@ add_gray_list(mrb_state *mrb, struct RBasic *obj) } static void -mark_context(mrb_state *mrb, struct mrb_context *c) +mark_context_stack(mrb_state *mrb, struct mrb_context *c) { size_t i; size_t e; - mrb_callinfo *ci; - /* mark stack */ e = c->stack - c->stbase; if (c->ci) e += c->ci->nregs; if (c->stbase + e > c->stend) e = c->stend - c->stbase; for (i=0; i<e; i++) { mrb_gc_mark_value(mrb, c->stbase[i]); } +} + +static void +mark_context(mrb_state *mrb, struct mrb_context *c) +{ + size_t i; + size_t e; + mrb_callinfo *ci; + + /* mark stack */ + mark_context_stack(mrb, c); + /* mark ensure stack */ e = (c->ci) ? c->ci->eidx : 0; for (i=0; i<e; i++) { @@ -424,7 +468,7 @@ mark_context(mrb_state *mrb, struct mrb_context *c) static void gc_mark_children(mrb_state *mrb, struct RBasic *obj) { - gc_assert(is_gray(obj)); + mrb_assert(is_gray(obj)); paint_black(obj); mrb->gray_list = obj->gcnext; mrb_gc_mark(mrb, (struct RBasic*)obj->c); @@ -521,7 +565,7 @@ mrb_gc_mark(mrb_state *mrb, struct RBasic *obj) { if (obj == 0) return; if (!is_white(obj)) return; - gc_assert((obj)->tt != MRB_TT_FREE); + mrb_assert((obj)->tt != MRB_TT_FREE); add_gray_list(mrb, obj); } @@ -561,7 +605,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj) if (e->cioff < 0) { mrb_free(mrb, e->stack); - e->stack = 0; + e->stack = NULL; } } break; @@ -613,12 +657,11 @@ obj_free(mrb_state *mrb, struct RBasic *obj) static void root_scan_phase(mrb_state *mrb) { - int j; - size_t i, e; + size_t i, e, j; if (!is_minor_gc(mrb)) { - mrb->gray_list = 0; - mrb->variable_gray_list = 0; + mrb->gray_list = NULL; + mrb->atomic_gray_list = NULL; } mrb_gc_mark_gv(mrb); @@ -728,6 +771,18 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj) return children; } + +static void +gc_mark_gray_list(mrb_state *mrb) { + while (mrb->gray_list) { + if (is_gray(mrb->gray_list)) + gc_mark_children(mrb, mrb->gray_list); + else + mrb->gray_list = mrb->gray_list->gcnext; + } +} + + static size_t incremental_marking_phase(mrb_state *mrb, size_t limit) { @@ -743,22 +798,13 @@ incremental_marking_phase(mrb_state *mrb, size_t limit) static void final_marking_phase(mrb_state *mrb) { - while (mrb->gray_list) { - if (is_gray(mrb->gray_list)) - gc_mark_children(mrb, mrb->gray_list); - else - mrb->gray_list = mrb->gray_list->gcnext; - } - gc_assert(mrb->gray_list == NULL); - mrb->gray_list = mrb->variable_gray_list; - mrb->variable_gray_list = 0; - while (mrb->gray_list) { - if (is_gray(mrb->gray_list)) - gc_mark_children(mrb, mrb->gray_list); - else - mrb->gray_list = mrb->gray_list->gcnext; - } - gc_assert(mrb->gray_list == NULL); + mark_context_stack(mrb, mrb->root_c); + gc_mark_gray_list(mrb); + mrb_assert(mrb->gray_list == NULL); + mrb->gray_list = mrb->atomic_gray_list; + mrb->atomic_gray_list = NULL; + gc_mark_gray_list(mrb); + mrb_assert(mrb->gray_list == NULL); } static void @@ -858,17 +904,31 @@ incremental_gc(mrb_state *mrb, size_t limit) } default: /* unknown state */ - gc_assert(0); + mrb_assert(0); return 0; } } static void -advance_phase(mrb_state *mrb, enum gc_state to_state) +incremental_gc_until(mrb_state *mrb, enum gc_state to_state) { - while (mrb->gc_state != to_state) { + do { incremental_gc(mrb, ~0); + } while (mrb->gc_state != to_state); +} + +static void +incremental_gc_step(mrb_state *mrb) +{ + size_t limit = 0, result = 0; + limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio; + while (result < limit) { + result += incremental_gc(mrb, limit); + if (mrb->gc_state == GC_STATE_NONE) + break; } + + mrb->gc_threshold = mrb->live + GC_STEP_SIZE; } static void @@ -876,15 +936,15 @@ clear_all_old(mrb_state *mrb) { size_t origin_mode = mrb->is_generational_gc_mode; - gc_assert(is_generational(mrb)); + mrb_assert(is_generational(mrb)); if (is_major_gc(mrb)) { - advance_phase(mrb, GC_STATE_NONE); + incremental_gc_until(mrb, GC_STATE_NONE); } mrb->is_generational_gc_mode = FALSE; prepare_incremental_sweep(mrb); - advance_phase(mrb, GC_STATE_NONE); - mrb->variable_gray_list = mrb->gray_list = NULL; + incremental_gc_until(mrb, GC_STATE_NONE); + mrb->atomic_gray_list = mrb->gray_list = NULL; mrb->is_generational_gc_mode = origin_mode; } @@ -897,26 +957,19 @@ mrb_incremental_gc(mrb_state *mrb) GC_TIME_START; if (is_minor_gc(mrb)) { - do { - incremental_gc(mrb, ~0); - } while (mrb->gc_state != GC_STATE_NONE); + incremental_gc_until(mrb, GC_STATE_NONE); } else { - size_t limit = 0, result = 0; - limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio; - while (result < limit) { - result += incremental_gc(mrb, limit); - if (mrb->gc_state == GC_STATE_NONE) - break; - } + incremental_gc_step(mrb); } if (mrb->gc_state == GC_STATE_NONE) { - gc_assert(mrb->live >= mrb->gc_live_after_mark); + mrb_assert(mrb->live >= mrb->gc_live_after_mark); mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; if (mrb->gc_threshold < GC_STEP_SIZE) { mrb->gc_threshold = GC_STEP_SIZE; } + if (is_major_gc(mrb)) { mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; mrb->gc_full = FALSE; @@ -928,28 +981,21 @@ mrb_incremental_gc(mrb_state *mrb) } } } - else { - mrb->gc_threshold = mrb->live + GC_STEP_SIZE; - } - GC_TIME_STOP_AND_REPORT; } +/* Perform a full gc cycle */ void -mrb_garbage_collect(mrb_state *mrb) +mrb_full_gc(mrb_state *mrb) { - size_t max_limit = ~0; - if (mrb->gc_disabled) return; - GC_INVOKE_TIME_REPORT("mrb_garbage_collect()"); + GC_INVOKE_TIME_REPORT("mrb_full_gc()"); GC_TIME_START; if (mrb->gc_state == GC_STATE_SWEEP) { /* finish sweep phase */ - while (mrb->gc_state != GC_STATE_NONE) { - incremental_gc(mrb, max_limit); - } + incremental_gc_until(mrb, GC_STATE_NONE); } /* clean all black object as old */ @@ -958,10 +1004,7 @@ mrb_garbage_collect(mrb_state *mrb) mrb->gc_full = TRUE; } - do { - incremental_gc(mrb, max_limit); - } while (mrb->gc_state != GC_STATE_NONE); - + incremental_gc_until(mrb, GC_STATE_NONE); mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; if (is_generational(mrb)) { @@ -972,6 +1015,12 @@ mrb_garbage_collect(mrb_state *mrb) GC_TIME_STOP_AND_REPORT; } +void +mrb_garbage_collect(mrb_state *mrb) +{ + mrb_full_gc(mrb); +} + int mrb_gc_arena_save(mrb_state *mrb) { @@ -995,14 +1044,14 @@ mrb_field_write_barrier(mrb_state *mrb, struct RBasic *obj, struct RBasic *value if (!is_black(obj)) return; if (!is_white(value)) return; - gc_assert(!is_dead(mrb, value) && !is_dead(mrb, obj)); - gc_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_NONE); + mrb_assert(!is_dead(mrb, value) && !is_dead(mrb, obj)); + mrb_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_NONE); if (is_generational(mrb) || mrb->gc_state == GC_STATE_MARK) { add_gray_list(mrb, value); } else { - gc_assert(mrb->gc_state == GC_STATE_SWEEP); + mrb_assert(mrb->gc_state == GC_STATE_SWEEP); paint_partial_white(mrb, obj); /* for never write barriers */ } } @@ -1021,11 +1070,11 @@ mrb_write_barrier(mrb_state *mrb, struct RBasic *obj) { if (!is_black(obj)) return; - gc_assert(!is_dead(mrb, obj)); - gc_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_NONE); + mrb_assert(!is_dead(mrb, obj)); + mrb_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_NONE); paint_gray(obj); - obj->gcnext = mrb->variable_gray_list; - mrb->variable_gray_list = obj; + obj->gcnext = mrb->atomic_gray_list; + mrb->atomic_gray_list = obj; } /* @@ -1039,7 +1088,7 @@ mrb_write_barrier(mrb_state *mrb, struct RBasic *obj) static mrb_value gc_start(mrb_state *mrb, mrb_value obj) { - mrb_garbage_collect(mrb); + mrb_full_gc(mrb); return mrb_nil_value(); } @@ -1159,11 +1208,11 @@ change_gen_gc_mode(mrb_state *mrb, mrb_int enable) { if (is_generational(mrb) && !enable) { clear_all_old(mrb); - gc_assert(mrb->gc_state == GC_STATE_NONE); + mrb_assert(mrb->gc_state == GC_STATE_NONE); mrb->gc_full = FALSE; } else if (!is_generational(mrb) && enable) { - advance_phase(mrb, GC_STATE_NONE); + incremental_gc_until(mrb, GC_STATE_NONE); mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; mrb->gc_full = FALSE; } @@ -1271,7 +1320,7 @@ test_mrb_field_write_barrier(void) mrb->gc_state = GC_STATE_MARK; mrb_field_write_barrier(mrb, obj, value); - gc_assert(is_gray(value)); + mrb_assert(is_gray(value)); puts(" in GC_STATE_SWEEP"); @@ -1279,8 +1328,8 @@ test_mrb_field_write_barrier(void) mrb->gc_state = GC_STATE_SWEEP; mrb_field_write_barrier(mrb, obj, value); - gc_assert(obj->color & mrb->current_white_part); - gc_assert(value->color & mrb->current_white_part); + mrb_assert(obj->color & mrb->current_white_part); + mrb_assert(value->color & mrb->current_white_part); puts(" fail with black"); @@ -1289,7 +1338,7 @@ test_mrb_field_write_barrier(void) paint_partial_white(mrb,value); mrb_field_write_barrier(mrb, obj, value); - gc_assert(obj->color & mrb->current_white_part); + mrb_assert(obj->color & mrb->current_white_part); puts(" fail with gray"); @@ -1298,7 +1347,7 @@ test_mrb_field_write_barrier(void) paint_gray(value); mrb_field_write_barrier(mrb, obj, value); - gc_assert(is_gray(value)); + mrb_assert(is_gray(value)); { @@ -1311,7 +1360,7 @@ test_mrb_field_write_barrier(void) mrb->gc_state = GC_STATE_MARK; mrb_field_write_barrier_value(mrb, obj, value); - gc_assert(is_gray(mrb_basic_ptr(value))); + mrb_assert(is_gray(mrb_basic_ptr(value))); } mrb_close(mrb); @@ -1331,15 +1380,15 @@ test_mrb_write_barrier(void) mrb->gc_state = GC_STATE_MARK; mrb_write_barrier(mrb, obj); - gc_assert(is_gray(obj)); - gc_assert(mrb->variable_gray_list == obj); + mrb_assert(is_gray(obj)); + mrb_assert(mrb->atomic_gray_list == obj); puts(" fail with gray"); paint_gray(obj); mrb_write_barrier(mrb, obj); - gc_assert(is_gray(obj)); + mrb_assert(is_gray(obj)); mrb_close(mrb); } @@ -1352,17 +1401,17 @@ test_add_gray_list(void) puts("test_add_gray_list"); change_gen_gc_mode(mrb, FALSE); - gc_assert(mrb->gray_list == NULL); + mrb_assert(mrb->gray_list == NULL); obj1 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); add_gray_list(mrb, obj1); - gc_assert(mrb->gray_list == obj1); - gc_assert(is_gray(obj1)); + mrb_assert(mrb->gray_list == obj1); + mrb_assert(is_gray(obj1)); obj2 = mrb_basic_ptr(mrb_str_new_cstr(mrb, "test")); add_gray_list(mrb, obj2); - gc_assert(mrb->gray_list == obj2); - gc_assert(mrb->gray_list->gcnext == obj1); - gc_assert(is_gray(obj2)); + mrb_assert(mrb->gray_list == obj2); + mrb_assert(mrb->gray_list->gcnext == obj1); + mrb_assert(is_gray(obj2)); mrb_close(mrb); } @@ -1381,8 +1430,8 @@ test_gc_gray_mark(void) obj = (struct RBasic*)mrb->object_class; paint_gray(obj); gray_num = gc_gray_mark(mrb, obj); - gc_assert(is_black(obj)); - gc_assert(gray_num > 1); + mrb_assert(is_black(obj)); + mrb_assert(gray_num > 1); puts(" in MRB_TT_ARRAY"); obj_v = mrb_ary_new(mrb); @@ -1391,9 +1440,9 @@ test_gc_gray_mark(void) paint_partial_white(mrb, mrb_basic_ptr(value_v)); mrb_ary_push(mrb, obj_v, value_v); gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v)); - gc_assert(is_black(mrb_basic_ptr(obj_v))); - gc_assert(is_gray(mrb_basic_ptr(value_v))); - gc_assert(gray_num == 1); + mrb_assert(is_black(mrb_basic_ptr(obj_v))); + mrb_assert(is_gray(mrb_basic_ptr(value_v))); + mrb_assert(gray_num == 1); mrb_close(mrb); } @@ -1409,16 +1458,16 @@ test_incremental_gc(void) puts("test_incremental_gc"); change_gen_gc_mode(mrb, FALSE); - puts(" in mrb_garbage_collect"); - mrb_garbage_collect(mrb); + puts(" in mrb_full_gc"); + mrb_full_gc(mrb); - gc_assert(mrb->gc_state == GC_STATE_NONE); + mrb_assert(mrb->gc_state == GC_STATE_NONE); puts(" in GC_STATE_NONE"); incremental_gc(mrb, max); - gc_assert(mrb->gc_state == GC_STATE_MARK); + mrb_assert(mrb->gc_state == GC_STATE_MARK); puts(" in GC_STATE_MARK"); - advance_phase(mrb, GC_STATE_SWEEP); - gc_assert(mrb->gc_state == GC_STATE_SWEEP); + incremental_gc_until(mrb, GC_STATE_SWEEP); + mrb_assert(mrb->gc_state == GC_STATE_SWEEP); puts(" in GC_STATE_SWEEP"); page = mrb->heaps; @@ -1438,13 +1487,13 @@ test_incremental_gc(void) total += MRB_HEAP_PAGE_SIZE; } - gc_assert(mrb->gray_list == NULL); + mrb_assert(mrb->gray_list == NULL); incremental_gc(mrb, max); - gc_assert(mrb->gc_state == GC_STATE_SWEEP); + mrb_assert(mrb->gc_state == GC_STATE_SWEEP); incremental_gc(mrb, max); - gc_assert(mrb->gc_state == GC_STATE_NONE); + mrb_assert(mrb->gc_state == GC_STATE_NONE); free = (RVALUE*)mrb->heaps->freelist; while (free) { @@ -1452,30 +1501,30 @@ test_incremental_gc(void) free = (RVALUE*)free->as.free.next; } - gc_assert(mrb->live == live); - gc_assert(mrb->live == total-freed); + mrb_assert(mrb->live == live); + mrb_assert(mrb->live == total-freed); puts("test_incremental_gc(gen)"); - advance_phase(mrb, GC_STATE_SWEEP); + incremental_gc_until(mrb, GC_STATE_SWEEP); change_gen_gc_mode(mrb, TRUE); - gc_assert(mrb->gc_full == FALSE); - gc_assert(mrb->gc_state == GC_STATE_NONE); + mrb_assert(mrb->gc_full == FALSE); + mrb_assert(mrb->gc_state == GC_STATE_NONE); puts(" in minor"); - gc_assert(is_minor_gc(mrb)); - gc_assert(mrb->majorgc_old_threshold > 0); + mrb_assert(is_minor_gc(mrb)); + mrb_assert(mrb->majorgc_old_threshold > 0); mrb->majorgc_old_threshold = 0; mrb_incremental_gc(mrb); - gc_assert(mrb->gc_full == TRUE); - gc_assert(mrb->gc_state == GC_STATE_NONE); + mrb_assert(mrb->gc_full == TRUE); + mrb_assert(mrb->gc_state == GC_STATE_NONE); puts(" in major"); - gc_assert(is_major_gc(mrb)); + mrb_assert(is_major_gc(mrb)); do { mrb_incremental_gc(mrb); } while (mrb->gc_state != GC_STATE_NONE); - gc_assert(mrb->gc_full == FALSE); + mrb_assert(mrb->gc_full == FALSE); mrb_close(mrb); } @@ -1490,12 +1539,12 @@ test_incremental_sweep_phase(void) add_heap(mrb); mrb->sweeps = mrb->heaps; - gc_assert(mrb->heaps->next->next == NULL); - gc_assert(mrb->free_heaps->next->next == NULL); + mrb_assert(mrb->heaps->next->next == NULL); + mrb_assert(mrb->free_heaps->next->next == NULL); incremental_sweep_phase(mrb, MRB_HEAP_PAGE_SIZE*3); - gc_assert(mrb->heaps->next == NULL); - gc_assert(mrb->heaps == mrb->free_heaps); + mrb_assert(mrb->heaps->next == NULL); + mrb_assert(mrb->heaps == mrb->free_heaps); mrb_close(mrb); } diff --git a/src/hash.c b/src/hash.c index e31f7b3d7..1ffaed5fb 100644 --- a/src/hash.c +++ b/src/hash.c @@ -145,7 +145,9 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr k = kh_get(ht, h, key); if (k == kh_end(h)) { /* expand */ + int ai = mrb_gc_arena_save(mrb); k = kh_put(ht, h, KEY(key)); + mrb_gc_arena_restore(mrb, ai); } kh_value(h, k) = val; @@ -169,7 +171,9 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) for (k = kh_begin(h); k != kh_end(h); k++) { if (kh_exist(h,k)) { + int ai = mrb_gc_arena_save(mrb); ret_k = kh_put(ht, ret_h, KEY(kh_key(h,k))); + mrb_gc_arena_restore(mrb, ai); kh_val(ret_h, ret_k) = kh_val(h,k); } } @@ -772,16 +776,9 @@ mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); - mrb_bool empty_p; - if (h) { - empty_p = (kh_size(h) == 0); - } - else { - empty_p = 1; - } - - return mrb_bool_value(empty_p); + if (h) return mrb_bool_value(kh_size(h) == 0); + return mrb_true_value(); } static mrb_value @@ -921,17 +918,12 @@ mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; - mrb_bool result; if (h) { k = kh_get(ht, h, key); - result = (k != kh_end(h)); - } - else { - result = 0; + return mrb_bool_value(k != kh_end(h)); } - - return mrb_bool_value(result); + return mrb_false_value(); } /* 15.2.13.4.13 */ diff --git a/src/kernel.c b/src/kernel.c index 4b3bed0d8..4b426c6b4 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -26,7 +26,7 @@ typedef enum { NOEX_RESPONDS = 0x80 } mrb_method_flag_t; -int +mrb_bool mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) { struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4)); @@ -521,7 +521,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) return mrb_yield_internal(mrb, b, 0, 0, self, c); } -int +mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c) { if (mrb_obj_class(mrb, obj) == c) return TRUE; @@ -549,15 +549,40 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self) } static void -check_iv_name(mrb_state *mrb, mrb_sym id) +valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, size_t len) +{ + if (len < 2 || !(s[0] == '@' && s[1] != '@')) { + mrb_name_error(mrb, iv_name_id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name_id)); + } +} + +static void +check_iv_name(mrb_state *mrb, mrb_sym iv_name_id) { const char *s; size_t len; - s = mrb_sym2name_len(mrb, id, &len); - if (len < 2 || !(s[0] == '@' && s[1] != '@')) { - mrb_name_error(mrb, id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, id)); + s = mrb_sym2name_len(mrb, iv_name_id, &len); + valid_iv_name(mrb, iv_name_id, s, len); +} + +static mrb_sym +get_valid_iv_sym(mrb_state *mrb, mrb_value iv_name) +{ + mrb_sym iv_name_id; + + mrb_assert(mrb_symbol_p(iv_name) || mrb_string_p(iv_name)); + + if (mrb_string_p(iv_name)) { + iv_name_id = mrb_intern_cstr(mrb, RSTRING_PTR(iv_name)); + valid_iv_name(mrb, iv_name_id, RSTRING_PTR(iv_name), RSTRING_LEN(iv_name)); + } + else { + iv_name_id = mrb_symbol(iv_name); + check_iv_name(mrb, iv_name_id); } + + return iv_name_id; } /* 15.3.1.3.20 */ @@ -582,10 +607,11 @@ mrb_value mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) { mrb_sym mid; + mrb_value sym; mrb_bool defined_p; - mrb_get_args(mrb, "n", &mid); - check_iv_name(mrb, mid); + mrb_get_args(mrb, "o", &sym); + mid = get_valid_iv_sym(mrb, sym); defined_p = mrb_obj_iv_defined(mrb, mrb_obj_ptr(self), mid); return mrb_bool_value(defined_p); @@ -614,12 +640,13 @@ mrb_obj_ivar_defined(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_ivar_get(mrb_state *mrb, mrb_value self) { - mrb_sym id; + mrb_sym iv_name_id; + mrb_value iv_name; - mrb_get_args(mrb, "n", &id); + mrb_get_args(mrb, "o", &iv_name); - check_iv_name(mrb, id); - return mrb_iv_get(mrb, self, id); + iv_name_id = get_valid_iv_sym(mrb, iv_name); + return mrb_iv_get(mrb, self, iv_name_id); } /* 15.3.1.3.22 */ @@ -645,12 +672,13 @@ mrb_obj_ivar_get(mrb_state *mrb, mrb_value self) mrb_value mrb_obj_ivar_set(mrb_state *mrb, mrb_value self) { - mrb_sym id; - mrb_value val; + mrb_sym iv_name_id; + mrb_value iv_name, val; + + mrb_get_args(mrb, "oo", &iv_name, &val); - mrb_get_args(mrb, "no", &id, &val); - check_iv_name(mrb, id); - mrb_iv_set(mrb, self, id, val); + iv_name_id = get_valid_iv_sym(mrb, iv_name); + mrb_iv_set(mrb, self, iv_name_id, val); return val; } @@ -938,7 +966,7 @@ mrb_obj_remove_instance_variable(mrb_state *mrb, mrb_value self) return val; } -static inline int +static inline mrb_bool basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub) { return mrb_respond_to(mrb, obj, id); @@ -1101,5 +1129,5 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); - mrb_alias_method(mrb, mrb->module_class, mrb_intern(mrb, "dup"), mrb_intern(mrb, "clone")); + mrb_alias_method(mrb, mrb->module_class, mrb_intern2(mrb, "dup", 3), mrb_intern2(mrb, "clone", 5)); } diff --git a/src/load.c b/src/load.c index 62010e425..092ddbde8 100644 --- a/src/load.c +++ b/src/load.c @@ -187,7 +187,6 @@ read_rite_section_irep(mrb_state *mrb, const uint8_t *bin) { int result; size_t sirep; - size_t i; uint32_t len; uint16_t nirep; uint16_t n; @@ -200,14 +199,14 @@ read_rite_section_irep(mrb_state *mrb, const uint8_t *bin) nirep = bin_to_uint16(header->nirep); //Read Binary Data Section - for (n = 0, i = sirep; n < nirep; n++, i++) { + for (n = 0; n < nirep; n++) { result = read_rite_irep_record(mrb, bin, &len); if (result != MRB_DUMP_OK) goto error_exit; bin += len; } - result = sirep + bin_to_uint16(header->sirep); + result = nirep; error_exit: if (result < MRB_DUMP_OK) { irep_free(sirep, mrb); @@ -368,7 +367,7 @@ mrb_read_irep(mrb_state *mrb, const uint8_t *bin) bin += bin_to_uint32(section_header->section_size); } while (memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0); - return total_nirep; + return sirep; } static void @@ -464,7 +463,6 @@ read_rite_section_irep_file(mrb_state *mrb, FILE *fp) { int32_t result; size_t sirep; - size_t i; uint16_t nirep; uint16_t n; uint32_t len, buf_size; @@ -488,7 +486,7 @@ read_rite_section_irep_file(mrb_state *mrb, FILE *fp) } //Read Binary Data Section - for (n = 0, i = sirep; n < nirep; n++, i++) { + for (n = 0; n < nirep; n++) { void *ptr; if (fread(buf, record_header_size, 1, fp) == 0) { @@ -516,7 +514,7 @@ read_rite_section_irep_file(mrb_state *mrb, FILE *fp) goto error_exit; } - result = sirep + bin_to_uint16(header.sirep); + result = nirep; error_exit: if (buf) { mrb_free(mrb, buf); @@ -539,7 +537,9 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) size_t sirep; struct rite_section_header section_header; long fpos; - const size_t block_size = 1 << 14; + size_t block_size = 1 << 14; + const uint8_t block_fallback_count = 4; + int i; const size_t buf_size = sizeof(struct rite_binary_header); if ((mrb == NULL) || (fp == NULL)) { @@ -564,7 +564,10 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) /* verify CRC */ fpos = ftell(fp); /* You don't need use SIZE_ERROR as block_size is enough small. */ - buf = mrb_malloc(mrb, block_size); + for (i = 0; i < block_fallback_count; i++,block_size >>= 1){ + buf = mrb_malloc_simple(mrb, block_size); + if (buf) break; + } if (!buf) { return MRB_DUMP_GENERAL_FAILURE; } @@ -609,7 +612,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) fseek(fp, fpos + section_size, SEEK_SET); } while (memcmp(section_header.section_identify, RITE_BINARY_EOF, sizeof(section_header.section_identify)) != 0); - return total_nirep; + return sirep; } mrb_value diff --git a/src/numeric.c b/src/numeric.c index 91843fdf8..cfde61c8c 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -4,7 +4,6 @@ ** See Copyright Notice in mruby.h */ -#include <assert.h> #include <float.h> #if defined(__FreeBSD__) && __FreeBSD__ < 4 # include <floatingpoint.h> @@ -240,7 +239,8 @@ mrb_flo_to_str(mrb_state *mrb, mrb_value flo, int max_digit) *(c++) = 'e'; if (exp > 0) { *(c++) = '+'; - } else { + } + else { *(c++) = '-'; exp = -exp; } @@ -781,7 +781,7 @@ fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp) { mrb_int div, mod; - /* TODO: add assert(y != 0) to make sure */ + /* TODO: add mrb_assert(y != 0) to make sure */ if (y < 0) { if (x < 0) @@ -998,7 +998,7 @@ fix_xor(mrb_state *mrb, mrb_value x) #define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1) static mrb_value -lshift(mrb_state *mrb, mrb_int val, int width) +lshift(mrb_state *mrb, mrb_int val, size_t width) { if (width > NUMERIC_SHIFT_WIDTH_MAX) { mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:sizeof(mrb_int)*CHAR_BIT-1)", @@ -1010,7 +1010,7 @@ lshift(mrb_state *mrb, mrb_int val, int width) } static mrb_value -rshift(mrb_int val, int width) +rshift(mrb_int val, size_t width) { if (width >= NUMERIC_SHIFT_WIDTH_MAX) { if (val < 0) { @@ -1253,12 +1253,14 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base) if (val == 0) { *--b = '0'; - } else if (val < 0) { + } + else if (val < 0) { do { *--b = mrb_digitmap[-(val % base)]; } while (val /= base); *--b = '-'; - } else { + } + else { do { *--b = mrb_digitmap[(int)(val % base)]; } while (val /= base); diff --git a/src/object.c b/src/object.c index a2162f77f..5b2278767 100644 --- a/src/object.c +++ b/src/object.c @@ -5,18 +5,19 @@ */ #include "mruby.h" +#include "mruby/array.h" #include "mruby/class.h" #include "mruby/numeric.h" #include "mruby/string.h" #include "error.h" -int +mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) { if (mrb_type(v1) != mrb_type(v2)) return FALSE; switch (mrb_type(v1)) { case MRB_TT_TRUE: - return 1; + return TRUE; case MRB_TT_FALSE: case MRB_TT_FIXNUM: @@ -32,14 +33,14 @@ mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) } } -int +mrb_bool mrb_obj_equal(mrb_state *mrb, mrb_value v1, mrb_value v2) { /* temporary definition */ return mrb_obj_eq(mrb, v1, v2); } -int +mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2) { mrb_value result; @@ -67,7 +68,7 @@ mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2) static mrb_value mrb_true(mrb_state *mrb, mrb_value obj) { - return mrb_true_value(); + return mrb_true_value(); } /* 15.2.4.3.5 */ @@ -171,9 +172,6 @@ true_to_s(mrb_state *mrb, mrb_value obj) static mrb_value true_or(mrb_state *mrb, mrb_value obj) { - mrb_bool obj2; - - mrb_get_args(mrb, "b", &obj2); return mrb_true_value(); } @@ -202,9 +200,6 @@ true_or(mrb_state *mrb, mrb_value obj) static mrb_value false_and(mrb_state *mrb, mrb_value obj) { - mrb_bool obj2; - - mrb_get_args(mrb, "b", &obj2); return mrb_false_value(); } @@ -302,7 +297,7 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho { mrb_sym m = 0; - m = mrb_intern(mrb, method); + m = mrb_intern_cstr(mrb, method); if (!mrb_respond_to(mrb, val, m)) { if (raise) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into %S", val, mrb_str_new_cstr(mrb, tname)); @@ -318,18 +313,18 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) { - mrb_value v; + mrb_value v; - if (mrb_type(val) == MRB_TT_FIXNUM) return val; - v = convert_type(mrb, val, "Integer", method, FALSE); - if (mrb_nil_p(v) || mrb_type(v) != MRB_TT_FIXNUM) { - return mrb_nil_value(); - } - return v; + if (mrb_type(val) == MRB_TT_FIXNUM) return val; + v = convert_type(mrb, val, "Integer", method, FALSE); + if (mrb_nil_p(v) || mrb_type(v) != MRB_TT_FIXNUM) { + return mrb_nil_value(); + } + return v; } mrb_value -mrb_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname, const char *method) +mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) { mrb_value v; @@ -343,7 +338,7 @@ mrb_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname, } mrb_value -mrb_check_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char *tname, const char *method) +mrb_check_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) { mrb_value v; @@ -354,8 +349,8 @@ mrb_check_convert_type(mrb_state *mrb, mrb_value val, mrb_int type, const char * } static const struct types { - unsigned char type; - const char *name; + unsigned char type; + const char *name; } builtin_types[] = { // {MRB_TT_NIL, "nil"}, {MRB_TT_FALSE, "false"}, @@ -473,7 +468,7 @@ mrb_any_to_s(mrb_state *mrb, mrb_value obj) * b.kind_of? M #=> true */ -int +mrb_bool mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) { struct RClass *cl = mrb_class(mrb, obj); @@ -499,21 +494,21 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) static mrb_value mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) { - mrb_value v; + mrb_value v; - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, TRUE); - if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", - val, val, mrb_str_new_cstr(mrb, method), v); - } - return v; + if (mrb_fixnum_p(val)) return val; + v = convert_type(mrb, val, "Integer", method, TRUE); + if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", + val, val, mrb_str_new_cstr(mrb, method), v); + } + return v; } mrb_value mrb_to_int(mrb_state *mrb, mrb_value val) { - return mrb_to_integer(mrb, val, "to_int"); + return mrb_to_integer(mrb, val, "to_int"); } static mrb_value @@ -529,7 +524,7 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base) case MRB_TT_FLOAT: if (base != 0) goto arg_error; if (FIXABLE(mrb_float(val))) { - break; + break; } return mrb_flo_to_fixnum(mrb, val); @@ -545,14 +540,14 @@ string_conv: break; } if (base != 0) { - tmp = mrb_check_string_type(mrb, val); - if (!mrb_nil_p(tmp)) goto string_conv; - arg_error: - mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); + tmp = mrb_check_string_type(mrb, val); + if (!mrb_nil_p(tmp)) goto string_conv; +arg_error: + mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); } tmp = convert_type(mrb, val, "Integer", "to_int", FALSE); if (mrb_nil_p(tmp)) { - return mrb_to_integer(mrb, val, "to_i"); + return mrb_to_integer(mrb, val, "to_i"); } return tmp; } @@ -560,14 +555,14 @@ string_conv: mrb_value mrb_Integer(mrb_state *mrb, mrb_value val) { - return mrb_convert_to_integer(mrb, val, 0); + return mrb_convert_to_integer(mrb, val, 0); } mrb_value mrb_Float(mrb_state *mrb, mrb_value val) { if (mrb_nil_p(val)) { - mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float"); + mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float"); } switch (mrb_type(val)) { case MRB_TT_FIXNUM: @@ -590,7 +585,7 @@ mrb_inspect(mrb_state *mrb, mrb_value obj) return mrb_obj_as_string(mrb, mrb_funcall(mrb, obj, "inspect", 0, 0)); } -int +mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2) { if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; diff --git a/src/opcode.h b/src/opcode.h index b4f843116..f87611119 100644 --- a/src/opcode.h +++ b/src/opcode.h @@ -17,27 +17,27 @@ /* Ax:OP = 25: 7 */ /* A:Bz:Cz:OP = 9:14: 2: 7 */ -#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f)) -#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff)) -#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff)) -#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f)) -#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff)) -#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx)) -#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff)) +#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f)) +#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff)) +#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff)) +#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f)) +#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff)) +#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx)) +#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff)) #define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1)))) #define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1)))) -#define GETARG_b(i) GETARG_UNPACK_b(i,14,2) -#define GETARG_c(i) GETARG_UNPACK_c(i,14,2) - -#define MKOPCODE(op) ((op) & 0x7f) -#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23) -#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14) -#define MKARG_C(c) (((c) & 0x7f) << 7) -#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7) -#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx) -#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7) +#define GETARG_b(i) GETARG_UNPACK_b(i,14,2) +#define GETARG_c(i) GETARG_UNPACK_c(i,14,2) + +#define MKOPCODE(op) ((op) & 0x7f) +#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23) +#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14) +#define MKARG_C(c) (((c) & 0x7f) << 7) +#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7) +#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx) +#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7) #define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7)) -#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2) +#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2) #define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a)) #define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b)) @@ -50,98 +50,101 @@ #define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c)) enum { -OP_NOP=0,/* */ -OP_MOVE,/* A B R(A) := R(B) */ -OP_LOADL,/* A Bx R(A) := Lit(Bx) */ -OP_LOADI,/* A sBx R(A) := sBx */ -OP_LOADSYM,/* A Bx R(A) := Sym(Bx) */ -OP_LOADNIL,/* A R(A) := nil */ -OP_LOADSELF,/* A R(A) := self */ -OP_LOADT,/* A R(A) := true */ -OP_LOADF,/* A R(A) := false */ - -OP_GETGLOBAL,/* A Bx R(A) := getglobal(Sym(Bx)) */ -OP_SETGLOBAL,/* A Bx setglobal(Sym(Bx), R(A)) */ -OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */ -OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */ -OP_GETIV,/* A Bx R(A) := ivget(Sym(Bx)) */ -OP_SETIV,/* A Bx ivset(Sym(Bx),R(A)) */ -OP_GETCV,/* A Bx R(A) := cvget(Sym(Bx)) */ -OP_SETCV,/* A Bx cvset(Sym(Bx),R(A)) */ -OP_GETCONST,/* A Bx R(A) := constget(Sym(Bx)) */ -OP_SETCONST,/* A Bx constset(Sym(Bx),R(A)) */ -OP_GETMCNST,/* A Bx R(A) := R(A)::Sym(B) */ -OP_SETMCNST,/* A Bx R(A+1)::Sym(B) := R(A) */ -OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */ -OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */ - -OP_JMP,/* sBx pc+=sBx */ -OP_JMPIF,/* A sBx if R(A) pc+=sBx */ -OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */ -OP_ONERR,/* sBx rescue_push(pc+sBx) */ -OP_RESCUE,/* A clear(exc); R(A) := exception (ignore when A=0) */ -OP_POPERR,/* A A.times{rescue_pop()} */ -OP_RAISE,/* A raise(R(A)) */ -OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */ -OP_EPOP,/* A A.times{ensure_pop().call} */ - -OP_SEND,/* A B C R(A) := call(R(A),mSym(B),R(A+1),...,R(A+C)) */ -OP_SENDB,/* A B C R(A) := call(R(A),mSym(B),R(A+1),...,R(A+C),&R(A+C+1))*/ -OP_FSEND,/* A B C R(A) := fcall(R(A),mSym(B),R(A+1),...,R(A+C-1)) */ -OP_CALL,/* A B C R(A) := self.call(R(A),.., R(A+C)) */ -OP_SUPER,/* A B C R(A) := super(R(A+1),... ,R(A+C-1)) */ -OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */ -OP_ENTER,/* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */ -OP_KARG,/* A B C R(A) := kdict[mSym(B)]; if C kdict.rm(mSym(B)) */ -OP_KDICT,/* A C R(A) := kdict */ - -OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */ -OP_TAILCALL,/* A B C return call(R(A),mSym(B),*R(C)) */ -OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */ - -OP_ADD,/* A B C R(A) := R(A)+R(A+1) (mSyms[B]=:+,C=1) */ -OP_ADDI,/* A B C R(A) := R(A)+C (mSyms[B]=:+) */ -OP_SUB,/* A B C R(A) := R(A)-R(A+1) (mSyms[B]=:-,C=1) */ -OP_SUBI,/* A B C R(A) := R(A)-C (mSyms[B]=:-) */ -OP_MUL,/* A B C R(A) := R(A)*R(A+1) (mSyms[B]=:*,C=1) */ -OP_DIV,/* A B C R(A) := R(A)/R(A+1) (mSyms[B]=:/,C=1) */ -OP_EQ,/* A B C R(A) := R(A)==R(A+1) (mSyms[B]=:==,C=1) */ -OP_LT,/* A B C R(A) := R(A)<R(A+1) (mSyms[B]=:<,C=1) */ -OP_LE,/* A B C R(A) := R(A)<=R(A+1) (mSyms[B]=:<=,C=1) */ -OP_GT,/* A B C R(A) := R(A)>R(A+1) (mSyms[B]=:>,C=1) */ -OP_GE,/* A B C R(A) := R(A)>=R(A+1) (mSyms[B]=:>=,C=1) */ - -OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ -OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */ -OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */ -OP_AREF,/* A B C R(A) := R(B)[C] */ -OP_ASET,/* A B C R(B)[C] := R(A) */ -OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A) */ - -OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */ -OP_STRCAT,/* A B str_cat(R(A),R(B)) */ - -OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ -OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cm) */ -OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */ - -OP_OCLASS,/* A R(A) := ::Object */ -OP_CLASS,/* A B R(A) := newclass(R(A),mSym(B),R(A+1)) */ -OP_MODULE,/* A B R(A) := newmodule(R(A),mSym(B)) */ -OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ -OP_METHOD,/* A B R(A).newmethod(mSym(B),R(A+1)) */ -OP_SCLASS,/* A B R(A) := R(B).singleton_class */ -OP_TCLASS,/* A R(A) := target_class */ - -OP_DEBUG,/* A print R(A) */ -OP_STOP,/* stop VM */ -OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */ - -OP_RSVD1,/* reserved instruction #1 */ -OP_RSVD2,/* reserved instruction #2 */ -OP_RSVD3,/* reserved instruction #3 */ -OP_RSVD4,/* reserved instruction #4 */ -OP_RSVD5,/* reserved instruction #5 */ + /*----------------------------------------------------------------------- + operation code operand description + ------------------------------------------------------------------------*/ + OP_NOP=0,/* */ + OP_MOVE,/* A B R(A) := R(B) */ + OP_LOADL,/* A Bx R(A) := Lit(Bx) */ + OP_LOADI,/* A sBx R(A) := sBx */ + OP_LOADSYM,/* A Bx R(A) := Sym(Bx) */ + OP_LOADNIL,/* A R(A) := nil */ + OP_LOADSELF,/* A R(A) := self */ + OP_LOADT,/* A R(A) := true */ + OP_LOADF,/* A R(A) := false */ + + OP_GETGLOBAL,/* A Bx R(A) := getglobal(Sym(Bx)) */ + OP_SETGLOBAL,/* A Bx setglobal(Sym(Bx), R(A)) */ + OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */ + OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */ + OP_GETIV,/* A Bx R(A) := ivget(Sym(Bx)) */ + OP_SETIV,/* A Bx ivset(Sym(Bx),R(A)) */ + OP_GETCV,/* A Bx R(A) := cvget(Sym(Bx)) */ + OP_SETCV,/* A Bx cvset(Sym(Bx),R(A)) */ + OP_GETCONST,/* A Bx R(A) := constget(Sym(Bx)) */ + OP_SETCONST,/* A Bx constset(Sym(Bx),R(A)) */ + OP_GETMCNST,/* A Bx R(A) := R(A)::Sym(B) */ + OP_SETMCNST,/* A Bx R(A+1)::Sym(B) := R(A) */ + OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */ + OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */ + + OP_JMP,/* sBx pc+=sBx */ + OP_JMPIF,/* A sBx if R(A) pc+=sBx */ + OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */ + OP_ONERR,/* sBx rescue_push(pc+sBx) */ + OP_RESCUE,/* A clear(exc); R(A) := exception (ignore when A=0) */ + OP_POPERR,/* A A.times{rescue_pop()} */ + OP_RAISE,/* A raise(R(A)) */ + OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */ + OP_EPOP,/* A A.times{ensure_pop().call} */ + + OP_SEND,/* A B C R(A) := call(R(A),mSym(B),R(A+1),...,R(A+C)) */ + OP_SENDB,/* A B C R(A) := call(R(A),mSym(B),R(A+1),...,R(A+C),&R(A+C+1))*/ + OP_FSEND,/* A B C R(A) := fcall(R(A),mSym(B),R(A+1),...,R(A+C-1)) */ + OP_CALL,/* A B C R(A) := self.call(R(A),.., R(A+C)) */ + OP_SUPER,/* A B C R(A) := super(R(A+1),... ,R(A+C-1)) */ + OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */ + OP_ENTER,/* Ax arg setup according to flags (24=5:5:1:5:5:1:1) */ + OP_KARG,/* A B C R(A) := kdict[mSym(B)]; if C kdict.rm(mSym(B)) */ + OP_KDICT,/* A C R(A) := kdict */ + + OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */ + OP_TAILCALL,/* A B C return call(R(A),mSym(B),*R(C)) */ + OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */ + + OP_ADD,/* A B C R(A) := R(A)+R(A+1) (mSyms[B]=:+,C=1) */ + OP_ADDI,/* A B C R(A) := R(A)+C (mSyms[B]=:+) */ + OP_SUB,/* A B C R(A) := R(A)-R(A+1) (mSyms[B]=:-,C=1) */ + OP_SUBI,/* A B C R(A) := R(A)-C (mSyms[B]=:-) */ + OP_MUL,/* A B C R(A) := R(A)*R(A+1) (mSyms[B]=:*,C=1) */ + OP_DIV,/* A B C R(A) := R(A)/R(A+1) (mSyms[B]=:/,C=1) */ + OP_EQ,/* A B C R(A) := R(A)==R(A+1) (mSyms[B]=:==,C=1) */ + OP_LT,/* A B C R(A) := R(A)<R(A+1) (mSyms[B]=:<,C=1) */ + OP_LE,/* A B C R(A) := R(A)<=R(A+1) (mSyms[B]=:<=,C=1) */ + OP_GT,/* A B C R(A) := R(A)>R(A+1) (mSyms[B]=:>,C=1) */ + OP_GE,/* A B C R(A) := R(A)>=R(A+1) (mSyms[B]=:>=,C=1) */ + + OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ + OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */ + OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */ + OP_AREF,/* A B C R(A) := R(B)[C] */ + OP_ASET,/* A B C R(B)[C] := R(A) */ + OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A) */ + + OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */ + OP_STRCAT,/* A B str_cat(R(A),R(B)) */ + + OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ + OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cm) */ + OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */ + + OP_OCLASS,/* A R(A) := ::Object */ + OP_CLASS,/* A B R(A) := newclass(R(A),mSym(B),R(A+1)) */ + OP_MODULE,/* A B R(A) := newmodule(R(A),mSym(B)) */ + OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ + OP_METHOD,/* A B R(A).newmethod(mSym(B),R(A+1)) */ + OP_SCLASS,/* A B R(A) := R(B).singleton_class */ + OP_TCLASS,/* A R(A) := target_class */ + + OP_DEBUG,/* A print R(A) */ + OP_STOP,/* stop VM */ + OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */ + + OP_RSVD1,/* reserved instruction #1 */ + OP_RSVD2,/* reserved instruction #2 */ + OP_RSVD3,/* reserved instruction #3 */ + OP_RSVD4,/* reserved instruction #4 */ + OP_RSVD5,/* reserved instruction #5 */ }; #define OP_L_STRICT 1 diff --git a/src/parse.y b/src/parse.y index f5dbdb6fd..9a83d5cbd 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1,6 +1,6 @@ /* ** parse.y - mruby parser -** +** ** See Copyright Notice in mruby.h */ @@ -272,7 +272,7 @@ new_scope(parser_state *p, node *body) static node* new_begin(parser_state *p, node *body) { - if (body) + if (body) return list2((node*)NODE_BEGIN, body); return cons((node*)NODE_BEGIN, 0); } @@ -909,7 +909,7 @@ parsing_heredoc_inf(parser_state *p) node *nd = p->parsing_heredoc; if (nd == NULL) return NULL; - /* assert(nd->car->car == NODE_HEREDOC); */ + /* mrb_assert(nd->car->car == NODE_HEREDOC); */ return (parser_heredoc_info*)nd->car->cdr; } @@ -2744,7 +2744,7 @@ var_ref : variable { $$ = var_reference(p, $1); } - | keyword_nil + | keyword_nil { $$ = new_nil(p); } @@ -3293,7 +3293,7 @@ peek_n(parser_state *p, int c, int n) list = push(list, (node*)(intptr_t)c0); } while(n--); if (p->pb) { - p->pb = push(p->pb, (node*)list); + p->pb = append(p->pb, (node*)list); } else { p->pb = list; @@ -3408,7 +3408,7 @@ scan_oct(const int *start, int len, int *retlen) const int *s = start; int retval = 0; - /* assert(len <= 3) */ + /* mrb_assert(len <= 3) */ while (len-- && *s >= '0' && *s <= '7') { retval <<= 3; retval |= *s++ - '0'; @@ -3426,7 +3426,7 @@ scan_hex(const int *start, int len, int *retlen) register int retval = 0; char *tmp; - /* assert(len <= 2) */ + /* mrb_assert(len <= 2) */ while (len-- && *s && (tmp = (char*)strchr(hexdigit, *s))) { retval <<= 4; retval |= (tmp - hexdigit) & 15; @@ -3620,12 +3620,14 @@ parse_string(parser_state *p) tokadd(p, '\n'); } else { - pushback(p, c); - - if(type & STR_FUNC_REGEXP) + if (type & STR_FUNC_REGEXP) { tokadd(p, '\\'); - - tokadd(p, read_escape(p)); + if (c != -1) + tokadd(p, c); + } else { + pushback(p, c); + tokadd(p, read_escape(p)); + } if (hinf) hinf->line_head = FALSE; } @@ -3684,7 +3686,7 @@ parse_string(parser_state *p) tokadd(p, c); - } + } tokfix(p); p->lstate = EXPR_END; @@ -3729,7 +3731,7 @@ parse_string(parser_state *p) yylval.nd = new_str(p, tok(p), toklen(p)); return tSTRING; } - + static int heredoc_identifier(parser_state *p) @@ -4811,7 +4813,7 @@ parser_yylex(parser_state *p) pushback(p, c); if (last_state == EXPR_FNAME) goto gvar; tokfix(p); - yylval.nd = new_nth_ref(p, atoi(tok(p))); + yylval.nd = new_nth_ref(p, atoi(tok(p))); return tNTH_REF; default: @@ -5174,7 +5176,7 @@ parser_state* mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) { parser_state *p; - + p = mrb_parser_new(mrb); if (!p) return 0; p->s = p->send = NULL; @@ -5559,7 +5561,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset) printf("NODE_CALL:\n"); parser_dump(mrb, tree->car, offset+1); dump_prefix(offset+1); - printf("method='%s' (%d)\n", + printf("method='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->cdr->car)), (int)(intptr_t)tree->cdr->car); tree = tree->cdr->cdr->car; diff --git a/src/pool.c b/src/pool.c index c992b5e53..f09df92c5 100644 --- a/src/pool.c +++ b/src/pool.c @@ -53,7 +53,7 @@ mrb_pool_open(mrb_state *mrb) if (pool) { pool->mrb = mrb; - pool->pages = 0; + pool->pages = NULL; } return pool; @@ -96,7 +96,7 @@ mrb_pool_alloc(mrb_pool *pool, size_t len) struct mrb_pool_page *page; size_t n; - if (!pool) return 0; + if (!pool) return NULL; len += ALIGN_PADDING(len); page = pool->pages; while (page) { @@ -109,7 +109,7 @@ mrb_pool_alloc(mrb_pool *pool, size_t len) page = page->next; } page = page_alloc(pool, len); - if (!page) return 0; + if (!page) return NULL; page->offset = len; page->next = pool->pages; pool->pages = page; @@ -118,7 +118,7 @@ mrb_pool_alloc(mrb_pool *pool, size_t len) return page->last; } -int +mrb_bool mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) { struct mrb_pool_page *page; @@ -145,7 +145,7 @@ mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen) struct mrb_pool_page *page; void *np; - if (!pool) return 0; + if (!pool) return NULL; oldlen += ALIGN_PADDING(oldlen); newlen += ALIGN_PADDING(newlen); page = pool->pages; @@ -177,10 +177,10 @@ main(void) mrb_pool *pool; void *p; - pool = mrb_pool_open(0); + pool = mrb_pool_open(NULL); p = mrb_pool_alloc(pool, len); for (i=1; i<20; i++) { - printf("%p (len=%d) %d\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); + printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); p = mrb_pool_realloc(pool, p, len, len*2); len *= 2; } diff --git a/src/proc.c b/src/proc.c index 5c50effaa..787a46492 100644 --- a/src/proc.c +++ b/src/proc.c @@ -139,7 +139,7 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self) mrb_code *iseq = mrb_proc_iseq(mrb, p); mrb_aspec aspec = GETARG_Ax(*iseq); int ma, ra, pa, arity; - + ma = MRB_ASPEC_REQ(aspec); ra = MRB_ASPEC_REST(aspec); pa = MRB_ASPEC_POST(aspec); @@ -201,8 +201,8 @@ mrb_init_proc(mrb_state *mrb) mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE()); m = mrb_proc_new(mrb, call_irep); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "call"), m); - mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern(mrb, "[]"), m); + mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern2(mrb, "call", 4), m); + mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern2(mrb, "[]", 2), m); mrb_define_class_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.2.6 */ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()); /* 15.3.1.3.27 */ diff --git a/src/range.c b/src/range.c index 10a03ddb4..1d6519a6e 100644 --- a/src/range.c +++ b/src/range.c @@ -152,33 +152,25 @@ mrb_range_eq(mrb_state *mrb, mrb_value range) struct RRange *rr; struct RRange *ro; mrb_value obj; - mrb_bool eq_p; mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) { - eq_p = 1; - } - else if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */ - eq_p = 0; - } - else { - rr = mrb_range_ptr(range); - ro = mrb_range_ptr(obj); - if (!mrb_obj_equal(mrb, rr->edges->beg, ro->edges->beg) || - !mrb_obj_equal(mrb, rr->edges->end, ro->edges->end) || - rr->excl != ro->excl) { - eq_p = 0; - } - else { - eq_p = 1; - } + if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); + if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */ + return mrb_false_value(); } - return mrb_bool_value(eq_p); + rr = mrb_range_ptr(range); + ro = mrb_range_ptr(obj); + if (!mrb_bool(mrb_funcall(mrb, rr->edges->beg, "==", 1, ro->edges->beg)) || + !mrb_bool(mrb_funcall(mrb, rr->edges->end, "==", 1, ro->edges->end)) || + rr->excl != ro->excl) { + return mrb_false_value(); + } + return mrb_true_value(); } -static int +static mrb_bool r_le(mrb_state *mrb, mrb_value a, mrb_value b) { mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ @@ -192,7 +184,7 @@ r_le(mrb_state *mrb, mrb_value a, mrb_value b) return FALSE; } -static int +static mrb_bool r_gt(mrb_state *mrb, mrb_value a, mrb_value b) { mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); @@ -205,7 +197,7 @@ r_gt(mrb_state *mrb, mrb_value a, mrb_value b) return FALSE; } -static int +static mrb_bool r_ge(mrb_state *mrb, mrb_value a, mrb_value b) { mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */ @@ -284,10 +276,10 @@ mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, if (beg < 0) { beg += len; - if (beg < 0) goto out_of_range; + if (beg < 0) return FALSE; } - if (beg > len) goto out_of_range; + if (beg > len) return FALSE; if (end > len) end = len; if (end < 0) end += len; @@ -298,9 +290,6 @@ mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, *begp = beg; *lenp = len; return TRUE; - -out_of_range: - return FALSE; } /* 15.2.14.4.12(x) */ @@ -385,34 +374,23 @@ range_eql(mrb_state *mrb, mrb_value range) { mrb_value obj; struct RRange *r, *o; - mrb_bool eql_p; mrb_get_args(mrb, "o", &obj); - if (mrb_obj_equal(mrb, range, obj)) { - eql_p = 1; - } - else if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) { - eql_p = 0; + + if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value(); + if (!mrb_obj_is_kind_of(mrb, obj, RANGE_CLASS)) { + return mrb_false_value(); } - else { - r = mrb_range_ptr(range); - if (mrb_type(obj) != MRB_TT_RANGE) { - eql_p = 0; - } - else { - o = mrb_range_ptr(obj); - if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || - !mrb_eql(mrb, r->edges->end, o->edges->end) || - (r->excl != o->excl)) { - eql_p = 0; - } - else { - eql_p = 1; - } - } + if (mrb_type(obj) != MRB_TT_RANGE) return mrb_false_value(); + + r = mrb_range_ptr(range); + o = mrb_range_ptr(obj); + if (!mrb_eql(mrb, r->edges->beg, o->edges->beg) || + !mrb_eql(mrb, r->edges->end, o->edges->end) || + (r->excl != o->excl)) { + return mrb_false_value(); } - - return mrb_bool_value(eql_p); + return mrb_true_value(); } /* 15.2.14.4.15(x) */ @@ -7,6 +7,7 @@ #ifndef RE_H #define RE_H -#define REGEXP_CLASS "Regexp" +#define REGEXP_CLASS "Regexp" +#define REGEXP_CLASS_CSTR_LEN 6 #endif diff --git a/src/state.c b/src/state.c index 34de1e45e..5dcc4a40a 100644 --- a/src/state.c +++ b/src/state.c @@ -21,10 +21,6 @@ inspect_main(mrb_state *mrb, mrb_value mod) return mrb_str_new(mrb, "main", 4); } -#ifdef MRB_NAN_BOXING -#include <assert.h> -#endif - mrb_state* mrb_open_allocf(mrb_allocf f, void *ud) { @@ -33,7 +29,7 @@ mrb_open_allocf(mrb_allocf f, void *ud) mrb_state *mrb; #ifdef MRB_NAN_BOXING - assert(sizeof(void*) == 4); + mrb_assert(sizeof(void*) == 4); #endif mrb = (mrb_state *)(f)(NULL, NULL, sizeof(mrb_state), ud); @@ -192,7 +188,7 @@ mrb_value mrb_top_self(mrb_state *mrb) { if (!mrb->top_self) { - mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class); + mrb->top_self = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb->object_class); mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE()); mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE()); } diff --git a/src/string.c b/src/string.c index 7cd727806..f3a788df3 100644 --- a/src/string.c +++ b/src/string.c @@ -74,7 +74,7 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) if (p) { memcpy(ptr, p, len); } - ptr[len] = 0; + ptr[len] = '\0'; s->ptr = ptr; s->aux.capa = len; str_decref(mrb, shared); @@ -104,10 +104,9 @@ mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) mrb_str_modify(mrb, s); slen = s->len; if (len != slen) { - if (slen < len || slen -len > 1024) { - s->ptr = (char *)mrb_realloc(mrb, s->ptr, len+1); + if (slen < len || slen - len > 256) { + RESIZE_CAPA(s, len); } - s->aux.capa = len; s->len = len; s->ptr[len] = '\0'; /* sentinel */ } @@ -261,14 +260,7 @@ mrb_str_new_cstr(mrb_state *mrb, const char *p) len = 0; } - s = mrb_obj_alloc_string(mrb); - s->ptr = (char *)mrb_malloc(mrb, len+1); - if (p) { - memcpy(s->ptr, p, len); - } - s->ptr[len] = 0; - s->len = (mrb_int)len; - s->aux.capa = (mrb_int)len; + s = str_new(mrb, p, len); return mrb_obj_value(s); } @@ -406,7 +398,7 @@ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other) } memcpy(s1->ptr+s1->len, s2->ptr, s2->len); s1->len = len; - s1->ptr[len] = 0; + s1->ptr[len] = '\0'; } /* @@ -603,7 +595,7 @@ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1) return mrb_fixnum_value(result); } -static int +static mrb_bool str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2) { const mrb_int len = RSTRING_LEN(str1); @@ -614,7 +606,7 @@ str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2) return FALSE; } -int +mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2) { if (mrb_obj_equal(mrb, str1, str2)) return TRUE; @@ -2542,7 +2534,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "*", mrb_str_times, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */ mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.3 */ mrb_define_method(mrb, s, "==", mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.4 */ - mrb_define_method(mrb, s, "=~", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.5 */ mrb_define_method(mrb, s, "[]", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.6 */ mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, MRB_ARGS_NONE()); /* 15.2.10.5.7 */ mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, MRB_ARGS_REQ(1)); /* 15.2.10.5.8 */ @@ -2555,26 +2546,18 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */ mrb_define_method(mrb, s, "eql?", mrb_str_eql, MRB_ARGS_REQ(1)); /* 15.2.10.5.17 */ - // NOTE: Regexp not implemented - mrb_define_method(mrb, s, "gsub", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.18 */ - mrb_define_method(mrb, s, "gsub!", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.19 */ - mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.20 */ mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */ mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY()); /* 15.2.10.5.22 */ mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */ mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */ mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */ - mrb_define_method(mrb, s, "match", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.27 */ mrb_define_method(mrb, s, "replace", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */ mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); /* 15.2.10.5.29 */ mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); /* 15.2.10.5.30 */ mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, MRB_ARGS_ANY()); /* 15.2.10.5.31 */ - mrb_define_method(mrb, s, "scan", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.32 */ mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */ mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */ - mrb_define_method(mrb, s, "sub", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.36 */ - mrb_define_method(mrb, s, "sub!", noregexp, MRB_ARGS_REQ(1)); /* 15.2.10.5.37 */ mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.38 */ mrb_define_method(mrb, s, "to_f", mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.39 */ diff --git a/src/symbol.c b/src/symbol.c index c0bb48f32..c145a4a1a 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -251,7 +251,7 @@ sym_to_sym(mrb_state *mrb, mrb_value sym) #endif #define is_identchar(c) (SIGN_EXTEND_CHAR(c)!=-1&&(ISALNUM(c) || (c) == '_')) -static int +static mrb_bool is_special_global_name(const char* m) { switch (*m) { @@ -274,7 +274,7 @@ is_special_global_name(const char* m) return !*m; } -static int +static mrb_bool symname_p(const char *name) { const char *m = name; @@ -382,7 +382,7 @@ mrb_sym2str(mrb_state *mrb, mrb_sym sym) size_t len; const char *name = mrb_sym2name_len(mrb, sym, &len); mrb_value str; - + if (!name) return mrb_undef_value(); /* can't happen */ str = mrb_str_new_static(mrb, name, len); if (symname_p(name) && strlen(name) == len) { @@ -452,5 +452,5 @@ mrb_init_symbol(mrb_state *mrb) mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1)); - mrb->init_sym = mrb_intern(mrb, "initialize"); + mrb->init_sym = mrb_intern2(mrb, "initialize", 10); } diff --git a/src/variable.c b/src/variable.c index 2610c5d7a..048b63bca 100644 --- a/src/variable.c +++ b/src/variable.c @@ -27,12 +27,21 @@ typedef struct segment { struct segment *next; } segment; +/* Instance variable table structure */ typedef struct iv_tbl { segment *rootseg; size_t size; size_t last_len; } iv_tbl; +/* + * Creates the instance variable table. + * + * Parameters + * mrb + * Returns + * the instance variable table. + */ static iv_tbl* iv_new(mrb_state *mrb) { @@ -47,6 +56,15 @@ iv_new(mrb_state *mrb) return t; } +/* + * Set the value for the symbol in the instance variable table. + * + * Parameters + * mrb + * t the instance variable table to be set in. + * sym the symbol to be used as the key. + * val the value to be set. + */ static void iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) { @@ -59,7 +77,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) while (seg) { for (i=0; i<MRB_SEGMENT_SIZE; i++) { mrb_sym key = seg->key[i]; - /* found room in last segment after last_len */ + /* Found room in last segment after last_len */ if (!seg->next && i >= t->last_len) { seg->key[i] = sym; seg->val[i] = val; @@ -80,7 +98,7 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) seg = seg->next; } - /* not found */ + /* Not found */ t->size++; if (matched_seg) { matched_seg->key[matched_idx] = sym; @@ -103,6 +121,18 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) return; } +/* + * Get a value for a symbol from the instance the variable table. + * + * Parameters + * mrb + * t the variable table to be searched. + * sym the symbol to be used as the key. + * vp the value pointer. Recieves the value if the specified symbol contains + * in the instance variable table. + * Returns + * true if the specfiyed symbol contains in the instance variable table. + */ static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { @@ -127,6 +157,17 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) return FALSE; } +/* + * Deletes the value for the symbol from the instance variable table. + * + * Parameters + * t the variable table to be searched. + * sym the symbol to be used as the key. + * vp the value pointer. Recieve the deleted value if the symbol contans + * in the instance varible table. + * Returns + * true if the specfied symbol contains in the instance variable table. + */ static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) { @@ -916,7 +957,7 @@ mrb_const_remove(mrb_state *mrb, mrb_value mod, mrb_sym sym) void mrb_define_const(mrb_state *mrb, struct RClass *mod, const char *name, mrb_value v) { - mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern(mrb, name), v); + mrb_obj_iv_set(mrb, (struct RObject*)mod, mrb_intern_cstr(mrb, name), v); } void @@ -1,4 +1,4 @@ -/* + /* ** vm.c - virtual machine for mruby ** ** See Copyright Notice in mruby.h @@ -92,12 +92,12 @@ stack_init(mrb_state *mrb) { struct mrb_context *c = mrb->c; - /* assert(mrb->stack == NULL); */ + /* mrb_assert(mrb->stack == NULL); */ c->stbase = (mrb_value *)mrb_calloc(mrb, STACK_INIT_SIZE, sizeof(mrb_value)); c->stend = c->stbase + STACK_INIT_SIZE; c->stack = c->stbase; - /* assert(ci == NULL); */ + /* mrb_assert(ci == NULL); */ c->cibase = (mrb_callinfo *)mrb_calloc(mrb, CALLINFO_INIT_SIZE, sizeof(mrb_callinfo)); c->ciend = c->cibase + CALLINFO_INIT_SIZE; c->ci = c->cibase; @@ -174,22 +174,22 @@ uvenv(mrb_state *mrb, int up) struct REnv *e = mrb->c->ci->proc->env; while (up--) { - if (!e) return 0; + if (!e) return NULL; e = (struct REnv*)e->c; } return e; } -static inline int +static inline mrb_bool is_strict(mrb_state *mrb, struct REnv *e) { int cioff = e->cioff; if (cioff >= 0 && mrb->c->cibase[cioff].proc && MRB_PROC_STRICT_P(mrb->c->cibase[cioff].proc)) { - return 1; + return TRUE; } - return 0; + return FALSE; } static inline struct REnv* @@ -279,7 +279,7 @@ ecall(mrb_state *mrb, int i) mrb_value mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) { - mrb_sym mid = mrb_intern(mrb, name); + mrb_sym mid = mrb_intern_cstr(mrb, name); if (argc == 0) { return mrb_funcall_argv(mrb, self, mid, 0, 0); @@ -544,7 +544,7 @@ void mrb_gv_val_set(mrb_state *mrb, mrb_sym sym, mrb_value val); mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { - /* assert(mrb_proc_cfunc_p(proc)) */ + /* mrb_assert(mrb_proc_cfunc_p(proc)) */ mrb_irep *irep = proc->body.irep; mrb_code *pc = irep->iseq; mrb_value *pool = irep->pool; @@ -1261,7 +1261,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) mrb->c->stack = mrb->c->stbase + ci[1].stackidx; if (ci[1].acc < 0 && prev_jmp) { mrb->jmp = prev_jmp; - longjmp(*(jmp_buf*)mrb->jmp, 1); + mrb_longjmp(mrb); } while (eidx > ci->eidx) { ecall(mrb, --eidx); @@ -2127,3 +2127,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } END_DISPATCH; } + +void +mrb_longjmp(mrb_state *mrb) +{ + longjmp(*(jmp_buf*)mrb->jmp, 1); +} diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 3363b4885..df55e749f 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -275,13 +275,20 @@ module MRuby req_versions = dep[:requirements] # check each GEM dependency against all available GEMs + found_dep_gem = false each do |dep_g| if name == dep_g.name unless dep_g.version_ok?(req_versions) fail "#{name} version should be #{req_versions.join(' and ')} but was '#{dep_g.version}'" end + + found_dep_gem = true + break end end + + fail "The GEM '#{g.name}' depends on the GEM '#{name}' but it could not be found" unless found_dep_gem + end end end diff --git a/tasks/mrbgems.rake b/tasks/mrbgems.rake index 5f156c45a..d8f56f88e 100644 --- a/tasks/mrbgems.rake +++ b/tasks/mrbgems.rake @@ -74,9 +74,10 @@ please check the following additional licenses too: GEMS_LEGAL gems.map do |g| + authors = [g.authors].flatten.sort.join(", ") f.puts f.puts "GEM: #{g.name}" - f.puts "Copyright (c) #{Time.now.year} #{g.authors}" + f.puts "Copyright (c) #{Time.now.year} #{authors}" f.puts "License: #{g.licenses}" end end diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake index 717f0d76b..1050b84bb 100644 --- a/tasks/mrbgems_test.rake +++ b/tasks/mrbgems_test.rake @@ -38,7 +38,7 @@ MRuby.each_target do f.puts %Q[ }] f.puts %Q[ mrb_const_set(mrb2, mrb_obj_value(mrb2->object_class), mrb_intern(mrb2, "GEMNAME"), mrb_str_new(mrb2, "#{g.name}", #{g.name.length}));] - if not g.test_args.empty? + unless g.test_args.empty? f.puts %Q[ test_args_hash = mrb_hash_new_capa(mrb, #{g.test_args.length}); ] g.test_args.each do |arg_name, arg_value| escaped_arg_name = arg_name.gsub('\\', '\\\\\\\\').gsub('"', '\"') diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake index eeebd161b..ef7f06a81 100644 --- a/tasks/mruby_build.rake +++ b/tasks/mruby_build.rake @@ -43,7 +43,7 @@ module MRuby end include Rake::DSL include LoadGems - attr_accessor :name, :bins, :exts, :file_separator + attr_accessor :name, :bins, :exts, :file_separator, :build_dir attr_reader :libmruby, :gems COMPILERS = %w(cc cxx objc asm) @@ -63,6 +63,7 @@ module MRuby end @file_separator = '/' + @build_dir = "#{MRUBY_ROOT}/build/#{@name}" @cc = Command::Compiler.new(self, %w(.c)) @cxx = Command::Compiler.new(self, %w(.cc .cxx .cpp)) @objc = Command::Compiler.new(self, %w(.m)) @@ -95,10 +96,6 @@ module MRuby MRUBY_ROOT end - def build_dir - "#{MRUBY_ROOT}/build/#{self.name}" - end - def mrbcfile MRuby.targets['host'].exefile("#{MRuby.targets['host'].build_dir}/bin/mrbc") end diff --git a/tasks/mruby_build_commands.rake b/tasks/mruby_build_commands.rake index 1d69fa54d..349b8717d 100644 --- a/tasks/mruby_build_commands.rake +++ b/tasks/mruby_build_commands.rake @@ -220,19 +220,28 @@ module MRuby class Command::Git < Command attr_accessor :flags - attr_accessor :clone_options + attr_accessor :clone_options, :pull_options def initialize(build) super @command = 'git' @flags = [] @clone_options = "clone %{flags} %{url} %{dir}" + @pull_options = "pull" end def run_clone(dir, url, _flags = []) _pp "GIT", url, dir.relative_path _run clone_options, { :flags => [flags, _flags].flatten.join(' '), :url => url, :dir => filename(dir) } end + + def run_pull(dir, url) + root = Dir.pwd + Dir.chdir dir + _pp "GIT PULL", url, dir.relative_path + _run pull_options + Dir.chdir root + end end class Command::Mrbc < Command @@ -250,9 +259,14 @@ module MRuby infiles.each do |f| _pp "MRBC", f.relative_path, nil, :indent => 2 end - IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}} #{infiles.join(' ')}", 'r+') do |io| + IO.popen("#{filename @command} #{@compile_options % {:funcname => funcname}} #{filename(infiles).join(' ')}", 'r+') do |io| out.puts io.read end + # if mrbc execution fail, drop the file + unless $?.exitstatus + File.delete(out.path) + exit -1 + end end end diff --git a/tasks/mruby_build_gem.rake b/tasks/mruby_build_gem.rake index 870ccfa57..24aea71ab 100644 --- a/tasks/mruby_build_gem.rake +++ b/tasks/mruby_build_gem.rake @@ -39,14 +39,20 @@ module MRuby gemdir = "#{root}/mrbgems/#{params[:core]}" elsif params[:git] url = params[:git] - gemdir = "build/mrbgems/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}" - return gemdir if File.exists?(gemdir) + gemdir = "#{build_dir}/mrbgems/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}" - options = [params[:options]] || [] - options << "--branch \"#{params[:branch]}\"" if params[:branch] - - FileUtils.mkdir_p "build/mrbgems" - git.run_clone gemdir, url, options + if File.exists?(gemdir) + if $pull_gems + git.run_pull gemdir, url + else + gemdir + end + else + options = [params[:options]] || [] + options << "--branch \"#{params[:branch]}\"" if params[:branch] + FileUtils.mkdir_p "#{build_dir}/mrbgems" + git.run_clone gemdir, url, options + end else fail "unknown gem option #{params}" end diff --git a/tasks/toolchains/androideabi.rake b/tasks/toolchains/androideabi.rake index a69fd1a9d..a20027c0d 100644 --- a/tasks/toolchains/androideabi.rake +++ b/tasks/toolchains/androideabi.rake @@ -41,20 +41,23 @@ MRuby::Toolchain.new(:androideabi) do |conf| end if ANDROID_STANDALONE_TOOLCHAIN == nil then - if RUBY_PLATFORM.include?('darwin') then + case RUBY_PLATFORM + when /cygwin|mswin|mingw|bccwin|wince|emx/i + HOST_PLATFORM = 'windows' + when /darwin/i HOST_PLATFORM = 'darwin-x86' - elsif RUBY_PLATFORM.include?('linux') then + when /x86_64-linux/i + HOST_PLATFORM = 'linux-x86_64' + when /linux/i HOST_PLATFORM = 'linux-x86' - elsif RUBY_PLATFORM.include?('win') then - HOST_PLATFORM = 'windows' else - # Unknown host platform. + # Unknown host platform end ANDROID_TARGET_PLATFORM = ENV['ANDROID_TARGET_PLATFORM'] || DEFAULT_ANDROID_TARGET_PLATFORM path_to_toolchain = ANDROID_NDK_HOME + '/toolchains/' - path_to_sysroot = ANDROID_NDK_HOME + '/platforms/' + ANDROID_TARGET_PLATFORM + path_to_sysroot = ANDROID_NDK_HOME + '/platforms/' + ANDROID_TARGET_PLATFORM if ANDROID_TOOLCHAIN.downcase == 'gcc' then case ANDROID_TARGET_ARCH.downcase when 'arch-arm', 'arm' then diff --git a/test/t/integer.rb b/test/t/integer.rb index 46011f94a..9b19216d9 100644 --- a/test/t/integer.rb +++ b/test/t/integer.rb @@ -104,6 +104,14 @@ assert('Integer#<<', '15.2.8.3.12') do # 00010111 (23) # = 00101110 (46) assert_equal 23 << 1, 46 + + # Left Shift by a negative is Right Shift + assert_equal 46 << -1, 23 + + # Raise when shift is too large + assert_raise(RangeError) do + 2 << 128 + end end assert('Integer#>>', '15.2.8.3.13') do @@ -111,6 +119,17 @@ assert('Integer#>>', '15.2.8.3.13') do # 00101110 (46) # = 00010111 (23) assert_equal 46 >> 1, 23 + + # Right Shift by a negative is Left Shift + assert_equal 23 >> -1, 46 + + # Don't raise on large Right Shift + assert_equal 23 >> 128, 0 + + # Raise when shift is too large + assert_raise(RangeError) do + 2 >> -128 + end end assert('Integer#ceil', '15.2.8.3.14') do diff --git a/test/t/module.rb b/test/t/module.rb index 9d735f5da..618b57f06 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -37,6 +37,145 @@ assert('Module#append_features', '15.2.2.4.10') do assert_equal Test4AppendFeatures2.const_get(:Const4AppendFeatures2), Test4AppendFeatures2 end +assert('Module#attr NameError') do + %w[ + foo? + @foo + @@foo + $foo + ].each do |name| + module NameTest; end + + assert_raise(NameError) do + NameTest.module_eval { attr_reader name.to_sym } + end + + assert_raise(NameError) do + NameTest.module_eval { attr_writer name.to_sym } + end + + assert_raise(NameError) do + NameTest.module_eval { attr name.to_sym } + end + + assert_raise(NameError) do + NameTest.module_eval { attr_accessor name.to_sym } + end + end + +end + +assert('Module#attr', '15.2.2.4.11') do + class AttrTest + class << self + attr :cattr + def cattr_val=(val) + @cattr = val + end + end + attr :iattr + def iattr_val=(val) + @iattr = val + end + end + + test = AttrTest.new + assert_true AttrTest.respond_to?(:cattr) + assert_true test.respond_to?(:iattr) + + assert_false AttrTest.respond_to?(:vattr=) + assert_false test.respond_to?(:iattr=) + + test.iattr_val = 'test' + assert_equal 'test', test.iattr + + AttrTest.cattr_val = 'test' + assert_equal 'test', AttrTest.cattr +end + +assert('Module#attr_accessor', '15.2.2.4.12') do + class AttrTestAccessor + class << self + attr_accessor :cattr + end + attr_accessor :iattr, 'iattr2' + end + + attr_instance = AttrTestAccessor.new + assert_true AttrTestAccessor.respond_to?(:cattr=) + assert_true attr_instance.respond_to?(:iattr=) + assert_true attr_instance.respond_to?(:iattr2=) + assert_true AttrTestAccessor.respond_to?(:cattr) + assert_true attr_instance.respond_to?(:iattr) + assert_true attr_instance.respond_to?(:iattr2) + + attr_instance.iattr = 'test' + assert_equal 'test', attr_instance.iattr + + AttrTestAccessor.cattr = 'test' + assert_equal 'test', AttrTestAccessor.cattr +end + +assert('Module#attr_reader', '15.2.2.4.13') do + class AttrTestReader + class << self + attr_reader :cattr + def cattr_val=(val) + @cattr = val + end + end + attr_reader :iattr, 'iattr2' + def iattr_val=(val) + @iattr = val + end + end + + attr_instance = AttrTestReader.new + assert_true AttrTestReader.respond_to?(:cattr) + assert_true attr_instance.respond_to?(:iattr) + assert_true attr_instance.respond_to?(:iattr2) + + assert_false AttrTestReader.respond_to?(:cattr=) + assert_false attr_instance.respond_to?(:iattr=) + assert_false attr_instance.respond_to?(:iattr2=) + + attr_instance.iattr_val = 'test' + assert_equal 'test', attr_instance.iattr + + AttrTestReader.cattr_val = 'test' + assert_equal 'test', AttrTestReader.cattr +end + +assert('Module#attr_writer', '15.2.2.4.14') do + class AttrTestWriter + class << self + attr_writer :cattr + def cattr_val + @cattr + end + end + attr_writer :iattr, 'iattr2' + def iattr_val + @iattr + end + end + + attr_instance = AttrTestWriter.new + assert_true AttrTestWriter.respond_to?(:cattr=) + assert_true attr_instance.respond_to?(:iattr=) + assert_true attr_instance.respond_to?(:iattr2=) + + assert_false AttrTestWriter.respond_to?(:cattr) + assert_false attr_instance.respond_to?(:iattr) + assert_false attr_instance.respond_to?(:iattr2) + + attr_instance.iattr = 'test' + assert_equal 'test', attr_instance.iattr_val + + AttrTestWriter.cattr = 'test' + assert_equal 'test', AttrTestWriter.cattr_val +end + assert('Module#class_eval', '15.2.2.4.15') do class Test4ClassEval @a = 11 diff --git a/test/t/nil.rb b/test/t/nil.rb index 99b1215e9..08d2acdf1 100644 --- a/test/t/nil.rb +++ b/test/t/nil.rb @@ -27,4 +27,3 @@ end assert('NilClass#to_s', '15.2.4.3.5') do assert_equal nil.to_s, '' end - diff --git a/test/t/range.rb b/test/t/range.rb index fdf6b415c..da25abc0e 100644 --- a/test/t/range.rb +++ b/test/t/range.rb @@ -12,6 +12,7 @@ end assert('Range#==', '15.2.14.4.1') do assert_true (1..10) == (1..10) assert_false (1..10) == (1..100) + assert_true (1..10) == Range.new(1.0, 10.0) end assert('Range#===', '15.2.14.4.2') do @@ -72,3 +73,10 @@ assert('Range#member?', '15.2.14.4.11') do assert_true a.member?(5) assert_false a.member?(20) end + +assert('Range#eql?', '15.2.14.4.14') do + assert_true (1..10).eql? (1..10) + assert_false (1..10).eql? (1..100) + assert_false (1..10).eql? (Range.new(1.0, 10.0)) + assert_false (1..10).eql? "1..10" +end diff --git a/test/t/string.rb b/test/t/string.rb index ddae92d4a..c208835b4 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -399,12 +399,12 @@ end assert('String#to_i', '15.2.10.5.38') do a = ''.to_i - b = '123456789'.to_i + b = '32143'.to_i c = 'a'.to_i(16) d = '100'.to_i(2) assert_equal a, 0 - assert_equal b, 123456789 + assert_equal b, 32143 assert_equal c, 10 assert_equal d, 4 end diff --git a/travis_config.rb b/travis_config.rb index 040b1a255..bd2939f94 100644 --- a/travis_config.rb +++ b/travis_config.rb @@ -3,4 +3,5 @@ MRuby::Build.new do |conf| # include all core GEMs conf.gembox 'full-core' + conf.cc.defines = %w(MRB_DEBUG) end |
