diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/AUTHORS mruby-1.2.0+20160315+git4f20d58a/AUTHORS --- mruby-1.1.0+20150906+git1cbbb7e1/AUTHORS 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/AUTHORS 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ Original Authors "mruby developers" are: Yukihiro Matsumoto - FUKUOKA CSK CORPORATION + SCSK KYUSHU CORPORATION Kyushu Institute of Technology Network Applied Communication Laboratory, Inc. Daniel Bovensiepen @@ -32,3 +32,5 @@ Manycolors, Inc. Shota Nakano Yuichi Osawa + Terence Lee + Zachary Scott diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/build_config.rb mruby-1.2.0+20160315+git4f20d58a/build_config.rb --- mruby-1.1.0+20150906+git1cbbb7e1/build_config.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/build_config.rb 2016-03-14 00:35:53.000000000 +0000 @@ -21,7 +21,6 @@ # include the default GEMs conf.gembox 'default' - # C compiler settings # conf.cc do |cc| # cc.command = ENV['CC'] || 'gcc' @@ -99,7 +98,7 @@ conf.gembox 'default' # C compiler settings - conf.cc.defines = %w(ENABLE_DEBUG) + conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK) # Generate mruby debugger command (require mruby-eval) conf.gem :core => "mruby-bin-debugger" @@ -109,7 +108,12 @@ end MRuby::Build.new('test') do |conf| - toolchain :gcc + # Gets set by the VS command prompts. + if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] + toolchain :visualcpp + else + toolchain :gcc + end enable_debug conf.enable_bintest @@ -117,6 +121,14 @@ conf.gembox 'default' end + +MRuby::Build.new('bench') do |conf| + toolchain :gcc + + conf.cc.flags << '-O3' + + conf.gembox 'default' +end # Define cross build settings # MRuby::CrossBuild.new('32bit') do |conf| diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/debian/changelog mruby-1.2.0+20160315+git4f20d58a/debian/changelog --- mruby-1.1.0+20150906+git1cbbb7e1/debian/changelog 2015-09-12 04:06:25.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/debian/changelog 2016-03-14 18:31:10.000000000 +0000 @@ -1,3 +1,30 @@ +mruby (1.2.0+20160315+git4f20d58a-1) unstable; urgency=medium + + * Snapshot, taken from the master (20160315). + * Bump Standards-Version to 3.9.7. + + -- Nobuhiro Iwamatsu Tue, 15 Mar 2016 03:29:36 +0900 + +mruby (1.2.0+20151223+git7e4a7abf-1) unstable; urgency=medium + + * Snapshot, taken from the master (20151223). + + -- Akira Mitsui Wed, 23 Dec 2015 13:32:13 +0900 + +mruby (1.2.0-1) unstable; urgency=medium + + * New upstream release(1.2.0). + * Remove patch. because it fixed in upstream + + -- Akira Mitsui Tue, 17 Nov 2015 22:47:07 +0900 + +mruby (1.1.0+20151021+git68ba3862-1) unstable; urgency=medium + + * Snapshot, taken from the master (20151021). + * Add patches/fix_bintest_for_debuild.patch. + + -- Akira Mitsui Wed, 21 Oct 2015 21:21:18 +0900 + mruby (1.1.0+20150906+git1cbbb7e1-1) unstable; urgency=medium * Snapshot, taken from the master (20150906). @@ -34,7 +61,7 @@ mruby (1.1.0+20150131+git089f1f6c-1) unstable; urgency=medium * Snapshot, taken from the master (20150131). - * rm patch. because it fixed in upstream + * Remove patch. because it fixed in upstream -- Akira Mitsui Sat, 31 Jan 2015 16:58:37 +0900 diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/debian/control mruby-1.2.0+20160315+git4f20d58a/debian/control --- mruby-1.1.0+20150906+git1cbbb7e1/debian/control 2015-09-12 04:06:25.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/debian/control 2016-03-14 18:31:28.000000000 +0000 @@ -4,7 +4,7 @@ Maintainer: Nobuhiro Iwamatsu Uploaders: Akira Mitsui Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), ruby, bison -Standards-Version: 3.9.6 +Standards-Version: 3.9.7 Vcs-Git: git://github.com/mruby-debian/mruby.git Vcs-Browser: https://github.com/mruby-debian/mruby diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/debian/patches/series mruby-1.2.0+20160315+git4f20d58a/debian/patches/series --- mruby-1.1.0+20150906+git1cbbb7e1/debian/patches/series 2015-09-12 04:06:25.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/debian/patches/series 2016-03-14 18:29:17.000000000 +0000 @@ -1,3 +1,4 @@ enable_verbose_build.patch change_optimize_O2.patch add_fpic_amd64.patch + diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/array.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/array.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/array.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/array.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,250 +0,0 @@ -### mrb_ary_new - -```C -mrb_value mrb_ary_new(mrb_state *mrb); -``` -Initializes an array. -#### Example -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case we are declaring a variable new_ary of data type mrb_value. Then we are initializing it with the mrb_ary_new function which only takes an mruby state as an argument. -```C -#include -#include -#include "mruby/array.h" // Needs the array header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_value new_ary; // Declare variable. - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - new_ary = mrb_ary_new(mrb); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, new_ary); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` -test.rb -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` - -### mrb_ary_push -```C -void mrb_ary_push(mrb_state*, mrb_value, mrb_value); -``` -Pushes given value into an array. -#### Example -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case after initializing our array. We are declaring two variables with the mrb_int data type random_value1 & random_value2 and we initialize them 70 and 60 respectively. Then we use the mrb_ary_push function to push values those values into the array. -```C -#include -#include -#include "mruby/array.h" // Needs the array header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_value new_ary; // Declare variable. - mrb_int random_value1 = 70; // Initialize variable - mrb_int random_value2 = 60; // Initialize variable - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - new_ary = mrb_ary_new(mrb); // Initialize ruby array. - /* Pushes the fixnum value from random_value1 to the new_ary instance. */ - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1)); - /* Pushes the fixnum value from random_value2 to the new_ary instance. */ - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2)); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, new_ary); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` -test.rb -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` -#### Result -After compiling you should get these results. -```Ruby -[70, 60] -Array -``` - -## mrb_ary_pop -```C -mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); -``` -Pops the last element from the array. -#### Example -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case after initializing our array. We are declaring two variables with the mrb_int data type random_value1 & random_value2 and we initialize them 70 and 60 respectively. Then we use the mrb_ary_push function to push values those values into the array. Now here in the Ruby files we add another method -called pop_ary that will return the array alone(just to be clean) and you should see the last element gone. -```C -#include -#include -#include "mruby/array.h" // Needs the array header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_value new_ary; // Declare variable. - mrb_int random_value1 = 70; // Initialize variable - mrb_int random_value2 = 60; // Initialize variable - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - new_ary = mrb_ary_new(mrb); // Initialize ruby array. - /* Pushes the fixnum value from random_value1 to the new_ary instance. */ - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1)); - /* Pushes the fixnum value from random_value2 to the new_ary instance. */ - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2)); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, new_ary); - mrb_ary_pop(mrb, new_ary); // Pops the last element of the array. In this case 60. - mrb_funcall(mrb, obj, "pop_ary", 1, new_ary); // Calls the method again to show the results. - fclose(fp); - mrb_close(mrb); - return 0; -} -``` -test.rb -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end - def pop_ary(a) - puts a - end -end -Example_Class.new -``` -#### Result -After compiling you should get these results. -```Ruby -[70, 60] -Array -[70] -``` -## mrb_ary_ref -```C -mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); -``` -Returns a reference to an element of the array. Specified by the value given to mrb_int n. -#### Example -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case we're declaring a variable ary_ref with the data type of mrb_value. Then we assign mrb_ary_ref to it getting new_ary's value at index 1. -```C -#include -#include -#include "mruby/array.h" // Needs the array header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_value ary_ref; // Declare variable. - mrb_value new_ary; // Declare variable. - mrb_int random_value1 = 70; // Initialize variable - mrb_int random_value2 = 60; // Initialize variable - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - new_ary = mrb_ary_new(mrb); // Initialize ruby array. - /* Pushes the fixnum value from random_value1 to the new_ary instance. */ - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1)); - /* Pushes the fixnum value from random_value2 to the new_ary instance. */ - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2)); - ary_ref = mrb_ary_ref(mrb, new_ary, 1); // Gets the value of new_ary's second element at index 1. - mrb_value obj = mrb_load_file(mrb,fp); - /* Passing the value from ary_ref to the method method_name.*/ - mrb_funcall(mrb, obj, "method_name", 1, ary_ref); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` -test.rb -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` -#### Result -After compiling you should get these results. -```Ruby -60 -Fixnum -``` - -### mrb_ary_set -```C -void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); -``` -Sets a value to an index. -#### Example -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument and what class the passed in value is. In this case we're declaring a variable ary_ref with the data type of mrb_value. Then we assign mrb_ary_ref to it getting new_ary's value at index 1. -```C -#include -#include -#include "mruby/array.h" // Needs the array header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_value new_ary; - mrb_value ary_obj; - mrb_int random_value1 = 70; - mrb_int random_value2 = 60; - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - new_ary = mrb_ary_new(mrb); - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value1)); - mrb_ary_push(mrb, new_ary, mrb_fixnum_value(random_value2)); - /* Sets the fixnum value of 7 to the second index of the array.*/ - mrb_ary_set(mrb, new_ary, 2, mrb_fixnum_value(7)); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "before_after", 1, new_ary); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` -test.rb -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end - def before_after(a) - puts a - end -end -Example_Class.new -``` -#### Result -After compiling you should get these results. -```Ruby -[70, 60, 7] -``` diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/hash.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/hash.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/hash.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/hash.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,380 +0,0 @@ -### mrb_hash_new - -```C -mrb_value mrb_hash_new(mrb_state *mrb); -``` - -Initializes a hash. -#### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. This example initializes a hash. In pure Ruby doing this is equivalent -to Hash.new. - -```C -#include -#include -#include "mruby/hash.h" // Needs the hash header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - mrb_value new_hash; // Declare variable. - FILE *fp = fopen("test_ext.rb","r"); - new_hash = mrb_hash_new(mrb); // Initialize hash. - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, new_hash); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` - -#### test_ext.rb - -``` Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` - -### mrb_hash_set - -```C -void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val); -``` - -Sets a keys and values to hashes. -#### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. This example sets a key and value pair to a hash. In pure Ruby doing this is equivalent to: - -```Ruby -a = {:da_key => 80} -``` - -```C -#include -#include -#include "mruby/hash.h" // Needs the hash header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - mrb_value new_hash; // Declare variable. - mrb_sym hash_key = mrb_intern_cstr(mrb, "da_key"); // Declare a symbol. - mrb_int hash_value = 80; // Declare a fixnum value. - FILE *fp = fopen("test_ext.rb","r"); - new_hash = mrb_hash_new(mrb); // Initialize hash. - mrb_value obj = mrb_load_file(mrb,fp); - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key), mrb_fixnum_value(hash_value)); // Set values to hash. - mrb_funcall(mrb, obj, "method_name", 1, new_hash); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` - -#### test_ext.rb - -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` - -#### Result - -After compiling you should get these results. - -```Ruby -{:da_key=>80} -Hash -``` - -### mrb_hash_get - -```C -mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key); -``` - -Gets a value from a key. -#### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. This example gets a value from a key. In pure Ruby doing this is equivalent to: - -```Ruby -a = {:da_key => 80} -a[:da_key] -``` - -```C -#include -#include -#include "mruby/hash.h" // Needs the hash header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - mrb_value new_hash; // Declare variable for new hash object. - mrb_value get_hash_value; // Declare variable for getting a value from a hash. - mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol. - mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol. - mrb_int hash_value_a = 80; // Declare a fixnum value. - mrb_int hash_value_b = 90; // Declare a fixnum value. - FILE *fp = fopen("test_ext.rb","r"); - new_hash = mrb_hash_new(mrb); // Initialize hash. - mrb_value obj = mrb_load_file(mrb,fp); - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash. - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash. - get_hash_value = mrb_hash_get(mrb, new_hash, mrb_symbol_value(hash_key_b)); // Get value from hash. - mrb_funcall(mrb, obj, "method_name", 1, get_hash_value); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` - -#### test_ext.rb - -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` - -#### Result - -After compiling you should get these results. - -```Ruby -90 -Fixnum -``` - -### mrb_hash_delete_key - -```C -mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); -``` - -Deletes hash key and value pair. -#### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. This example deletes hash key and value pair. In pure Ruby doing this is equivalent to: - -```Ruby -a = {:da_key1 => 80,:da_key2 => 90} -a.delete(:da_key2) -``` - -```C -#include -#include -#include "mruby/hash.h" // Needs the hash header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - mrb_value new_hash; // Declare variable for new hash object. - mrb_value get_hash_value; // Declare variable for getting a value from a hash. - mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol. - mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol. - mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol. - mrb_int hash_value_a = 80; // Declare a fixnum value. - mrb_int hash_value_b = 90; // Declare a fixnum value. - FILE *fp = fopen("test_ext.rb","r"); - new_hash = mrb_hash_new(mrb); // Initialize hash. - mrb_value obj = mrb_load_file(mrb,fp); - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash. - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash. - mrb_funcall(mrb, obj, "method_name", 1, new_hash); - mrb_hash_delete_key(mrb, new_hash, mrb_symbol_value(hash_key_b)); - mrb_funcall(mrb, obj, "another_method_name", 1, new_hash); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` - -#### test_ext.rb - -```Ruby -class Example_Class - def method_name(a) - puts "Hash pre deletion #{a}" - #puts a.class - end - # Show deleted key and value pair. - def another_method_name(a) - puts "Hash post deletion #{a}" - end -end -Example_Class.new -``` - -#### Result - -After compiling you should get these results. - -```Ruby -Hash pre deletion {:da_key1 => 80, :da_key2 => 90} -Hash post deletion {:da_key1 => 80} -``` - -### mrb_hash_keys - -```C -mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash); -``` - -Gets an array of keys. -#### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. This example gets an array of keys from a hash. - -```C -#include -#include -#include "mruby/hash.h" // Needs the hash header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - mrb_value new_hash; // Declare variable for new hash object. - mrb_value get_hash_keys; // Declare variable for getting an array of keys. - mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol. - mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol. - mrb_int hash_value_a = 80; // Declare a fixnum value. - mrb_int hash_value_b = 90; // Declare a fixnum value. - FILE *fp = fopen("test_ext.rb","r"); - new_hash = mrb_hash_new(mrb); // Initialize hash. - mrb_value obj = mrb_load_file(mrb,fp); - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash. - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash. - get_hash_keys = mrb_hash_keys(mrb, new_hash); // get an array of keys. - mrb_funcall(mrb, obj, "method_name", 1, get_hash_keys); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` - -#### test_ext.rb - -```Ruby -class Example_Class - def method_name(a) - puts a - puts a.class - end -end -Example_Class.new -``` - -#### Result - -After compiling you should get these results. - -```Ruby -[:da_key1, :da_key2] -Array -``` - -### mrb_hash_clear - -```C -mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash); -``` - -Clears the hash. -#### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. This example clears the hash. In pure Ruby doing this is equivalent to: - -```Ruby -a = {:da_key1 => 80,:da_key2 => 90} -a.clear -``` - -```C -#include -#include -#include "mruby/hash.h" // Needs the hash header. -#include "mruby/compile.h" - -int main(int argc, char *argv[]) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - mrb_value new_hash; // Declare variable for new hash object. - mrb_value get_hash; // Declare variable for getting a hash. - mrb_sym hash_key_a = mrb_intern_cstr(mrb, "da_key1"); // Declare a symbol. - mrb_sym hash_key_b = mrb_intern_cstr(mrb, "da_key2"); // Declare a symbol. - mrb_int hash_value_a = 80; // Declare a fixnum value. - mrb_int hash_value_b = 90; // Declare a fixnum value. - FILE *fp = fopen("test_ext.rb","r"); - new_hash = mrb_hash_new(mrb); // Initialize hash. - mrb_value obj = mrb_load_file(mrb,fp); - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_a), mrb_fixnum_value(hash_value_a)); // Set values to hash. - mrb_hash_set(mrb, new_hash, mrb_symbol_value(hash_key_b), mrb_fixnum_value(hash_value_b)); // Set values to hash. - mrb_funcall(mrb, obj, "method_name", 1, new_hash); - get_hash = mrb_hash_clear(mrb, new_hash); - mrb_funcall(mrb, obj, "another_method_name", 1, get_hash); - fclose(fp); - mrb_close(mrb); - return 0; -} -``` - -#### test_ext.rb - -```Ruby -class Example_Class - def method_name(a) - puts "Hash pre clear #{a}" - #puts a.class - end - # Show clear hash. - def another_method_name(a) - puts "Hash post clear #{a}" - end -end -Example_Class.new -``` - -#### Result - -After compiling you should get these results. - -```Ruby -Hash pre clear {:da_key1 => 80, :da_key2 => 90} -Hash post clear {} -``` diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/range.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/range.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/range.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/range.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -#### mrb_range_new -```C - mrb_value mrb_range_new(mrb_state*, mrb_value, mrb_value, mrb_bool); -``` -Initializes a Range. The first mrb_value being the beginning value and second being the ending value. -The third parameter is an mrb_bool value that represents the inclusion or exclusion of the last value. -If the third parameter is 0 then it includes the last value in the range. If the third parameter is 1 -then it excludes the last value in the range. -C code -```C - #include - #include - #include "mruby/range.h" // Needs the range header. - #include "mruby/compile.h" - - int main(int argc, char *argv[]) - { - mrb_int beg = 0; - mrb_int end = 2; - mrb_bool exclude = 1; - mrb_value range_obj; - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - range_obj = mrb_range_new(mrb, mrb_fixnum_value(beg), mrb_fixnum_value(end), exclude); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, range_obj); - fclose(fp); - mrb_close(mrb); - return 0; - } -``` -Ruby code -```Ruby - class Example_Class - def method_name(a) - puts a - puts a.class - end - end - Example_Class.new -``` -This returns the following: -```Ruby - 0...2 - Range -``` diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/re.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/re.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/re.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/re.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -### Macros -#### REGEXP_CLASS -A string with the name of the REGEXP class. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/string.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/string.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/string.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/string.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -## Macros -### mrb_str_ptr(s) -Returns a pointer from a Ruby string. -## Functions -### mrb_str_plus -```C - mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); -``` -Adds to strings together. -### mrb_ptr_to_str -```C - mrb_value mrb_ptr_to_str(mrb_state *, void*); -``` -Converts pointer into a Ruby string. -### mrb_obj_as_string -```C - mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); -``` -Returns an object as a Ruby string. -### mrb_str_resize -```C - mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); -``` -Resizes the string's length. -### mrb_str_substr -```C - mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); -``` -Returns a sub string. -### mrb_string_type -```C - mrb_value mrb_string_type(mrb_state *mrb, mrb_value str); -``` -Returns a Ruby string type. -### mrb_str_new_cstr -```C - const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); -``` -Returns a Ruby string as a C string. -### mrb_str_dup -```C - mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); -``` -Duplicates a string object. -### mrb_str_intern -```C - mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); -``` -Returns a symbol from a passed in string. -### mrb_str_to_str -```C - mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); -``` -Returns a converted string type. -### mrb_str_equal -```C - mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); -``` -Returns true if the strings match and false if the strings don't match. -### mrb_str_cat -```C - mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len); -``` -Returns a concated string comprised of a Ruby string and a C string. -### mrb_str_cat_cstr -```C - mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2); -``` -Returns a concated string comprised of a Ruby string and a C string(A shorter alternative to mrb_str_cat). -### mrb_str_append -```C - mrb_value mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2); -``` -Adds str2 to the end of str1. -### mrb_str_cmp -```C - int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2); -``` -Returns 0 if both Ruby strings are equal. -Returns a value < 0 if Ruby str1 is less than Ruby str2. -Returns a value > 0 if Ruby str2 is greater than Ruby str1. -### mrb_str_to_cstr -```C - char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str); -``` -Returns a C string from a Ruby string. -### mrb_str_inspect -```C - mrb_str_inspect(mrb_state *mrb, mrb_value str); -``` -Returns a printable version of str, surrounded by quote marks, with special characters escaped. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/value.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/value.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/value.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/value.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,238 +0,0 @@ -### mrb_float_value -```C -static inline mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f) -``` - -Returns a float in Ruby. - -##### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. In this case we are passing in mrb_float f = 0.09. Alternatively -double i = 0.09 could also be used. - - -example.c -```C -#include -#include -#include "mruby/compile.h" -#include "mruby/string.h" - -int -main(void) -{ - mrb_float f = 0.09;// or double i = 0.09; - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, mrb_float_value(mrb, f)); - fclose(fp); - mrb_close(mrb); - return 0; -} - -``` - -test.rb -```Ruby -class My_Class - def method_name(s) - puts s - puts s.class - end -end -a = My_Class.new -``` - -### mrb_fixnum_value - -```C -static inline mrb_value mrb_fixnum_value(mrb_int i) -``` - -Returns a fixnum in Ruby. - -##### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. In this case we are passing in mrb_int i = 99. Alternativly int i = 99 -could also be used. - - -example.c -```C -#include -#include -#include "mruby/compile.h" - -int -main(void) -{ - mrb_int i = 99; // or int i = 99; - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i)); - fclose(fp); - mrb_close(mrb); - return 0; -} - -``` - -test.rb -```Ruby -class My_Class - def method_name(s) - puts s - puts s.class - end -end -a = My_Class.new -``` - - - -### mrb_nil_value - -```C -static inline mrb_value mrb_nil_value(void) -``` - -Returns nil in Ruby. - -##### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. In this case we are passing in nothing and we will get NillClass. - - -example.c -```C -#include -#include -#include "mruby/compile.h" - -int -main(void) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, mrb_nil_value()); - fclose(fp); - mrb_close(mrb); - return 0; -} - -``` - -test.rb -```Ruby -class My_Class - def method_name(s) - puts s - puts s.class - end -end -a = My_Class.new -``` - - -### mrb_false_value - -```C -static inline mrb_value mrb_false_value(void) -``` - -Returns false in Ruby. - -##### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. In this case we are passing in nothing and we will get FalseClass. - - -example.c -```C -#include -#include -#include "mruby/compile.h" - -int -main(void) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, mrb_false_value()); - fclose(fp); - mrb_close(mrb); - return 0; -} - -``` - -test.rb -```Ruby -class My_Class - def method_name(s) - puts s - puts s.class - end -end -a = My_Class.new -``` - - - -### mrb_true_value - -```C -static inline mrb_value mrb_true_value(void) -``` - -Returns true in Ruby. - -##### Example - -In this example we read from a Ruby file inside C. The Ruby code will print what you pass as an argument -and what class the passed in value is. In this case we are passing in nothing and we will get TrueClass. - - -example.c -```C -#include -#include -#include "mruby/compile.h" - -int -main(void) -{ - mrb_state *mrb = mrb_open(); - if (!mrb) { /* handle error */ } - FILE *fp = fopen("test.rb","r"); - mrb_value obj = mrb_load_file(mrb,fp); - mrb_funcall(mrb, obj, "method_name", 1, mrb_true_value()); - fclose(fp); - mrb_close(mrb); - return 0; -} - -``` - -test.rb -```Ruby -class My_Class - def method_name(s) - puts s - puts s.class - end -end -a = My_Class.new -``` diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/version.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/version.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby/version.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby/version.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -### Macros -#### MRUBY_RUBY_VERSION -The version of Ruby used by mruby. -#### MRUBY_RUBY_ENGINE -Ruby engine. -#### MRUBY_VERSION -The mruby version. -#### MRUBY_RELEASE_MAJOR -Major release version. -#### MRUBY_RELEASE_MINOR -Minor release version. -#### MRUBY_RELEASE_NO -Release number. -#### MRUBY_RELEASE_DATE -Release date as a string. -#### MRUBY_RELEASE_YEAR -Release year. -#### MRUBY_RELEASE_MONTH -Release month. -#### MRUBY_RELEASE_DAY -Release day. -#### MRUBY_BIRTH_YEAR -The year mruby was first created. -#### MRUBY_AUTHOR -Mruby's authors. -#### MRB_STRINGIZE0(expr) -A passed in expression. -#### MRB_STRINGIZE(expr) -Passes in an expression to MRB_STRINGIZE0. -#### MRUBY_DESCRIPTION -mruby's version, and release date. -#### MRUBY_COPYRIGHT -mruby's copyright information. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby.h.md mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby.h.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/mruby.h.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/mruby.h.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,217 +0,0 @@ -# mruby.h - -Basic header of mruby. -It includes **mrbconf.h**, **mruby/value.h**, **mruby/version.h** internally. - -## `mrb_state` management - -### mrb_open -```C -mrb_state* mrb_open(); -``` -Creates new `mrb_state`. - -### mrb_allocf -```C -typedef void* (*mrb_allocf) (struct mrb_state *mrb, void *ptr, size_t s, void *ud); -``` -Function pointer type of custom allocator used in `mrb_open_allocf`. - -The function pointing it must behave similarly as `realloc` except: -* If `ptr` is `NULL` it must allocate new space. -* If `s` is `NULL`, `ptr` must be freed. - -### mrb_open_allocf -```C -mrb_state* mrb_open_allocf(mrb_allocf f, void *ud); -``` -Create new `mrb_state` with custom allocator. -`ud` will be passed to custom allocator `f`. -If user data isn't required just pass `NULL`. -Function pointer `f` must satisfy requirements of its type. - -### mrb_close -```C -void mrb_close(mrb_state *mrb); -``` -Deletes `mrb_state`. - -## Method - -### mrb_get_args -```C -int mrb_get_args(mrb_state *mrb, const char *format, ...); -``` -Retrieve arguments from `mrb_state`. -When applicable, implicit conversions (such as `to_str`, -`to_ary`, `to_hash`) are applied to received arguments. -Use it inside a function pointed by `mrb_func_t`. -It returns the number of arguments retrieved. -`format` is a list of following format specifiers: - -char|mruby type|retrieve types|note -:---:|----------|--------------|--- -`o`|`Object`|`mrb_value`|Could be used to retrieve any type of argument -`C`|`Class`/`Module`|`mrb_value`| -`S`|`String`|`mrb_value`|when ! follows, the value may be nil -`A`|`Array`|`mrb_value`|when ! follows, the value may be nil -`H`|`Hash`|`mrb_value`|when ! follows, the value may be nil -`s`|`String`|`char*`, `mrb_int`|Receive two arguments; s! gives (NULL,0) for nil -`z`|`String`|`char*`|NUL terminated string; z! gives NULL for nil -`a`|`Array`|`mrb_value*`, `mrb_int`|Receive two arguments; a! gives (NULL,0) for nil -`f`|`Float`|`mrb_float`| -`i`|`Integer`|`mrb_int`| -`b`|boolean|`mrb_bool`| -`n`|`Symbol`|`mrb_sym`| -`&`|block|`mrb_value`| -`*`|rest arguments|`mrb_value*`, `mrb_int`|Receive the rest of arguments as an array. -||optional||After this spec following specs would be optional. -`?`|optional given|`mrb_bool`|True if preceding argument is given. Used to check optional argument is given. - -The passing variadic arguments must be a pointer of retrieving type. - -### mrb_define_class -```C -MRB_API struct RClass *mrb_define_class(mrb_state *, const char*, struct RClass*); -``` -Defines a new class. If you're creating a gem it may look something like this: - -```C -void mrb_example_gem_init(mrb_state* mrb) { - struct RClass *example_class; - example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class); -} - -void mrb_example_gem_final(mrb_state* mrb) { - //free(TheAnimals); -} -``` -### mrb_define_method - -```C -MRB_API void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); -``` - -Defines a global function in ruby. If you're creating a gem it may look something like this: - -```C -mrb_value example_method(mrb_state* mrb, mrb_value self){ - puts("Executing example command!"); - return self; -} - -void mrb_example_gem_init(mrb_state* mrb) { - mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE()); -} - -void mrb_example_gem_final(mrb_state* mrb) { - //free(TheAnimals); -} -``` - -Or maybe you want to create a class method for a class? It might look something like this: - -```C -mrb_value example_method(mrb_state* mrb, mrb_value self){ - puts("Examples are like pizza..."); - return self; -} - -void mrb_example_gem_init(mrb_state* mrb) { - struct RClass *example_class; - example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class); - mrb_define_method(mrb, example_class, "example_method", example_method, MRB_ARGS_NONE()); -} - -void mrb_example_gem_final(mrb_state* mrb) { - //free(TheAnimals); -} -``` -### mrb_define_module - -```C -MRB_API struct RClass *mrb_define_module(mrb_state *, const char*); -``` - -Defines a module. If you're creating a gem it may look something like this: - -```C -mrb_value example_method(mrb_state* mrb, mrb_value self){ - puts("Examples are like tacos..."); - return self; -} - -void mrb_example_gem_init(mrb_state* mrb) { - struct RClass *example_module; - example_module = mrb_define_module(mrb, "Example_Module"); -} - -void mrb_example_gem_final(mrb_state* mrb) { - //free(TheAnimals); -} -``` - -### mrb_define_module_function - -```C -MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); -``` - -Defines a module function. If you're creating a gem it may look something like this: - - -```C -mrb_value example_method(mrb_state* mrb, mrb_value self){ - puts("Examples are like hot wings..."); - return self; -} - -void mrb_example_gem_init(mrb_state* mrb) { - struct RClass *example_module; - example_module = mrb_define_module(mrb, "Example_Module"); - mrb_define_module_function(mrb, example_module, "example_method", example_method, MRB_ARGS_NONE()); -} - -void mrb_example_gem_final(mrb_state* mrb) { - //free(TheAnimals); -} -``` - -### mrb_define_const - -```C -MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); -``` - -Defines a constant. If you're creating a gem it may look something like this: - -```C -mrb_value example_method(mrb_state* mrb, mrb_value self){ - puts("Examples are like hot wings..."); - return self; -} - -void mrb_example_gem_init(mrb_state* mrb) { - mrb_define_const(mrb, mrb->kernel_module, "EXAPMLE_CONSTANT", mrb_fixnum_value(0x00000001)); -} - -void mrb_example_gem_final(mrb_state* mrb) { - //free(TheAnimals); -} -``` - -### mrb_str_new_cstr - -```C -MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*); -``` - -Turns a C string into a Ruby string value. - - -### mrb_value mrb_funcall - -```C -MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); -``` -Call existing ruby functions. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/api/README.md mruby-1.2.0+20160315+git4f20d58a/doc/api/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/api/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/api/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -# C API Reference - -This is a C API Reference. -The structure of this document will follow the directory structure of `include/` directory. - -## Headers list -Header name|Features ------------|-------- -[mrbconf.h](../mrbconf/README.md)|Defines macros for mruby configurations. -[mruby.h](./mruby.h.md)|Main header of mruby C API. Include this first. -[mruby/array.h](./mruby/array.h.md)|`Array` class. -[mruby/class.h](./mruby/class.h.md)|`Class` class. -[mruby/compile.h](./mruby/compile.h.md)|mruby compiler. -[mruby/data.h](./mruby/data.h.md)|User defined object. -[mruby/debug.h](./mruby/debug.h.md)|Debugging. -[mruby/dump.h](./mruby/dump.h.md)|Dumping compiled mruby script. -[mruby/error.h](./mruby/error.h.md)|Error handling. -[mruby/gc.h](./mruby/gc.h.md)|Uncommon memory management stuffs. -[mruby/hash.h](./mruby/hash.h.md)|`Hash` class. -[mruby/irep.h](./mruby/irep.h.md)|Compiled mruby script. -[mruby/khash.h](./mruby/khash.h.md)|Defines of khash which is used in hash table of mruby. -[mruby/numeric.h](./mruby/numeric.h.md)|`Numeric` class and sub-classes of it. -[mruby/opode.h](./mruby/opcode.h.md)|Operation codes used in mruby VM. -[mruby/proc.h](./mruby/proc.h.md)|`Proc` class. -[mruby/range.h](./mruby/range.h.md)|`Range` class. -[mruby/re.h](./mruby/re.h.md)|`Regexp` class. -[mruby/string.h](./mruby/string.h.md)|`String` class. -[mruby/value.h](./mruby/value.h.md)|`mrb_value` functions and macros. -[mruby/variable.h](./mruby/variable.h.md)|Functions to access to mruby variables. -[mruby/version.h](./mruby/version.h.md)|Macros of mruby version. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/compile/README.md mruby-1.2.0+20160315+git4f20d58a/doc/compile/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/compile/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/compile/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,481 +0,0 @@ -# Compile - -mruby uses Rake to compile and cross-compile all libraries and -binaries. - -## Prerequisites - -To compile mruby out of the source code you need the following tools: -* C Compiler (i.e. ```gcc```) -* Linker (i.e. ```gcc```) -* Archive utility (i.e. ```ar```) -* Parser generator (i.e. ```bison```) -* Ruby 1.8 or 1.9 (i.e. ```ruby``` or ```jruby```) - -Optional: -* GIT (to update mruby source and integrate mrbgems easier) -* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc) -* Assembler (to use GEMs which include \*.asm) - -## Usage - -Inside of the root directory of the mruby source a file exists -called *build_config.rb*. This file contains the build configuration -of mruby and looks like this for example: -```ruby -MRuby::Build.new do |conf| - toolchain :gcc -end -``` - -All tools necessary to compile mruby can be set or modified here. In case -you want to maintain an additional *build_config.rb* you can define a -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```. To see full command line on -build, call ```./minirake -v```. - -## Build Configuration - -Inside of the *build_config.rb* the following options can be configured -based on your environment. - -### Toolchains - -The mruby build system already contains a set of toolchain templates which -configure the build environment for specific compiler infrastructures. - -#### GCC - -Toolchain configuration for the GNU C Compiler. -```ruby -toolchain :gcc -``` - -#### clang - -Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the -GCC toolchain. -```ruby -toolchain :clang -``` - -#### Visual Studio 2010, 2012 and 2013 - -Toolchain configuration for Visual Studio on Windows. If you use the -[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx), -you normally do not have to specify this manually, since it gets automatically detected by our build process. -``` -toolchain :visualcpp -``` - -#### Android - -Toolchain configuration for Android. -```ruby -toolchain :androideabi -``` - -Requires the custom standalone Android NDK and the toolchain path -in ```ANDROID_STANDALONE_TOOLCHAIN```. - -### Binaries - -It is possible to select which tools should be compiled during the compilation -process. The following tools can be selected: -* mruby (mruby interpreter) -* mirb (mruby interactive shell) - -To select them declare conf.gem as follows: -```ruby -conf.gem "#{root}/mrbgems/mruby-bin-mruby" -conf.gem "#{root}/mrbgems/mruby-bin-mirb" -``` - -### File Separator - -Some environments require a different file separator character. It is possible to -set the character via ```conf.file_separator```. -```ruby -conf.file_separator = '/' -``` - -### C Compiler - -Configuration of the C compiler binary, flags and include paths. -```ruby -conf.cc do |cc| - cc.command = ... - cc.flags = ... - cc.include_paths = ... - cc.defines = ... - cc.option_include_path = ... - cc.option_define = ... - cc.compile_options = ... -end -``` - -C Compiler has header searcher to detect installed library. - -If you need a include path of header file use ```search_header_path```: -```ruby -# Searches ```iconv.h```. -# If found it will return include path of the header file. -# Otherwise it will return nil . -fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h' -``` - -If you need a full file name of header file use ```search_header```: -```ruby -# Searches ```iconv.h```. -# If found it will return full path of the header file. -# Otherwise it will return nil . -iconv_h = conf.cc.search_header 'iconv.h' -print "iconv.h found: #{iconv_h}\n" -``` - -Header searcher uses compiler's ```include_paths``` by default. -When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain) -it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```) - -If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler: -```ruby -def conf.cc.header_search_paths - ['/opt/local/include'] + include_paths -end -``` - -### Linker - -Configuration of the Linker binary, flags and library paths. -```ruby -conf.linker do |linker| - linker.command = ... - linker.flags = ... - linker.flags_before_libraries = ... - linker.libraries = ... - linker.flags_after_libraries = ... - linker.library_paths = .... - linker.option_library = ... - linker.option_library_path = ... - linker.link_options = ... -end -``` - -### Archiver - -Configuration of the Archiver binary and flags. -```ruby -conf.archiver do |archiver| - archiver.command = ... - archiver.archive_options = ... -end -``` - -### Parser Generator - -Configuration of the Parser Generator binary and flags. -```ruby -conf.yacc do |yacc| - yacc.command = ... - yacc.compile_options = ... -end -``` - -### GPerf - -Configuration of the GPerf binary and flags. -```ruby -conf.gperf do |gperf| - gperf.command = ... - gperf.compile_options = ... -end -``` - -### File Extensions -```ruby -conf.exts do |exts| - exts.object = ... - exts.executable = ... - exts.library = ... -end -``` - -### Mrbgems - -Integrate GEMs in the build process. -```ruby -# Integrate GEM with additional configuration -conf.gem 'path/to/gem' do |g| - g.cc.flags << ... -end - -# Integrate GEM without additional configuration -conf.gem 'path/to/another/gem' -``` - -See doc/mrbgems/README.md for more option about mrbgems. - -### Mrbtest - -Configuration Mrbtest build process. - -If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only``` -```ruby -conf.build_mrbtest_lib_only -``` - -### Bintest - -Tests for mrbgem tools using CRuby. -To have bintests place \*.rb scripts to ```bintest/``` directory of mrbgems. -See ```mruby-bin-*/bintest/*.rb``` if you need examples. -If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```. - -You can enable it with following: -```ruby -conf.enable_bintest -``` - -### C++ ABI - -mruby can use C++ exception to raise exception internally. -It is called C++ ABI mode. -By using C++ exception it can release C++ stack object correctly. -Whenever you mix C++ code C++ ABI mode would be enabled automatically. -If you need to enable C++ ABI mode explicitly add the following: -```ruby -conf.enable_cxx_abi -``` - -#### C++ exception disabling. - -If you need to force C++ exception disable -(For example using a compiler option to disable C++ exception) -add following: -```ruby -conf.disable_cxx_exception -``` - -Note that it must be called before ```enable_cxx_abi``` or ```gem``` method. - -### Debugging mode - -To enable debugging mode add the following: -```ruby -conf.enable_debug -``` - -When debugging mode is enabled -* Macro ```MRB_DEBUG``` would be defined. - * Which means ```mrb_assert()``` macro is enabled. -* Debug information of irep would be generated by ```mrbc```. - * Because ```-g``` flag would be added to ```mrbc``` runner. - * You can have better backtrace of mruby scripts with this. - -## Cross-Compilation - -mruby can also be cross-compiled from one platform to another. To -achieve this the *build_config.rb* needs to contain an instance of -```MRuby::CrossBuild```. This instance defines the compilation -tools and flags for the target platform. An example could look -like this: -```ruby -MRuby::CrossBuild.new('32bit') do |conf| - toolchain :gcc - - conf.cc.flags << "-m32" - conf.linker.flags << "-m32" -end -``` - -All configuration options of ```MRuby::Build``` can also be used -in ```MRuby::CrossBuild```. - -### Mrbtest in Cross-Compilation - -In cross compilation, you can run ```mrbtest``` on emulator if -you have it by changing configuration of test runner. -```ruby -conf.test_runner do |t| - t.command = ... # set emulator. this value must be non nil or false - t.flags = ... # set flags of emulator - - def t.run(bin) # override `run` if you need to change the behavior of it - ... # `bin` is the full path of mrbtest - end -end -``` - -## Build process - -During the build process the directory *build* will be created in the -root directory. The structure of this directory will look like this: - - +- build - | - +- host - | - +- bin <- Binaries (mirb, mrbc and mruby) - | - +- lib <- Libraries (libmruby.a and libmruby_core.a) - | - +- mrblib - | - +- src - | - +- test <- mrbtest tool - | - +- tools - | - +- mirb - | - +- mrbc - | - +- mruby - -The compilation workflow will look like this: -* compile all files under *src* (object files will be stored -in *build/host/src*) -* generate parser grammar out of *src/parse.y* (generated -result will be stored in *build/host/src/y.tab.c*) -* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o* -* create *build/host/lib/libmruby_core.a* out of all object files (C only) -* create ```build/host/bin/mrbc``` by compiling *tools/mrbc/mrbc.c* and -linking with *build/host/lib/libmruby_core.a* -* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files -under *mrblib* with ```build/host/bin/mrbc``` -* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o* -* create *build/host/lib/libmruby.a* out of all object files (C and Ruby) -* create ```build/host/bin/mruby``` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and -linking with *build/host/lib/libmruby.a* -* create ```build/host/bin/mirb``` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and -linking with *build/host/lib/libmruby.a* - -``` - _____ _____ ______ ____ ____ _____ _____ ____ -| CC |->|GEN |->|AR |->|CC |->|CC |->|AR |->|CC |->|CC | -| *.c | |y.tab| |core.a| |mrbc| |*.rb| |lib.a| |mruby| |mirb| - ----- ----- ------ ---- ---- ----- ----- ---- -``` - -### Cross-Compilation - -In case of a cross-compilation to *i386* the *build* directory structure looks -like this: - - +- build - | - +- host - | | - | +- bin <- Native Binaries - | | - | +- lib <- Native Libraries - | | - | +- mrblib - | | - | +- src - | | - | +- test <- Native mrbtest tool - | | - | +- tools - | | - | +- mirb - | | - | +- mrbc - | | - | +- mruby - +- i386 - | - +- bin <- Cross-compiled Binaries - | - +- lib <- Cross-compiled Libraries - | - +- mrblib - | - +- src - | - +- test <- Cross-compiled mrbtest tool - | - +- tools - | - +- mirb - | - +- mrbc - | - +- mruby - -An extra directory is created for the target platform. In case you -compile for *i386* a directory called *i386* is created under the -build directory. - -The cross compilation workflow starts in the same way as the normal -compilation by compiling all *native* libraries and binaries. -Afterwards the cross compilation process proceeds like this: -* cross-compile all files under *src* (object files will be stored -in *build/i386/src*) -* generate parser grammar out of *src/parse.y* (generated -result will be stored in *build/i386/src/y.tab.c*) -* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o* -* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files -under *mrblib* with the native ```build/host/bin/mrbc``` -* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o* -* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby) -* create ```build/i386/bin/mruby``` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and -linking with *build/i386/lib/libmruby.a* -* create ```build/i386/bin/mirb``` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and -linking with *build/i386/lib/libmruby.a* -* create *build/i386/lib/libmruby_core.a* out of all object files (C only) -* create ```build/i386/bin/mrbc``` by cross-compiling *tools/mrbc/mrbc.c* and -linking with *build/i386/lib/libmruby_core.a* - -``` - _______________________________________________________________ -| Native Compilation for Host System | -| _____ ______ _____ ____ ____ _____ | -| | CC | -> |AR | -> |GEN | -> |CC | -> |CC | -> |AR | | -| | *.c | |core.a| |y.tab| |mrbc| |*.rb| |lib.a| | -| ----- ------ ----- ---- ---- ----- | - --------------------------------------------------------------- - || - \||/ - \/ - ________________________________________________________________ -| Cross Compilation for Target System | -| _____ _____ _____ ____ ______ _____ | -| | CC | -> |AR | -> |CC | -> |CC | -> |AR | -> |CC | | -| | *.c | |lib.a| |mruby| |mirb| |core.a| |mrbc | | -| ----- ----- ----- ---- ------ ----- | - ---------------------------------------------------------------- -``` - -## Build Configuration Examples - -### Minimal Library - -To build a minimal mruby library you need to use the Cross Compiling -feature due to the reason that there are functions (i.e. stdio) which -can't be disabled for the main build. - -```ruby -MRuby::CrossBuild.new('Minimal') do |conf| - toolchain :gcc - - conf.cc.defines = %w(DISABLE_STDIO) - conf.bins = [] -end -``` - -This configuration defines a cross compile build called 'Minimal' which -is using the GCC and compiles for the host machine. It also disables -all usages of stdio and doesn't compile any binaries (i.e. mrbc). - -## Test Environment - -mruby's build process includes a test environment. In case you start the testing -of mruby, a native binary called ```mrbtest``` will be generated and executed. -This binary contains all test cases which are defined under *test/t*. In case -of a cross-compilation an additional cross-compiled *mrbtest* binary is -generated. You can copy this binary and run on your target system. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/debugger/README.md mruby-1.2.0+20160315+git4f20d58a/doc/debugger/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/debugger/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/debugger/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,370 +0,0 @@ -# How to Use the mruby Debugger - -copyright (c) 2014 Specified Non-Profit Corporation mruby Forum - -## 1. Summary - -This file documents the mruby debugger ('mrdb') methods. - -## 2 Debugging with mrdb - -## 2.1 Building mrdb - -The trunk of the mruby source tree, with the most recent mrdb, can be checked out with the following command: - -```bash -$ git clone https://github.com/mruby/mruby.git -``` - -To run the `make` command: - -```bash -$ cd mruby -$ make -``` - -By default, the `make` command will install the debugger files into mruby/bin. - -You can add the path for mrdb on your host environment with the following command: - -```bash -$ echo "export PATH=\$PATH:MRUBY_ROOT/bin" >> ~/.bashrc -$ source ~/.bashrc -``` - -`*MRUBY_ROOT` is the directory in which mruby source code will be installed. - -To confirm mrdb was installed properly, run mrdb with the `--version` option: - -```bash -$ mrdb --version -mruby 1.1.0 (2014-11-19) -``` - -## 2.2 Basic Operation - -### 2.2.1 Debugging mruby Script Files (rb file) with mrdb - -To invoke the mruby debugger, just type `mrdb`. - -To specify the script file: - -```bash -$ mrdb [option] file name -``` - -For example: Debugging sample.rb - -```bash -$ mrdb sample.rb -``` - -You can execute the shell commands listed below: - -|command|description| -|:-:|:--| -|run|execute programs| -|step|execute stepping| -|continue|execute continuing program| -|break|configure the breaking point| -|delete|deleting the breaking points| -|disable|disabling the breaking points| -|enable|enabling the breaking points| -|info breakpoints|showing list of the breaking points| -|print|evaluating and printing the values of the mruby expressions in the script| -|list|displaying the source cords| -|help|showing help| -|quit|terminating the mruby debugger| - -### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb - -You can debug the mruby binary files. - -#### 2.2.2.1 Debugging the binary files - -* notice -To debug mruby binary files, you need to compile mruby files with option `-g`. - -```bash -$ mrbc -g sample.rb -``` - -You can debug the mruby binary files with following command and the option `-b`. - -```bash -$ mrdb -b sample.mrb -``` - -Then you can execute all debugger shell commands. - -#### Break Command - -You can use any breakpoint to stop the program by specifying the line number and method name. -The breakpoint list will be displayed after you have set the breakpoint successfully. - -Usage: - -``` -break [file:]linenum -b [file:]linenum -break [class:]method -b [class:]method -``` - -The breakpoint will be ordered in serial from 1. -The number, which was given to the deleted breakpoint, will never be given to another breakpoint again. - -You can give multiple breakpoints to specified the line number and method. -Be ware that breakpoint command will not check the validity of the class name and method name. - -You can get the current breakpoint information by the following options. - -breakpoint breakpoint number : file name. line number - -breakpoint breakpoint number : [class name,] method name - -#### Continue Command - -Usage: - -``` -continue [N] -c [N] -``` - -N: the next breakpoint number - -When resuming the program, it will stop at breakpoint N (N-1 breakpoint will be ignored). - -When you run the `continue` command without specifying N, the program will be stopped at the next breakpoint. - -Example: - -``` -(foo.rb:1) continue 3 -``` - -This will resume the program and stop it at the third breakpoint. - -#### Delete Command - -This will delete the specified breakpoint. - -Usage: - -``` -delete [breakpoint-no] -d [breakpoint-no] -``` - -breakpoint-no: breakpoint number - -Example: - -``` -(foo.rb:1) delete -``` - -This will delete all of the breakpoints. - -``` -(foo.rb:1) delete 1 3 -``` - -This will delete the breakpoint at 1 and 3. - -#### Disable Command - -This will disable the specified breakpoint. - -Usage: - -``` -disable [breakpoint-no] -dis [breakpoint-no] -``` - -reappointing: breakpoint number - -Example: - -``` -(foo.rb:1) disable -``` - -Use `disable` if you would like to disable all of the breakpoints. - -``` -(foo.rb:1) disable 1 3 -``` - -This will disable the breakpoints at 1 and 3. - -#### Enable Command - -This will enable the specified breakpoints. - -Usage: - -``` -enable [breakpoint-no] -e [breakpoint-no] -``` - -breakpoint-no: breakpoint number - -Example: - -``` -(foo.rb:1) enable -``` - -Enabling all breakpoints -``` -(foo.rb:1) enable 1 3 -``` - -Enabling the breakpoint 1 and 3 - -#### eval command - -Evaluating the string as source code and printing the value. - -Same as print command, please see print command. - -#### help command - -Displaying the help message. - -Usage: - -``` -help [command] -h [command] -``` - -Typing `help` without any options will display the command list. - -#### Info Breakpoints Command - -Displaying the specified breakpoint information. - -Usage: - -``` -info breakpoints [breakpoint-no] -i b [breakpoint-no] -``` - -breakpoint-no: breakpoint number - -Typing "info breakpoints" without ant option will display all breakpoint information. -Example: - -``` -(sample.rb:1) info breakpoints -Num Type Enb What -1 breakpoint y at sample.rb:3 -> file name,line number -2 breakpoint n in Sample_class:sample_class_method -> [class:]method name -3 breakpoint y in sample_global_method -``` - -Displaying the specified breakpoint number: - -``` -(foo.rb:1) info breakpoints 1 3 -Num Type Enb What -1 breakpoint y at sample.rb:3 -3 breakpoint y in sample_global_method -``` - -#### List Command - -To display the code of the source file. - -Usage: - -``` -list [filename:]first[,last] -l [filename]:first[,last] -``` - -first: the opening row number -last : the closing row number - -When you specify the `first`, but not the `last` option, you will receive 10 rows. -When you do not specify both the `first` and `last` options, you will receive the next 10 rows. - -Example: - -``` -Specifying file name and first row number -sample.rb:1) list sample2.rb:5 -``` - -Specifying the file name and the first and last row number: - -``` -(sample.rb:1) list sample2.rb:6,7 -``` - -#### Print Command - -Evaluating the string as source code and printing the value. - -Usage: - -``` -print [expr] -p [expr] -``` - -expr: expression - -The expression is mandatory. -The displayed expressions will be serially ordered from 1. -If an exception occurs, the exception information will be displayed and the debugging will be continued. - -Example: - -``` -(sample.rb:1) print 1+2 -$1 = 3 -(sample.rb:1) print self -$2 = main -``` - -Below is the case of the exception: - -``` -(sample.rb:1) print (1+2 -$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')' -``` - -#### Quit Command - -Quitting the debugger. - -Usage: - -``` -quit -q -``` - -#### Run Command - -Running the program and stopping at the first breakpoint. - -Usage: - -``` -run -r -``` - -#### Step Command - -This will run the program step by step. -When the method and the block are invoked, the program will be stop at the first row. -The program, which is developed in C, will be ignored. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/compile.md mruby-1.2.0+20160315+git4f20d58a/doc/guides/compile.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/compile.md 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/guides/compile.md 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,481 @@ +# Compile + +mruby uses Rake to compile and cross-compile all libraries and +binaries. + +## Prerequisites + +To compile mruby out of the source code you need the following tools: +* C Compiler (i.e. ```gcc```) +* Linker (i.e. ```gcc```) +* Archive utility (i.e. ```ar```) +* Parser generator (i.e. ```bison```) +* Ruby 1.8 or 1.9 (i.e. ```ruby``` or ```jruby```) + +Optional: +* GIT (to update mruby source and integrate mrbgems easier) +* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc) +* Assembler (to use GEMs which include \*.asm) + +## Usage + +Inside of the root directory of the mruby source a file exists +called *build_config.rb*. This file contains the build configuration +of mruby and looks like this for example: +```ruby +MRuby::Build.new do |conf| + toolchain :gcc +end +``` + +All tools necessary to compile mruby can be set or modified here. In case +you want to maintain an additional *build_config.rb* you can define a +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```. To see full command line on +build, call ```./minirake -v```. + +## Build Configuration + +Inside of the *build_config.rb* the following options can be configured +based on your environment. + +### Toolchains + +The mruby build system already contains a set of toolchain templates which +configure the build environment for specific compiler infrastructures. + +#### GCC + +Toolchain configuration for the GNU C Compiler. +```ruby +toolchain :gcc +``` + +#### clang + +Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the +GCC toolchain. +```ruby +toolchain :clang +``` + +#### Visual Studio 2010, 2012 and 2013 + +Toolchain configuration for Visual Studio on Windows. If you use the +[Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx), +you normally do not have to specify this manually, since it gets automatically detected by our build process. +``` +toolchain :visualcpp +``` + +#### Android + +Toolchain configuration for Android. +```ruby +toolchain :android +``` + +Requires the custom standalone Android NDK and the toolchain path +in ```ANDROID_STANDALONE_TOOLCHAIN```. + +### Binaries + +It is possible to select which tools should be compiled during the compilation +process. The following tools can be selected: +* mruby (mruby interpreter) +* mirb (mruby interactive shell) + +To select them declare conf.gem as follows: +```ruby +conf.gem "#{root}/mrbgems/mruby-bin-mruby" +conf.gem "#{root}/mrbgems/mruby-bin-mirb" +``` + +### File Separator + +Some environments require a different file separator character. It is possible to +set the character via ```conf.file_separator```. +```ruby +conf.file_separator = '/' +``` + +### C Compiler + +Configuration of the C compiler binary, flags and include paths. +```ruby +conf.cc do |cc| + cc.command = ... + cc.flags = ... + cc.include_paths = ... + cc.defines = ... + cc.option_include_path = ... + cc.option_define = ... + cc.compile_options = ... +end +``` + +C Compiler has header searcher to detect installed library. + +If you need a include path of header file use ```search_header_path```: +```ruby +# Searches ```iconv.h```. +# If found it will return include path of the header file. +# Otherwise it will return nil . +fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h' +``` + +If you need a full file name of header file use ```search_header```: +```ruby +# Searches ```iconv.h```. +# If found it will return full path of the header file. +# Otherwise it will return nil . +iconv_h = conf.cc.search_header 'iconv.h' +print "iconv.h found: #{iconv_h}\n" +``` + +Header searcher uses compiler's ```include_paths``` by default. +When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain) +it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```) + +If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler: +```ruby +def conf.cc.header_search_paths + ['/opt/local/include'] + include_paths +end +``` + +### Linker + +Configuration of the Linker binary, flags and library paths. +```ruby +conf.linker do |linker| + linker.command = ... + linker.flags = ... + linker.flags_before_libraries = ... + linker.libraries = ... + linker.flags_after_libraries = ... + linker.library_paths = .... + linker.option_library = ... + linker.option_library_path = ... + linker.link_options = ... +end +``` + +### Archiver + +Configuration of the Archiver binary and flags. +```ruby +conf.archiver do |archiver| + archiver.command = ... + archiver.archive_options = ... +end +``` + +### Parser Generator + +Configuration of the Parser Generator binary and flags. +```ruby +conf.yacc do |yacc| + yacc.command = ... + yacc.compile_options = ... +end +``` + +### GPerf + +Configuration of the GPerf binary and flags. +```ruby +conf.gperf do |gperf| + gperf.command = ... + gperf.compile_options = ... +end +``` + +### File Extensions +```ruby +conf.exts do |exts| + exts.object = ... + exts.executable = ... + exts.library = ... +end +``` + +### Mrbgems + +Integrate GEMs in the build process. +```ruby +# Integrate GEM with additional configuration +conf.gem 'path/to/gem' do |g| + g.cc.flags << ... +end + +# Integrate GEM without additional configuration +conf.gem 'path/to/another/gem' +``` + +See doc/mrbgems/README.md for more option about mrbgems. + +### Mrbtest + +Configuration Mrbtest build process. + +If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only``` +```ruby +conf.build_mrbtest_lib_only +``` + +### Bintest + +Tests for mrbgem tools using CRuby. +To have bintests place \*.rb scripts to ```bintest/``` directory of mrbgems. +See ```mruby-bin-*/bintest/*.rb``` if you need examples. +If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```. + +You can enable it with following: +```ruby +conf.enable_bintest +``` + +### C++ ABI + +mruby can use C++ exception to raise exception internally. +It is called C++ ABI mode. +By using C++ exception it can release C++ stack object correctly. +Whenever you mix C++ code C++ ABI mode would be enabled automatically. +If you need to enable C++ ABI mode explicitly add the following: +```ruby +conf.enable_cxx_abi +``` + +#### C++ exception disabling. + +If you need to force C++ exception disable +(For example using a compiler option to disable C++ exception) +add following: +```ruby +conf.disable_cxx_exception +``` + +Note that it must be called before ```enable_cxx_abi``` or ```gem``` method. + +### Debugging mode + +To enable debugging mode add the following: +```ruby +conf.enable_debug +``` + +When debugging mode is enabled +* Macro ```MRB_DEBUG``` would be defined. + * Which means ```mrb_assert()``` macro is enabled. +* Debug information of irep would be generated by ```mrbc```. + * Because ```-g``` flag would be added to ```mrbc``` runner. + * You can have better backtrace of mruby scripts with this. + +## Cross-Compilation + +mruby can also be cross-compiled from one platform to another. To +achieve this the *build_config.rb* needs to contain an instance of +```MRuby::CrossBuild```. This instance defines the compilation +tools and flags for the target platform. An example could look +like this: +```ruby +MRuby::CrossBuild.new('32bit') do |conf| + toolchain :gcc + + conf.cc.flags << "-m32" + conf.linker.flags << "-m32" +end +``` + +All configuration options of ```MRuby::Build``` can also be used +in ```MRuby::CrossBuild```. + +### Mrbtest in Cross-Compilation + +In cross compilation, you can run ```mrbtest``` on emulator if +you have it by changing configuration of test runner. +```ruby +conf.test_runner do |t| + t.command = ... # set emulator. this value must be non nil or false + t.flags = ... # set flags of emulator + + def t.run(bin) # override `run` if you need to change the behavior of it + ... # `bin` is the full path of mrbtest + end +end +``` + +## Build process + +During the build process the directory *build* will be created in the +root directory. The structure of this directory will look like this: + + +- build + | + +- host + | + +- bin <- Binaries (mirb, mrbc and mruby) + | + +- lib <- Libraries (libmruby.a and libmruby_core.a) + | + +- mrblib + | + +- src + | + +- test <- mrbtest tool + | + +- tools + | + +- mirb + | + +- mrbc + | + +- mruby + +The compilation workflow will look like this: +* compile all files under *src* (object files will be stored +in *build/host/src*) +* generate parser grammar out of *src/parse.y* (generated +result will be stored in *build/host/src/y.tab.c*) +* compile *build/host/src/y.tab.c* to *build/host/src/y.tab.o* +* create *build/host/lib/libmruby_core.a* out of all object files (C only) +* create ```build/host/bin/mrbc``` by compiling *tools/mrbc/mrbc.c* and +linking with *build/host/lib/libmruby_core.a* +* create *build/host/mrblib/mrblib.c* by compiling all \*.rb files +under *mrblib* with ```build/host/bin/mrbc``` +* compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o* +* create *build/host/lib/libmruby.a* out of all object files (C and Ruby) +* create ```build/host/bin/mruby``` by compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and +linking with *build/host/lib/libmruby.a* +* create ```build/host/bin/mirb``` by compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and +linking with *build/host/lib/libmruby.a* + +``` + _____ _____ ______ ____ ____ _____ _____ ____ +| CC |->|GEN |->|AR |->|CC |->|CC |->|AR |->|CC |->|CC | +| *.c | |y.tab| |core.a| |mrbc| |*.rb| |lib.a| |mruby| |mirb| + ----- ----- ------ ---- ---- ----- ----- ---- +``` + +### Cross-Compilation + +In case of a cross-compilation to *i386* the *build* directory structure looks +like this: + + +- build + | + +- host + | | + | +- bin <- Native Binaries + | | + | +- lib <- Native Libraries + | | + | +- mrblib + | | + | +- src + | | + | +- test <- Native mrbtest tool + | | + | +- tools + | | + | +- mirb + | | + | +- mrbc + | | + | +- mruby + +- i386 + | + +- bin <- Cross-compiled Binaries + | + +- lib <- Cross-compiled Libraries + | + +- mrblib + | + +- src + | + +- test <- Cross-compiled mrbtest tool + | + +- tools + | + +- mirb + | + +- mrbc + | + +- mruby + +An extra directory is created for the target platform. In case you +compile for *i386* a directory called *i386* is created under the +build directory. + +The cross compilation workflow starts in the same way as the normal +compilation by compiling all *native* libraries and binaries. +Afterwards the cross compilation process proceeds like this: +* cross-compile all files under *src* (object files will be stored +in *build/i386/src*) +* generate parser grammar out of *src/parse.y* (generated +result will be stored in *build/i386/src/y.tab.c*) +* cross-compile *build/i386/src/y.tab.c* to *build/i386/src/y.tab.o* +* create *build/i386/mrblib/mrblib.c* by compiling all \*.rb files +under *mrblib* with the native ```build/host/bin/mrbc``` +* cross-compile *build/host/mrblib/mrblib.c* to *build/host/mrblib/mrblib.o* +* create *build/i386/lib/libmruby.a* out of all object files (C and Ruby) +* create ```build/i386/bin/mruby``` by cross-compiling *mrbgems/mruby-bin-mruby/tools/mruby/mruby.c* and +linking with *build/i386/lib/libmruby.a* +* create ```build/i386/bin/mirb``` by cross-compiling *mrbgems/mruby-bin-mirb/tools/mirb/mirb.c* and +linking with *build/i386/lib/libmruby.a* +* create *build/i386/lib/libmruby_core.a* out of all object files (C only) +* create ```build/i386/bin/mrbc``` by cross-compiling *tools/mrbc/mrbc.c* and +linking with *build/i386/lib/libmruby_core.a* + +``` + _______________________________________________________________ +| Native Compilation for Host System | +| _____ ______ _____ ____ ____ _____ | +| | CC | -> |AR | -> |GEN | -> |CC | -> |CC | -> |AR | | +| | *.c | |core.a| |y.tab| |mrbc| |*.rb| |lib.a| | +| ----- ------ ----- ---- ---- ----- | + --------------------------------------------------------------- + || + \||/ + \/ + ________________________________________________________________ +| Cross Compilation for Target System | +| _____ _____ _____ ____ ______ _____ | +| | CC | -> |AR | -> |CC | -> |CC | -> |AR | -> |CC | | +| | *.c | |lib.a| |mruby| |mirb| |core.a| |mrbc | | +| ----- ----- ----- ---- ------ ----- | + ---------------------------------------------------------------- +``` + +## Build Configuration Examples + +### Minimal Library + +To build a minimal mruby library you need to use the Cross Compiling +feature due to the reason that there are functions (i.e. stdio) which +can't be disabled for the main build. + +```ruby +MRuby::CrossBuild.new('Minimal') do |conf| + toolchain :gcc + + conf.cc.defines = %w(MRB_DISABLE_STDIO) + conf.bins = [] +end +``` + +This configuration defines a cross compile build called 'Minimal' which +is using the GCC and compiles for the host machine. It also disables +all usages of stdio and doesn't compile any binaries (i.e. mrbc). + +## Test Environment + +mruby's build process includes a test environment. In case you start the testing +of mruby, a native binary called ```mrbtest``` will be generated and executed. +This binary contains all test cases which are defined under *test/t*. In case +of a cross-compilation an additional cross-compiled *mrbtest* binary is +generated. You can copy this binary and run on your target system. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/debugger.md mruby-1.2.0+20160315+git4f20d58a/doc/guides/debugger.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/debugger.md 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/guides/debugger.md 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,370 @@ +# How to Use the mruby Debugger + +copyright (c) 2014 Specified Non-Profit Corporation mruby Forum + +## 1. Summary + +This file documents the mruby debugger ('mrdb') methods. + +## 2 Debugging with mrdb + +## 2.1 Building mrdb + +The trunk of the mruby source tree, with the most recent mrdb, can be checked out with the following command: + +```bash +$ git clone https://github.com/mruby/mruby.git +``` + +To run the `make` command: + +```bash +$ cd mruby +$ make +``` + +By default, the `make` command will install the debugger files into mruby/bin. + +You can add the path for mrdb on your host environment with the following command: + +```bash +$ echo "export PATH=\$PATH:MRUBY_ROOT/bin" >> ~/.bashrc +$ source ~/.bashrc +``` + +`*MRUBY_ROOT` is the directory in which mruby source code will be installed. + +To confirm mrdb was installed properly, run mrdb with the `--version` option: + +```bash +$ mrdb --version +mruby 1.2.0 (2014-11-17) +``` + +## 2.2 Basic Operation + +### 2.2.1 Debugging mruby Script Files (rb file) with mrdb + +To invoke the mruby debugger, just type `mrdb`. + +To specify the script file: + +```bash +$ mrdb [option] file name +``` + +For example: Debugging sample.rb + +```bash +$ mrdb sample.rb +``` + +You can execute the shell commands listed below: + +|command|description| +|:-:|:--| +|run|execute programs| +|step|execute stepping| +|continue|execute continuing program| +|break|configure the breaking point| +|delete|deleting the breaking points| +|disable|disabling the breaking points| +|enable|enabling the breaking points| +|info breakpoints|showing list of the breaking points| +|print|evaluating and printing the values of the mruby expressions in the script| +|list|displaying the source cords| +|help|showing help| +|quit|terminating the mruby debugger| + +### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb + +You can debug the mruby binary files. + +#### 2.2.2.1 Debugging the binary files + +* notice +To debug mruby binary files, you need to compile mruby files with option `-g`. + +```bash +$ mrbc -g sample.rb +``` + +You can debug the mruby binary files with following command and the option `-b`. + +```bash +$ mrdb -b sample.mrb +``` + +Then you can execute all debugger shell commands. + +#### Break Command + +You can use any breakpoint to stop the program by specifying the line number and method name. +The breakpoint list will be displayed after you have set the breakpoint successfully. + +Usage: + +``` +break [file:]linenum +b [file:]linenum +break [class:]method +b [class:]method +``` + +The breakpoint will be ordered in serial from 1. +The number, which was given to the deleted breakpoint, will never be given to another breakpoint again. + +You can give multiple breakpoints to specified the line number and method. +Be ware that breakpoint command will not check the validity of the class name and method name. + +You can get the current breakpoint information by the following options. + +breakpoint breakpoint number : file name. line number + +breakpoint breakpoint number : [class name,] method name + +#### Continue Command + +Usage: + +``` +continue [N] +c [N] +``` + +N: the next breakpoint number + +When resuming the program, it will stop at breakpoint N (N-1 breakpoint will be ignored). + +When you run the `continue` command without specifying N, the program will be stopped at the next breakpoint. + +Example: + +``` +(foo.rb:1) continue 3 +``` + +This will resume the program and stop it at the third breakpoint. + +#### Delete Command + +This will delete the specified breakpoint. + +Usage: + +``` +delete [breakpoint-no] +d [breakpoint-no] +``` + +breakpoint-no: breakpoint number + +Example: + +``` +(foo.rb:1) delete +``` + +This will delete all of the breakpoints. + +``` +(foo.rb:1) delete 1 3 +``` + +This will delete the breakpoint at 1 and 3. + +#### Disable Command + +This will disable the specified breakpoint. + +Usage: + +``` +disable [breakpoint-no] +dis [breakpoint-no] +``` + +reappointing: breakpoint number + +Example: + +``` +(foo.rb:1) disable +``` + +Use `disable` if you would like to disable all of the breakpoints. + +``` +(foo.rb:1) disable 1 3 +``` + +This will disable the breakpoints at 1 and 3. + +#### Enable Command + +This will enable the specified breakpoints. + +Usage: + +``` +enable [breakpoint-no] +e [breakpoint-no] +``` + +breakpoint-no: breakpoint number + +Example: + +``` +(foo.rb:1) enable +``` + +Enabling all breakpoints +``` +(foo.rb:1) enable 1 3 +``` + +Enabling the breakpoint 1 and 3 + +#### eval command + +Evaluating the string as source code and printing the value. + +Same as print command, please see print command. + +#### help command + +Displaying the help message. + +Usage: + +``` +help [command] +h [command] +``` + +Typing `help` without any options will display the command list. + +#### Info Breakpoints Command + +Displaying the specified breakpoint information. + +Usage: + +``` +info breakpoints [breakpoint-no] +i b [breakpoint-no] +``` + +breakpoint-no: breakpoint number + +Typing "info breakpoints" without ant option will display all breakpoint information. +Example: + +``` +(sample.rb:1) info breakpoints +Num Type Enb What +1 breakpoint y at sample.rb:3 -> file name,line number +2 breakpoint n in Sample_class:sample_class_method -> [class:]method name +3 breakpoint y in sample_global_method +``` + +Displaying the specified breakpoint number: + +``` +(foo.rb:1) info breakpoints 1 3 +Num Type Enb What +1 breakpoint y at sample.rb:3 +3 breakpoint y in sample_global_method +``` + +#### List Command + +To display the code of the source file. + +Usage: + +``` +list [filename:]first[,last] +l [filename]:first[,last] +``` + +first: the opening row number +last : the closing row number + +When you specify the `first`, but not the `last` option, you will receive 10 rows. +When you do not specify both the `first` and `last` options, you will receive the next 10 rows. + +Example: + +``` +Specifying file name and first row number +sample.rb:1) list sample2.rb:5 +``` + +Specifying the file name and the first and last row number: + +``` +(sample.rb:1) list sample2.rb:6,7 +``` + +#### Print Command + +Evaluating the string as source code and printing the value. + +Usage: + +``` +print [expr] +p [expr] +``` + +expr: expression + +The expression is mandatory. +The displayed expressions will be serially ordered from 1. +If an exception occurs, the exception information will be displayed and the debugging will be continued. + +Example: + +``` +(sample.rb:1) print 1+2 +$1 = 3 +(sample.rb:1) print self +$2 = main +``` + +Below is the case of the exception: + +``` +(sample.rb:1) print (1+2 +$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')' +``` + +#### Quit Command + +Quitting the debugger. + +Usage: + +``` +quit +q +``` + +#### Run Command + +Running the program and stopping at the first breakpoint. + +Usage: + +``` +run +r +``` + +#### Step Command + +This will run the program step by step. +When the method and the block are invoked, the program will be stop at the first row. +The program, which is developed in C, will be ignored. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/gc-arena-howto.md mruby-1.2.0+20160315+git4f20d58a/doc/guides/gc-arena-howto.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/gc-arena-howto.md 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/guides/gc-arena-howto.md 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,177 @@ +# How to use `mrb_gc_arena_save()`/`mrb_gc_arena_restore()`/`mrb_gc_protect()` + +_This is an English translation of [Matz's blog post][matz blog post] +written in Japanese._ +_Some parts are updated to reflect recent changes._ +[matz blog post]: http://www.rubyist.net/~matz/20130731.html + +When you are extending mruby using C language, you may encounter +mysterious "arena overflow error" or memory leak or very slow +execution speed. This is an error indicating overflow of "GC arena" +implementing "conservative GC". + +GC (garbage collector) must ensure that object is "alive", in other +words, that it is referenced by somewhere from program. This can be +determined by checking if the object can be directly or indirectly +referenced by root. The local variables, global variables and +constants etc are root. + +If program execution is performed inside mruby VM, there is nothing to +worry about because GC can access all roots owned by VM. + +The problem arises when executing C functions. The object referenced +by C variable is also "alive", but mruby GC cannot aware of this, so +it might mistakenly recognize the objects referenced by only C +variables as dead. + +This can be a fatal bug if the GC tries to collect a live object. + +In CRuby, we scan C stack area, and use C variable as root to check +whether object is alive or not. Of course, because we are accessing C +stack just as memory region, we never know it is an integer or a +pointer. We workaround this by assuming that if it looks like a +pointer, then assume it as a pointer. We call it "conservative". + +By the way, CRuby's "conservative GC" has some problems. + +The biggest problem is we have no way to access to the stack area in +portable way. Therefore, we cannot use this method if we'd like to +implement highly portable runtime, like mruby. + +So we came up with an another plan to implement "conservative GC" in mruby. + +Again, the problem is when an object which was created in C function, becomes +no longer referenced in the Ruby world, and cannot be treated as garbage. + +In mruby, we recognize all objects created in C function are alive. +Then we have no problem such as confusing a live object as dead. + +This means that because we cannot collect truly dead object, we may +lose efficiency, but as a trade-off the GC itself is highly portable. +We can say goodbye to the problem that GC deletes live objects due to +optimization which sometimes occurs in CRuby. + +According to this idea, we have a table, called "GC arena", which +remembers objects created in C function. + +The arena is stack structure, when C function execution is returned to mruby +VM, all objects registered in the arena are popped. + +This works very well, but can cause another problem: "arena overflow error" or +memory leak. + +As of this writing, mruby automatically extend arena to remember +objects (See `MRB_GC_FIXED_ARENA` and `MRB_GC_ARENA_SIZE` in +doc/guides/mrbconf.md). + +If you create many objects in C functions, memory usage will increase, since +GC never kick in. This memory usage may look like memory leak, but will also +make execution slower as more memory will need to be allocated. + +With the build time configuration, you can limit the maximum size of +arena (e.g., 100). Then if you create many objects, arena overflows, +thus you will get an "arena overflow error". + +To workaround these problems, we have `mrb_gc_arena_save()` and +`mrb_gc_arena_restore()` functions. + +`int mrb_gc_arena_save(mrb)` returns the current position of the stack +top of GC arena, and `void mrb_gc_arena_restore(mrb, idx)` sets the +stack top position to back to given `idx`. + +We can use them like this: + +```c +int arena_idx = mrb_gc_arena_save(mrb); + +// ...create objects... +mrb_gc_arena_restore(mrb, arena_idx); + +``` + +In mruby, C function calls are surrounded by this save/restore, but we +can further optimize memory usage by surrounding save/restore, and can +avoid creating arena overflow bugs. + +Let's take a real example. Here is the source code of `Array#inspect`: + +```c +static mrb_value +inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list) +{ + mrb_int i; + mrb_value s, arystr; + char head[] = { '[' }; + char sep[] = { ',', ' ' }; + char tail[] = { ']' }; + + /* check recursive */ + for(i=0; i 0) { + mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep)); + } + if (mrb_array_p(RARRAY_PTR(ary)[i])) { + s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list); + } + else { + s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]); + } + mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s)); + mrb_gc_arena_restore(mrb, ai); + } + + mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail)); + mrb_ary_pop(mrb, list); + + return arystr; +} +``` + +This is a real example, so a little bit complicated, but bear with me. +The essence of `Array#inspect` is that after stringifying each element +of array using `inspect` method, we join them together so that we can +get `inspect` representation of the entire array. + +After the `inspect` representation is created, we no longer require the +individual string representation. This means that we don't have to register +these temporal objects into GC arena. + +Therefore, in order to keep the arena size small; the `ary_inspect()` function +will do the following: + +* save the position of the stack top using `mrb_gc_arena_save()`. +* get `inspect` representation of each element. +* append it to the constructing entire `inspect` representation of array. +* restore stack top position using `mrb_gc_arena_restore()`. + +Please note that the final `inspect` representation of entire array +was created before the call of `mrb_gc_arena_restore()`. Otherwise, +required temporal object may be deleted by GC. + +We may have a usecase where after creating many temporal objects, we'd +like to keep some of them. In this case, we cannot use the same idea +in `ary_inspect()` like appending objects to existing one. +Instead, after `mrb_gc_arena_restore()`, we must re-register the objects we +want to keep in the arena using `mrb_gc_protect(mrb, obj)`. +Use `mrb_gc_protect()` with caution because it could also lead to an "arena +overflow error". + +We must also mention that when `mrb_funcall` is called in top level, the return +value is also registered to GC arena, so repeated use of `mrb_funcall` may +eventually lead to an "arena overflow error". + +Use `mrb_gc_arena_save()` and `mrb_gc_arena_restore()` or possible use of +`mrb_gc_protect()` to workaround this. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/mrbconf.md mruby-1.2.0+20160315+git4f20d58a/doc/guides/mrbconf.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/mrbconf.md 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/guides/mrbconf.md 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,157 @@ +# mruby configuration macros. + +## How to use these macros. +You can use mrbconfs with following ways: +* Write them in `mrbconf.h`. + * Using compiler flags is preferred when building a cross binaries or multiple mruby binaries + since it's easier to use different mrbconf per each `MRuby::Build`. + * Most flags can be enabled by just commenting in. +* Pass them as compiler flags. + * Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`) + changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed. + +## stdio setting. +`MRB_DISABLE_STDIO` +* When defined `` functions won't be used. +* Some features will be disabled when this is enabled: + * `mrb_irep` load/dump from/to file. + * Compiling mruby script from file. + * Printing features in **src/print.c**. + +## Debug macros. +`MRB_ENABLE_DEBUG_HOOK` +* When defined code fetch hook and debug OP hook will be enabled. +* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`. +* Fetch hook will be called before any OP. +* Debug OP hook will be called when dispatching `OP_DEBUG`. + +`MRB_DEBUG` +* When defined `mrb_assert*` macro will be defined with macros from ``. +* Could be enabled via `enable_debug` method of `MRuby::Build`. + +## Stack configuration + +`MRB_STACK_EXTEND_DOUBLING` +* If defined doubles the stack size when extending it. +* Else extends stack with `MRB_STACK_GROWTH`. + +`MRB_STACK_GROWTH` +* Default value is `128`. +* Used in stack extending. +* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined. + +`MRB_STACK_MAX` +* Default value is `0x40000 - MRB_STACK_GROWTH`. +* Raises `RuntimeError` when stack size exceeds this value. + +## Primitive type configuration. + +`MRB_USE_FLOAT` +* When defined single precision floating point type(C type `float`) is used as `mrb_float`. +* Else double precision floating point type(C type `double`) is used as `mrb_float`. + +`MRB_INT16` +* When defined `int16_t` will be defined as `mrb_int`. +* Conflicts with `MRB_INT64`. + +`MRB_INT64` +* When defined `int64_t` will be defined as `mrb_int`. +* Conflicts with `MRB_INT16`. +* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer) +will be defined as `mrb_int`. + +## Garbage collector configuration. + +`MRB_GC_STRESS` +* When defined full GC is emitted per each `RBasic` allocation. +* Mainly used in memory manager debugging. + +`MRB_GC_TURN_OFF_GENERATIONAL` +* When defined turns generational GC by default. + +`MRB_GC_FIXED_ARENA` +* When defined used fixed size GC arena. +* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`. +* Useful tracking unnecessary mruby object allocation. + +`MRB_GC_ARENA_SIZE` +* Default value is `100`. +* Ignored when `MRB_GC_FIXED_ARENA` isn't defined. +* Defines fixed GC arena size. + +`MRB_HEAP_PAGE_SIZE` +* Defines value is `1024`. +* Specifies number of `RBasic` per each heap page. + +## Memory pool configuration. + +`POOL_ALIGNMENT` +* Default value is `4`. +* If you're allocating data types that requires alignment more than default value define the +largest value of required alignment. + +`POOL_PAGE_SIZE` +* Default value is `16000`. +* Specifies page size of pool page. +* Smaller the value is increases memory overhead. + +## State atexit configuration. + +`MRB_FIXED_STATE_ATEXIT_STACK` +* If defined enables fixed size `mrb_state` atexit stack. +* Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds +`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value. + +`MRB_FIXED_STATE_ATEXIT_STACK_SIZE` +* Default value is `5`. +* If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored. + +## `mrb_value` configuration. + +`MRB_ENDIAN_BIG` +* If defined compiles mruby for big endian machines. +* Used in `MRB_NAN_BOXING`. +* Some mrbgem use this mrbconf. + +`MRB_NAN_BOXING` +* If defined represent `mrb_value` in boxed `double`. +* Conflicts with `MRB_USE_FLOAT`. + +`MRB_WORD_BOXING` +* If defined represent `mrb_value` as a word. +* If defined `Float` will be a mruby object with `RBasic`. + +## Instance variable configuration. +`MRB_USE_IV_SEGLIST` +* If defined enable segmented list in instance variable table instead of khash. +* Segmented list is a linked list of key and value segments. +* It will linear search instead of hash search. + +`MRB_SEGMENT_SIZE` +* Default value is `4`. +* Specifies size of each segment in segment list. +* Ignored when `MRB_USE_IV_SEGLIST` isn't defined. + +`MRB_IVHASH_INIT_SIZE` +* Default value is `8`. +* Specifies initial size for instance variable table. +* Ignored when `MRB_USE_IV_SEGLIST` is defined. + +## Other configuration. +`MRB_UTF8_STRING` +* Adds UTF-8 encoding support to character-oriented String instance methods. +* If it isn't defined, they only support the US-ASCII encoding. + +`MRB_FUNCALL_ARGC_MAX` +* Default value is `16`. +* Specifies 4th argument(`argc`) max value of `mrb_funcall`. +* Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`. + +`KHASH_DEFAULT_SIZE` +* Default value is `32`. +* Specifies default size of khash table bucket. +* Used in `kh_init_ ## name` function. + +`MRB_STR_BUF_MIN_SIZE` +* Default value is `128`. +* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function.. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/mrbgems.md mruby-1.2.0+20160315+git4f20d58a/doc/guides/mrbgems.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/guides/mrbgems.md 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/guides/mrbgems.md 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,337 @@ +# mrbgems + +mrbgems is a library manager to integrate C and Ruby extension in an easy and +standardised way into mruby. + +## Usage + +By default mrbgems is currently deactivated. As soon as you add a GEM to your +build configuration (i.e. *build_config.rb*), mrbgems will be activated and the +extension integrated. + +To add a GEM into the *build_config.rb* add the following line for example: +```ruby +conf.gem '/path/to/your/gem/dir' +``` + +You can also use a relative path which would be relative from the mruby root: +```ruby +conf.gem 'examples/mrbgems/ruby_extension_example' +``` + +A remote GIT repository location for a GEM is also supported: +```ruby +conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master' +conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' +conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' +``` + +To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option: +```ruby +conf.gem :mgem => 'mruby-yaml' +conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted +``` + +If there is missing dependencies, mrbgem dependencies solver will reference +mrbgem from core or mgem-list. + +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 + +There are instances when you wish to add a collection of mrbgems into mruby at +once, or be able to substitute mrbgems based on configuration, without having to +add each gem to the *build_config.rb* file. A packaged collection of mrbgems +is called a GemBox. A GemBox is a file that contains a list of mrbgems to load +into mruby, in the same format as if you were adding them to *build_config.rb* +via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are +loaded into mruby via `config.gembox 'boxname'`. + +Below we have created a GemBox containing *mruby-time* and *mrbgems-example*: +```ruby +MRuby::GemBox.new do |conf| + conf.gem "#{root}/mrbgems/mruby-time" + conf.gem :github => 'masuidrive/mrbgems-example' +end +``` + +As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox +must be saved with a *.gembox* extension inside the *mrbgems* directory to to be +picked up by mruby. + +To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems* +directory in mruby, and add the following to our *build_config.rb* file inside +the build block: +```ruby +conf.gembox 'custom' +``` +This will cause the *custom* GemBox to be read in during the build process, +adding *mruby-time* and *mrbgems-example* to the build. + +If you want, you can put GemBox outside of mruby directory. In that case you must +specify an absolute path like below. +```ruby +conf.gembox "#{ENV["HOME"]}/mygemboxes/custom" +``` + +There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox) +and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox +contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox) +contains every gem found in the *mrbgems* directory. + +## GEM Structure + +The maximal GEM structure looks like this: + + +- GEM_NAME <- Name of GEM + | + +- include/ <- Header for Ruby extension (will exported) + | + +- mrblib/ <- Source for Ruby extension + | + +- src/ <- Source for C extension + | + +- test/ <- Test code (Ruby) + | + +- mrbgem.rake <- GEM Specification + | + +- README.md <- Readme for GEM + +The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src* +contains C/C++ files to extend mruby. The folder *include* contains C/C++ header +files. The folder *test* contains C/C++ and pure Ruby files for testing purposes +which will be used by `mrbtest`. *mrbgem.rake* contains the specification +to compile C and Ruby files. *README.md* is a short description of your GEM. + +## Build process + +mrbgems expects a specification file called *mrbgem.rake* inside of your +GEM directory. A typical GEM specification could look like this for example: +```ruby +MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Example mrbgem using C and ruby' +end +``` + +The mrbgems build process will use this specification to compile Object and Ruby +files. The compilation results will be added to *lib/libmruby.a*. This file exposes +the GEM functionality to tools like `mruby` and `mirb`. + +The following properties can be set inside of your `MRuby::Gem::Specification` for +information purpose: + +* `spec.license` or `spec.licenses` (A single license or a list of them under which this GEM is licensed) +* `spec.author` or `spec.authors` (Developer name or a list of them) +* `spec.version` (Current version) +* `spec.description` (Detailed description) +* `spec.summary` + * One line short description of mrbgem. + * Printed in build summary of rake when set. +* `spec.homepage` (Homepage) +* `spec.requirements` (External requirements as information for user) + +The `license` and `author` properties are required in every GEM! + +In case your GEM is depending on other GEMs please use +`spec.add_dependency(gem, *requirements[, default_get_info])` like: +```ruby +MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + + # Add GEM dependency mruby-parser. + # The version must be between 1.0.0 and 1.5.2 . + spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2') + + # Use any version of mruby-uv from github. + spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv') + + # Use latest mruby-onig-regexp from github. (version requirements can be omitted) + spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp') +end +``` + +The version requirements and default gem information are optional. + +Version requirement supports following operators: +* '=': is equal +* '!=': is not equal +* '>': is greater +* '<': is lesser +* '>=': is equal or greater +* '<=': is equal or lesser +* '~>': is equal or greater and is lesser than the next major version + * example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0' + * example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0' + +When more than one version requirements is passed, the dependency must satisfy all of it. + +You can have default gem to use as depedency when it's not defined in *build_config.rb*. +When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information. +Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location. + +When a special version of depedency is required, +use `MRuby::Build#gem` in *build_config.rb* to override default gem. + +If you have conflicting GEMs use the following method: +* `spec.add_conflict(gem, *requirements)` + * The `requirements` argument is same as in `add_dependency` method. + +like following code: +```ruby +MRuby::Gem::Specification.new 'some-regexp-binding' do |spec| + spec.license = 'BSD' + spec.author = 'John Doe' + + spec.add_conflict 'mruby-onig-regexp', '> 0.0.0' + spec.add_conflict 'mruby-hs-regexp' + spec.add_conflict 'mruby-pcre-regexp' + spec.add_conflict 'mruby-regexp-pcre' +end +``` + +In case your GEM has more complex build requirements you can use +the following options additionally inside of your GEM specification: + +* `spec.cc.flags` (C compiler flags) +* `spec.cc.defines` (C compiler defines) +* `spec.cc.include_paths` (C compiler include paths) +* `spec.linker.flags` (Linker flags) +* `spec.linker.libraries` (Linker libraries) +* `spec.linker.library_paths` (Linker additional library path) +* `spec.bins` (Generate binary file) +* `spec.rbfiles` (Ruby files to compile) +* `spec.objs` (Object files to compile) +* `spec.test_rbfiles` (Ruby test files for integration into mrbtest) +* `spec.test_objs` (Object test files for integration into mrbtest) +* `spec.test_preload` (Initialization files for mrbtest) + +You also can use `spec.mruby.cc` and `spec.mruby.linker` to add extra global parameters for compiler and linker. + +### include_paths and dependency + +Your GEM can export include paths to another GEMs that depends on your GEM. +By default, `/...absolute path.../{GEM_NAME}/include` will be exported. +So it is recommended not to put GEM's local header files on include/. + +These exports are retroactive. +For example: when B depends to C and A depends to B, A will get include paths exported by C. + +Exported include_paths are automatically appended to GEM local include_paths by Minirake. +You can use `spec.export_include_paths` accessor if you want more complex build. + + +## C Extension + +mruby can be extended with C. This is possible by using the C API to +integrate C libraries into mruby. + +### Preconditions + +mrbgems expects that you have implemented a C method called +`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced +by the name of your GEM. If you call your GEM *c_extension_example*, your +initialisation method could look like this: +```C +void +mrb_c_extension_example_gem_init(mrb_state* mrb) { + struct RClass *class_cextension = mrb_define_module(mrb, "CExtension"); + mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); +} +``` + +### Finalize + +mrbgems expects that you have implemented a C method called +`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced +by the name of your GEM. If you call your GEM *c_extension_example*, your +finalizer method could look like this: + +```C +void +mrb_c_extension_example_gem_final(mrb_state* mrb) { + free(someone); +} +``` + +### Example + + +- c_extension_example/ + | + +- src/ + | | + | +- example.c <- C extension source + | + +- test/ + | | + | +- example.rb <- Test code for C extension + | + +- mrbgem.rake <- GEM specification + | + +- README.md + +## Ruby Extension + +mruby can be extended with pure Ruby. It is possible to override existing +classes or add new ones in this way. Put all Ruby files into the *mrblib* +folder. + + +### Pre-Conditions + +none + +### Example + + +- ruby_extension_example/ + | + +- mrblib/ + | | + | +- example.rb <- Ruby extension source + | + +- test/ + | | + | +- example.rb <- Test code for Ruby extension + | + +- mrbgem.rake <- GEM specification + | + +- README.md + +## C and Ruby Extension + +mruby can be extended with C and Ruby at the same time. It is possible to +override existing classes or add new ones in this way. Put all Ruby files +into the *mrblib* folder and all C files into the *src* folder. + +mruby codes under *mrblib* directory would be executed after gem init C +function is called. Make sure *mruby script* depends on *C code* and +*C code* doesn't depend on *mruby script*. + +### Pre-Conditions + +See C and Ruby example. + +### Example + + +- c_and_ruby_extension_example/ + | + +- mrblib/ + | | + | +- example.rb <- Ruby extension source + | + +- src/ + | | + | +- example.c <- C extension source + | + +- test/ + | | + | +- example.rb <- Test code for C and Ruby extension + | + +- mrbgem.rake <- GEM specification + | + +- README.md diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/language/Core.md mruby-1.2.0+20160315+git4f20d58a/doc/language/Core.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/language/Core.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/language/Core.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,1590 +0,0 @@ -# Core Classes - -## Array - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.12 | n/a | src/array.c - -### Class Methods - -#### [] - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.4.1 | src/array.c | mrb_ary_s_create - -### Methods - -#### * - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.2 | src/array.c | mrb_ary_times - -#### + - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.1 | src/array.c | mrb_ary_plus - -#### << - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.3 | src/array.c | mrb_ary_push_m - -#### [] - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.4 | src/array.c | mrb_ary_aget - -#### []= - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.5 | src/array.c | mrb_ary_aset - -#### __ary_cmp - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/array.c | mrb_ary_cmp - -#### __ary_eq - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/array.c | mrb_ary_eq - -#### clear - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.6 | src/array.c | mrb_ary_clear - -#### concat - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.8 | src/array.c | mrb_ary_concat_m - -#### delete_at - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.9 | src/array.c | mrb_ary_delete_at - -#### empty? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.12 | src/array.c | mrb_ary_empty_p - -#### first - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.13 | src/array.c | mrb_ary_first - -#### index - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.14 | src/array.c | mrb_ary_index_m - -#### initialize_copy - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.16 | src/array.c | mrb_ary_replace_m - -#### join - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.17 | src/array.c | mrb_ary_join_m - -#### last - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.18 | src/array.c | mrb_ary_last - -#### length - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.19 | src/array.c | mrb_ary_size - -#### pop - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.21 | src/array.c | mrb_ary_pop - -#### push - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.22 | src/array.c | mrb_ary_push_m - -#### replace - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.23 | src/array.c | mrb_ary_replace_m - -#### reverse - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.24 | src/array.c | mrb_ary_reverse - -#### reverse! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.25 | src/array.c | mrb_ary_reverse_bang - -#### rindex - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.26 | src/array.c | mrb_ary_rindex_m - -#### shift - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.27 | src/array.c | mrb_ary_shift - -#### size - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.28 | src/array.c | mrb_ary_size - -#### slice - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.29 | src/array.c | mrb_ary_aget - -#### unshift - -ISO Code | Source File | C Function ---- | --- | --- -15.2.12.5.30 | src/array.c | mrb_ary_unshift_m - -## Exception - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.22 | n/a | src/error.c - -### Class Methods - -#### exception - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/class.c | mrb_instance_new - -### Methods - -#### == - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/error.c | exc_equal - -#### backtrace - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/backtrace.c | mrb_exc_backtrace - -#### exception - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/error.c | exc_exception - -#### initialize - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/error.c | exc_initialize - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/error.c | exc_inspect - -#### message - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/error.c | exc_message - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/error.c | exc_to_s - -## FalseClass - -ISO Code | Mixins | Source File ---- | --- | --- -n/a | n/a | src/object.c - -### Methods - -#### & - -ISO Code | Source File | C Function ---- | --- | --- -15.2.6.3.1 | src/object.c | false_and - -#### ^ - -ISO Code | Source File | C Function ---- | --- | --- -15.2.6.3.2 | src/object.c | false_xor - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/object.c | false_to_s - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.6.3.3 | src/object.c | false_to_s - -#### | - -ISO Code | Source File | C Function ---- | --- | --- -15.2.6.3.4 | src/object.c | false_or - -## Fixnum - -ISO Code | Mixins | Source File ---- | --- | --- -n/a | n/a | src/numeric.c - -### Methods - -#### % - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.5 | src/numeric.c | fix_mod - -#### & - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.9 | src/numeric.c | fix_and - -#### * - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.3 | src/numeric.c | fix_mul - -#### + - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.1 | src/numeric.c | fix_plus - -#### - - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.2 | src/numeric.c | fix_minus - -#### << - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.12 | src/numeric.c | fix_lshift - -#### == - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.7 | src/numeric.c | fix_equal - -#### >> - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.13 | src/numeric.c | fix_rshift - -#### ^ - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.11 | src/numeric.c | fix_xor - -#### divmod - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.30 | src/numeric.c | fix_divmod - -#### eql? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.16 | src/numeric.c | fix_eql - -#### hash - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.18 | src/numeric.c | flo_hash - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | fix_to_s - -#### to_f - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.23 | src/numeric.c | fix_to_f - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.25 | src/numeric.c | fix_to_s - -#### | - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.10 | src/numeric.c | fix_or - -#### ~ - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.8 | src/numeric.c | fix_rev - -## Float - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.9 | n/a | src/numeric.c - -### Methods - -#### % - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.5 | src/numeric.c | flo_mod - -#### * - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.3 | src/numeric.c | flo_mul - -#### + - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.1 | src/numeric.c | flo_plus - -#### - - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.2 | src/numeric.c | flo_minus - -#### == - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.7 | src/numeric.c | flo_eq - -#### ceil - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.8 | src/numeric.c | flo_ceil - -#### divmod - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | flo_divmod - -#### eql? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.16 | src/numeric.c | flo_eql - -#### finite? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.9 | src/numeric.c | flo_finite_p - -#### floor - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.10 | src/numeric.c | flo_floor - -#### infinite? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.11 | src/numeric.c | flo_infinite_p - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | flo_to_s - -#### nan? - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | flo_nan_p - -#### round - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.12 | src/numeric.c | flo_round - -#### to_f - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.13 | src/numeric.c | flo_to_f - -#### to_i - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.14 | src/numeric.c | flo_truncate - -#### to_int - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | flo_truncate - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.16 | src/numeric.c | flo_to_s - -#### truncate - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.15 | src/numeric.c | flo_truncate - -## Hash - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.13 | n/a | src/hash.c - -### Methods - -#### [] - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.2 | src/hash.c | mrb_hash_aget - -#### []= - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.3 | src/hash.c | mrb_hash_aset - -#### __delete - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.8 | src/hash.c | mrb_hash_delete - -#### clear - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.4 | src/hash.c | mrb_hash_clear - -#### default - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.5 | src/hash.c | mrb_hash_default - -#### default= - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.6 | src/hash.c | mrb_hash_set_default - -#### default_proc - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.7 | src/hash.c | mrb_hash_default_proc - -#### default_proc= - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.7 | src/hash.c | mrb_hash_set_default_proc - -#### dup - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/hash.c | mrb_hash_dup - -#### empty? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.12 | src/hash.c | mrb_hash_empty_p - -#### has_key? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.13 | src/hash.c | mrb_hash_has_key - -#### has_value? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.14 | src/hash.c | mrb_hash_has_value - -#### include? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.15 | src/hash.c | mrb_hash_has_key - -#### initialize - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.16 | src/hash.c | mrb_hash_init - -#### key? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.18 | src/hash.c | mrb_hash_has_key - -#### keys - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.19 | src/hash.c | mrb_hash_keys - -#### length - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.20 | src/hash.c | mrb_hash_size_m - -#### member? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.21 | src/hash.c | mrb_hash_has_key - -#### shift - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.24 | src/hash.c | mrb_hash_shift - -#### size - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.25 | src/hash.c | mrb_hash_size_m - -#### store - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.26 | src/hash.c | mrb_hash_aset - -#### to_hash - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.29 | src/hash.c | mrb_hash_to_hash - -#### value? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.27 | src/hash.c | mrb_hash_has_value - -#### values - -ISO Code | Source File | C Function ---- | --- | --- -15.2.13.4.28 | src/hash.c | mrb_hash_values - -## Integer - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.8 | n/a | src/numeric.c - -### Methods - -#### to_i - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.24 | src/numeric.c | int_to_i - -#### to_int - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | int_to_i - -## NilClass - -ISO Code | Mixins | Source File ---- | --- | --- -n/a | n/a | src/object.c - -### Methods - -#### & - -ISO Code | Source File | C Function ---- | --- | --- -15.2.4.3.1 | src/object.c | false_and - -#### ^ - -ISO Code | Source File | C Function ---- | --- | --- -15.2.4.3.2 | src/object.c | false_xor - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/object.c | nil_inspect - -#### nil? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.4.3.4 | src/object.c | mrb_true - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.4.3.5 | src/object.c | nil_to_s - -#### | - -ISO Code | Source File | C Function ---- | --- | --- -15.2.4.3.3 | src/object.c | false_or - -## Numeric - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.7 | n/a | src/numeric.c - -### Methods - -#### ** - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/numeric.c | num_pow - -#### / - -ISO Code | Source File | C Function ---- | --- | --- -15.2.8.3.4 | src/numeric.c | num_div - -#### <=> - -ISO Code | Source File | C Function ---- | --- | --- -15.2.9.3.6 | src/numeric.c | num_cmp - -#### quo - -ISO Code | Source File | C Function ---- | --- | --- -15.2.7.4.5 | src/numeric.c | num_div - -## Proc - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.17 | n/a | src/proc.c - -### Methods - -#### arity - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/proc.c | mrb_proc_arity - -#### initialize - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/proc.c | mrb_proc_initialize - -#### initialize_copy - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/proc.c | mrb_proc_init_copy - -## Range - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.14 | n/a | src/range.c - -### Methods - -#### == - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.1 | src/range.c | mrb_range_eq - -#### === - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.2 | src/range.c | mrb_range_include - -#### begin - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.3 | src/range.c | mrb_range_beg - -#### end - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.5 | src/range.c | mrb_range_end - -#### eql? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.14 | src/range.c | range_eql - -#### exclude_end? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.6 | src/range.c | mrb_range_excl - -#### first - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.7 | src/range.c | mrb_range_beg - -#### include? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.8 | src/range.c | mrb_range_include - -#### initialize - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.9 | src/range.c | mrb_range_initialize - -#### initialize_copy - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.15 | src/range.c | range_initialize_copy - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.13 | src/range.c | range_inspect - -#### last - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.10 | src/range.c | mrb_range_end - -#### member? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.11 | src/range.c | mrb_range_include - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.14.4.12 | src/range.c | range_to_s - -## RuntimeError - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.28 | n/a | src/error.c - -## ScriptError - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.37 | n/a | src/error.c - -## StandardError - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.23 | n/a | src/error.c - -## String - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.10 | n/a | src/string.c - -### Methods - -#### * - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.5 | src/string.c | mrb_str_times - -#### + - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.4 | src/string.c | mrb_str_plus_m - -#### <=> - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.1 | src/string.c | mrb_str_cmp_m - -#### == - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.2 | src/string.c | mrb_str_equal_m - -#### [] - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.6 | src/string.c | mrb_str_aref_m - -#### bytes - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/string.c | mrb_str_bytes - -#### bytesize - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/string.c | mrb_str_size - -#### capitalize - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.7 | src/string.c | mrb_str_capitalize - -#### capitalize! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.8 | src/string.c | mrb_str_capitalize_bang - -#### chomp - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.9 | src/string.c | mrb_str_chomp - -#### chomp! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.10 | src/string.c | mrb_str_chomp_bang - -#### chop - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.11 | src/string.c | mrb_str_chop - -#### chop! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.12 | src/string.c | mrb_str_chop_bang - -#### downcase - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.13 | src/string.c | mrb_str_downcase - -#### downcase! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.14 | src/string.c | mrb_str_downcase_bang - -#### empty? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.16 | src/string.c | mrb_str_empty_p - -#### eql? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.17 | src/string.c | mrb_str_eql - -#### hash - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.20 | src/string.c | mrb_str_hash_m - -#### include? - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.21 | src/string.c | mrb_str_include - -#### index - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.22 | src/string.c | mrb_str_index_m - -#### initialize - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.23 | src/string.c | mrb_str_init - -#### initialize_copy - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.24 | src/string.c | mrb_str_replace - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.46 | src/string.c | mrb_str_inspect - -#### intern - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.25 | src/string.c | mrb_str_intern - -#### length - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.26 | src/string.c | mrb_str_size - -#### replace - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.28 | src/string.c | mrb_str_replace - -#### reverse - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.29 | src/string.c | mrb_str_reverse - -#### reverse! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.30 | src/string.c | mrb_str_reverse_bang - -#### rindex - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.31 | src/string.c | mrb_str_rindex_m - -#### size - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.33 | src/string.c | mrb_str_size - -#### slice - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.34 | src/string.c | mrb_str_aref_m - -#### split - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.35 | src/string.c | mrb_str_split_m - -#### to_f - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.38 | src/string.c | mrb_str_to_f - -#### to_i - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.39 | src/string.c | mrb_str_to_i - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.40 | src/string.c | mrb_str_to_s - -#### to_str - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/string.c | mrb_str_to_s - -#### to_sym - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.41 | src/string.c | mrb_str_intern - -#### upcase - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.42 | src/string.c | mrb_str_upcase - -#### upcase! - -ISO Code | Source File | C Function ---- | --- | --- -15.2.10.5.43 | src/string.c | mrb_str_upcase_bang - -## Symbol - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.11 | n/a | src/symbol.c - -### Methods - -#### <=> - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/symbol.c | sym_cmp - -#### === - -ISO Code | Source File | C Function ---- | --- | --- -15.2.11.3.1 | src/symbol.c | sym_equal - -#### id2name - -ISO Code | Source File | C Function ---- | --- | --- -15.2.11.3.2 | src/symbol.c | mrb_sym_to_s - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -15.2.11.3.5 | src/symbol.c | sym_inspect - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.11.3.3 | src/symbol.c | mrb_sym_to_s - -#### to_sym - -ISO Code | Source File | C Function ---- | --- | --- -15.2.11.3.4 | src/symbol.c | sym_to_sym - -## SyntaxError - -ISO Code | Mixins | Source File ---- | --- | --- -15.2.38 | n/a | src/error.c - -## TrueClass - -ISO Code | Mixins | Source File ---- | --- | --- -n/a | n/a | src/object.c - -### Methods - -#### & - -ISO Code | Source File | C Function ---- | --- | --- -15.2.5.3.1 | src/object.c | true_and - -#### ^ - -ISO Code | Source File | C Function ---- | --- | --- -15.2.5.3.2 | src/object.c | true_xor - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/object.c | true_to_s - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.2.5.3.3 | src/object.c | true_to_s - -#### | - -ISO Code | Source File | C Function ---- | --- | --- -15.2.5.3.4 | src/object.c | true_or - -# Core Modules - -## Comparable - -ISO Code | Source File ---- | --- -15.3.3 | src/compar.c - -## Enumerable - -ISO Code | Source File ---- | --- -15.3.2 | src/enum.c - -## GC - -ISO Code | Source File ---- | --- -n/a | src/gc.c - -### Class Methods - -#### disable - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_disable - -#### enable - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_enable - -#### generational_mode - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_generational_mode_get - -#### generational_mode= - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_generational_mode_set - -#### interval_ratio - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_interval_ratio_get - -#### interval_ratio= - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_interval_ratio_set - -#### start - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_start - -#### step_ratio - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_step_ratio_get - -#### step_ratio= - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_step_ratio_set - -#### test - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/gc.c | gc_test - -## Kernel - -ISO Code | Source File ---- | --- -15.3.1 | src/kernel.c - -### Class Methods - -#### block_given? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.2.2 | src/kernel.c | mrb_f_block_given_p_m - -#### global_variables - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.2.4 | src/kernel.c | mrb_f_global_variables - -#### iterator? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.2.5 | src/kernel.c | mrb_f_block_given_p_m - -#### local_variables - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.2.7 | src/kernel.c | mrb_local_variables - -#### raise - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.2.12 | src/kernel.c | mrb_f_raise - -### Methods - -#### != - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/kernel.c | mrb_obj_not_equal_m - -#### == - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.1 | src/kernel.c | mrb_obj_equal_m - -#### === - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.2 | src/kernel.c | mrb_equal_m - -#### __case_eqq - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/kernel.c | mrb_obj_ceqq - -#### __id__ - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.3 | src/kernel.c | mrb_obj_id_m - -#### __send__ - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.4 | src/kernel.c | mrb_f_send - -#### block_given? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.6 | src/kernel.c | mrb_f_block_given_p_m - -#### class - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.7 | src/kernel.c | mrb_obj_class_m - -#### clone - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.8 | src/kernel.c | mrb_obj_clone - -#### define_singleton_method - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/kernel.c | mod_define_singleton_method - -#### dup - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.9 | src/kernel.c | mrb_obj_dup - -#### eql? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.10 | src/kernel.c | mrb_obj_equal_m - -#### equal? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.11 | src/kernel.c | mrb_obj_equal_m - -#### extend - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.13 | src/kernel.c | mrb_obj_extend_m - -#### global_variables - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.14 | src/kernel.c | mrb_f_global_variables - -#### hash - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.15 | src/kernel.c | mrb_obj_hash - -#### initialize_copy - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.16 | src/kernel.c | mrb_obj_init_copy - -#### inspect - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.17 | src/kernel.c | mrb_obj_inspect - -#### instance_eval - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.18 | src/kernel.c | mrb_obj_instance_eval - -#### instance_of? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.19 | src/kernel.c | obj_is_instance_of - -#### instance_variable_defined? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.20 | src/kernel.c | mrb_obj_ivar_defined - -#### instance_variable_get - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.21 | src/kernel.c | mrb_obj_ivar_get - -#### instance_variable_set - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.22 | src/kernel.c | mrb_obj_ivar_set - -#### instance_variables - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.23 | src/kernel.c | mrb_obj_instance_variables - -#### is_a? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.24 | src/kernel.c | mrb_obj_is_kind_of_m - -#### iterator? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.25 | src/kernel.c | mrb_f_block_given_p_m - -#### kind_of? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.26 | src/kernel.c | mrb_obj_is_kind_of_m - -#### local_variables - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.28 | src/kernel.c | mrb_local_variables - -#### methods - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.31 | src/kernel.c | mrb_obj_methods_m - -#### nil? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.32 | src/kernel.c | mrb_false - -#### object_id - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.33 | src/kernel.c | mrb_obj_id_m - -#### private_methods - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.36 | src/kernel.c | mrb_obj_private_methods - -#### protected_methods - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.37 | src/kernel.c | mrb_obj_protected_methods - -#### public_methods - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.38 | src/kernel.c | mrb_obj_public_methods - -#### raise - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.40 | src/kernel.c | mrb_f_raise - -#### remove_instance_variable - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.41 | src/kernel.c | mrb_obj_remove_instance_variable - -#### respond_to? - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.43 | src/kernel.c | obj_respond_to - -#### send - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.44 | src/kernel.c | mrb_f_send - -#### singleton_class - -ISO Code | Source File | C Function ---- | --- | --- -n/a | src/kernel.c | mrb_singleton_class - -#### singleton_methods - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.45 | src/kernel.c | mrb_obj_singleton_methods_m - -#### to_s - -ISO Code | Source File | C Function ---- | --- | --- -15.3.1.3.46 | src/kernel.c | mrb_any_to_s - diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/language/generator.rb mruby-1.2.0+20160315+git4f20d58a/doc/language/generator.rb --- mruby-1.1.0+20150906+git1cbbb7e1/doc/language/generator.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/language/generator.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -#!/usr/bin/env ruby - -require 'pty' - -c_dir = File.dirname(__FILE__) -MRUBY_ROOT = File.expand_path("#{c_dir}/../..") -DOC_DIR = File.expand_path(c_dir) - -cmd = "ruby #{DOC_DIR}/mrbdoc/mrbdoc.rb #{MRUBY_ROOT} #{DOC_DIR} false" -IO.popen(cmd, "r+") do |io| - io.close_write - while line = io.gets - puts line - end -end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/language/mrbdoc/lib/mrbdoc_analyze.rb mruby-1.2.0+20160315+git4f20d58a/doc/language/mrbdoc/lib/mrbdoc_analyze.rb --- mruby-1.1.0+20150906+git1cbbb7e1/doc/language/mrbdoc/lib/mrbdoc_analyze.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/language/mrbdoc/lib/mrbdoc_analyze.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,231 +0,0 @@ -class MRBDoc - SRC_DIR = 'src' - MRBLIB_DIR = 'mrblib' - - def analyze_code dir, &block - @mrb_files = {} - @dir = File.expand_path(dir) - - block.call "MRBDOC\tanalyze #{@dir}" - - analyze(dir) do |progress| - block.call progress - end - end - - def each_file(&block); @mrb_files.each {|k,v| block.call k,v}; end - - def find_c_func(c_func_name) - each_file do |file_name, file| - c_func = file.c_funcs(c_func_name) - return c_func unless c_func.nil? - end - {} - end - - def find_c_file(rb_obj_name, c_func_name) - last_file_name_match = '' - each_file do |file_name, file| - c_func = file.c_funcs(c_func_name) - if c_func and file.rb_class(rb_obj_name) or file.rb_module(rb_obj_name) - return file_name - elsif c_func - last_file_name_match = file_name - end - end - last_file_name_match - end - - def find_c_file_by_class(name) - each_file do |file_name, file| - rb_class = file.rb_class(name) - return file_name unless rb_class.nil? - end - 'nil' - end - - def find_c_file_by_module(name) - each_file do |file_name, file| - rb_module = file.rb_module(name) - return file_name unless rb_module.nil? - end - 'nil' - end - - private - - def analyze dir, &block - collect_all_files dir, &block - end - - def collect_all_files dir, &block - l = lambda {|f| block.call " - #{f.name}"} - collect_files(src_code_dir(dir), /\.c$/, &l) - collect_files(mrb_code_dir(dir), /\.rb$/, &l) - end - - def collect_files dir, rxp, &block - Dir.foreach(dir) do |file| - next unless file =~ rxp - - file_path = "#{dir}/#{file}" - mrb_file = MRBFile.new "#{file_path}" - @mrb_files["#{file_path}"] = mrb_file - - block.call mrb_file - end - end - - def src_code_dir dir; File.expand_path SRC_DIR, dir; end - def mrb_code_dir dir; File.expand_path MRBLIB_DIR, dir; end -end - -class MRBFile - attr_reader :name - attr_reader :file - - def initialize mrb_file - @file = mrb_file - @name = File.basename file - @c_funcs = {} - @rb_class_c_def = {} - @rb_method_c_def = {} - @rb_class_method_c_def = {} - @rb_module_c_def = {} - @last_line = nil - @assignments = {} - - @assignments['mrb->object_class'] = 'Object' - @assignments['mrb->kernel_module'] = 'Kernel' - @assignments['mrb->module_class'] = 'Module' - @assignments['mrb->nil_class'] = 'NilClass' - @assignments['mrb->true_class'] = 'TrueClass' - @assignments['mrb->class_class'] = 'Class' - - analyze - end - - def each_class &block - @rb_class_c_def.each do |class_name, class_hsh| - block.call class_name, class_hsh - end - end - - def each_method name, &block - @rb_method_c_def.each do |met_name, met_hsh| - met_name_tmp = met_name.sub /^#{name}_/, '' - block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name - end - end - - def each_class_method name, &block - @rb_class_method_c_def.each do |met_name, met_hsh| - met_name_tmp = met_name.sub /^#{name}_/, '' - block.call met_name_tmp, met_hsh if met_hsh[:rb_class] == name - end - end - - def each_module &block - @rb_module_c_def.each do |module_name, module_hsh| - block.call module_name, module_hsh - end - end - - def each_core_object &block - each_class {|n| block.call n} - each_module {|n| block.call n} - end - - def c_funcs c_func_name; @c_funcs[c_func_name]; end - def rb_class rb_class_name; @rb_class_c_def[rb_class_name]; end - def rb_module rb_module_name; @rb_module_c_def[rb_module_name]; end - - private - - def analyze - File.open(file).each_line.each_with_index do |line, idx| - line_no = idx.succ - if c_file? - analyze_c_line line, line_no - elsif rb_file? - analyze_rb_line line, line_no - else - raise ArgumentError.new "#{file} is a not supported file type" - end - @last_line = line.strip - end - end - - def c_file?; (name =~ /\.c$/); end - def rb_file?; (name =~ /\.rb$/); end - - RXP_C_VAR = /\s*([^\s]*?)\s*?/ - RXP_C_STR = /\s*?\"(.*?)\"\s*?/ - #RXP_C_ISO = /\s*\;\s*[\/\*]*\s*.*?([15\.]{0,3}[0-9\.]*)\s*[\\\\\*]*/ - RXP_C_ISO = /\s*;\s*[\/\*]*[\sa-zA-Z]*([\d\.]*)[\sa-zA-Z]*[\*\/]*/ - - def analyze_c_line line, line_no - case line.strip - when /^([a-zA-Z\_][a-zA-Z\_0-9]*?)\((.*?)\)\s*?$/ - # assuming c method definition - @c_funcs[$1] = {:line_no => line_no, :args => $2, :return => @last_line} - when /mrb_define_class\(.*?\,#{RXP_C_STR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/ - # assuming ruby class definition in c - class_name = $1.clone - iso = $3.clone - iso.strip! - @rb_class_c_def[class_name] = {:c_object => $2, :iso => iso} - assigns = line.split '=' - if assigns.size > 1 - assigns[0..-2].each do |v| - @assignments[v.strip] = class_name - end - end - when /mrb_define_module\(.*?\,#{RXP_C_STR}\)#{RXP_C_ISO}/ - # assuming ruby class definition in c - module_name = $1.clone - iso = $2.clone - iso.strip! - @rb_module_c_def[module_name] = {:iso => iso} - assigns = line.split '=' - if assigns.size > 1 - assigns[0..-2].each do |v| - @assignments[v.strip] = module_name - end - end - when /mrb_define_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/ - # assuming ruby method definition in c - name = $1.clone - name = resolve_obj(name) - iso = $5.clone - iso.strip! - @rb_method_c_def["#{name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => name, :iso => iso} - when /mrb_define_class_method\(.*?\,#{RXP_C_VAR}\,#{RXP_C_STR}\,#{RXP_C_VAR}\,#{RXP_C_VAR}\)#{RXP_C_ISO}/ - # assuming ruby class method definition in c - class_name = $1.clone - class_name = resolve_obj(class_name) - iso = $5.clone - iso.strip! - @rb_class_method_c_def["#{class_name}_#{$2}"] = {:c_func => $3, :args => $4, :rb_class => class_name, :iso => iso} - when /mrb_name_class\(.*?\,#{RXP_C_VAR}\,\s*mrb_intern\(.*?,#{RXP_C_STR}\)\)#{RXP_C_ISO}/ - class_name = $2.clone - iso = $3.clone - iso.strip! - @rb_class_c_def[class_name] = {:c_object => $1, :iso => iso} - @assignments[$1] = class_name - when /mrb_include_module\(.*?\,#{RXP_C_VAR}\,\s*mrb_class_get\(.*?\,#{RXP_C_STR}\)\)/ - class_name = resolve_obj($1) - mod = $2.clone - @rb_class_c_def[class_name][:include] = [] unless @rb_class_c_def[class_name].has_key? :include - @rb_class_c_def[class_name][:include] << mod - end - end - - def analyze_rb_line line, line_no - - end - - def resolve_obj c_var - @assignments[c_var] - end -end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/language/mrbdoc/lib/mrbdoc_docu.rb mruby-1.2.0+20160315+git4f20d58a/doc/language/mrbdoc/lib/mrbdoc_docu.rb --- mruby-1.1.0+20150906+git1cbbb7e1/doc/language/mrbdoc/lib/mrbdoc_docu.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/language/mrbdoc/lib/mrbdoc_docu.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -class MRBDoc - def write_documentation dir, cfg, &block - block.call "MRBDOC\twrite to #{File.expand_path(dir)}" - - write(dir, cfg) do |progress| - block.call progress - end - end - - private - - def write dir, cfg - File.open(File.expand_path('Core.md', dir), 'wb+') do |io| - print_core_classes(io, cfg) - print_core_modules(io, cfg) - end - end - - def get_core_list id - core_list = {} - each_file do |file_path, mrb_file| - mrb_file.send(id) do |name, cls_hsh| - core_list[name] = {:data => cls_hsh, :methods => {}, :class_methods => {}} - mrb_file.each_method name do |met_name, met_hsh| - core_list[name][:methods][met_name] = met_hsh - end - mrb_file.each_class_method name do |met_name, met_hsh| - core_list[name][:class_methods][met_name] = met_hsh - end - end - end - core_list - end - - def print_core_classes(io, cfg) - core_list = get_core_list :each_class - io.puts "# Core Classes\n\n" - core_list.sort.each do |name, hsh| - file = find_c_file_by_class(name) - file = file.split("#{@dir}/")[1] - iso = hsh[:data][:iso] - iso = 'n/a' if iso.nil? or iso == '' - mixins = hsh[:data][:include].join(', ') unless hsh[:data][:include].nil? - mixins = 'n/a' if mixins.nil? or mixins == '' - - io.puts < 0 - io.puts "### Methods\n\n" - hsh[:methods].sort.each do |met_name, met_hsh| - print_method(io, met_name, met_hsh, cfg) - end - end - - def print_class_methods(io, hsh, cfg) - return unless hsh[:class_methods].size > 0 - io.puts "### Class Methods\n\n" - hsh[:class_methods].sort.each do |met_name, met_hsh| - print_method(io, met_name, met_hsh, cfg) - end - end - - def print_method(io, met_name, met_hsh, cfg) - if cfg[:print_line_no] - line_no_head = ' | Line' - line_no = " | #{find_c_func(met_hsh[:c_func])[:line_no]}" - else - line_no, line_no_head = '', '' - end - file = find_c_file(met_hsh[:rb_class], met_hsh[:c_func]) - file = file.split("#{@dir}/")[1] - iso = met_hsh[:iso] - iso = 'n/a' if iso.nil? or iso == '' - - io.puts < WRITE_LINE_NO} -mrbdoc.write_documentation DOC_ROOT, cfg do |progress| - puts progress -end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/language/README.md mruby-1.2.0+20160315+git4f20d58a/doc/language/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/language/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/language/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -# Language - -mruby is an implementation of the Ruby programming language. -These documents are describing the language features and libraries -which are provided together with mruby. - -## Built-In Class and Modules - -see *doc/language/Core.md* diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/limitations.md mruby-1.2.0+20160315+git4f20d58a/doc/limitations.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/limitations.md 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/limitations.md 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,208 @@ +# Limitations and Differences + +The philosophy of mruby is to be a lightweight implementation of +the Ruby ISO standard. These two objectives are partially contradicting. +Ruby is an expressive language with complex implementation details which +are difficult to implement in a lightweight manner. To cope with this, +limitations to the "Ruby Compatibility" are defined. + +This document is collecting these limitations. + +## Integrity + +This document does not contain a complete list of limitations. +Please help to improve it by submitting your findings. + + +## ```1/2``` gives ```0.5``` + +Since mruby does not have ```Bignum```, bigger integers are represented +by ```Float``` numbers. To enhance interoperability between ```Float``` +and ```Float```, mruby provides ``Float#upto``` and other iterating +methods for ```Float`` class. As a side effect, ```1/2``` gives ```0.5``` +not ```0```. + +## ```Array``` passed to ```puts``` + +Passing an Array to ```puts``` results in different output. + +```ruby +puts [1,2,3] +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +``` +1 +2 +3 +``` + +#### mruby [1.2.0 (2015-11-17)] + +``` +[1, 2, 3] +``` + +## ```Kernel.raise``` in rescue clause + +```Kernel.raise``` without arguments does not raise the current exception within +a rescue clause. + +```ruby +begin + 1 / 0 +rescue + raise +end +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +```ZeroDivisionError``` is raised. + +#### mruby [1.2.0 (2015-11-17)] + +No exception is raised. + +## Check of infinite recursion + +mruby does not check infinite recursion across C extensions. + +```ruby +def test; eval 'test'; end; test +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +```SystemStackError``` is raised. + +#### mruby [1.2.0 (2015-11-17)] + +Segmentation fault. + +## Fiber execution can't cross C function boundary + +mruby's ```Fiber``` is implemented in a similar way to Lua's co-routine. This +results in the consequence that you can't switch context within C functions. +Only exception is ```mrb_fiber_yield``` at return. + +## ```Array``` does not support instance variables + +To reduce memory consumption ```Array``` does not support instance variables. + +```ruby +class Liste < Array + def initialize(str = nil) + @feld = str + end +end + +p Liste.new "foobar" +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +``` [] ``` + +#### mruby [1.2.0 (2015-11-17)] + +```ArgumentError``` is raised. + +## Method visibility + +For simplicity reasons no method visibility (public/private/protected) is +supported. + +```ruby +class VisibleTest + + def public_method; end + + private + def private_method; end + +end + +p VisibleTest.new.respond_to?(:private_method, false) +p VisibleTest.new.respond_to?(:private_method, true) +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +``` +false +true +``` + +#### mruby [1.2.0 (2015-11-17)] + +``` +true +true +``` + +## defined? + +The ```defined?``` keyword is considered to complex to be fully +implemented. It is recommended to use ```const_defined?``` and +other reflection methods instead. + +```ruby +defined?(Foo) +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +``` +nil +``` + +#### mruby [1.2.0 (2015-11-17)] + +```NameError``` is raised. + +## ```alias``` on global variables + +Aliasing a global variable works in CRuby but is not part +of the ISO standard. + +```ruby +alias $a $__a__ +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +``` nil ``` + +#### mruby [1.2.0 (2015-11-17)] + +Syntax error + +## Operator modification + +An operator can't be overwritten by the user. + +```ruby +class String + def + + end +end + +'a' + 'b' +``` + +#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)] + +```ArgumentError``` is raised. +The re-defined ```+``` operator does not accept any arguments. + +#### mruby [1.2.0 (2015-11-17)] + +``` 'ab' ``` +Behavior of the operator wasn't changed. + +## ```Kernel.binding``` missing + +```Kernel.binding``` is not implemented as it is not in the +ISO standard. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/mrbconf/README.md mruby-1.2.0+20160315+git4f20d58a/doc/mrbconf/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/mrbconf/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/mrbconf/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,160 +0,0 @@ -# mruby configuration macros. - -## How to use these macros. -You can use mrbconfs with following ways: -* Write them in `mrbconf.h`. - * Using compiler flags is preferred when building a cross binaries or multiple mruby binaries - since it's easier to use different mrbconf per each `MRuby::Build`. - * Most flags can be enabled by just commenting in. -* Pass them as compiler flags. - * Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`) - changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed. - -## stdio setting. -`ENABLE_STDIO` -* Will be defined automatically if `DISABLE_STDIO` isn't defined. -* Uses `` functions. - -`DISABLE_STDIO` -* When defined `` functions won't be used. -* Some features will be disabled when this is enabled: - * `mrb_irep` load/dump from/to file. - * Compiling mruby script from file. - * Printing features in **src/print.c**. - -## Debug macros. -`ENABLE_DEBUG` -* When defined code fetch hook and debug OP hook will be enabled. -* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`. -* Fetch hook will be called before any OP. -* Debug OP hook will be called when dispatching `OP_DEBUG`. - -`DISABLE_DEBUG` -* Will be define automatically if `ENABLE_DEBUG` isn't defined. - -`MRB_DEBUG` -* When defined `mrb_assert*` macro will be defined with macros from ``. -* Could be enabled via `enable_debug` method of `MRuby::Build`. - -## Stack configuration - -`MRB_STACK_EXTEND_DOUBLING` -* If defined doubles the stack size when extending it. -* Else extends stack with `MRB_STACK_GROWTH`. - -`MRB_STACK_GROWTH` -* Default value is `128`. -* Used in stack extending. -* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined. - -`MRB_STACK_MAX` -* Default value is `0x40000 - MRB_STACK_GROWTH`. -* Raises `RuntimeError` when stack size exceeds this value. - -## Primitive type configuration. - -`MRB_USE_FLOAT` -* When defined single precision floating point type(C type `float`) is used as `mrb_float`. -* Else double precision floating point type(C type `double`) is used as `mrb_float`. - -`MRB_INT16` -* When defined `int16_t` will be defined as `mrb_int`. -* Conflicts with `MRB_INT64`. - -`MRB_INT64` -* When defined `int64_t` will be defined as `mrb_int`. -* Conflicts with `MRB_INT16`. -* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer) -will be defined as `mrb_int`. - -## Garbage collector configuration. - -`MRB_GC_STRESS` -* When defined full GC is emitted per each `RBasic` allocation. -* Mainly used in memory manager debugging. - -`MRB_GC_TURN_OFF_GENERATIONAL` -* When defined turns generational GC by default. - -`MRB_GC_FIXED_ARENA` -* When defined used fixed size GC arena. -* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`. -* Useful tracking unnecessary mruby object allocation. - -`MRB_GC_ARENA_SIZE` -* Default value is `100`. -* Ignored when `MRB_GC_FIXED_ARENA` isn't defined. -* Defines fixed GC arena size. - -`MRB_HEAP_PAGE_SIZE` -* Defines value is `1024`. -* Specifies number of `RBasic` per each heap page. - -## Memory pool configuration. - -`POOL_ALIGNMENT` -* Default value is `4`. -* If you're allocating data types that requires alignment more than default value define the -largest value of required alignment. - -`POOL_PAGE_SIZE` -* Default value is `16000`. -* Specifies page size of pool page. -* Smaller the value is increases memory overhead. - -## State atexit configuration. - -`MRB_FIXED_STATE_ATEXIT_STACK` -* If defined enables fixed size `mrb_state` atexit stack. -* Raises `RuntimeError` when `mrb_state_atexit` call count to same `mrb_state` exceeds -`MRB_FIXED_STATE_ATEXIT_STACK_SIZE`'s value. - -`MRB_FIXED_STATE_ATEXIT_STACK_SIZE` -* Default value is `5`. -* If `MRB_FIXED_STATE_ATEXIT_STACK` isn't defined this macro is ignored. - -## `mrb_value` configuration. - -`MRB_ENDIAN_BIG` -* If defined compiles mruby for big endian machines. -* Used in `MRB_NAN_BOXING`. -* Some mrbgem use this mrbconf. - -`MRB_NAN_BOXING` -* If defined represent `mrb_value` in boxed `double`. -* Conflicts with `MRB_USE_FLOAT`. - -`MRB_WORD_BOXING` -* If defined represent `mrb_value` as a word. -* If defined `Float` will be a mruby object with `RBasic`. - -## Instance variable configuration. -`MRB_USE_IV_SEGLIST` -* If defined enable segmented list in instance variable table instead of khash. -* Segmented list is a linked list of key and value segments. -* It will linear search instead of hash search. - -`MRB_SEGMENT_SIZE` -* Default value is `4`. -* Specifies size of each segment in segment list. -* Ignored when `MRB_USE_IV_SEGLIST` isn't defined. - -`MRB_IVHASH_INIT_SIZE` -* Default value is `8`. -* Specifies initial size for instance variable table. -* Ignored when `MRB_USE_IV_SEGLIST` is defined. - -## Other configuration. -`MRB_FUNCALL_ARGC_MAX` -* Default value is `16`. -* Specifies 4th argument(`argc`) max value of `mrb_funcall`. -* Raises `ArgumentError` when the `argc` argument is bigger then this value `mrb_funcall`. - -`KHASH_DEFAULT_SIZE` -* Default value is `32`. -* Specifies default size of khash table bucket. -* Used in `kh_init_ ## name` function. - -`MRB_STR_BUF_MIN_SIZE` -* Default value is `128`. -* Specifies initial capacity of `RString` created by `mrb_str_buf_new` function.. diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/doc/mrbgems/README.md mruby-1.2.0+20160315+git4f20d58a/doc/mrbgems/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/doc/mrbgems/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/doc/mrbgems/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,337 +0,0 @@ -# mrbgems - -mrbgems is a library manager to integrate C and Ruby extension in an easy and -standardised way into mruby. - -## Usage - -By default mrbgems is currently deactivated. As soon as you add a GEM to your -build configuration (i.e. *build_config.rb*), mrbgems will be activated and the -extension integrated. - -To add a GEM into the *build_config.rb* add the following line for example: -```ruby -conf.gem '/path/to/your/gem/dir' -``` - -You can also use a relative path which would be relative from the mruby root: -```ruby -conf.gem 'examples/mrbgems/ruby_extension_example' -``` - -A remote GIT repository location for a GEM is also supported: -```ruby -conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master' -conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' -conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' -``` - -To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option: -```ruby -conf.gem :mgem => 'mruby-yaml' -conf.gem :mgem => 'yaml' # 'mruby-' prefix could be omitted -``` - -If there is missing dependencies, mrbgem dependencies solver will reference -mrbgem from core or mgem-list. - -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 - -There are instances when you wish to add a collection of mrbgems into mruby at -once, or be able to substitute mrbgems based on configuration, without having to -add each gem to the *build_config.rb* file. A packaged collection of mrbgems -is called a GemBox. A GemBox is a file that contains a list of mrbgems to load -into mruby, in the same format as if you were adding them to *build_config.rb* -via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are -loaded into mruby via `config.gembox 'boxname'`. - -Below we have created a GemBox containing *mruby-time* and *mrbgems-example*: -```ruby -MRuby::GemBox.new do |conf| - conf.gem "#{root}/mrbgems/mruby-time" - conf.gem :github => 'masuidrive/mrbgems-example' -end -``` - -As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox -must be saved with a *.gembox* extension inside the *mrbgems* directory to to be -picked up by mruby. - -To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems* -directory in mruby, and add the following to our *build_config.rb* file inside -the build block: -```ruby -conf.gembox 'custom' -``` -This will cause the *custom* GemBox to be read in during the build process, -adding *mruby-time* and *mrbgems-example* to the build. - -If you want, you can put GemBox outside of mruby directory. In that case you must -specify an absolute path like below. -```ruby -conf.gembox "#{ENV["HOME"]}/mygemboxes/custom" -``` - -There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox) -and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox -contains several core components of mruby, and [full-core](../../mrbgems/full-core.gembox) -contains every gem found in the *mrbgems* directory. - -## GEM Structure - -The maximal GEM structure looks like this: - - +- GEM_NAME <- Name of GEM - | - +- include/ <- Header for Ruby extension (will exported) - | - +- mrblib/ <- Source for Ruby extension - | - +- src/ <- Source for C extension - | - +- test/ <- Test code (Ruby) - | - +- mrbgem.rake <- GEM Specification - | - +- README.md <- Readme for GEM - -The folder *mrblib* contains pure Ruby files to extend mruby. The folder *src* -contains C/C++ files to extend mruby. The folder *include* contains C/C++ header -files. The folder *test* contains C/C++ and pure Ruby files for testing purposes -which will be used by `mrbtest`. *mrbgem.rake* contains the specification -to compile C and Ruby files. *README.md* is a short description of your GEM. - -## Build process - -mrbgems expects a specification file called *mrbgem.rake* inside of your -GEM directory. A typical GEM specification could look like this for example: -```ruby -MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'Example mrbgem using C and ruby' -end -``` - -The mrbgems build process will use this specification to compile Object and Ruby -files. The compilation results will be added to *lib/libmruby.a*. This file exposes -the GEM functionality to tools like `mruby` and `mirb`. - -The following properties can be set inside of your `MRuby::Gem::Specification` for -information purpose: - -* `spec.license` or `spec.licenses` (A single license or a list of them under which this GEM is licensed) -* `spec.author` or `spec.authors` (Developer name or a list of them) -* `spec.version` (Current version) -* `spec.description` (Detailed description) -* `spec.summary` - * One line short description of mrbgem. - * Printed in build summary of rake when set. -* `spec.homepage` (Homepage) -* `spec.requirements` (External requirements as information for user) - -The `license` and `author` properties are required in every GEM! - -In case your GEM is depending on other GEMs please use -`spec.add_dependency(gem, *requirements[, default_get_info])` like: -```ruby -MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - - # Add GEM dependency mruby-parser. - # The version must be between 1.0.0 and 1.5.2 . - spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2') - - # Use any version of mruby-uv from github. - spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv') - - # Use latest mruby-onig-regexp from github. (version requirements can be omitted) - spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp') -end -``` - -The version requirements and default gem information are optional. - -Version requirement supports following operators: -* '=': is equal -* '!=': is not equal -* '>': is greater -* '<': is lesser -* '>=': is equal or greater -* '<=': is equal or lesser -* '~>': is equal or greater and is lesser than the next major version - * example 1: '~> 2.2.2' means '>= 2.2.2' and '< 2.3.0' - * example 2: '~> 2.2' means '>= 2.2.0' and '< 3.0.0' - -When more than one version requirements is passed, the dependency must satisfy all of it. - -You can have default gem to use as depedency when it's not defined in *build_config.rb*. -When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information. -Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location. - -When a special version of depedency is required, -use `MRuby::Build#gem` in *build_config.rb* to override default gem. - -If you have conflicting GEMs use the following method: -* `spec.add_conflict(gem, *requirements)` - * The `requirements` argument is same as in `add_dependency` method. - -like following code: -```ruby -MRuby::Gem::Specification.new 'some-regexp-binding' do |spec| - spec.license = 'BSD' - spec.author = 'John Doe' - - spec.add_conflict 'mruby-onig-regexp', '> 0.0.0' - spec.add_conflict 'mruby-hs-regexp' - spec.add_conflict 'mruby-pcre-regexp' - spec.add_conflict 'mruby-regexp-pcre' -end -``` - -In case your GEM has more complex build requirements you can use -the following options additionally inside of your GEM specification: - -* `spec.cc.flags` (C compiler flags) -* `spec.cc.defines` (C compiler defines) -* `spec.cc.include_paths` (C compiler include paths) -* `spec.linker.flags` (Linker flags) -* `spec.linker.libraries` (Linker libraries) -* `spec.linker.library_paths` (Linker additional library path) -* `spec.bins` (Generate binary file) -* `spec.rbfiles` (Ruby files to compile) -* `spec.objs` (Object files to compile) -* `spec.test_rbfiles` (Ruby test files for integration into mrbtest) -* `spec.test_objs` (Object test files for integration into mrbtest) -* `spec.test_preload` (Initialization files for mrbtest) - -You also can use `spec.mruby.cc` and `spec.mruby.linker` to add extra global parameters for compiler and linker. - -### include_paths and dependency - -Your GEM can export include paths to another GEMs that depends on your GEM. -By default, `/...absolute path.../{GEM_NAME}/include` will be exported. -So it is recommended not to put GEM's local header files on include/. - -These exports are retroactive. -For example: when B depends to C and A depends to B, A will get include paths exported by C. - -Exported include_paths are automatically appended to GEM local include_paths by Minirake. -You can use `spec.export_include_paths` accessor if you want more complex build. - - -## C Extension - -mruby can be extended with C. This is possible by using the C API to -integrate C libraries into mruby. - -### Preconditions - -mrbgems expects that you have implemented a C method called -`mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced -by the name of your GEM. If you call your GEM *c_extension_example*, your -initialisation method could look like this: -```C -void -mrb_c_extension_example_gem_init(mrb_state* mrb) { - struct RClass *class_cextension = mrb_define_module(mrb, "CExtension"); - mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); -} -``` - -### Finalize - -mrbgems expects that you have implemented a C method called -`mrb_YOURGEMNAME_gem_final(mrb_state)`. `YOURGEMNAME` will be replaced -by the name of your GEM. If you call your GEM *c_extension_example*, your -finalizer method could look like this: - -```C -void -mrb_c_extension_example_gem_final(mrb_state* mrb) { - free(someone); -} -``` - -### Example - - +- c_extension_example/ - | - +- src/ - | | - | +- example.c <- C extension source - | - +- test/ - | | - | +- example.rb <- Test code for C extension - | - +- mrbgem.rake <- GEM specification - | - +- README.md - -## Ruby Extension - -mruby can be extended with pure Ruby. It is possible to override existing -classes or add new ones in this way. Put all Ruby files into the *mrblib* -folder. - - -### Pre-Conditions - -none - -### Example - - +- ruby_extension_example/ - | - +- mrblib/ - | | - | +- example.rb <- Ruby extension source - | - +- test/ - | | - | +- example.rb <- Test code for Ruby extension - | - +- mrbgem.rake <- GEM specification - | - +- README.md - -## C and Ruby Extension - -mruby can be extended with C and Ruby at the same time. It is possible to -override existing classes or add new ones in this way. Put all Ruby files -into the *mrblib* folder and all C files into the *src* folder. - -mruby codes under *mrblib* directory would be executed after gem init C -function is called. Make sure *mruby script* depends on *C code* and -*C code* doesn't depend on *mruby script*. - -### Pre-Conditions - -See C and Ruby example. - -### Example - - +- c_and_ruby_extension_example/ - | - +- mrblib/ - | | - | +- example.rb <- Ruby extension source - | - +- src/ - | | - | +- example.c <- C extension source - | - +- test/ - | | - | +- example.rb <- Test code for C and Ruby extension - | - +- mrbgem.rake <- GEM specification - | - +- README.md diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/examples/mrbgems/ruby_extension_example/mrbgem.rake mruby-1.2.0+20160315+git4f20d58a/examples/mrbgems/ruby_extension_example/mrbgem.rake --- mruby-1.1.0+20150906+git1cbbb7e1/examples/mrbgems/ruby_extension_example/mrbgem.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/examples/mrbgems/ruby_extension_example/mrbgem.rake 2016-03-14 00:35:53.000000000 +0000 @@ -11,6 +11,8 @@ # Add libraries # spec.linker.libraries << 'external_lib' + spec.add_dependency('mruby-print', :core => 'mruby-print') + # Default build files # spec.rbfiles = Dir.glob("#{dir}/mrblib/*.rb") # spec.objs = Dir.glob("#{dir}/src/*.{c,cpp,m,asm,S}").map { |f| objfile(f.relative_path_from(dir).pathmap("#{build_dir}/%X")) } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/examples/targets/build_config_ArduinoDue.rb mruby-1.2.0+20160315+git4f20d58a/examples/targets/build_config_ArduinoDue.rb --- mruby-1.1.0+20150906+git1cbbb7e1/examples/targets/build_config_ArduinoDue.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/examples/targets/build_config_ArduinoDue.rb 2016-03-14 00:35:53.000000000 +0000 @@ -50,7 +50,7 @@ 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(MRB_DISABLE_STDIO) #if you dont need stdio. #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/examples/targets/build_config_chipKITMax32.rb mruby-1.2.0+20160315+git4f20d58a/examples/targets/build_config_chipKITMax32.rb --- mruby-1.1.0+20150906+git1cbbb7e1/examples/targets/build_config_chipKITMax32.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/examples/targets/build_config_chipKITMax32.rb 2016-03-14 00:35:53.000000000 +0000 @@ -47,7 +47,7 @@ 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(MRB_DISABLE_STDIO) #if you dont need stdio. #cc.defines << %w(POOL_PAGE_SIZE=1000) #effective only for use with mruby-eval end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/.gitignore mruby-1.2.0+20160315+git4f20d58a/.gitignore --- mruby-1.1.0+20150906+git1cbbb7e1/.gitignore 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/.gitignore 2016-03-14 00:35:53.000000000 +0000 @@ -20,4 +20,6 @@ /src/y.tab.c /bin /build -/lib +/mruby-source-*.gem +doc/api +.yardoc diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mrbconf.h mruby-1.2.0+20160315+git4f20d58a/include/mrbconf.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mrbconf.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mrbconf.h 2016-03-14 00:35:53.000000000 +0000 @@ -26,6 +26,9 @@ /* represent mrb_value as a word (natural unit of data for the processor) */ //#define MRB_WORD_BOXING +/* string class to handle UTF-8 encoding */ +//#define MRB_UTF8_STRING + /* argv max size in mrb_funcall */ //#define MRB_FUNCALL_ARGC_MAX 16 @@ -72,23 +75,25 @@ /* fixed size state atexit stack */ //#define MRB_FIXED_STATE_ATEXIT_STACK -/* -DDISABLE_XXXX to drop following features */ -//#define DISABLE_STDIO /* use of stdio */ +/* -DMRB_DISABLE_XXXX to drop following features */ +//#define MRB_DISABLE_STDIO /* use of stdio */ -/* -DENABLE_XXXX to enable following features */ -//#define ENABLE_DEBUG /* hooks for debugger */ +/* -DMRB_ENABLE_XXXX to enable following features */ +//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */ /* end of configuration */ -/* define ENABLE_XXXX from DISABLE_XXX */ -#ifndef DISABLE_STDIO -#define ENABLE_STDIO +/* define MRB_DISABLE_XXXX from DISABLE_XXX (for compatibility) */ +#ifdef DISABLE_STDIO +#define MRB_DISABLE_STDIO #endif -#ifndef ENABLE_DEBUG -#define DISABLE_DEBUG + +/* define MRB_ENABLE_XXXX from ENABLE_XXX (for compatibility) */ +#ifdef ENABLE_DEBUG +#define MRB_ENABLE_DEBUG_HOOK #endif -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO # include #endif @@ -100,15 +105,4 @@ # define TRUE 1 #endif -#if defined(MRB_BUILD_AS_DLL) - -#if defined(MRB_CORE) || defined(MRB_LIB) -#define MRB_API __declspec(dllexport) -#else -#define MRB_API __declspec(dllimport) -#endif -#else -#define MRB_API extern -#endif - #endif /* MRUBYCONF_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/array.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/array.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/array.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/array.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,13 @@ #ifndef MRUBY_ARRAY_H #define MRUBY_ARRAY_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/* + * Array class + */ +MRB_BEGIN_DECL + typedef struct mrb_shared_array { int refcnt; @@ -41,15 +45,78 @@ void mrb_ary_decref(mrb_state*, mrb_shared_array*); MRB_API void mrb_ary_modify(mrb_state*, struct RArray*); MRB_API mrb_value mrb_ary_new_capa(mrb_state*, mrb_int); + +/* + * Initializes a new array. + * + * Equivalent to: + * + * Array.new + * + * @param mrb The mruby state reference. + * @return The initialized array + */ MRB_API mrb_value mrb_ary_new(mrb_state *mrb); + MRB_API mrb_value mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals); MRB_API mrb_value mrb_assoc_new(mrb_state *mrb, mrb_value car, mrb_value cdr); MRB_API void mrb_ary_concat(mrb_state*, mrb_value, mrb_value); MRB_API mrb_value mrb_ary_splat(mrb_state*, mrb_value); -MRB_API void mrb_ary_push(mrb_state*, mrb_value, mrb_value); + +/* + * Pushes value into array. + * + * Equivalent to: + * + * ary << value + * + * @param mrb The mruby state reference. + * @param ary The array in which the value will be pushed + * @param value The value to be pushed into array + */ +MRB_API void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value); + +/* + * Pops the last element from the array. + * + * Equivalent to: + * + * ary.pop + * + * @param mrb The mruby state reference. + * @param ary The array from which the value will be poped. + * @return The poped value. + */ MRB_API mrb_value mrb_ary_pop(mrb_state *mrb, mrb_value ary); + +/* + * Returns a reference to an element of the array on the given index. + * + * Equivalent to: + * + * ary[n] + * + * @param mrb The mruby state reference. + * @param ary The target array. + * @param n The array index being referenced + * @return The referenced value. + */ MRB_API mrb_value mrb_ary_ref(mrb_state *mrb, mrb_value ary, mrb_int n); + +/* + * Sets a value on an array at the given index + * + * Equivalent to: + * + * ary[n] = val + * + * @param mrb The mruby state reference. + * @param ary The target array. + * @param n The array index being referenced. + * @param val The value being setted. + */ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val); + MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value a, mrb_value b); MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self); MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item); @@ -67,8 +134,6 @@ return RARRAY_LEN(ary); } -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_ARRAY_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/class.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/class.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/class.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/class.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef MRUBY_CLASS_H #define MRUBY_CLASS_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Class class + */ +MRB_BEGIN_DECL struct RClass { MRB_OBJECT_HEADER; @@ -81,8 +84,6 @@ size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*); void mrb_gc_free_mt(mrb_state*, struct RClass*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_CLASS_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/common.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/common.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/common.h 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/common.h 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,67 @@ +/* +**"common.h - mruby common platform definition" +** +** See Copyright Notice in mruby.h +*/ + +#ifndef MRUBY_COMMON_H +#define MRUBY_COMMON_H + + +#ifdef __cplusplus +# define MRB_BEGIN_DECL extern "C" { +# define MRB_END_DECL } +#else +/** Start declarations in C mode */ +# define MRB_BEGIN_DECL +/** End declarations in C mode */ +# define MRB_END_DECL +#endif + +/** + * Shared compiler macros + */ +MRB_BEGIN_DECL + +/** Declare a function that never returns. */ +#if __STDC_VERSION__ >= 201112L +# define mrb_noreturn _Noreturn +#elif defined __GNUC__ && !defined __STRICT_ANSI__ +# define mrb_noreturn __attribute__((noreturn)) +#elif defined _MSC_VER +# define mrb_noreturn __declspec(noreturn) +#else +# define mrb_noreturn +#endif + +/** Mark a function as deprecated. */ +#if defined __GNUC__ && !defined __STRICT_ANSI__ +# define mrb_deprecated __attribute__((deprecated)) +#elif defined _MSC_VER +# define mrb_deprecated __declspec(deprecated) +#else +# define mrb_deprecated +#endif + +/** Declare a function as always inlined. */ +#if defined(_MSC_VER) +# define MRB_INLINE static __inline +#else +# define MRB_INLINE static inline +#endif + + +/** Declare a public MRuby API function. */ +#if defined(MRB_BUILD_AS_DLL) +#if defined(MRB_CORE) || defined(MRB_LIB) +# define MRB_API __declspec(dllexport) +#else +# define MRB_API __declspec(dllimport) +#endif +#else +# define MRB_API extern +#endif + +MRB_END_DECL + +#endif /* MRUBY_COMMON_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/compile.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/compile.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/compile.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/compile.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,11 +7,14 @@ #ifndef MRUBY_COMPILE_H #define MRUBY_COMPILE_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * MRuby Compiler + */ +MRB_BEGIN_DECL -#include "mruby.h" +#include struct mrb_jmpbuf; @@ -37,8 +40,6 @@ MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data); -MRB_API mrb_value mrb_toplevel_run_keep(mrb_state*, struct RProc*, unsigned int); - /* AST node structure */ typedef struct mrb_ast_node { struct mrb_ast_node *car, *cdr; @@ -109,7 +110,7 @@ struct mrb_pool *pool; mrb_ast_node *cells; const char *s, *send; -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO FILE *f; #endif mrbc_context *cxt; @@ -164,7 +165,7 @@ MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); /* utility functions */ -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); #endif MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); @@ -172,19 +173,16 @@ MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); /* program load functions */ -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO MRB_API mrb_value mrb_load_file(mrb_state*,FILE*); +MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); #endif MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s); MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len); -#ifdef ENABLE_STDIO -MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); -#endif MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt); MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +/** @} */ +MRB_END_DECL #endif /* MRUBY_COMPILE_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/data.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/data.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/data.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/data.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,12 +7,23 @@ #ifndef MRUBY_DATA_H #define MRUBY_DATA_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" +/** + * Custom C wrapped data. + * + * Defining Ruby wrappers around native objects. + */ +MRB_BEGIN_DECL + +/** + * Custom data type description. + */ typedef struct mrb_data_type { + /** data type name */ const char *struct_name; + + /** data type release function pointer */ void (*dfree)(mrb_state *mrb, void*); } mrb_data_type; @@ -59,8 +70,6 @@ DATA_TYPE(v) = type; } -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_DATA_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/debug.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/debug.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/debug.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/debug.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef MRUBY_DEBUG_H #define MRUBY_DEBUG_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * MRuby Debugging. + */ +MRB_BEGIN_DECL typedef enum mrb_debug_line_type { mrb_debug_line_ary = 0, @@ -58,8 +61,6 @@ MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep); MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_DEBUG_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/dump.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/dump.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/dump.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/dump.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,12 +7,14 @@ #ifndef MRUBY_DUMP_H #define MRUBY_DUMP_H -#if defined(__cplusplus) -extern "C" { -#endif +#include +#include +#include "common.h" -#include "mruby.h" -#include "mruby/irep.h" +/** + * Dumping compiled mruby script. + */ +MRB_BEGIN_DECL #define DUMP_DEBUG_INFO 1 #define DUMP_ENDIAN_BIG 2 @@ -21,7 +23,7 @@ #define DUMP_ENDIAN_MASK 6 int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size); -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*); int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname); mrb_irep *mrb_read_irep_file(mrb_state*, FILE*); @@ -185,11 +187,9 @@ return (uint8_t)bin[0]; } -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL -/* crc.c */ +/** @internal crc.c */ uint16_t calc_crc_16_ccitt(const uint8_t *src, size_t nbytes, uint16_t crc); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/error.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/error.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/error.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/error.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef MRUBY_ERROR_H #define MRUBY_ERROR_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * MRuby error handling. + */ +MRB_BEGIN_DECL struct RException { MRB_OBJECT_HEADER; @@ -29,18 +32,38 @@ /* declaration for fail method */ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value); -/* functions defined in mruby-error mrbgem */ +/** + * Protect + * + * @mrbgem mruby-error + */ MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state); + +/** + * Ensure + * + * @mrbgem mruby-error + */ MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data); + +/** + * Rescue + * + * @mrbgem mruby-error + */ MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data); + +/** + * Rescue exception + * + * @mrbgem mruby-error + */ MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data, mrb_int len, struct RClass **classes); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_ERROR_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/gc.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/gc.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/gc.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/gc.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,16 +7,71 @@ #ifndef MRUBY_GC_H #define MRUBY_GC_H -#if defined(__cplusplus) -extern "C" { +#include "common.h" + +/** + * Uncommon memory management stuffs. + */ +MRB_BEGIN_DECL + + +struct mrb_state; + +typedef void (mrb_each_object_callback)(struct mrb_state *mrb, struct RBasic *obj, void *data); +void mrb_objspace_each_objects(struct mrb_state *mrb, mrb_each_object_callback *callback, void *data); +MRB_API void mrb_free_context(struct mrb_state *mrb, struct mrb_context *c); + +#ifndef MRB_GC_ARENA_SIZE +#define MRB_GC_ARENA_SIZE 100 #endif -typedef void (mrb_each_object_callback)(mrb_state *mrb, struct RBasic *obj, void *data); -void mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data); -MRB_API void mrb_free_context(mrb_state *mrb, struct mrb_context *c); +typedef enum { + MRB_GC_STATE_ROOT = 0, + MRB_GC_STATE_MARK, + MRB_GC_STATE_SWEEP +} mrb_gc_state; -#if defined(__cplusplus) -} /* extern "C" { */ +typedef struct mrb_heap_page { + struct RBasic *freelist; + struct mrb_heap_page *prev; + struct mrb_heap_page *next; + struct mrb_heap_page *free_next; + struct mrb_heap_page *free_prev; + mrb_bool old:1; + void *objects[]; +} mrb_heap_page; + +typedef struct mrb_gc { + mrb_heap_page *heaps; /* heaps for GC */ + mrb_heap_page *sweeps; + mrb_heap_page *free_heaps; + size_t live; /* count of live objects */ +#ifdef MRB_GC_FIXED_ARENA + struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */ +#else + struct RBasic **arena; /* GC protection array */ + int arena_capa; #endif + int arena_idx; + + mrb_gc_state state; /* state of gc */ + int current_white_part; /* make white object by white_part */ + struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */ + struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */ + size_t live_after_mark; + size_t threshold; + int interval_ratio; + int step_ratio; + mrb_bool disabled :1; + mrb_bool full :1; + mrb_bool generational :1; + mrb_bool out_of_memory :1; + size_t majorgc_old_threshold; +} mrb_gc; + +MRB_API mrb_bool +mrb_object_dead_p(struct mrb_state *mrb, struct RBasic *object); + +MRB_END_DECL #endif /* MRUBY_GC_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/hash.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/hash.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/hash.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/hash.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,13 @@ #ifndef MRUBY_HASH_H #define MRUBY_HASH_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" +#include + +/** + * Hash class + */ +MRB_BEGIN_DECL struct RHash { MRB_OBJECT_HEADER; @@ -21,17 +25,50 @@ #define mrb_hash_value(p) mrb_obj_value((void*)(p)) MRB_API mrb_value mrb_hash_new_capa(mrb_state*, int); + +/* + * Initializes a new hash. + */ MRB_API mrb_value mrb_hash_new(mrb_state *mrb); +/* + * Sets a keys and values to hashes. + */ MRB_API void mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val); + +/* + * Gets a value from a key. + */ MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key); + MRB_API mrb_value mrb_hash_fetch(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value def); + +/* + * Deletes hash key and value pair. + */ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key); + +/* + * Gets an array of keys. + */ MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash); MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self); + +/* + * Clears the hash. + */ MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash); +/* declaration of struct kh_ht */ +/* be careful when you touch the internal */ +typedef struct { + mrb_value v; + mrb_int n; +} mrb_hash_value; + +KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE) + /* RHASH_TBL allocates st_table if not available. */ #define RHASH(obj) ((struct RHash*)(mrb_ptr(obj))) #define RHASH_TBL(h) (RHASH(h)->ht) @@ -39,7 +76,9 @@ #define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h) MRB_API struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash); -#define MRB_HASH_PROC_DEFAULT 256 +#define MRB_HASH_DEFAULT 1 +#define MRB_HASH_PROC_DEFAULT 2 +#define MRB_RHASH_DEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_DEFAULT) #define MRB_RHASH_PROCDEFAULT_P(h) (RHASH(h)->flags & MRB_HASH_PROC_DEFAULT) /* GC functions */ @@ -47,8 +86,6 @@ size_t mrb_gc_mark_hash_size(mrb_state*, struct RHash*); void mrb_gc_free_hash(mrb_state*, struct RHash*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_HASH_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/irep.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/irep.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/irep.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/irep.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,11 +7,13 @@ #ifndef MRUBY_IREP_H #define MRUBY_IREP_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" +#include -#include "mruby/compile.h" +/** + * Compiled mruby scripts. + */ +MRB_BEGIN_DECL enum irep_pool_type { IREP_TT_STRING, @@ -53,8 +55,6 @@ void mrb_irep_incref(mrb_state*, struct mrb_irep*); void mrb_irep_decref(mrb_state*, struct mrb_irep*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_IREP_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/khash.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/khash.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/khash.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/khash.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,13 +7,16 @@ #ifndef MRUBY_KHASH_H #define MRUBY_KHASH_H -#if defined(__cplusplus) -extern "C" { -#endif - -#include "mruby.h" #include +#include +#include "common.h" + +/** + * khash definitions used in mruby's hash table. + */ +MRB_BEGIN_DECL + typedef uint32_t khint_t; typedef khint_t khiter_t; @@ -266,8 +269,6 @@ typedef const char *kh_cstr_t; -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_KHASH_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/numeric.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/numeric.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/numeric.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/numeric.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,14 @@ #ifndef MRUBY_NUMERIC_H #define MRUBY_NUMERIC_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Numeric class and it's sub-classes. + * + * Integer, Float and Fixnum + */ +MRB_BEGIN_DECL #define POSFIXABLE(f) ((f) <= MRB_INT_MAX) #define NEGFIXABLE(f) ((f) >= MRB_INT_MIN) @@ -30,11 +35,7 @@ #define MRB_UINT_MAKE(n) MRB_UINT_MAKE2(n) #define mrb_uint MRB_UINT_MAKE(MRB_INT_BIT) -#ifdef MRB_WORD_BOXING -# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT)) -#else -# define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1)) -#endif +#define MRB_INT_OVERFLOW_MASK ((mrb_uint)1 << (MRB_INT_BIT - 1 - MRB_FIXNUM_SHIFT)) /* Idea from Potion: https://github.com/perl11/potion (MIT) */ #if (defined(__clang__) && ((__clang_major__ > 3) || (__clang_major__ == 3 && __clang_minor__ >= 4))) \ @@ -104,8 +105,6 @@ #undef MRB_UINT_MAKE #undef MRB_UINT_MAKE2 -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_NUMERIC_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/object.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/object.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/object.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/object.h 2016-03-14 00:35:53.000000000 +0000 @@ -16,24 +16,6 @@ #define MRB_FLAG_TEST(obj, flag) ((obj)->flags & flag) -/* white: 011, black: 100, gray: 000 */ -#define MRB_GC_GRAY 0 -#define MRB_GC_WHITE_A 1 -#define MRB_GC_WHITE_B (1 << 1) -#define MRB_GC_BLACK (1 << 2) -#define MRB_GC_WHITES (MRB_GC_WHITE_A | MRB_GC_WHITE_B) -#define MRB_GC_COLOR_MASK 7 - -#define paint_gray(o) ((o)->color = MRB_GC_GRAY) -#define paint_black(o) ((o)->color = MRB_GC_BLACK) -#define paint_white(o) ((o)->color = MRB_GC_WHITES) -#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part) -#define is_gray(o) ((o)->color == MRB_GC_GRAY) -#define is_white(o) ((o)->color & MRB_GC_WHITES) -#define is_black(o) ((o)->color & MRB_GC_BLACK) -#define is_dead(s, o) (((o)->color & other_white_part(s) & MRB_GC_WHITES) || (o)->tt == MRB_TT_FREE) -#define flip_white_part(s) ((s)->current_white_part = other_white_part(s)) -#define other_white_part(s) ((s)->current_white_part ^ MRB_GC_WHITES) struct RBasic { MRB_OBJECT_HEADER; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/proc.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/proc.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/proc.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/proc.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,11 +7,13 @@ #ifndef MRUBY_PROC_H #define MRUBY_PROC_H -#include "mruby/irep.h" +#include "common.h" +#include -#if defined(__cplusplus) -extern "C" { -#endif +/** + * Proc class + */ +MRB_BEGIN_DECL struct REnv { MRB_OBJECT_HEADER; @@ -25,6 +27,8 @@ #define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1) #define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0) +MRB_API void mrb_env_unshare(mrb_state*, struct REnv*); + struct RProc { MRB_OBJECT_HEADER; union { @@ -66,11 +70,9 @@ /* old name */ #define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx) -#include "mruby/khash.h" +#include KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE) -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_PROC_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/range.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/range.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/range.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/range.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef MRUBY_RANGE_H #define MRUBY_RANGE_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Range class + */ +MRB_BEGIN_DECL typedef struct mrb_range_edges { mrb_value beg; @@ -25,12 +28,21 @@ #define mrb_range_ptr(v) ((struct RRange*)(mrb_ptr(v))) #define mrb_range_value(p) mrb_obj_value((void*)(p)) -MRB_API mrb_value mrb_range_new(mrb_state*, mrb_value, mrb_value, mrb_bool); +/* + * Initializes a Range. + * + * If the third parameter is FALSE then it includes the last value in the range. + * If the third parameter is TRUE then it excludes the last value in the range. + * + * @param start the beginning value. + * @param end the ending value. + * @param exclude represents the inclusion or exclusion of the last value. + */ +MRB_API mrb_value mrb_range_new(mrb_state *mrb, mrb_value start, mrb_value end, mrb_bool exclude); + MRB_API mrb_bool mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len); mrb_value mrb_get_values_at(mrb_state *mrb, mrb_value obj, mrb_int olen, mrb_int argc, const mrb_value *argv, mrb_value (*func)(mrb_state*, mrb_value, mrb_int)); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_RANGE_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/string.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/string.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/string.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/string.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef MRUBY_STRING_H #define MRUBY_STRING_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * String class + */ +MRB_BEGIN_DECL extern const char mrb_digitmap[]; @@ -63,11 +66,14 @@ #define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) #define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) +/* + * Returns a pointer from a Ruby string + */ #define mrb_str_ptr(s) ((struct RString*)(mrb_ptr(s))) #define RSTRING(s) mrb_str_ptr(s) #define RSTRING_PTR(s) RSTR_PTR(RSTRING(s)) #define RSTRING_EMBED_LEN(s) RSTR_ENBED_LEN(RSTRING(s)) -#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) +#define RSTRING_LEN(s) RSTR_LEN(RSTRING(s)) #define RSTRING_CAPA(s) RSTR_CAPA(RSTRING(s)) #define RSTRING_END(s) (RSTRING_PTR(s) + RSTRING_LEN(s)) mrb_int mrb_str_strlen(mrb_state*, struct RString*); @@ -75,41 +81,125 @@ #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 #define MRB_STR_FROZEN 4 -#define MRB_STR_EMBED 8 -#define MRB_STR_EMBED_LEN_MASK 0x1f0 -#define MRB_STR_EMBED_LEN_SHIFT 4 +#define MRB_STR_NO_UTF 8 +#define MRB_STR_EMBED 16 +#define MRB_STR_EMBED_LEN_MASK 0x3e0 +#define MRB_STR_EMBED_LEN_SHIFT 5 void mrb_gc_free_str(mrb_state*, struct RString*); MRB_API void mrb_str_modify(mrb_state*, struct RString*); MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value); + +/* + * Adds two strings together. + */ MRB_API mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value); + +/* + * Converts pointer into a Ruby string. + */ MRB_API mrb_value mrb_ptr_to_str(mrb_state *, void*); + +/* + * Returns an object as a Ruby string. + */ MRB_API mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj); + +/* + * Resizes the string's length. + */ MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len); + +/* + * Returns a sub string. + */ MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); + +/* + * Returns a Ruby string type. + */ MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str); + MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str); MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa); MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr); -MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr); +MRB_API const char *mrb_string_value_ptr(mrb_state *mrb, mrb_value str); +MRB_API mrb_int mrb_string_value_len(mrb_state *mrb, mrb_value str); + +/* + * Duplicates a string object. + */ MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); + +/* + * Returns a symbol from a passed in string. + */ MRB_API mrb_value mrb_str_intern(mrb_state *mrb, mrb_value self); + MRB_API mrb_value mrb_str_to_inum(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck); MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck); + +/* + * Returns a converted string type. + */ MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str); + +/* + * Returns true if the strings match and false if the strings don't match. + */ MRB_API mrb_bool mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2); + +/* + * Returns a concated string comprised of a Ruby string and a C string. + * + * @see mrb_str_cat_cstr + */ MRB_API mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len); + +/* + * Returns a concated string comprised of a Ruby string and a C string. + * + * @see mrb_str_cat + */ MRB_API mrb_value mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr); MRB_API mrb_value mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2); #define mrb_str_cat_lit(mrb, str, lit) mrb_str_cat(mrb, str, lit, mrb_strlen_lit(lit)) + +/* + * Adds str2 to the end of str1. + */ MRB_API mrb_value mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2); +/* + * Returns 0 if both Ruby strings are equal. Returns a value < 0 if Ruby str1 is less than Ruby str2. Returns a value > 0 if Ruby str2 is greater than Ruby str1. + */ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2); + +/* + * Returns a newly allocated C string from a Ruby string. + * This is an utility function to pass a Ruby string to C library functions. + * + * - Returned string does not contain any NUL characters (but terminator). + * - It raises an ArgumentError exception if Ruby string contains + * NUL characters. + * - Retured string will be freed automatically on next GC. + * - Caller can modify returned string without affecting Ruby string + * (e.g. it can be used for mkstemp(3)). + * + * @param [mrb_state *] mrb The current mruby state. + * @param [mrb_value] str Ruby string. Must be an instance of String. + * @return [char *] A newly allocated C string. + */ MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str); + mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str); mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str); mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str); + +/* + * Returns a printable version of str, surrounded by quote marks, with special characters escaped. + */ mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str); void mrb_noregexp(mrb_state *mrb, mrb_value self); @@ -120,8 +210,6 @@ #define mrb_str_buf_cat(mrb, str, ptr, len) mrb_str_cat(mrb, str, ptr, len) #define mrb_str_buf_append(mrb, str, str2) mrb_str_cat_str(mrb, str, str2) -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_STRING_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/throw.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/throw.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/throw.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/throw.h 2016-03-14 00:35:53.000000000 +0000 @@ -20,11 +20,19 @@ #include -#define MRB_TRY(buf) do { if (setjmp((buf)->impl) == 0) { +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#define MRB_SETJMP _setjmp +#define MRB_LONGJMP _longjmp +#else +#define MRB_SETJMP setjmp +#define MRB_LONGJMP longjmp +#endif + +#define MRB_TRY(buf) do { if (MRB_SETJMP((buf)->impl) == 0) { #define MRB_CATCH(buf) } else { #define MRB_END_EXC(buf) } } while(0) -#define MRB_THROW(buf) longjmp((buf)->impl, 1); +#define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1); #define mrb_jmpbuf_impl jmp_buf #endif diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/value.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/value.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/value.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/value.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,6 +7,13 @@ #ifndef MRUBY_VALUE_H #define MRUBY_VALUE_H +#include "common.h" + +/** + * MRuby Value definition functions and macros. + */ +MRB_BEGIN_DECL + typedef uint32_t mrb_sym; typedef uint8_t mrb_bool; struct mrb_state; @@ -15,21 +22,32 @@ # error "You can't define MRB_INT16 and MRB_INT64 at the same time." #endif +#include + #if defined(MRB_INT64) typedef int64_t mrb_int; # define MRB_INT_BIT 64 # define MRB_INT_MIN (INT64_MIN>>MRB_FIXNUM_SHIFT) # define MRB_INT_MAX (INT64_MAX>>MRB_FIXNUM_SHIFT) +# define MRB_PRIo PRIo64 +# define MRB_PRId PRId64 +# define MRB_PRIx PRIx64 #elif defined(MRB_INT16) typedef int16_t mrb_int; # define MRB_INT_BIT 16 # define MRB_INT_MIN (INT16_MIN>>MRB_FIXNUM_SHIFT) # define MRB_INT_MAX (INT16_MAX>>MRB_FIXNUM_SHIFT) +# define MRB_PRIo PRIo16 +# define MRB_PRId PRId16 +# define MRB_PRIx PRIx16 #else typedef int32_t mrb_int; # define MRB_INT_BIT 32 # define MRB_INT_MIN (INT32_MIN>>MRB_FIXNUM_SHIFT) # define MRB_INT_MAX (INT32_MAX>>MRB_FIXNUM_SHIFT) +# define MRB_PRIo PRIo32 +# define MRB_PRId PRId32 +# define MRB_PRIx PRIx32 #endif #ifdef MRB_USE_FLOAT @@ -89,7 +107,23 @@ MRB_TT_MAXDEFINE /* 23 */ }; -#include "mruby/object.h" +#include + +#ifdef MRB_DOCUMENTATION_BLOCK + +/** + * @abstract + * MRuby value boxing. + * + * Actual implementation depends on configured boxing type. + * + * @see mruby/boxing_no.h Default boxing representation + * @see mruby/boxing_word.h Word representation + * @see mruby/boxing_nan.h Boxed double representation + */ +typedef void mrb_value; + +#endif #if defined(MRB_NAN_BOXING) #include "boxing_nan.h" @@ -121,8 +155,10 @@ #define mrb_test(o) mrb_bool(o) MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value); -static inline mrb_value -mrb_float_value(struct mrb_state *mrb, mrb_float f) +/* + * Returns a float in Ruby. + */ +MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f) { mrb_value v; (void) mrb; @@ -139,8 +175,10 @@ return v; } -static inline mrb_value -mrb_fixnum_value(mrb_int i) +/* + * Returns a fixnum in Ruby. + */ +MRB_INLINE mrb_value mrb_fixnum_value(mrb_int i) { mrb_value v; SET_INT_VALUE(v, i); @@ -163,24 +201,34 @@ return v; } -static inline mrb_value -mrb_nil_value(void) + +/* + * Get a nil mrb_value object. + * + * @return + * nil mrb_value object reference. + */ +MRB_INLINE mrb_value mrb_nil_value(void) { mrb_value v; SET_NIL_VALUE(v); return v; } -static inline mrb_value -mrb_false_value(void) +/* + * Returns false in Ruby. + */ +MRB_INLINE mrb_value mrb_false_value(void) { mrb_value v; SET_FALSE_VALUE(v); return v; } -static inline mrb_value -mrb_true_value(void) +/* + * Returns true in Ruby. + */ +MRB_INLINE mrb_value mrb_true_value(void) { mrb_value v; SET_TRUE_VALUE(v); @@ -226,4 +274,6 @@ # define mrb_ro_data_p(p) FALSE #endif +MRB_END_DECL + #endif /* MRUBY_VALUE_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/variable.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/variable.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/variable.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/variable.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,12 @@ #ifndef MRUBY_VARIABLE_H #define MRUBY_VARIABLE_H -#if defined(__cplusplus) -extern "C" { -#endif +#include "common.h" + +/** + * Functions to access mruby variables. + */ +MRB_BEGIN_DECL typedef struct global_variable { int counter; @@ -74,8 +77,6 @@ size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*); void mrb_gc_free_iv(mrb_state*, struct RObject*); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_VARIABLE_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/version.h mruby-1.2.0+20160315+git4f20d58a/include/mruby/version.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby/version.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby/version.h 2016-03-14 00:35:53.000000000 +0000 @@ -7,36 +7,104 @@ #ifndef MRUBY_VERSION_H #define MRUBY_VERSION_H +#include "common.h" + +/** + * mruby version definition macros + */ +MRB_BEGIN_DECL + +/* + * A passed in expression. + */ #define MRB_STRINGIZE0(expr) #expr + +/* + * Passes in an expression to MRB_STRINGIZE0. + */ #define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr) +/* + * The version of Ruby used by mruby. + */ #define MRUBY_RUBY_VERSION "1.9" + +/* + * Ruby engine. + */ #define MRUBY_RUBY_ENGINE "mruby" +/* + * Major release version number. + */ #define MRUBY_RELEASE_MAJOR 1 -#define MRUBY_RELEASE_MINOR 1 -#define MRUBY_RELEASE_TEENY 1 +/* + * Minor release version number. + */ +#define MRUBY_RELEASE_MINOR 2 + +/* + * Tiny release version number. + */ +#define MRUBY_RELEASE_TEENY 0 + +/* + * The mruby version. + */ #define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR) "." MRB_STRINGIZE(MRUBY_RELEASE_MINOR) "." MRB_STRINGIZE(MRUBY_RELEASE_TEENY) + +/* + * Release number. + */ #define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY) -#define MRUBY_RELEASE_YEAR 2014 + +/* + * Release year. + */ +#define MRUBY_RELEASE_YEAR 2015 + +/* + * Release month. + */ #define MRUBY_RELEASE_MONTH 11 -#define MRUBY_RELEASE_DAY 19 + +/* + * Release day. + */ +#define MRUBY_RELEASE_DAY 17 + +/* + * Release date as a string. + */ #define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR) "-" MRB_STRINGIZE(MRUBY_RELEASE_MONTH) "-" MRB_STRINGIZE(MRUBY_RELEASE_DAY) +/* + * The year mruby was first created. + */ #define MRUBY_BIRTH_YEAR 2010 +/* + * MRuby's authors. + */ #define MRUBY_AUTHOR "mruby developers" - +/* + * mruby's version, and release date. + */ #define MRUBY_DESCRIPTION \ "mruby " MRUBY_VERSION \ " (" MRUBY_RELEASE_DATE ") " \ +/* + * mruby's copyright information. + */ #define MRUBY_COPYRIGHT \ "mruby - Copyright (c) " \ MRB_STRINGIZE(MRUBY_BIRTH_YEAR)"-" \ MRB_STRINGIZE(MRUBY_RELEASE_YEAR)" " \ MRUBY_AUTHOR \ +MRB_END_DECL + #endif /* MRUBY_VERSION_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/include/mruby.h mruby-1.2.0+20160315+git4f20d58a/include/mruby.h --- mruby-1.1.0+20150906+git1cbbb7e1/include/mruby.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/include/mruby.h 2016-03-14 00:35:53.000000000 +0000 @@ -1,7 +1,7 @@ /* ** mruby - An embeddable Ruby implementation ** -** Copyright (c) mruby developers 2010-2015 +** Copyright (c) mruby developers 2010-2016 ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the @@ -28,30 +28,43 @@ #ifndef MRUBY_H #define MRUBY_H -#if defined(__cplusplus) -extern "C" { -#endif - #include #include #include #include "mrbconf.h" -#include "mruby/value.h" -#include "mruby/version.h" +#include "mruby/common.h" +#include +#include +#include + +/** + * MRuby C API entry point + */ +MRB_BEGIN_DECL typedef uint32_t mrb_code; + +/** + * Required arguments signature type. + */ typedef uint32_t mrb_aspec; + struct mrb_irep; struct mrb_state; +/** + * Function pointer type of custom allocator used in @see mrb_open_allocf. + * + * The function pointing it must behave similarly as realloc except: + * - If ptr is NULL it must allocate new space. + * - If s is NULL, ptr must be freed. + * + * See @see mrb_default_allocf for the default implementation. + */ typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud); -#ifndef MRB_GC_ARENA_SIZE -#define MRB_GC_ARENA_SIZE 100 -#endif - #ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE #define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5 #endif @@ -74,7 +87,7 @@ enum mrb_fiber_state { MRB_FIBER_CREATED = 0, MRB_FIBER_RUNNING, - MRB_FIBER_RESUMING, + MRB_FIBER_RESUMED, MRB_FIBER_SUSPENDED, MRB_FIBER_TRANSFERRED, MRB_FIBER_TERMINATED, @@ -95,22 +108,29 @@ int esize; enum mrb_fiber_state status; + mrb_bool vmexec; struct RFiber *fib; }; -enum gc_state { - GC_STATE_ROOT = 0, - GC_STATE_MARK, - GC_STATE_SWEEP -}; - struct mrb_jmpbuf; +typedef struct { + const char *filename; + int lineno; + struct RClass *klass; + char sep; + mrb_sym method_id; +} mrb_backtrace_entry; + typedef void (*mrb_atexit_func)(struct mrb_state*); +#define MRB_STATE_NO_REGEXP 1 +#define MRB_STATE_REGEXP 2 + typedef struct mrb_state { struct mrb_jmpbuf *jmp; + uint32_t flags; mrb_allocf allocf; /* memory allocation function */ void *allocf_ud; /* auxiliary data of allocf */ @@ -118,6 +138,12 @@ struct mrb_context *root_c; struct RObject *exc; /* exception */ + struct { + struct RObject *exc; + int n; + int n_allocated; + mrb_backtrace_entry *entries; + } backtrace; struct iv_tbl *globals; /* global variable table */ struct RObject *top_self; @@ -137,39 +163,15 @@ struct RClass *symbol_class; struct RClass *kernel_module; - struct heap_page *heaps; /* heaps for GC */ - struct heap_page *sweeps; - struct heap_page *free_heaps; - size_t live; /* count of live objects */ -#ifdef MRB_GC_FIXED_ARENA - struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */ -#else - struct RBasic **arena; /* GC protection array */ - int arena_capa; -#endif - int arena_idx; - - enum gc_state gc_state; /* state of gc */ - int current_white_part; /* make white object by white_part */ - struct RBasic *gray_list; /* list of gray objects to be traversed incrementally */ - struct RBasic *atomic_gray_list; /* list of objects to be traversed atomically */ - size_t gc_live_after_mark; - size_t gc_threshold; - int gc_interval_ratio; - int gc_step_ratio; - mrb_bool gc_disabled:1; - mrb_bool gc_full:1; - mrb_bool is_generational_gc_mode:1; - mrb_bool out_of_memory:1; - size_t majorgc_old_threshold; struct alloca_header *mems; + mrb_gc gc; mrb_sym symidx; struct kh_n2s *name2sym; /* symbol hash */ struct symbol_name *symtbl; /* symbol table */ size_t symcapa; -#ifdef ENABLE_DEBUG +#ifdef MRB_ENABLE_DEBUG_HOOK void (*code_fetch_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); void (*debug_op_hook)(struct mrb_state* mrb, struct mrb_irep *irep, mrb_code *pc, mrb_value *regs); #endif @@ -188,73 +190,577 @@ mrb_int atexit_stack_len; } mrb_state; -#if __STDC_VERSION__ >= 201112L -# define mrb_noreturn _Noreturn -#elif defined __GNUC__ && !defined __STRICT_ANSI__ -# define mrb_noreturn __attribute__((noreturn)) -# define mrb_deprecated __attribute__((deprecated)) -#elif defined _MSC_VER -# define mrb_noreturn __declspec(noreturn) -# define mrb_deprecated __declspec(deprecated) -#else -# define mrb_noreturn -# define mrb_deprecated -#endif typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value); -MRB_API struct RClass *mrb_define_class(mrb_state *, const char*, struct RClass*); + +/** + * Defines a new class. + * + * If you're creating a gem it may look something like this: + * + * !!!c + * void mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class); + * } + * + * void mrb_example_gem_final(mrb_state* mrb) { + * //free(TheAnimals); + * } + * + * @param [mrb_state *] mrb The current mruby state. + * @param [const char *] name The name of the defined class. + * @param [struct RClass *] super The new class parent. + * @return [struct RClass *] Reference to the newly defined class. + * @see mrb_define_class_under + */ +MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super); + +/** + * Defines a new module. + * + * @param [mrb_state *] mrb_state* The current mruby state. + * @param [const char *] char* The name of the module. + * @return [struct RClass *] Reference to the newly defined module. + */ MRB_API struct RClass *mrb_define_module(mrb_state *, const char*); MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value); + +/** + * Include a module in another class or module. + * Equivalent to: + * + * module B + * include A + * end + * @param [mrb_state *] mrb_state* The current mruby state. + * @param [struct RClass *] RClass* A reference to module or a class. + * @param [struct RClass *] RClass* A reference to the module to be included. + */ MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*); + +/** + * Prepends a module in another class or module. + * + * Equivalent to: + * module B + * prepend A + * end + * @param [mrb_state *] mrb_state* The current mruby state. + * @param [struct RClass *] RClass* A reference to module or a class. + * @param [struct RClass *] RClass* A reference to the module to be prepended. + */ MRB_API void mrb_prepend_module(mrb_state*, struct RClass*, struct RClass*); -MRB_API void mrb_define_method(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); +/** + * Defines a global function in ruby. + * + * If you're creating a gem it may look something like this + * + * Example: + * + * !!!c + * mrb_value example_method(mrb_state* mrb, mrb_value self) + * { + * puts("Executing example command!"); + * return self; + * } + * + * void mrb_example_gem_init(mrb_state* mrb) + * { + * mrb_define_method(mrb, mrb->kernel_module, "example_method", example_method, MRB_ARGS_NONE()); + * } + * + * @param [mrb_state *] mrb The MRuby state reference. + * @param [struct RClass *] cla The class pointer where the method will be defined. + * @param [const char *] name The name of the method being defined. + * @param [mrb_func_t] func The function pointer to the method definition. + * @param [mrb_aspec] aspec The method parameters declaration. + */ +MRB_API void mrb_define_method(mrb_state *mrb, struct RClass *cla, const char *name, mrb_func_t func, mrb_aspec aspec); + +/** + * Defines a class method. + * + * Example: + * + * # Ruby style + * class Foo + * def Foo.bar + * end + * end + * // C style + * mrb_value bar_method(mrb_state* mrb, mrb_value self){ + * return mrb_nil_value(); + * } + * void mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *foo; + * foo = mrb_define_class(mrb, "Foo", mrb->object_class); + * mrb_define_class_method(mrb, foo, "bar", bar_method, MRB_ARGS_NONE()); + * } + * @param [mrb_state *] mrb_state* The MRuby state reference. + * @param [struct RClass *] RClass* The class where the class method will be defined. + * @param [const char *] char* The name of the class method being defined. + * @param [mrb_func_t] mrb_func_t The function pointer to the class method definition. + * @param [mrb_aspec] mrb_aspec The method parameters declaration. + */ MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec); MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec); + +/** + * Defines a module fuction. + * + * Example: + * + * # Ruby style + * module Foo + * def Foo.bar + * end + * end + * // C style + * mrb_value bar_method(mrb_state* mrb, mrb_value self){ + * return mrb_nil_value(); + * } + * void mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *foo; + * foo = mrb_define_module(mrb, "Foo"); + * mrb_define_module_function(mrb, foo, "bar", bar_method, MRB_ARGS_NONE()); + * } + * @param [mrb_state *] mrb_state* The MRuby state reference. + * @param [struct RClass *] RClass* The module where the module function will be defined. + * @param [const char *] char* The name of the module function being defined. + * @param [mrb_func_t] mrb_func_t The function pointer to the module function definition. + * @param [mrb_aspec] mrb_aspec The method parameters declaration. + */ MRB_API void mrb_define_module_function(mrb_state*, struct RClass*, const char*, mrb_func_t, mrb_aspec); + +/** + * Defines a constant. + * + * Example: + * + * # Ruby style + * class ExampleClass + * AGE = 22 + * end + * // C style + * #include + * #include + * + * void + * mrb_example_gem_init(mrb_state* mrb){ + * mrb_define_const(mrb, mrb->kernel_module, "AGE", mrb_fixnum_value(22)); + * } + * + * mrb_value + * mrb_example_gem_final(mrb_state* mrb){ + * } + * @param [mrb_state *] mrb_state* The MRuby state reference. + * @param [struct RClass *] RClass* A class or module the constant is defined in. + * @param [const char *] name The name of the constant being defined. + * @param [mrb_value] mrb_value The value for the constant. + */ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_value); + +/** + * Undefines a method. + * + * Example: + * + * # Ruby style + * + * class ExampleClassA + * def example_method + * "example" + * end + * end + * ExampleClassA.new.example_method # => example + * + * class ExampleClassB < ExampleClassA + * undef_method :example_method + * end + * + * ExampleClassB.new.example_method # => undefined method 'example_method' for ExampleClassB (NoMethodError) + * + * // C style + * #include + * #include + * + * mrb_value + * mrb_example_method(mrb_state *mrb){ + * return mrb_str_new_cstr(mrb, "example"); + * } + * + * void + * mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *example_class_a; + * struct RClass *example_class_b; + * struct RClass *example_class_c; + * + * example_class_a = mrb_define_class(mrb, "ExampleClassA", mrb->object_class); + * mrb_define_method(mrb, example_class_a, "example_method", mrb_example_method, MRB_ARGS_NONE()); + * example_class_b = mrb_define_class(mrb, "ExampleClassB", example_class_a); + * example_class_c = mrb_define_class(mrb, "ExampleClassC", example_class_b); + * mrb_undef_method(mrb, example_class_c, "example_method"); + * } + * + * mrb_example_gem_final(mrb_state* mrb){ + * } + * @param [mrb_state*] mrb_state* The mruby state reference. + * @param [struct RClass*] RClass* A class the method will be undefined from. + * @param [const char*] constchar* The name of the method to be undefined. + */ MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*); + +/** + * Undefine a class method. + * Example: + * + * # Ruby style + * class ExampleClass + * def self.example_method + * "example" + * end + * end + * + * ExampleClass.example_method + * + * // C style + * #include + * #include + * + * mrb_value + * mrb_example_method(mrb_state *mrb){ + * return mrb_str_new_cstr(mrb, "example"); + * } + * + * void + * mrb_example_gem_init(mrb_state* mrb){ + * struct RClass *example_class; + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); + * mrb_define_class_method(mrb, example_class, "example_method", mrb_example_method, MRB_ARGS_NONE()); + * mrb_undef_class_method(mrb, example_class, "example_method"); + * } + * + * void + * mrb_example_gem_final(mrb_state* mrb){ + * } + * @param [mrb_state*] mrb_state* The mruby state reference. + * @param [RClass*] RClass* A class the class method will be undefined from. + * @param [constchar*] constchar* The name of the class method to be undefined. + */ MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*); + +/** + * Initialize a new object instace of c class. + * + * Example: + * + * # Ruby style + * class ExampleClass + * end + * + * p ExampleClass # => # + * // C style + * #include + * #include + * + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * mrb_value obj; + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); # => class ExampleClass; end + * obj = mrb_obj_new(mrb, example_class, 0, NULL); # => ExampleClass.new + * mrb_p(mrb, obj); // => Kernel#p + * } + * @param [mrb_state*] mrb The current mruby state. + * @param [RClass*] c Reference to the class of the new object. + * @param [mrb_int] argc Number of arguments in argv + * @param [const mrb_value *] argv Array of mrb_value to initialize the object + * @return [mrb_value] The newly initialized object + */ MRB_API mrb_value mrb_obj_new(mrb_state *mrb, struct RClass *c, mrb_int argc, const mrb_value *argv); -#define mrb_class_new_instance(mrb,argc,argv,c) mrb_obj_new(mrb,c,argc,argv) + +/** @see mrb_obj_new */ +MRB_INLINE mrb_value mrb_class_new_instance(mrb_state *mrb, mrb_int argc, const mrb_value *argv, struct RClass *c) +{ + return mrb_obj_new(mrb,c,argc,argv); +} + MRB_API mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv); + +/** + * Creates a new instance of Class, Class. + * + * Example: + * + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * + * mrb_value obj; + * example_class = mrb_class_new(mrb, mrb->object_class); + * obj = mrb_obj_new(mrb, example_class, 0, NULL); // => #<#:0x9a94588> + * mrb_p(mrb, obj); // => Kernel#p + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @param [struct RClass *] super The super class or parent. + * @return [struct RClass *] Reference to the new class. + */ MRB_API struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super); + +/** + * Creates a new module, Module. + * + * Example: + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_module; + * + * example_module = mrb_module_new(mrb); + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @return [struct RClass *] Reference to the new module. + */ MRB_API struct RClass * mrb_module_new(mrb_state *mrb); + +/** + * Returns an mrb_bool. True if class was defined, and false if the class was not defined. + * + * Example: + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * mrb_bool cd; + * + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); + * cd = mrb_class_defined(mrb, "ExampleClass"); + * + * // If mrb_class_defined returns 1 then puts "True" + * // If mrb_class_defined returns 0 then puts "False" + * if (cd == 1){ + * puts("True"); + * } + * else { + * puts("False"); + * } + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] name A string representing the name of the class. + * @return [mrb_bool] A boolean value. + */ MRB_API mrb_bool mrb_class_defined(mrb_state *mrb, const char *name); + +/** + * Gets a class. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] name The name of the class. + * @return [struct RClass *] A reference to the class. +*/ MRB_API struct RClass * mrb_class_get(mrb_state *mrb, const char *name); + +/** + * Gets a child class. + * @param [mrb_state*] mrb The current mruby state. + * @param [struct RClass *] outer The name of the parent class. + * @param [const char *] name The name of the class. + * @return [struct RClass *] A reference to the class. +*/ MRB_API struct RClass * mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name); + +/** + * Gets a module. + * @param [mrb_state*] mrb The current mruby state. + * @param [const char *] name The name of the module. + * @return [struct RClass *] A reference to the module. +*/ MRB_API struct RClass * mrb_module_get(mrb_state *mrb, const char *name); + +/** + * Gets a module defined under another module. + * @param [mrb_state*] mrb The current mruby state. + * @param [struct RClass *] outer The name of the outer module. + * @param [const char *] name The name of the module. + * @return [struct RClass *] A reference to the module. +*/ MRB_API struct RClass * mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name); MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value); +/** + * Duplicate an object. + * + * Equivalent to: + * Object#dup + * @param [mrb_state*] mrb The current mruby state. + * @param [mrb_value] obj Object to be duplicate. + * @return [mrb_value] The newly duplicated object. + */ MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj); MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method); + +/** + * Returns true if obj responds to the given method. If the method was defined for that + * class it returns true, it returns false otherwise. + * + * Example: + * # Ruby style + * class ExampleClass + * def example_method + * end + * end + * + * ExampleClass.new.respond_to?(:example_method) # => true + * + * // C style + * void + * mrb_example_gem_init(mrb_state* mrb) { + * struct RClass *example_class; + * mrb_sym mid; + * mrb_bool obj_resp; + * + * example_class = mrb_define_class(mrb, "ExampleClass", mrb->object_class); + * mrb_define_method(mrb, example_class, "example_method", exampleMethod, MRB_ARGS_NONE()); + * mid = mrb_intern_str(mrb, mrb_str_new_cstr(mrb, "example_method" )); + * obj_resp = mrb_obj_respond_to(mrb, example_class, mid); // => 1(true in Ruby world) + * + * // If mrb_obj_respond_to returns 1 then puts "True" + * // If mrb_obj_respond_to returns 0 then puts "False" + * if (obj_resp == 1) { + * puts("True"); + * } + * else if (obj_resp == 0) { + * puts("False"); + * } + * } + * + * @param [mrb_state*] mrb The current mruby state. + * @param [struct RClass *] c A reference to a class. + * @param [mrb_sym] mid A symbol referencing a method id. + * @return [mrb_bool] A boolean value. + */ MRB_API mrb_bool mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid); + +/** + * Defines a new class under a given module + * + * @param [mrb_state*] mrb The current mruby state. + * @param [struct RClass *] outer Reference to the module under which the new class will be defined + * @param [const char *] name The name of the defined class + * @param [struct RClass *] super The new class parent + * @return [struct RClass *] Reference to the newly defined class + * @see mrb_define_class + */ MRB_API struct RClass * mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super); + MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name); -/* required arguments */ +/** + * Function requires n arguments. + * + * @param n + * The number of required arguments. + */ #define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18) -/* optional arguments */ + +/** + * Funtion takes n optional arguments + * + * @param n + * The number of optional arguments. + */ #define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13) -/* mandatory and optinal arguments */ + +/** + * Funtion takes n1 mandatory arguments and n2 optional arguments + * + * @param n1 + * The number of required arguments. + * @param n2 + * The number of optional arguments. + */ #define MRB_ARGS_ARG(n1,n2) (MRB_ARGS_REQ(n1)|MRB_ARGS_OPT(n2)) -/* rest argument */ +/** rest argument */ #define MRB_ARGS_REST() ((mrb_aspec)(1 << 12)) -/* required arguments after rest */ + +/** required arguments after rest */ #define MRB_ARGS_POST(n) ((mrb_aspec)((n)&0x1f) << 7) -/* keyword arguments (n of keys, kdict) */ + +/** keyword arguments (n of keys, kdict) */ #define MRB_ARGS_KEY(n1,n2) ((mrb_aspec)((((n1)&0x1f) << 2) | ((n2)?(1<<1):0))) -/* block argument */ + +/** + * Function takes a block argument + */ #define MRB_ARGS_BLOCK() ((mrb_aspec)1) -/* accept any number of arguments */ +/** + * Function accepts any number of arguments + */ #define MRB_ARGS_ANY() MRB_ARGS_REST() -/* accept no arguments */ + +/** + * Function accepts no arguments + */ #define MRB_ARGS_NONE() ((mrb_aspec)0) -MRB_API mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...); +/** + * Format specifiers for {mrb_get_args} function + * + * Must be a C string composed of the following format specifiers: + * + * | char | Ruby type | C types | Notes | + * |:----:|----------------|-------------------|----------------------------------------------------| + * | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument | + * | `C` | {Class}/{Module} | {mrb_value} | | + * | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` | + * | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` | + * | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` | + * | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` | + * | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` | + * | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` | + * | `f` | {Float} | {mrb_float} | | + * | `i` | {Integer} | {mrb_int} | | + * | `b` | boolean | {mrb_bool} | | + * | `n` | {Symbol} | {mrb_sym} | | + * | `&` | block | {mrb_value} | | + * | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. | + * | | | optional | | After this spec following specs would be optional. | + * | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. | + * + * @see mrb_get_args + */ +typedef const char *mrb_args_format; + +/** + * Retrieve arguments from mrb_state. + * + * When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are + * applied to received arguments. + * Used inside a function of mrb_func_t type. + * + * @param mrb The current MRuby state. + * @param format [mrb_args_format] is a list of format specifiers + * @param ... The passing variadic arguments must be a pointer of retrieving type. + * @return the number of arguments retrieved. + * @see mrb_args_format + */ +MRB_API mrb_int mrb_get_args(mrb_state *mrb, mrb_args_format format, ...); + +static inline mrb_sym +mrb_get_mid(mrb_state *mrb) /* get method symbol */ +{ + return mrb->c->ci->mid; +} + +static inline int +mrb_get_argc(mrb_state *mrb) /* get argc */ +{ + return mrb->c->ci->argc; +} /* `strlen` for character string literals (use with caution or `strlen` instead) Adjacent string literals are concatenated in C/C++ in translation phase 6. @@ -264,9 +770,80 @@ */ #define mrb_strlen_lit(lit) (sizeof(lit "") - 1) +/** + * Call existing ruby functions. + * + * #include + * #include + * #include "mruby/compile.h" + * + * int + * main() + * { + * mrb_int i = 99; + * mrb_state *mrb = mrb_open(); + * + * if (!mrb) { } + * FILE *fp = fopen("test.rb","r"); + * mrb_value obj = mrb_load_file(mrb,fp); + * mrb_funcall(mrb, obj, "method_name", 1, mrb_fixnum_value(i)); + * fclose(fp); + * mrb_close(mrb); + * } + * @param [mrb_state*] mrb_state* The current mruby state. + * @param [mrb_value] mrb_value A reference to an mruby value. + * @param [const char*] const char* The name of the method. + * @param [mrb_int] mrb_int The number of arguments the method has. + * @param [...] ... Variadic values(not type safe!). + * @return [mrb_value] mrb_value mruby function value. + */ MRB_API mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, mrb_int,...); +/** + * Call existing ruby functions. This is basically the type safe version of mrb_funcall. + * + * #include + * #include + * #include "mruby/compile.h" + * int + * main() + * { + * mrb_int i = 99; + * mrb_state *mrb = mrb_open(); + * + * if (!mrb) { } + * mrb_sym m_sym = mrb_intern_cstr(mrb, "method_name"); // Symbol for method. + * + * FILE *fp = fopen("test.rb","r"); + * mrb_value obj = mrb_load_file(mrb,fp); + * mrb_funcall_argv(mrb, obj, m_sym, 1, &obj); // Calling ruby function from test.rb. + * fclose(fp); + * mrb_close(mrb); + * } + * @param [mrb_state*] mrb_state* The current mruby state. + * @param [mrb_value] mrb_value A reference to an mruby value. + * @param [mrb_sym] mrb_sym The symbol representing the method. + * @param [mrb_int] mrb_int The number of arguments the method has. + * @param [const mrb_value*] mrb_value* Pointer to the object. + * @return [mrb_value] mrb_value mruby function value. + * @see mrb_funcall + */ MRB_API mrb_value mrb_funcall_argv(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*); +/** + * Call existing ruby functions with a block. + */ MRB_API mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, mrb_int, const mrb_value*, mrb_value); +/** + * Create a symbol + * + * # Ruby style: + * :pizza # => :pizza + * + * // C style: + * mrb_sym m_sym = mrb_intern_cstr(mrb, "pizza"); // => :pizza + * @param [mrb_state*] mrb_state* The current mruby state. + * @param [const char*] const char* The name of the method. + * @return [mrb_sym] mrb_sym A symbol. + */ MRB_API mrb_sym mrb_intern_cstr(mrb_state*,const char*); MRB_API mrb_sym mrb_intern(mrb_state*,const char*,size_t); MRB_API mrb_sym mrb_intern_static(mrb_state*,const char*,size_t); @@ -288,21 +865,85 @@ MRB_API void mrb_free(mrb_state*, void*); MRB_API mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); + +/** + * Turns a C string into a Ruby string value. + */ MRB_API mrb_value mrb_str_new_cstr(mrb_state*, const char*); MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len); #define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit)) +#ifdef _WIN32 +char* mrb_utf8_from_locale(const char *p, size_t len); +char* mrb_locale_from_utf8(const char *p, size_t len); +#define mrb_locale_free(p) free(p) +#define mrb_utf8_free(p) free(p) +#else +#define mrb_utf8_from_locale(p, l) (p) +#define mrb_locale_from_utf8(p, l) (p) +#define mrb_locale_free(p) +#define mrb_utf8_free(p) +#endif + +/** + * Creates new mrb_state. + * + * @return + * Pointer to the newly created mrb_state. + */ MRB_API mrb_state* mrb_open(void); -MRB_API mrb_state* mrb_open_allocf(mrb_allocf, void *ud); -MRB_API mrb_state* mrb_open_core(mrb_allocf, void *ud); -MRB_API void mrb_close(mrb_state*); +/** + * Create new mrb_state with custom allocators. + * + * @param f + * Reference to the allocation function. + * @param ud + * User data will be passed to custom allocator f. + * If user data isn't required just pass NULL. + * @return + * Pointer to the newly created mrb_state. + */ +MRB_API mrb_state* mrb_open_allocf(mrb_allocf f, void *ud); + +/** + * Create new mrb_state with just the MRuby core + * + * @param f + * Reference to the allocation function. + * Use mrb_default_allocf for the default + * @param ud + * User data will be passed to custom allocator f. + * If user data isn't required just pass NULL. + * @return + * Pointer to the newly created mrb_state. + */ +MRB_API mrb_state* mrb_open_core(mrb_allocf f, void *ud); + +/** + * Closes and frees a mrb_state. + * + * @param mrb + * Pointer to the mrb_state to be closed. + */ +MRB_API void mrb_close(mrb_state *mrb); + +/** + * The default allocation function. + * + * @see mrb_allocf + */ MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*); MRB_API mrb_value mrb_top_self(mrb_state *); MRB_API mrb_value mrb_run(mrb_state*, struct RProc*, mrb_value); -MRB_API mrb_value mrb_toplevel_run(mrb_state*, struct RProc*); -MRB_API mrb_value mrb_context_run(mrb_state*, struct RProc*, mrb_value, unsigned int); +MRB_API mrb_value mrb_top_run(mrb_state*, struct RProc*, mrb_value, unsigned int); +MRB_API mrb_value mrb_vm_run(mrb_state*, struct RProc*, mrb_value, unsigned int); +MRB_API mrb_value mrb_vm_exec(mrb_state*, struct RProc*, mrb_code*); +/* compatibility macros */ +#define mrb_toplevel_run_keep(m,p,k) mrb_top_run((m),(p),mrb_top_self(m),(k)) +#define mrb_toplevel_run(m,p) mrb_toplevel_run_keep((m),(p),0) +#define mrb_context_run(m,p,s,k) mrb_vm_run((m),(p),(s),(k)) MRB_API void mrb_p(mrb_state*, mrb_value); MRB_API mrb_int mrb_obj_id(mrb_value obj); @@ -396,7 +1037,13 @@ MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv); MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c); +/* mrb_gc_protect() leaves the object in the arena */ MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj); +/* mrb_gc_register() keeps the object from GC. */ +MRB_API void mrb_gc_register(mrb_state *mrb, mrb_value obj); +/* mrb_gc_unregister() removes the object from GC root. */ +MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj); + MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val); #define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val)) MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t); @@ -417,9 +1064,26 @@ MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); -/* fiber functions (you need to link mruby-fiber mrbgem to use) */ + +/* + * Resume a Fiber + * + * @mrbgem mruby-fiber + */ MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv); + +/* + * Yield a Fiber + * + * @mrbgem mruby-fiber + */ MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv); + +/* + * FiberError reference + * + * @mrbgem mruby-fiber + */ #define E_FIBER_ERROR (mrb_class_get(mrb, "FiberError")) /* memory pool implementation */ @@ -453,8 +1117,6 @@ MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...); -#if defined(__cplusplus) -} /* extern "C" { */ -#endif +MRB_END_DECL #endif /* MRUBY_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/lib/mruby/source.rb mruby-1.2.0+20160315+git4f20d58a/lib/mruby/source.rb --- mruby-1.1.0+20150906+git1cbbb7e1/lib/mruby/source.rb 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/lib/mruby/source.rb 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,30 @@ +require "pathname" + +module MRuby + module Source + # MRuby's source root directory + ROOT = Pathname.new(File.expand_path('../../../',__FILE__)) + + # Reads a constant defined at version.h + MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] } + + MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION'] + MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE'] + + MRUBY_RELEASE_MAJOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MAJOR']) + MRUBY_RELEASE_MINOR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MINOR']) + MRUBY_RELEASE_TEENY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_TEENY']) + + MRUBY_VERSION = [MRUBY_RELEASE_MAJOR,MRUBY_RELEASE_MINOR,MRUBY_RELEASE_TEENY].join('.') + MRUBY_RELEASE_NO = (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY) + + MRUBY_RELEASE_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_YEAR']) + MRUBY_RELEASE_MONTH = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_MONTH']) + MRUBY_RELEASE_DAY = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_RELEASE_DAY']) + MRUBY_RELEASE_DATE = [MRUBY_RELEASE_YEAR,MRUBY_RELEASE_MONTH,MRUBY_RELEASE_DAY].join('.') + + MRUBY_BIRTH_YEAR = Integer(MRUBY_READ_VERSION_CONSTANT['MRUBY_BIRTH_YEAR']) + + MRUBY_AUTHOR = MRUBY_READ_VERSION_CONSTANT['MRUBY_AUTHOR'] + end +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/MITL mruby-1.2.0+20160315+git4f20d58a/MITL --- mruby-1.1.0+20150906+git1cbbb7e1/MITL 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/MITL 2016-03-14 00:35:53.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (c) 2015 mruby developers +Copyright (c) 2016 mruby developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-array-ext/mrblib/array.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-array-ext/mrblib/array.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-array-ext/mrblib/array.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-array-ext/mrblib/array.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,31 @@ class Array ## # call-seq: + # Array.try_convert(obj) -> array or nil + # + # Tries to convert +obj+ into an array, using +to_ary+ method. + # converted array or +nil+ if +obj+ cannot be converted for any reason. + # This method can be used to check if an argument is an array. + # + # Array.try_convert([1]) #=> [1] + # Array.try_convert("1") #=> nil + # + # if tmp = Array.try_convert(arg) + # # the argument is an array + # elsif tmp = String.try_convert(arg) + # # the argument is a string + # end + # + def self.try_convert(obj) + if obj.respond_to?(:to_ary) + obj.to_ary + else + nil + end + end + + ## + # call-seq: # ary.uniq! -> ary or nil # ary.uniq! { |item| ... } -> ary or nil # @@ -681,4 +706,42 @@ return nil if self.size == result.size self.replace(result) end + + ## + # call-seq: + # ary.index(val) -> int or nil + # ary.index {|item| block } -> int or nil + # + # Returns the _index_ of the first object in +ary+ such that the object is + # == to +obj+. + # + # If a block is given instead of an argument, returns the _index_ of the + # first object for which the block returns +true+. Returns +nil+ if no + # match is found. + # + # ISO 15.2.12.5.14 + def index(val=NONE, &block) + return to_enum(:find_index, val) if !block && val == NONE + + if block + idx = 0 + self.each do |*e| + return idx if block.call(*e) + idx += 1 + end + else + return self.__ary_index(val) + end + nil + end + + ## + # call-seq: + # ary.to_ary -> ary + # + # Returns +self+. + # + def to_ary + self + end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-array-ext/src/array.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-array-ext/src/array.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-array-ext/src/array.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-array-ext/src/array.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,8 +1,8 @@ -#include "mruby.h" -#include "mruby/value.h" -#include "mruby/array.h" -#include "mruby/range.h" -#include "mruby/hash.h" +#include +#include +#include +#include +#include /* * call-seq: @@ -113,8 +113,9 @@ * Returns the result of interpreting aray as an array of * [key, value] paris. * - * [[:foo, :bar], [1, 2]].to_h - * # => {:foo => :bar, 1 => 2} + * [[:foo, :bar], [1, 2]].to_h + * # => {:foo => :bar, 1 => 2} + * */ static mrb_value diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-array-ext/test/array.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-array-ext/test/array.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-array-ext/test/array.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-array-ext/test/array.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,13 @@ ## # Array(Ext) Test +assert("Array.try_convert") do + assert_nil Array.try_convert(0) + assert_nil Array.try_convert(nil) + assert_equal [], Array.try_convert([]) + assert_equal [1,2,3], Array.try_convert([1,2,3]) +end + assert("Array#assoc") do s1 = [ "colors", "red", "blue", "green" ] s2 = [ "letters", "a", "b", "c" ] @@ -293,3 +300,13 @@ assert_raise(TypeError) { [1].to_h } assert_raise(ArgumentError) { [[1]].to_h } end + +assert("Array#index (block)") do + assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } + assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 } +end + +assert("Array#to_ary") do + assert_equal [], [].to_ary + assert_equal [1,2,3], [1,2,3].to_ary +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,14 +4,14 @@ */ #include -#include "mruby.h" -#include "mruby/irep.h" +#include +#include #include "mrdb.h" -#include "mruby/debug.h" -#include "mruby/opcode.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/variable.h" +#include +#include +#include +#include +#include #include "mrdberror.h" #include "apibreak.h" @@ -450,7 +450,7 @@ { mrb_debug_breakpoint *bp; mrb_debug_linepoint *line_p; - int i; + uint32_t i; if((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) { return MRB_DEBUG_INVALID_ARGUMENT; @@ -488,7 +488,7 @@ { mrb_debug_breakpoint *bp; int32_t bpno; - int i; + uint32_t i; if((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) { return MRB_DEBUG_INVALID_ARGUMENT; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h 2016-03-14 00:35:53.000000000 +0000 @@ -6,7 +6,7 @@ #ifndef APIBREAK_H_ #define APIBREAK_H_ -#include "mruby.h" +#include #include "mrdb.h" int32_t mrb_debug_set_break_line( mrb_state *, mrb_debug_context *, const char *, uint16_t ); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c 2016-03-14 00:35:53.000000000 +0000 @@ -9,9 +9,9 @@ #include "mrdb.h" #include "mrdberror.h" #include "apilist.h" -#include "mruby/compile.h" -#include "mruby/irep.h" -#include "mruby/debug.h" +#include +#include +#include #define LINE_BUF_SIZE MAX_COMMAND_LINE diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h 2016-03-14 00:35:53.000000000 +0000 @@ -5,7 +5,7 @@ #ifndef APILIST_H_ #define APILIST_H_ -#include "mruby.h" +#include #include "mrdb.h" int32_t mrb_debug_list(mrb_state *, mrb_debug_context *, char *, uint16_t, uint16_t); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c 2016-03-14 00:35:53.000000000 +0000 @@ -5,12 +5,12 @@ #include #include "mrdb.h" -#include "mruby/value.h" -#include "mruby/class.h" -#include "mruby/compile.h" -#include "mruby/error.h" -#include "mruby/numeric.h" -#include "mruby/string.h" +#include +#include +#include +#include +#include +#include #include "apiprint.h" static void diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h 2016-03-14 00:35:53.000000000 +0000 @@ -5,7 +5,7 @@ #ifndef APIPRINT_H_ #define APIPRINT_H_ -#include "mruby.h" +#include #include "mrdb.h" mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c 2016-03-14 00:35:53.000000000 +0000 @@ -5,10 +5,10 @@ #include #include -#include "mruby.h" -#include "mruby/dump.h" -#include "mruby/debug.h" -#include "mruby/string.h" +#include +#include +#include +#include #include "mrdb.h" #include "mrdberror.h" #include "apibreak.h" diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c 2016-03-14 00:35:53.000000000 +0000 @@ -8,7 +8,7 @@ #include #include "apilist.h" -#include "mruby/compile.h" +#include typedef struct help_msg { const char *cmd1; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c 2016-03-14 00:35:53.000000000 +0000 @@ -5,12 +5,12 @@ #include #include "mrdb.h" -#include "mruby/value.h" -#include "mruby/class.h" -#include "mruby/compile.h" -#include "mruby/error.h" -#include "mruby/numeric.h" -#include "mruby/string.h" +#include +#include +#include +#include +#include +#include #include "apiprint.h" dbgcmd_state diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c 2016-03-14 00:35:53.000000000 +0000 @@ -3,7 +3,7 @@ ** */ -#include "mruby/opcode.h" +#include #include "mrdb.h" dbgcmd_state @@ -52,3 +52,11 @@ mrdb->dbg->xm = DBG_STEP; return DBGST_CONTINUE; } + +dbgcmd_state +dbgcmd_next(mrb_state *mrb, mrdb_state *mrdb) +{ + mrdb->dbg->xm = DBG_NEXT; + mrdb->dbg->prvci = mrb->c->ci; + return DBGST_CONTINUE; +} diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c 2016-03-14 00:35:53.000000000 +0000 @@ -8,12 +8,12 @@ #include #include -#include "mruby.h" -#include "mruby/dump.h" -#include "mruby/debug.h" -#include "mruby/class.h" -#include "mruby/opcode.h" -#include "mruby/variable.h" +#include +#include +#include +#include +#include +#include #include "mrdb.h" #include "apibreak.h" @@ -57,6 +57,7 @@ {"quit", NULL, 1, 0, 0, DBGCMD_QUIT, dbgcmd_quit}, /* q[uit] */ {"run", NULL, 1, 0, 0, DBGCMD_RUN, dbgcmd_run}, /* r[un] */ {"step", NULL, 1, 0, 1, DBGCMD_STEP, dbgcmd_step}, /* s[tep] */ + {"next", NULL, 1, 0, 1, DBGCMD_NEXT, dbgcmd_next}, /* n[ext] */ {NULL} }; @@ -560,6 +561,7 @@ dbg->root_irep = irep; dbg->prvfile = NULL; dbg->prvline = 0; + dbg->prvci = NULL; dbg->xm = DBG_RUN; dbg->xphase = DBG_PHASE_RUNNING; } @@ -569,7 +571,6 @@ switch (dbg->xm) { case DBG_STEP: - case DBG_NEXT: // temporary if (!file || (dbg->prvfile == file && dbg->prvline == line)) { return; } @@ -577,6 +578,18 @@ dbg->bm = BRK_STEP; break; + case DBG_NEXT: + if (!file || (dbg->prvfile == file && dbg->prvline == line)) { + return; + } + if((uint32_t)(dbg->prvci) < (uint32_t)(mrb->c->ci)) { + return; + } + dbg->prvci = NULL; + dbg->method_bpno = 0; + dbg->bm = BRK_NEXT; + break; + case DBG_RUN: bpno = check_method_breakpoint(mrb, irep, pc, regs); if (bpno > 0) { diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h 2016-03-14 00:35:53.000000000 +0000 @@ -6,7 +6,7 @@ #ifndef MRDB_H #define MRDB_H -#include "mruby.h" +#include #include "mrdbconf.h" @@ -109,6 +109,7 @@ const char *prvfile; int32_t prvline; + mrb_callinfo *prvci; mrdb_exemode xm; mrdb_exephase xphase; @@ -146,6 +147,7 @@ dbgcmd_state dbgcmd_run(mrb_state*, mrdb_state*); dbgcmd_state dbgcmd_continue(mrb_state*, mrdb_state*); dbgcmd_state dbgcmd_step(mrb_state*, mrdb_state*); +dbgcmd_state dbgcmd_next(mrb_state*, mrdb_state*); /* cmdbreak.c */ dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*); dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c 2016-03-14 00:35:53.000000000 +0000 @@ -11,6 +11,9 @@ #include #include +#include +#include + #ifdef ENABLE_READLINE #include #include @@ -29,11 +32,21 @@ #define MIRB_USING_HISTORY() #endif -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/proc.h" -#include "mruby/compile.h" -#include "mruby/string.h" +#ifndef _WIN32 +#define MIRB_SIGSETJMP(env) sigsetjmp(env, 1) +#define MIRB_SIGLONGJMP(env, val) siglongjmp(env, val) +#define SIGJMP_BUF sigjmp_buf +#else +#define MIRB_SIGSETJMP(env) setjmp(env) +#define MIRB_SIGLONGJMP(env, val) longjmp(env, val) +#define SIGJMP_BUF jmp_buf +#endif + +#include +#include +#include +#include +#include #ifdef ENABLE_READLINE @@ -194,6 +207,7 @@ } struct _args { + FILE *rfp; mrb_bool verbose : 1; int argc; char** argv; @@ -251,12 +265,30 @@ return EXIT_FAILURE; } } + + if (args->rfp == NULL) { + if (*argv != NULL) { + args->rfp = fopen(argv[0], "r"); + if (args->rfp == NULL) { + printf("Cannot open program file. (%s)\n", *argv); + return EXIT_FAILURE; + } + argc--; argv++; + } + } + args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1)); + memcpy(args->argv, argv, (argc+1) * sizeof(char*)); + args->argc = argc; + return EXIT_SUCCESS; } static void cleanup(mrb_state *mrb, struct _args *args) { + if (args->rfp) + fclose(args->rfp); + mrb_free(mrb, args->argv); mrb_close(mrb); } @@ -307,23 +339,43 @@ return 1; } + +#ifndef ENABLE_READLINE +volatile sig_atomic_t input_canceled = 0; +void +ctrl_c_handler(int signo) +{ + input_canceled = 1; +} +#else +SIGJMP_BUF ctrl_c_buf; +void +ctrl_c_handler(int signo) +{ + MIRB_SIGLONGJMP(ctrl_c_buf, 1); +} +#endif + int main(int argc, char **argv) { - char ruby_code[1024] = { 0 }; + char ruby_code[4096] = { 0 }; char last_code_line[1024] = { 0 }; #ifndef ENABLE_READLINE int last_char; - int char_index; + size_t char_index; #else char *history_path; + char* line; #endif mrbc_context *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; struct _args args; + mrb_value ARGV; int n; + int i; mrb_bool code_block_open = FALSE; int ai; unsigned int stack_keep = 0; @@ -334,7 +386,6 @@ fputs("Invalid mrb interpreter, exiting mirb\n", stderr); return EXIT_FAILURE; } - mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE) { @@ -343,6 +394,16 @@ return n; } + ARGV = mrb_ary_new_capa(mrb, args.argc); + for (i = 0; i < args.argc; i++) { + char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); + if (utf8) { + mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); + mrb_utf8_free(utf8); + } + } + mrb_define_global_const(mrb, "ARGV", ARGV); + #ifdef ENABLE_READLINE history_path = get_history_path(mrb); if (history_path == NULL) { @@ -366,9 +427,18 @@ ai = mrb_gc_arena_save(mrb); while (TRUE) { + char *utf8; + + if (args.rfp) { + if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL) + goto done; + break; + } + #ifndef ENABLE_READLINE print_cmdline(code_block_open); + signal(SIGINT, ctrl_c_handler); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; @@ -378,6 +448,15 @@ } last_code_line[char_index++] = last_char; } + signal(SIGINT, SIG_DFL); + if (input_canceled) { + ruby_code[0] = '\0'; + last_code_line[0] = '\0'; + code_block_open = FALSE; + puts("^C"); + input_canceled = 0; + continue; + } if (last_char == EOF) { fputs("\n", stdout); break; @@ -386,7 +465,19 @@ last_code_line[char_index++] = '\n'; last_code_line[char_index] = '\0'; #else - char* line = MIRB_READLINE(code_block_open ? "* " : "> "); + if (MIRB_SIGSETJMP(ctrl_c_buf) == 0) { + ; + } + else { + ruby_code[0] = '\0'; + last_code_line[0] = '\0'; + code_block_open = FALSE; + puts("^C"); + } + signal(SIGINT, ctrl_c_handler); + line = MIRB_READLINE(code_block_open ? "* " : "> "); + signal(SIGINT, SIG_DFL); + if (line == NULL) { printf("\n"); break; @@ -401,6 +492,8 @@ free(line); #endif +done: + if (code_block_open) { if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) { fputs("concatenated input string too long\n", stderr); @@ -415,17 +508,21 @@ strcpy(ruby_code, last_code_line); } + utf8 = mrb_utf8_from_locale(ruby_code, -1); + if (!utf8) abort(); + /* parse code */ parser = mrb_parser_new(mrb); if (parser == NULL) { fputs("create parser state error\n", stderr); break; } - parser->s = ruby_code; - parser->send = ruby_code + strlen(ruby_code); + parser->s = utf8; + parser->send = utf8 + strlen(utf8); parser->lineno = cxt->lineno; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); + mrb_utf8_free(utf8); if (code_block_open) { /* no evaluation of code */ @@ -449,7 +546,7 @@ } /* pass a proc for evaulation */ /* evaluate the bytecode */ - result = mrb_context_run(mrb, + result = mrb_vm_run(mrb, proc, mrb_top_self(mrb), stack_keep); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,10 +1,10 @@ #include #include #include -#include "mruby.h" -#include "mruby/compile.h" -#include "mruby/dump.h" -#include "mruby/proc.h" +#include +#include +#include +#include #define RITEBIN_EXT ".mrb" #define C_EXT ".c" diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mruby/bintest/mruby.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mruby/bintest/mruby.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mruby/bintest/mruby.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mruby/bintest/mruby.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,17 +1,17 @@ require 'tempfile' assert('regression for #1564') do - o = `bin/mruby -e '<<' 2>&1` + o = `#{cmd('mruby')} -e #{shellquote('<<')} 2>&1` assert_equal o, "-e:1:2: syntax error, unexpected tLSHFT\n" - o = `bin/mruby -e '<<-' 2>&1` + o = `#{cmd('mruby')} -e #{shellquote('<<-')} 2>&1` assert_equal o, "-e:1:3: syntax error, unexpected tLSHFT\n" end assert('regression for #1572') do script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb') - system "echo 'p \"ok\"' > #{script.path}" - system "bin/mrbc -g -o #{bin.path} #{script.path}" - o = `bin/mruby -b #{bin.path}`.strip + File.write script.path, 'p "ok"' + system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}" + o = `#{cmd('mruby')} -b #{bin.path}`.strip assert_equal o, '"ok"' end @@ -21,14 +21,14 @@ # .rb script script.write "p $0\n" script.flush - assert_equal "\"#{script.path}\"", `./bin/mruby "#{script.path}"`.chomp + assert_equal "\"#{script.path}\"", `#{cmd('mruby')} "#{script.path}"`.chomp # .mrb file - `./bin/mrbc -o "#{bin.path}" "#{script.path}"` - assert_equal "\"#{bin.path}\"", `./bin/mruby -b "#{bin.path}"`.chomp + `#{cmd('mrbc')} -o "#{bin.path}" "#{script.path}"` + assert_equal "\"#{bin.path}\"", `#{cmd('mruby')} -b "#{bin.path}"`.chomp # one liner - assert_equal '"-e"', `./bin/mruby -e 'p $0'`.chomp + assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp end assert '__END__', '8.6' do @@ -42,5 +42,5 @@ p 'legend' EOS script.flush - assert_equal "\"test\"\n\"fin\"\n", `./bin/mruby #{script.path}` + assert_equal "\"test\"\n\"fin\"\n", `#{cmd('mruby')} #{script.path}` end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,13 +1,13 @@ #include #include #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/compile.h" -#include "mruby/dump.h" -#include "mruby/variable.h" +#include +#include +#include +#include +#include -#ifndef ENABLE_STDIO +#ifdef MRB_DISABLE_STDIO static void p(mrb_state *mrb, mrb_value obj) { @@ -191,7 +191,11 @@ ARGV = mrb_ary_new_capa(mrb, args.argc); for (i = 0; i < args.argc; i++) { - mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, args.argv[i])); + char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); + if (utf8) { + mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); + mrb_utf8_free(utf8); + } } mrb_define_global_const(mrb, "ARGV", ARGV); @@ -222,7 +226,10 @@ v = mrb_load_file_cxt(mrb, args.rfp, c); } else { - v = mrb_load_string_cxt(mrb, args.cmdline, c); + char* utf8 = mrb_utf8_from_locale(args.cmdline, -1); + if (!utf8) abort(); + v = mrb_load_string_cxt(mrb, utf8, c); + mrb_utf8_free(utf8); } mrbc_context_free(mrb, c); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,13 +1,13 @@ require 'tempfile' assert('no files') do - o = `bin/mruby-strip 2>&1` + o = `#{cmd('mruby-strip')} 2>&1` assert_equal 1, $?.exitstatus assert_equal "no files to strip", o.split("\n")[0] end assert('file not found') do - o = `bin/mruby-strip not_found.mrb 2>&1` + o = `#{cmd('mruby-strip')} not_found.mrb 2>&1` assert_equal 1, $?.exitstatus assert_equal "can't open file for reading not_found.mrb\n", o end @@ -16,7 +16,7 @@ t = Tempfile.new('script.rb') t.write 'p test\n' t.flush - o = `bin/mruby-strip #{t.path} 2>&1` + o = `#{cmd('mruby-strip')} #{t.path} 2>&1` assert_equal 1, $?.exitstatus assert_equal "can't read irep file #{t.path}\n", o end @@ -26,15 +26,15 @@ Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb') script_file.write "p 'test'\n" script_file.flush - `bin/mrbc -g -o #{compiled1.path} #{script_file.path}` - `bin/mrbc -g -o #{compiled2.path} #{script_file.path}` + `#{cmd('mrbc')} -g -o #{compiled1.path} #{script_file.path}` + `#{cmd('mrbc')} -g -o #{compiled2.path} #{script_file.path}` - o = `bin/mruby-strip #{compiled1.path}` + o = `#{cmd('mruby-strip')} #{compiled1.path}` assert_equal 0, $?.exitstatus assert_equal "", o - assert_equal `bin/mruby #{script_file.path}`, `bin/mruby -b #{compiled1.path}` + assert_equal `#{cmd('mruby')} #{script_file.path}`, `#{cmd('mruby')} -b #{compiled1.path}` - o = `bin/mruby-strip #{compiled1.path} #{compiled2.path}` + o = `#{cmd('mruby-strip')} #{compiled1.path} #{compiled2.path}` assert_equal 0, $?.exitstatus assert_equal "", o end @@ -44,12 +44,12 @@ Tempfile.new('script.rb'), Tempfile.new('c1.mrb'), Tempfile.new('c2.mrb') script_file.write "p 'test'\n" script_file.flush - `bin/mrbc -o #{without_debug.path} #{script_file.path}` - `bin/mrbc -g -o #{with_debug.path} #{script_file.path}` + `#{cmd('mrbc')} -o #{without_debug.path} #{script_file.path}` + `#{cmd('mrbc')} -g -o #{with_debug.path} #{script_file.path}` assert_true with_debug.size >= without_debug.size - `bin/mruby-strip #{with_debug.path}` + `#{cmd('mruby-strip')} #{with_debug.path}` assert_equal without_debug.size, with_debug.size end @@ -62,12 +62,12 @@ p Kernel.local_variables EOS script_file.flush - `bin/mrbc -o #{with_lv.path} #{script_file.path}` - `bin/mrbc -o #{without_lv.path} #{script_file.path}` + `#{cmd('mrbc')} -o #{with_lv.path} #{script_file.path}` + `#{cmd('mrbc')} -o #{without_lv.path} #{script_file.path}` - `bin/mruby-strip -l #{without_lv.path}` + `#{cmd('mruby-strip')} -l #{without_lv.path}` assert_true without_lv.size < with_lv.size - assert_equal '[:a, :b]', `bin/mruby -b #{with_lv.path}`.chomp - assert_equal '[]', `bin/mruby -b #{without_lv.path}`.chomp + assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp + assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,9 +1,9 @@ #include #include #include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/dump.h" +#include +#include +#include struct strip_args { int argc_start; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/bintest/mrbc.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/bintest/mrbc.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/bintest/mrbc.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/bintest/mrbc.rb 2016-03-14 00:35:53.000000000 +0000 @@ -6,7 +6,7 @@ a.flush b.write('module B; end') b.flush - result = `bin/mrbc -c -o #{out.path} #{a.path} #{b.path} 2>&1` - assert_equal "bin/mrbc:#{a.path}:Syntax OK", result.chomp + result = `#{cmd('mrbc')} -c -o #{out.path} #{a.path} #{b.path} 2>&1` + assert_equal "#{cmd('mrbc')}:#{a.path}:Syntax OK", result.chomp assert_equal 0, $?.exitstatus end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/core/codegen.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/core/codegen.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/core/codegen.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/core/codegen.c 2016-03-14 00:35:53.000000000 +0000 @@ -8,16 +8,16 @@ #include #include #include -#include "mruby.h" -#include "mruby/compile.h" -#include "mruby/proc.h" -#include "mruby/numeric.h" -#include "mruby/string.h" -#include "mruby/debug.h" +#include +#include +#include +#include +#include +#include #include "node.h" -#include "mruby/opcode.h" -#include "mruby/re.h" -#include "mruby/throw.h" +#include +#include +#include typedef mrb_ast_node node; typedef struct mrb_parser_state parser_state; @@ -96,7 +96,7 @@ mrb_pool_close(s->mpool); s = tmp; } -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO if (s->filename && s->lineno) { fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message); } @@ -339,6 +339,12 @@ return 0; } } + if (c0 == OP_LOADNIL) { + if (GETARG_B(i) == GETARG_A(i0)) { + s->pc--; + return 0; + } + } break; case OP_JMPIF: case OP_JMPNOT: @@ -375,7 +381,7 @@ case OP_ONERR: break; default: -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO fprintf(stderr, "bug: dispatch on non JMP op\n"); #endif scope_error(s); @@ -978,7 +984,7 @@ break; default: -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO printf("unknown lhs %d\n", type); #endif break; @@ -1179,7 +1185,13 @@ { int nt; - if (!tree) return; + if (!tree) { + if (val) { + genop(s, MKOP_A(OP_LOADNIL, cursp())); + push(); + } + return; + } if (s->irep && s->filename_index != tree->filename_index) { s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index); @@ -1330,15 +1342,22 @@ int pos1, pos2; node *e = tree->cdr->cdr->car; + switch ((intptr_t)tree->car->car) { + case NODE_TRUE: + case NODE_INT: + case NODE_STR: + codegen(s, tree->cdr->car, val); + return; + case NODE_FALSE: + case NODE_NIL: + codegen(s, e, val); + return; + } codegen(s, tree->car, VAL); pop(); pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL); codegen(s, tree->cdr->car, val); - if (val && !(tree->cdr->car)) { - genop(s, MKOP_A(OP_LOADNIL, cursp())); - push(); - } if (e) { if (val) pop(); pos2 = genop(s, MKOP_sBx(OP_JMP, 0)); @@ -2216,7 +2235,8 @@ case NODE_REGX: if (val) { char *p1 = (char*)tree->car; - char *p2 = (char*)tree->cdr; + char *p2 = (char*)tree->cdr->car; + char *p3 = (char*)tree->cdr->cdr; int ai = mrb_gc_arena_save(s->mrb); int sym = new_sym(s, mrb_intern_lit(s->mrb, REGEXP_CLASS)); int off = new_lit(s, mrb_str_new_cstr(s->mrb, p1)); @@ -2226,11 +2246,22 @@ genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym)); push(); genop(s, MKOP_ABx(OP_STRING, cursp(), off)); - if (p2) { + if (p2 || p3) { push(); - off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); - genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + if (p2) { + off = new_lit(s, mrb_str_new_cstr(s->mrb, p2)); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + } else { + genop(s, MKOP_A(OP_LOADNIL, cursp())); + } argc++; + if (p3) { + push(); + off = new_lit(s, mrb_str_new(s->mrb, p3, 1)); + genop(s, MKOP_ABx(OP_STRING, cursp(), off)); + argc++; + pop(); + } pop(); } pop(); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/core/node.h mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/core/node.h --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/core/node.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/core/node.h 2016-03-14 00:35:53.000000000 +0000 @@ -4,8 +4,8 @@ ** See Copyright Notice in mruby.h */ -#ifndef NODE_H -#define NODE_H +#ifndef MRUBY_COMPILER_NODE_H +#define MRUBY_COMPILER_NODE_H enum node_type { NODE_METHOD, @@ -114,4 +114,4 @@ NODE_LAST }; -#endif /* NODE_H */ +#endif /* MRUBY_COMPILER_NODE_H */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/core/parse.y mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/core/parse.y --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-compiler/core/parse.y 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-compiler/core/parse.y 2016-03-14 00:35:53.000000000 +0000 @@ -22,12 +22,12 @@ #include #include #include -#include "mruby.h" -#include "mruby/compile.h" -#include "mruby/proc.h" -#include "mruby/error.h" +#include +#include +#include +#include +#include #include "node.h" -#include "mruby/throw.h" #define YYLEX_PARAM p @@ -761,9 +761,9 @@ /* (:str . (a . a)) */ static node* -new_regx(parser_state *p, const char *p1, const char* p2) +new_regx(parser_state *p, const char *p1, const char* p2, const char* p3) { - return cons((node*)NODE_REGX, cons((node*)p1, (node*)p2)); + return cons((node*)NODE_REGX, cons((node*)p1, cons((node*)p2, (node*)p3))); } /* (:dregx . a) */ @@ -852,19 +852,24 @@ { node *n; - if (a->car == (node*)NODE_SUPER || - a->car == (node*)NODE_ZSUPER) { + switch ((enum node_type)(intptr_t)a->car) { + case NODE_SUPER: + case NODE_ZSUPER: if (!a->cdr) a->cdr = cons(0, b); else { args_with_block(p, a->cdr, b); } - } - else { + break; + case NODE_CALL: + case NODE_FCALL: n = a->cdr->cdr->cdr; if (!n->car) n->car = cons(0, b); else { args_with_block(p, n->car, b); } + break; + default: + break; } } @@ -1295,7 +1300,7 @@ } | keyword_END '{' compstmt '}' { - yyerror(p, "END not suported"); + yyerror(p, "END not supported"); $$ = new_postexe(p, $3); } | command_asgn @@ -2824,7 +2829,7 @@ { $$ = new_sym(p, $1); } - | tSYMBEG tSTRING_BEG string_interp tSTRING + | tSYMBEG tSTRING_BEG string_rep tSTRING { p->lstate = EXPR_END; $$ = new_dsym(p, push($3, $4)); @@ -3294,7 +3299,7 @@ int n; if (! p->capture_errors) { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO if (p->filename) { fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); } @@ -3330,7 +3335,7 @@ int n; if (! p->capture_errors) { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO if (p->filename) { fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s); } @@ -3401,7 +3406,7 @@ cons_free(tmp); } else { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO if (p->f) { if (feof(p->f)) goto eof; c = fgetc(p->f); @@ -3468,6 +3473,7 @@ do { c0 = nextc(p); if (c0 == -1) return c0; /* do not skip partial EOF */ + if (c0 >= 0) --p->column; list = push(list, (node*)(intptr_t)c0); } while(n--); if (p->pb) { @@ -3491,7 +3497,7 @@ { int len = strlen(s); -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO if (p->f) { int n = 0; while (*s) { @@ -3986,6 +3992,8 @@ char *s = strndup(tok(p), toklen(p)); char flags[3]; char *flag = flags; + char enc = '\0'; + char *encp; char *dup; newtok(p); @@ -3994,6 +4002,8 @@ case 'i': f |= 1; break; case 'x': f |= 2; break; case 'm': f |= 4; break; + case 'u': f |= 16; break; + case 'n': f |= 32; break; default: tokadd(p, re_opt); break; } } @@ -4009,12 +4019,20 @@ if (f & 1) *flag++ = 'i'; if (f & 2) *flag++ = 'x'; if (f & 4) *flag++ = 'm'; - dup = strndup(flags, (size_t)(flag - flags)); + if (f & 16) enc = 'u'; + if (f & 32) enc = 'n'; } - else { + if (flag > flags) { + dup = strndup(flags, (size_t)(flag - flags)); + } else { dup = NULL; } - yylval.nd = new_regx(p, s, dup); + if (enc) { + encp = strndup(&enc, 1); + } else { + encp = NULL; + } + yylval.nd = new_regx(p, s, dup, encp); return tREGEXP; } @@ -5430,7 +5448,7 @@ p->pool = pool; p->s = p->send = NULL; -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO p->f = NULL; #endif @@ -5529,7 +5547,7 @@ } } -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO MRB_API parser_state* mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) { @@ -5616,12 +5634,12 @@ if (mrb->c->ci) { mrb->c->ci->target_class = target; } - v = mrb_toplevel_run_keep(mrb, proc, keep); + v = mrb_top_run(mrb, proc, mrb_top_self(mrb), keep); if (mrb->exc) return mrb_nil_value(); return v; } -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO MRB_API mrb_value mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) { @@ -5659,7 +5677,7 @@ return mrb_load_string_cxt(mrb, s, NULL); } -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO static void dump_prefix(node *tree, int offset) @@ -5685,7 +5703,7 @@ void mrb_parser_dump(mrb_state *mrb, node *tree, int offset) { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO int nodetype; if (!tree) return; @@ -5792,10 +5810,9 @@ printf("post mandatory args:\n"); dump_recur(mrb, n->car, offset+2); } - n = n->cdr; - if (n) { + if (n->cdr) { dump_prefix(n, offset+1); - printf("blk=&%s\n", mrb_sym2name(mrb, sym(n))); + printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr))); } } dump_prefix(tree, offset+1); @@ -5972,9 +5989,7 @@ break; case NODE_COLON3: - printf("NODE_COLON3:\n"); - dump_prefix(tree, offset+1); - printf("::%s\n", mrb_sym2name(mrb, sym(tree))); + printf("NODE_COLON3: ::%s\n", mrb_sym2name(mrb, sym(tree))); break; case NODE_ARRAY: diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enumerator/mrblib/enumerator.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enumerator/mrblib/enumerator.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enumerator/mrblib/enumerator.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enumerator/mrblib/enumerator.rb 2016-03-14 00:35:53.000000000 +0000 @@ -6,92 +6,91 @@ # A class which allows both internal and external iteration. # # An Enumerator can be created by the following methods. -# - Kernel#to_enum -# - Kernel#enum_for -# - Enumerator.new +# - {Kernel#to_enum} +# - {Kernel#enum_for} +# - {Enumerator#initialize Enumerator.new} # # Most methods have two forms: a block form where the contents # are evaluated for each item in the enumeration, and a non-block form # which returns a new Enumerator wrapping the iteration. # -# enumerator = %w(one two three).each -# puts enumerator.class # => Enumerator +# enumerator = %w(one two three).each +# puts enumerator.class # => Enumerator # -# enumerator.each_with_object("foo") do |item, obj| -# puts "#{obj}: #{item}" -# end -# -# # foo: one -# # foo: two -# # foo: three -# -# enum_with_obj = enumerator.each_with_object("foo") -# puts enum_with_obj.class # => Enumerator -# -# enum_with_obj.each do |item, obj| -# puts "#{obj}: #{item}" -# end -# -# # foo: one -# # foo: two -# # foo: three +# enumerator.each_with_object("foo") do |item, obj| +# puts "#{obj}: #{item}" +# end +# +# # foo: one +# # foo: two +# # foo: three +# +# enum_with_obj = enumerator.each_with_object("foo") +# puts enum_with_obj.class # => Enumerator +# +# enum_with_obj.each do |item, obj| +# puts "#{obj}: #{item}" +# end +# +# # foo: one +# # foo: two +# # foo: three # # This allows you to chain Enumerators together. For example, you # can map a list's elements to strings containing the index # and the element as a string via: # -# puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" } -# # => ["0:foo", "1:bar", "2:baz"] +# puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" } +# # => ["0:foo", "1:bar", "2:baz"] # # An Enumerator can also be used as an external iterator. # For example, Enumerator#next returns the next value of the iterator # or raises StopIteration if the Enumerator is at the end. # -# e = [1,2,3].each # returns an enumerator object. -# puts e.next # => 1 -# puts e.next # => 2 -# puts e.next # => 3 -# puts e.next # raises StopIteration +# e = [1,2,3].each # returns an enumerator object. +# puts e.next # => 1 +# puts e.next # => 2 +# puts e.next # => 3 +# puts e.next # raises StopIteration # # You can use this to implement an internal iterator as follows: # -# def ext_each(e) -# while true -# begin -# vs = e.next_values -# rescue StopIteration -# return $!.result +# def ext_each(e) +# while true +# begin +# vs = e.next_values +# rescue StopIteration +# return $!.result +# end +# y = yield(*vs) +# e.feed y +# end # end -# y = yield(*vs) -# e.feed y -# end -# end -# -# o = Object.new -# -# def o.each -# puts yield -# puts yield(1) -# puts yield(1, 2) -# 3 -# end -# -# # use o.each as an internal iterator directly. -# puts o.each {|*x| puts x; [:b, *x] } -# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 -# -# # convert o.each to an external iterator for -# # implementing an internal iterator. -# puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] } -# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 - +# +# o = Object.new +# +# def o.each +# puts yield +# puts yield(1) +# puts yield(1, 2) +# 3 +# end +# +# # use o.each as an internal iterator directly. +# puts o.each {|*x| puts x; [:b, *x] } +# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 +# +# # convert o.each to an external iterator for +# # implementing an internal iterator. +# puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] } +# # => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3 +# class Enumerator include Enumerable ## - # call-seq: - # Enumerator.new(size = nil) { |yielder| ... } - # Enumerator.new(obj, method = :each, *args) + # @overload initialize(size = nil, &block) + # @overload initialize(obj, method = :each, *args) # # Creates a new Enumerator object, which can be used as an # Enumerable. @@ -100,15 +99,15 @@ # which a "yielder" object, given as block parameter, can be used to # yield a value by calling the +yield+ method (aliased as +<<+): # - # fib = Enumerator.new do |y| - # a = b = 1 - # loop do - # y << a - # a, b = b, a + b + # fib = Enumerator.new do |y| + # a = b = 1 + # loop do + # y << a + # a, b = b, a + b + # end # end - # end # - # p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + # p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] # def initialize(obj=nil, meth=:each, *args, &block) if block_given? @@ -188,8 +187,7 @@ # # If no block is given, returns a new Enumerator. # - # === Example - # + # @example # to_three = Enumerator.new do |y| # 3.times do |x| # y << x @@ -582,27 +580,27 @@ # # Here is such an example, with parameter passing and a sizing block: # - # module Enumerable - # # a generic method to repeat the values of any enumerable - # def repeat(n) - # raise ArgumentError, "#{n} is negative!" if n < 0 - # unless block_given? - # return to_enum(__method__, n) do # __method__ is :repeat here - # sz = size # Call size and multiply by n... - # sz * n if sz # but return nil if size itself is nil + # module Enumerable + # # a generic method to repeat the values of any enumerable + # def repeat(n) + # raise ArgumentError, "#{n} is negative!" if n < 0 + # unless block_given? + # return to_enum(__method__, n) do # __method__ is :repeat here + # sz = size # Call size and multiply by n... + # sz * n if sz # but return nil if size itself is nil + # end + # end + # each do |*val| + # n.times { yield *val } # end - # end - # each do |*val| - # n.times { yield *val } # end # end - # end # - # %i[hello world].repeat(2) { |w| puts w } - # # => Prints 'hello', 'hello', 'world', 'world' - # enum = (1..14).repeat(3) - # # => returns an Enumerator when called without a block - # enum.first(4) # => [1, 1, 1, 2] + # %i[hello world].repeat(2) { |w| puts w } + # # => Prints 'hello', 'hello', 'world', 'world' + # enum = (1..14).repeat(3) + # # => returns an Enumerator when called without a block + # enum.first(4) # => [1, 1, 1, 2] # def to_enum(meth=:each, *args) Enumerator.new self, meth, *args diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enumerator/test/enumerator.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enumerator/test/enumerator.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enumerator/test/enumerator.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enumerator/test/enumerator.rb 2016-03-14 00:35:53.000000000 +0000 @@ -427,7 +427,6 @@ assert_equal i, e.next i += 1 } - assert_nil loop_ret end assert 'Integral#times' do diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enum-ext/mrblib/enum.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enum-ext/mrblib/enum.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enum-ext/mrblib/enum.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enum-ext/mrblib/enum.rb 2016-03-14 00:35:53.000000000 +0000 @@ -77,11 +77,11 @@ # Passes elements to the block until the block returns +nil+ or +false+, # then stops iterating and returns an array of all prior elements. # - # If no block is given, an enumerator is returned instead. + # If no block is given, an enumerator is returned instead. + # + # a = [1, 2, 3, 4, 5, 0] + # a.take_while {|i| i < 3 } #=> [1, 2] # - # a = [1, 2, 3, 4, 5, 0] - # a.take_while {|i| i < 3 } #=> [1, 2] - def take_while(&block) return to_enum :take_while unless block @@ -94,13 +94,12 @@ end ## - # call-seq: - # enum.each_cons(n) {...} -> nil - # # Iterates the given block for each array of consecutive # elements. # - # e.g.: + # @return [nil] + # + # @example # (1..10).each_cons(3) {|a| p a} # # outputs below # [1, 2, 3] @@ -116,6 +115,7 @@ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) raise ArgumentError, "invalid size" if n <= 0 + return to_enum(:each_cons,n) unless block ary = [] n = n.to_int self.each do |*val| @@ -126,12 +126,11 @@ end ## - # call-seq: - # enum.each_slice(n) {...} -> nil - # # Iterates the given block for each slice of elements. # - # e.g.: + # @return [nil] + # + # @example # (1..10).each_slice(3) {|a| p a} # # outputs below # [1, 2, 3] @@ -143,6 +142,7 @@ raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) raise ArgumentError, "invalid slice size" if n <= 0 + return to_enum(:each_slice,n) unless block ary = [] n = n.to_int self.each do |*val| @@ -164,8 +164,8 @@ # block, and values are arrays of elements in enum # corresponding to the key. # - # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} - + # (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]} + # def group_by(&block) return to_enum :group_by unless block diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enum-lazy/mrblib/lazy.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-enum-lazy/mrblib/lazy.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-enum-lazy/mrblib/lazy.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,30 +1,29 @@ -# = Enumerable#lazy implementation -# -# Enumerable#lazy returns an instance of Enumerable::Lazy. -# You can use it just like as normal Enumerable object, -# except these methods act as 'lazy': -# -# - map collect -# - select find_all -# - reject -# - grep -# - drop -# - drop_while -# - take_while -# - flat_map collect_concat -# - zip -# -# == Acknowledgements -# -# Based on https://github.com/yhara/enumerable-lazy -# Inspired by https://github.com/antimon2/enumerable_lz -# http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja) - module Enumerable + + # = Enumerable#lazy implementation + # + # Enumerable#lazy returns an instance of Enumerable::Lazy. + # You can use it just like as normal Enumerable object, + # except these methods act as 'lazy': + # + # - map collect + # - select find_all + # - reject + # - grep + # - drop + # - drop_while + # - take_while + # - flat_map collect_concat + # - zip def lazy Lazy.new(self) end + # == Acknowledgements + # + # Based on https://github.com/yhara/enumerable-lazy + # Inspired by https://github.com/antimon2/enumerable_lz + # http://jp.rubyist.net/magazine/?0034-Enumerable_lz (ja) class Lazy < Enumerator def initialize(obj, &block) super(){|yielder| diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-error/src/exception.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-error/src/exception.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-error/src/exception.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-error/src/exception.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ -#include "mruby.h" -#include "mruby/throw.h" -#include "mruby/error.h" +#include +#include +#include MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-error/test/exception.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-error/test/exception.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-error/test/exception.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-error/test/exception.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ -#include "mruby.h" -#include "mruby/error.h" -#include "mruby/array.h" +#include +#include +#include static mrb_value protect_cb(mrb_state *mrb, mrb_value b) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-eval/src/eval.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-eval/src/eval.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-eval/src/eval.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-eval/src/eval.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,9 +1,9 @@ -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/compile.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/opcode.h" +#include +#include +#include +#include +#include +#include static struct mrb_irep * get_closure_irep(mrb_state *mrb, int level) @@ -130,8 +130,10 @@ } } +void mrb_codedump_all(mrb_state*, struct RProc*); + static struct RProc* -create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, char *file, mrb_int line) +create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line) { mrbc_context *cxt; struct mrb_parser_state *p; @@ -145,9 +147,11 @@ cxt = mrbc_context_new(mrb); cxt->lineno = line; - if (file) { - mrbc_filename(mrb, cxt, file); + + if (!file) { + file = "(eval)"; } + mrbc_filename(mrb, cxt, file); cxt->capture_errors = TRUE; cxt->no_optimize = TRUE; @@ -209,7 +213,7 @@ mrb_get_args(mrb, "s|ozi", &s, &len, &binding, &file, &line); proc = create_proc_from_string(mrb, s, len, binding, file, line); - ret = mrb_toplevel_run(mrb, proc); + ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0); if (mrb->exc) { mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); } @@ -235,13 +239,15 @@ mrb_int len; char *file = NULL; mrb_int line = 1; + mrb_value cv; + struct RProc *proc; mrb_get_args(mrb, "s|zi", &s, &len, &file, &line); c->ci->acc = CI_ACC_SKIP; - if (c->ci->target_class->tt == MRB_TT_ICLASS) { - c->ci->target_class = c->ci->target_class->c; - } - return mrb_run(mrb, create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line), self); + cv = mrb_singleton_class(mrb, self); + c->ci->target_class = mrb_class_ptr(cv); + proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line); + return mrb_top_run(mrb, proc, mrb->c->stack[0], 0); } else { mrb_get_args(mrb, "&", &b); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-eval/test/eval.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-eval/test/eval.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-eval/test/eval.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-eval/test/eval.rb 2016-03-14 00:35:53.000000000 +0000 @@ -78,3 +78,22 @@ assert_equal('class') { obj.const_string } end +assert('Object#instance_eval with begin-rescue-ensure execution order') do + class HellRaiser + def raise_hell + order = [:enter_raise_hell] + begin + order.push :begin + self.instance_eval("raise 'error'") + rescue + order.push :rescue + ensure + order.push :ensure + end + order + end + end + + hell_raiser = HellRaiser.new + assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell) +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-exit/src/mruby-exit.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-exit/src/mruby-exit.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-exit/src/mruby-exit.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-exit/src/mruby-exit.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,5 +1,5 @@ #include -#include "mruby.h" +#include static mrb_value f_exit(mrb_state *mrb, mrb_value self) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-fiber/src/fiber.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-fiber/src/fiber.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-fiber/src/fiber.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-fiber/src/fiber.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,12 +1,13 @@ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/proc.h" +#include +#include +#include +#include #define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o)) #define FIBER_STACK_INIT_SIZE 64 #define FIBER_CI_INIT_SIZE 8 +#define CI_ACC_RESUMED -3 /* * call-seq: @@ -155,10 +156,9 @@ /* mark return from context modifying method */ #define MARK_CONTEXT_MODIFY(c) (c)->ci->target_class = NULL -static mrb_value -fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume) +static void +fiber_check_cfunc(mrb_state *mrb, struct mrb_context *c) { - struct mrb_context *c = fiber_check(mrb, self); mrb_callinfo *ci; for (ci = c->ci; ci >= c->cibase; ci--) { @@ -166,16 +166,26 @@ mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary"); } } +} + +static mrb_value +fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mrb_bool resume, mrb_bool vmexec) +{ + struct mrb_context *c = fiber_check(mrb, self); + struct mrb_context *old_c = mrb->c; + mrb_value value; + + fiber_check_cfunc(mrb, c); if (resume && c->status == MRB_FIBER_TRANSFERRED) { mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber"); } - if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMING) { - mrb_raise(mrb, E_FIBER_ERROR, "double resume"); + if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) { + mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)"); } if (c->status == MRB_FIBER_TERMINATED) { mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber"); } - mrb->c->status = resume ? MRB_FIBER_RESUMING : MRB_FIBER_TRANSFERRED; + mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED; c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c); if (c->status == MRB_FIBER_CREATED) { mrb_value *b = c->stack+1; @@ -185,22 +195,24 @@ *b++ = *a++; } c->cibase->argc = len; - if (c->prev->fib) - mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib); - mrb_write_barrier(mrb, (struct RBasic*)c->fib); - c->status = MRB_FIBER_RUNNING; - mrb->c = c; - - MARK_CONTEXT_MODIFY(c); - return c->ci->proc->env->stack[0]; + value = c->stack[0] = c->ci->proc->env->stack[0]; + } + else { + value = fiber_result(mrb, a, len); } - MARK_CONTEXT_MODIFY(c); - if (c->prev->fib) - mrb_field_write_barrier(mrb, (struct RBasic*)c->fib, (struct RBasic*)c->prev->fib); mrb_write_barrier(mrb, (struct RBasic*)c->fib); c->status = MRB_FIBER_RUNNING; mrb->c = c; - return fiber_result(mrb, a, len); + + if (vmexec) { + c->vmexec = TRUE; + value = mrb_vm_exec(mrb, c->ci[-1].proc, c->ci->pc); + mrb->c = old_c; + } + else { + MARK_CONTEXT_MODIFY(c); + } + return value; } /* @@ -223,16 +235,20 @@ { mrb_value *a; mrb_int len; + mrb_bool vmexec = FALSE; mrb_get_args(mrb, "*", &a, &len); - return fiber_switch(mrb, self, len, a, TRUE); + if (mrb->c->ci->acc < 0) { + vmexec = TRUE; + } + return fiber_switch(mrb, self, len, a, TRUE, vmexec); } /* resume thread with given arguments */ MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a) { - return fiber_switch(mrb, fib, len, a, TRUE); + return fiber_switch(mrb, fib, len, a, TRUE, TRUE); } /* @@ -280,6 +296,7 @@ mrb_value* a; mrb_int len; + fiber_check_cfunc(mrb, mrb->c); mrb_get_args(mrb, "*", &a, &len); if (c == mrb->root_c) { @@ -295,7 +312,7 @@ return fiber_result(mrb, a, len); } - return fiber_switch(mrb, self, len, a, FALSE); + return fiber_switch(mrb, self, len, a, FALSE, FALSE); } /* yield values to the caller fiber */ @@ -304,13 +321,7 @@ mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a) { struct mrb_context *c = mrb->c; - mrb_callinfo *ci; - for (ci = c->ci; ci >= c->cibase; ci--) { - if (ci->acc < 0) { - mrb_raise(mrb, E_FIBER_ERROR, "can't cross C function boundary"); - } - } if (!c->prev) { mrb_raise(mrb, E_FIBER_ERROR, "can't yield from root fiber"); } @@ -319,8 +330,12 @@ c->status = MRB_FIBER_SUSPENDED; mrb->c = c->prev; c->prev = NULL; - MARK_CONTEXT_MODIFY(mrb->c); + if (c->vmexec) { + c->vmexec = FALSE; + mrb->c->ci->acc = CI_ACC_RESUMED; + } mrb_write_barrier(mrb, (struct RBasic*)c->fib); + MARK_CONTEXT_MODIFY(mrb->c); return fiber_result(mrb, a, len); } @@ -332,7 +347,9 @@ * along any arguments that were passed to it. The fiber will resume * processing at this point when resume is called next. * Any arguments passed to the next resume will be the - * value that this Fiber.yield expression evaluates to. + * + * mruby limitation: Fiber resume/yield cannot cross C function boundary. + * thus you cannot yield from #initialize which is called by mrb_funcall(). */ static mrb_value fiber_yield(mrb_state *mrb, mrb_value self) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-hash-ext/mrblib/hash.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-hash-ext/mrblib/hash.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-hash-ext/mrblib/hash.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-hash-ext/mrblib/hash.rb 2016-03-14 00:35:53.000000000 +0000 @@ -5,22 +5,22 @@ ## # call-seq: - # Hash[ key, value, ... ] -> new_hash - # Hash[ [ [key, value], ... ] ] -> new_hash - # Hash[ object ] -> new_hash + # Hash[ key, value, ... ] -> new_hash + # Hash[ [ [key, value], ... ] ] -> new_hash + # Hash[ object ] -> new_hash # # Creates a new hash populated with the given objects. # - # Similar to the literal { _key_ => _value_, ... }. In the first + # Similar to the literal `{ _key_ => _value_, ... }`. In the first # form, keys and values occur in pairs, so there must be an even number of # arguments. # # The second and third form take a single argument which is either an array # of key-value pairs or an object convertible to a hash. # - # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200} - # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200} - # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200} + # Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200} + # Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200} + # Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200} # def self.[](*object) @@ -62,6 +62,25 @@ ## # call-seq: + # Hash.try_convert(obj) -> hash or nil + # + # Try to convert obj into a hash, using to_hash method. + # Returns converted hash or nil if obj cannot be converted + # for any reason. + # + # Hash.try_convert({1=>2}) # => {1=>2} + # Hash.try_convert("1=>2") # => nil + # + def self.try_convert(obj) + if obj.respond_to?(:to_hash) + obj.to_hash + else + nil + end + end + + ## + # call-seq: # hsh.merge!(other_hash) -> hsh # hsh.merge!(other_hash){|key, oldval, newval| block} -> hsh # @@ -126,11 +145,11 @@ def fetch(key, none=NONE, &block) unless self.key?(key) if block - block.call + block.call(key) elsif none != NONE none else - raise RuntimeError, "Key not found: #{key}" + raise KeyError, "Key not found: #{key}" end else self[key] @@ -156,7 +175,7 @@ self.each do |k, v| self.delete(k) if block.call(k, v) - end + end self end @@ -250,4 +269,100 @@ def to_h self end + + ## + # call-seq: + # hash < other -> true or false + # + # Returns true if hash is subset of + # other. + # + # h1 = {a:1, b:2} + # h2 = {a:1, b:2, c:3} + # h1 < h2 #=> true + # h2 < h1 #=> false + # h1 < h1 #=> false + # + def <(hash) + begin + hash = hash.to_hash + rescue NoMethodError + raise TypeError, "can't convert #{hash.class} to Hash" + end + size < hash.size and all? {|key, val| + hash.key?(key) and hash[key] == val + } + end + + ## + # call-seq: + # hash <= other -> true or false + # + # Returns true if hash is subset of + # other or equals to other. + # + # h1 = {a:1, b:2} + # h2 = {a:1, b:2, c:3} + # h1 <= h2 #=> true + # h2 <= h1 #=> false + # h1 <= h1 #=> true + # + def <=(hash) + begin + hash = hash.to_hash + rescue NoMethodError + raise TypeError, "can't convert #{hash.class} to Hash" + end + size <= hash.size and all? {|key, val| + hash.key?(key) and hash[key] == val + } + end + + ## + # call-seq: + # hash > other -> true or false + # + # Returns true if other is subset of + # hash. + # + # h1 = {a:1, b:2} + # h2 = {a:1, b:2, c:3} + # h1 > h2 #=> false + # h2 > h1 #=> true + # h1 > h1 #=> false + # + def >(hash) + begin + hash = hash.to_hash + rescue NoMethodError + raise TypeError, "can't convert #{hash.class} to Hash" + end + size > hash.size and hash.all? {|key, val| + key?(key) and self[key] == val + } + end + + ## + # call-seq: + # hash >= other -> true or false + # + # Returns true if other is subset of + # hash or equals to hash. + # + # h1 = {a:1, b:2} + # h2 = {a:1, b:2, c:3} + # h1 >= h2 #=> false + # h2 >= h1 #=> true + # h1 >= h1 #=> true + # + def >=(hash) + begin + hash = hash.to_hash + rescue NoMethodError + raise TypeError, "can't convert #{hash.class} to Hash" + end + size >= hash.size and hash.all? {|key, val| + key?(key) and self[key] == val + } + end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-hash-ext/src/hash-ext.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-hash-ext/src/hash-ext.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-hash-ext/src/hash-ext.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-hash-ext/src/hash-ext.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,9 +4,9 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/hash.h" +#include +#include +#include /* * call-seq: diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-hash-ext/test/hash.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-hash-ext/test/hash.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-hash-ext/test/hash.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-hash-ext/test/hash.rb 2016-03-14 00:35:53.000000000 +0000 @@ -39,6 +39,12 @@ end end +assert('Hash.try_convert') do + assert_nil Hash.try_convert(nil) + assert_nil Hash.try_convert("{1=>2}") + assert_equal({1=>2}, Hash.try_convert({1=>2})) +end + assert('Hash#merge!') do a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' } b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' } @@ -75,10 +81,9 @@ assert_equal "feline", h.fetch("cat") assert_equal "mickey", h.fetch("mouse", "mickey") assert_equal "minny", h.fetch("mouse"){"minny"} - begin + assert_equal "mouse", h.fetch("mouse"){|k| k} + assert_raise(KeyError) do h.fetch("gnu") - rescue => e - assert_kind_of(StandardError, e); end end @@ -159,3 +164,75 @@ assert_equal Hash, h.to_h.class assert_equal h, h.to_h end + +assert('Hash#<') do + h1 = {a:1, b:2} + h2 = {a:1, b:2, c:3} + + assert_false(h1 < h1) + assert_true(h1 < h2) + assert_false(h2 < h1) + assert_false(h2 < h2) + + h1 = {a:1} + h2 = {a:2} + + assert_false(h1 < h1) + assert_false(h1 < h2) + assert_false(h2 < h1) + assert_false(h2 < h2) +end + +assert('Hash#<=') do + h1 = {a:1, b:2} + h2 = {a:1, b:2, c:3} + + assert_true(h1 <= h1) + assert_true(h1 <= h2) + assert_false(h2 <= h1) + assert_true(h2 <= h2) + + h1 = {a:1} + h2 = {a:2} + + assert_true(h1 <= h1) + assert_false(h1 <= h2) + assert_false(h2 <= h1) + assert_true(h2 <= h2) +end + +assert('Hash#>=') do + h1 = {a:1, b:2} + h2 = {a:1, b:2, c:3} + + assert_true(h1 >= h1) + assert_false(h1 >= h2) + assert_true(h2 >= h1) + assert_true(h2 >= h2) + + h1 = {a:1} + h2 = {a:2} + + assert_true(h1 >= h1) + assert_false(h1 >= h2) + assert_false(h2 >= h1) + assert_true(h2 >= h2) +end + +assert('Hash#>') do + h1 = {a:1, b:2} + h2 = {a:1, b:2, c:3} + + assert_false(h1 > h1) + assert_false(h1 > h2) + assert_true(h2 > h1) + assert_false(h2 > h2) + + h1 = {a:1} + h2 = {a:2} + + assert_false(h1 > h1) + assert_false(h1 > h2) + assert_false(h2 > h1) + assert_false(h2 > h2) +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-kernel-ext/src/kernel.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-kernel-ext/src/kernel.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-kernel-ext/src/kernel.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-kernel-ext/src/kernel.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,7 +1,7 @@ -#include "mruby.h" -#include "mruby/error.h" -#include "mruby/array.h" -#include "mruby/hash.h" +#include +#include +#include +#include /* * call-seq: @@ -138,10 +138,11 @@ * arg.to_hash. Returns an empty Hash when * arg is nil or []. * - * Hash([]) #=> {} - * Hash(nil) #=> {} - * Hash(key: :value) #=> {:key => :value} - * Hash([1, 2, 3]) #=> TypeError + * Hash([]) #=> {} + * Hash(nil) #=> {} + * Hash(key: :value) #=> {:key => :value} + * Hash([1, 2, 3]) #=> TypeError + * */ static mrb_value mrb_f_hash(mrb_state *mrb, mrb_value self) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-kernel-ext/test/kernel.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-kernel-ext/test/kernel.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-kernel-ext/test/kernel.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-kernel-ext/test/kernel.rb 2016-03-14 00:35:53.000000000 +0000 @@ -22,6 +22,8 @@ assert_equal(26, Integer("0x1a")) assert_equal(930, Integer("0930", 10)) assert_equal(7, Integer("111", 2)) + assert_equal(0, Integer("0")) + assert_equal(0, Integer("00000")) assert_raise(TypeError) { Integer(nil) } end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-math/src/math.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-math/src/math.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-math/src/math.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-math/src/math.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,8 +4,8 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/array.h" +#include +#include #include @@ -19,7 +19,7 @@ } /* math functions not provided by Microsoft Visual C++ 2012 or older */ -#if defined _MSC_VER && _MSC_VER < 1800 +#if defined _MSC_VER && _MSC_VER <= 1700 #include @@ -236,7 +236,8 @@ * call-seq: * Math.asin(x) -> float * - * Computes the arc sine of x. Returns -{PI/2} .. {PI/2}. + * Computes the arc sine of x. + * @return computed value between `-(PI/2)` and `(PI/2)`. */ static mrb_value math_asin(mrb_state *mrb, mrb_value obj) @@ -276,7 +277,7 @@ * call-seq: * Math.atan(x) -> float * - * Computes the arc tangent of x. Returns -{PI/2} .. {PI/2}. + * Computes the arc tangent of x. Returns `-(PI/2) .. (PI/2)`. */ static mrb_value math_atan(mrb_state *mrb, mrb_value obj) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb 2016-03-14 00:35:53.000000000 +0000 @@ -2,4 +2,16 @@ def div(other) self.divmod(other)[0] end + + def zero? + self == 0 + end + + def nonzero? + if self == 0 + nil + else + self + end + end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-numeric-ext/src/numeric_ext.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-numeric-ext/src/numeric_ext.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-numeric-ext/src/numeric_ext.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-numeric-ext/src/numeric_ext.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,5 +1,5 @@ #include -#include "mruby.h" +#include static mrb_value mrb_int_chr(mrb_state *mrb, mrb_value x) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-numeric-ext/test/numeric.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-numeric-ext/test/numeric.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-numeric-ext/test/numeric.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-numeric-ext/test/numeric.rb 2016-03-14 00:35:53.000000000 +0000 @@ -16,3 +16,13 @@ assert('Float#div') do assert_float 52, 365.2425.div(7) end + +assert('Integer#zero?') do + assert_equal true, 0.zero? + assert_equal false, 1.zero? +end + +assert('Integer#nonzero?') do + assert_equal nil, 0.nonzero? + assert_equal 1000, 1000.nonzero? +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-object-ext/src/object.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-object-ext/src/object.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-object-ext/src/object.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-object-ext/src/object.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" +#include +#include +#include /* * call-seq: diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-objectspace/src/mruby_objectspace.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-objectspace/src/mruby_objectspace.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-objectspace/src/mruby_objectspace.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-objectspace/src/mruby_objectspace.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,7 +1,7 @@ -#include "mruby.h" -#include "mruby/gc.h" -#include "mruby/hash.h" -#include "mruby/class.h" +#include +#include +#include +#include struct os_count_struct { mrb_int total; @@ -17,7 +17,7 @@ obj_count->total++; - if (is_dead(mrb, obj)) { + if (mrb_object_dead_p(mrb, obj)) { obj_count->freed++; } else { @@ -115,7 +115,7 @@ struct os_each_object_data *d = (struct os_each_object_data*)ud; /* filter dead objects */ - if (is_dead(mrb, obj)) { + if (mrb_object_dead_p(mrb, obj)) { return; } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-print/src/print.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-print/src/print.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-print/src/print.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-print/src/print.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,17 +1,34 @@ -#include "mruby.h" -#include "mruby/string.h" +#include +#include #include +#include +#include +#if defined(__MINGW32__) || defined(__MINGW64__) +# include +# include +#endif static void printstr(mrb_state *mrb, mrb_value obj) { - char *s; - mrb_int len; - if (mrb_string_p(obj)) { - s = RSTRING_PTR(obj); - len = RSTRING_LEN(obj); - fwrite(s, len, 1, stdout); +#if defined(__MINGW32__) || defined(__MINGW64__) + if (isatty(fileno(stdout))) { + DWORD written; + int mlen = RSTRING_LEN(obj); + char* utf8 = RSTRING_PTR(obj); + int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0); + wchar_t* utf16 = mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t)); + if (utf16 == NULL) return; + if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) { + utf16[wlen] = 0; + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), + utf16, wlen, &written, NULL); + } + mrb_free(mrb, utf16); + } else +#endif + fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout); } } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-proc-ext/src/proc.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-proc-ext/src/proc.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-proc-ext/src/proc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-proc-ext/src/proc.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,9 +1,9 @@ -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/opcode.h" -#include "mruby/array.h" -#include "mruby/string.h" -#include "mruby/debug.h" +#include +#include +#include +#include +#include +#include static mrb_value mrb_proc_lambda(mrb_state *mrb, mrb_value self) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-proc-ext/test/proc.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-proc-ext/test/proc.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-proc-ext/test/proc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-proc-ext/test/proc.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/class.h" +#include +#include +#include static mrb_value return_func_name(mrb_state *mrb, mrb_value self) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-random/src/mt19937ar.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-random/src/mt19937ar.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-random/src/mt19937ar.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-random/src/mt19937ar.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,7 +4,7 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" +#include #include "mt19937ar.h" /* Period parameters */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-random/src/random.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-random/src/random.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-random/src/random.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-random/src/random.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,11 +4,11 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/variable.h" -#include "mruby/class.h" -#include "mruby/data.h" -#include "mruby/array.h" +#include +#include +#include +#include +#include #include "mt19937ar.h" #include @@ -79,10 +79,10 @@ mrb_get_args(mrb, "|o", &arg); if (!mrb_nil_p(arg)) { - if (!mrb_fixnum_p(arg)) { + arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int"); + if (mrb_nil_p(arg)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); } - arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int"); if (mrb_fixnum(arg) < 0) { arg = mrb_fixnum_value(0 - mrb_fixnum(arg)); } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-random/src/random.h mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-random/src/random.h --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-random/src/random.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-random/src/random.h 2016-03-14 00:35:53.000000000 +0000 @@ -4,8 +4,8 @@ ** See Copyright Notice in mruby.h */ -#ifndef RANDOM_H -#define RANDOM_H +#ifndef MRUBY_RANDOM_H +#define MRUBY_RANDOM_H void mrb_mruby_random_gem_init(mrb_state *mrb); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-range-ext/src/range.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-range-ext/src/range.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-range-ext/src/range.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-range-ext/src/range.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,5 +1,5 @@ -#include "mruby.h" -#include "mruby/range.h" +#include +#include #include static mrb_bool diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-sprintf/src/kernel.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-sprintf/src/kernel.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-sprintf/src/kernel.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-sprintf/src/kernel.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,7 +4,7 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" +#include mrb_value mrb_f_sprintf(mrb_state *mrb, mrb_value obj); /* in sprintf.c */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-sprintf/src/sprintf.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-sprintf/src/sprintf.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-sprintf/src/sprintf.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-sprintf/src/sprintf.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,14 +4,14 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" +#include #include #include #include -#include "mruby/string.h" -#include "mruby/hash.h" -#include "mruby/numeric.h" +#include +#include +#include #include #include @@ -71,7 +71,7 @@ static mrb_value mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base) { - char buf[64], *b = buf + sizeof buf; + char buf[66], *b = buf + sizeof buf; mrb_int num = mrb_fixnum(x); uint64_t val = (uint64_t)num; char d; @@ -79,10 +79,6 @@ if (base != 2) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base)); } - - if (val >= (1 << 10)) - val &= 0x3ff; - if (val == 0) { return mrb_str_new_lit(mrb, "0"); } @@ -763,11 +759,11 @@ case 'B': case 'u': { mrb_value val = GETARG(); - char fbuf[32], nbuf[64], *s; + char nbuf[68], *s; const char *prefix = NULL; int sign = 0, dots = 0; char sc = 0; - mrb_int v = 0, org_v = 0; + mrb_int v = 0; int base; mrb_int len; @@ -800,10 +796,6 @@ bin_retry: switch (mrb_type(val)) { case MRB_TT_FLOAT: - if (FIXABLE(mrb_float(val))) { - val = mrb_fixnum_value((mrb_int)mrb_float(val)); - goto bin_retry; - } val = mrb_flo_to_fixnum(mrb, val); if (mrb_fixnum_p(val)) goto bin_retry; break; @@ -835,7 +827,6 @@ } if (base == 2) { - org_v = v; if (v < 0 && !sign) { val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base); dots = 1; @@ -843,12 +834,8 @@ else { val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base); } - v = mrb_fixnum(mrb_str_to_inum(mrb, val, 10, FALSE)); } if (sign) { - char c = *p; - if (c == 'i') c = 'd'; /* %d and %i are identical */ - if (base == 2) c = 'd'; if (v < 0) { v = -v; sc = '-'; @@ -862,20 +849,41 @@ sc = ' '; width--; } - snprintf(fbuf, sizeof(fbuf), "%%l%c", c); - snprintf(nbuf, sizeof(nbuf), fbuf, v); + switch (base) { + case 2: + strncpy(nbuf, RSTRING_PTR(val), sizeof(nbuf)); + break; + case 8: + snprintf(nbuf, sizeof(nbuf), "%"MRB_PRIo, v); + break; + case 10: + snprintf(nbuf, sizeof(nbuf), "%"MRB_PRId, v); + break; + case 16: + snprintf(nbuf, sizeof(nbuf), "%"MRB_PRIx, v); + break; + } s = nbuf; } else { - char c = *p; - if (c == 'X') c = 'x'; - if (base == 2) c = 'd'; s = nbuf; if (v < 0) { dots = 1; } - snprintf(fbuf, sizeof(fbuf), "%%l%c", c); - snprintf(++s, sizeof(nbuf) - 1, fbuf, v); + switch (base) { + case 2: + strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1); + break; + case 8: + snprintf(++s, sizeof(nbuf)-1, "%"MRB_PRIo, v); + break; + case 10: + snprintf(++s, sizeof(nbuf)-1, "%"MRB_PRId, v); + break; + case 16: + snprintf(++s, sizeof(nbuf)-1, "%"MRB_PRIx, v); + break; + } if (v < 0) { char d; @@ -965,7 +973,7 @@ CHECK(prec - len); if (dots) PUSH("..", 2); - if (v < 0 || (base == 2 && org_v < 0)) { + if (v < 0) { char c = sign_bits(base, p); while (len < prec--) { buf[blen++] = c; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-sprintf/test/sprintf.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-sprintf/test/sprintf.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-sprintf/test/sprintf.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-sprintf/test/sprintf.rb 2016-03-14 00:35:53.000000000 +0000 @@ -5,4 +5,5 @@ assert_equal "one=1", "one=%d" % 1 assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ] assert_equal "123 < 456", "%{num} < %s" % { num: 123, str: "456" } + assert_equal 16, ("%b" % (1<<15)).size end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-ext/mrblib/string.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-ext/mrblib/string.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-ext/mrblib/string.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-ext/mrblib/string.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,25 @@ class String ## + # call-seq: + # String.try_convert(obj) -> string or nil + # + # Try to convert obj into a String, using to_str method. + # Returns converted string or nil if obj cannot be converted + # for any reason. + # + # String.try_convert("str") #=> "str" + # String.try_convert(/re/) #=> nil + # + def self.try_convert(obj) + if obj.respond_to?(:to_str) + obj.to_str + else + nil + end + end + + ## # call-seq: # string.clear -> string # @@ -268,6 +287,29 @@ return newstr.slice(0,idx) end + ## + # call-seq: + # str.rjust(integer, padstr=' ') -> new_str + # + # If integer is greater than the length of str, returns a new + # String of length integer with str right justified + # and padded with padstr; otherwise, returns str. + # + # "hello".rjust(4) #=> "hello" + # "hello".rjust(20) #=> " hello" + # "hello".rjust(20, '1234') #=> "123412341234123hello" + def rjust(idx, padstr = ' ') + if idx <= self.size + return self + end + padsize = idx - self.size + newstr = padstr.dup + while newstr.size <= padsize + newstr << padstr + end + return newstr.slice(0,padsize) + self + end + # str.upto(other_str, exclusive=false) {|s| block } -> str # str.upto(other_str, exclusive=false) -> an_enumerator # @@ -310,4 +352,30 @@ return self if excl && str == other_str end end + + def chars(&block) + if block_given? + self.split('').map do |i| + block.call(i) + end + self + else + self.split('') + end + end + alias each_char chars + + def codepoints(&block) + len = self.size + + if block_given? + self.split('').map do|x| + block.call(x.ord) + end + self + else + self.split('').map{|x| x.ord} + end + end + alias each_codepoint codepoints end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-ext/src/string.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-ext/src/string.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-ext/src/string.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-ext/src/string.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,9 +1,9 @@ #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/string.h" -#include "mruby/range.h" +#include +#include +#include +#include +#include static mrb_value mrb_str_getbyte(mrb_state *mrb, mrb_value str) @@ -245,6 +245,51 @@ return mrb_str_substr(mrb, self, 0, 1); } +static mrb_value +mrb_fixnum_chr(mrb_state *mrb, mrb_value num) +{ + mrb_int cp = mrb_fixnum(num); +#ifdef MRB_UTF8_STRING + char utf8[4]; + mrb_int len; + + if (cp < 0 || 0x10FFFF < cp) { + mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num); + } + if (cp < 0x80) { + utf8[0] = (char)cp; + len = 1; + } + else if (cp < 0x800) { + utf8[0] = (char)(0xC0 | (cp >> 6)); + utf8[1] = (char)(0x80 | (cp & 0x3F)); + len = 2; + } + else if (cp < 0x10000) { + utf8[0] = (char)(0xE0 | (cp >> 12)); + utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F)); + utf8[2] = (char)(0x80 | ( cp & 0x3F)); + len = 3; + } + else { + utf8[0] = (char)(0xF0 | (cp >> 18)); + utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F)); + utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F)); + utf8[3] = (char)(0x80 | ( cp & 0x3F)); + len = 4; + } + return mrb_str_new(mrb, utf8, len); +#else + char c; + + if (cp < 0 || 0xff < cp) { + mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num); + } + c = (char)cp; + return mrb_str_new(mrb, &c, 1); +#endif +} + /* * call-seq: * string.lines -> array of string @@ -422,6 +467,72 @@ return self; } +#ifdef MRB_UTF8_STRING +static const char utf8len_codepage_zero[256] = +{ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, +}; + +static mrb_int +utf8code(unsigned char* p) +{ + mrb_int len; + + if (p[0] < 0x80) + return p[0]; + + len = utf8len_codepage_zero[p[0]]; + if (len > 1 && (p[1] & 0xc0) == 0x80) { + if (len == 2) + return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f); + if ((p[2] & 0xc0) == 0x80) { + if (len == 3) + return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + + (p[2] & 0x3f); + if ((p[3] & 0xc0) == 0x80) { + if (len == 4) + return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) + + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f); + if ((p[4] & 0xc0) == 0x80) { + if (len == 5) + return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18) + + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6) + + (p[4] & 0x3f); + if ((p[5] & 0xc0) == 0x80 && len == 6) + return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24) + + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12) + + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f); + } + } + } + } + return p[0]; +} + +static mrb_value +mrb_str_ord(mrb_state* mrb, mrb_value str) +{ + if (RSTRING_LEN(str) == 0) + mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); + return mrb_fixnum_value(utf8code((unsigned char*) RSTRING_PTR(str))); +} +#else +static mrb_value +mrb_str_ord(mrb_state* mrb, mrb_value str) +{ + if (RSTRING_LEN(str) == 0) + mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); + return mrb_fixnum_value(RSTRING_PTR(str)[0]); +} +#endif + void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -446,6 +557,9 @@ mrb_define_method(mrb, s, "prepend", mrb_str_prepend, MRB_ARGS_REQ(1)); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); + mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); + + mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE()); } void diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-ext/test/string.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-ext/test/string.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-ext/test/string.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-ext/test/string.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,15 @@ ## # String(Ext) Test +UTF8STRING = ("\343\201\202".size == 1) + +assert('String.try_convert') do + assert_nil String.try_convert(nil) + assert_nil String.try_convert(:foo) + assert_equal "", String.try_convert("") + assert_equal "1,2,3", String.try_convert("1,2,3") +end + assert('String#getbyte') do str1 = "hello" bytes1 = [104, 101, 108, 108, 111] @@ -180,6 +189,8 @@ assert('String#chr') do assert_equal "a", "abcde".chr + # test Fixnum#chr as well + assert_equal "a", 97.chr end assert('String#lines') do @@ -374,8 +385,8 @@ assert_equal "-b-", a a = "-z-"; a.succ! assert_equal "-aa-", a - a = "あa"; a.succ! - assert_equal "あb", a + a = "あb"; a.succ! + assert_equal "あc", a a = "あaz"; a.succ! assert_equal "あba", a end @@ -410,6 +421,13 @@ assert_equal "hello", "hello".ljust(-3) end +assert('String#rjust') do + assert_equal "hello", "hello".rjust(4) + assert_equal " hello", "hello".rjust(20) + assert_equal "123412341234123hello", "hello".rjust(20, '1234') + assert_equal "hello", "hello".rjust(-3) +end + assert('String#upto') do a = "aa" start = "aa" @@ -471,3 +489,96 @@ }) assert_equal(2, count) end + +assert('String#ord') do + got = "hello!".split('').map {|x| x.ord} + expect = [104, 101, 108, 108, 111, 33] + assert_equal expect, got +end + +assert('String#ord(UTF-8)') do + got = "こんにちは世界!".split('').map {|x| x.ord} + expect = [0x3053,0x3093,0x306b,0x3061,0x306f,0x4e16,0x754c,0x21] + assert_equal expect, got +end if UTF8STRING + +assert('String#chr') do + assert_equal "h", "hello!".chr +end +assert('String#chr(UTF-8)') do + assert_equal "こ", "こんにちは世界!".chr +end if UTF8STRING + +assert('String#chars') do + expect = ["h", "e", "l", "l", "o", "!"] + assert_equal expect, "hello!".chars + s = "" + "hello!".chars do |x| + s += x + end + assert_equal "hello!", s +end + +assert('String#chars(UTF-8)') do + expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'] + assert_equal expect, "こんにちは世界!".chars + s = "" + "こんにちは世界!".chars do |x| + s += x + end + assert_equal "こんにちは世界!", s +end if UTF8STRING + +assert('String#each_char') do + s = "" + "hello!".each_char do |x| + s += x + end + assert_equal "hello!", s +end + +assert('String#each_char(UTF-8)') do + s = "" + "こんにちは世界!".each_char do |x| + s += x + end + assert_equal "こんにちは世界!", s +end if UTF8STRING + +assert('String#codepoints') do + expect = [104, 101, 108, 108, 111, 33] + assert_equal expect, "hello!".codepoints + cp = [] + "hello!".codepoints do |x| + cp << x + end + assert_equal expect, cp +end + +assert('String#codepoints(UTF-8)') do + expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] + assert_equal expect, "こんにちは世界!".codepoints + cp = [] + "こんにちは世界!".codepoints do |x| + cp << x + end + assert_equal expect, cp +end if UTF8STRING + +assert('String#each_codepoint') do + expect = [104, 101, 108, 108, 111, 33] + cp = [] + "hello!".each_codepoint do |x| + cp << x + end + assert_equal expect, cp +end + +assert('String#each_codepoint(UTF-8)') do + expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] + cp = [] + "こんにちは世界!".each_codepoint do |x| + cp << x + end + assert_equal expect, cp +end if UTF8STRING diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-utf8/mrbgem.rake mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-utf8/mrbgem.rake --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-utf8/mrbgem.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-utf8/mrbgem.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -MRuby::Gem::Specification.new('mruby-string-utf8') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - spec.summary = 'UTF-8 support in String class' - spec.add_dependency('mruby-string-ext', :core => 'mruby-string-ext') -end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-utf8/src/string.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-utf8/src/string.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-utf8/src/string.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-utf8/src/string.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,731 +0,0 @@ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/string.h" -#include "mruby/range.h" -#include "mruby/numeric.h" -#include "mruby/re.h" -#include - -static const char utf8len_codepage[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1, -}; - -static const char utf8len_codepage_zero[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, -}; - -static mrb_int -utf8code(unsigned char* p) -{ - mrb_int len; - - if (p[0] < 0x80) - return p[0]; - - len = utf8len_codepage_zero[p[0]]; - if (len > 1 && (p[1] & 0xc0) == 0x80) { - if (len == 2) - return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f); - if ((p[2] & 0xc0) == 0x80) { - if (len == 3) - return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) - + (p[2] & 0x3f); - if ((p[3] & 0xc0) == 0x80) { - if (len == 4) - return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) - + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f); - if ((p[4] & 0xc0) == 0x80) { - if (len == 5) - return ((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18) - + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6) - + (p[4] & 0x3f); - if ((p[5] & 0xc0) == 0x80 && len == 6) - return ((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24) - + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12) - + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f); - } - } - } - } - return p[0]; -} - -static mrb_value mrb_fixnum_chr(mrb_state*, mrb_value); - -static mrb_int -utf8len(unsigned char* p) -{ - mrb_int len; - mrb_int i; - - if (*p == 0) - return 1; - len = utf8len_codepage[*p]; - for (i = 1; i < len; ++i) - if ((p[i] & 0xc0) != 0x80) - return 1; - return len; -} - -static mrb_int -mrb_utf8_strlen(mrb_value str, mrb_int len) -{ - mrb_int total = 0; - unsigned char* p = (unsigned char*) RSTRING_PTR(str); - unsigned char* e = p; - e += len < 0 ? RSTRING_LEN(str) : len; - while (p n) return -1; - else if (m == n) { - return memcmp(x0, y0, m) == 0 ? 0 : -1; - } - else if (m < 1) { - return 0; - } - else if (m == 1) { - const unsigned char *ys = y, *ye = ys + n; - for (; y < ye; ++y) { - if (*x == *y) - return y - ys; - } - return -1; - } - return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n); -} - -static mrb_value -str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) -{ - mrb_int i; - unsigned char *p = (unsigned char*) RSTRING_PTR(str), *t; - unsigned char *e = p + RSTRING_LEN(str); - - for (i = 0; i < beg && p len8) return mrb_nil_value(); - if (beg < 0) { - beg += len8; - if (beg < 0) return mrb_nil_value(); - } - if (beg + len > len8) - len = len8 - beg; - if (len <= 0) { - len = 0; - } - str2 = str_subseq(mrb, str, beg, len); - - return str2; -} - -static mrb_int -str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) -{ - mrb_int pos; - char *s, *sptr; - mrb_int len, slen; - - len = RSTRING_LEN(str); - slen = RSTRING_LEN(sub); - if (offset < 0) { - offset += len; - if (offset < 0) return -1; - } - if (len - offset < slen) return -1; - s = RSTRING_PTR(str); - if (offset) { - s += offset; - } - if (slen == 0) return offset; - /* need proceed one character at a time */ - sptr = RSTRING_PTR(sub); - slen = RSTRING_LEN(sub); - len = RSTRING_LEN(str) - offset; - pos = mrb_memsearch(sptr, slen, s, len); - if (pos < 0) return pos; - return pos + offset; -} - -static mrb_int -str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) -{ - char *s, *sbeg, *t; - struct RString *ps = mrb_str_ptr(str); - mrb_int len = RSTRING_LEN(sub); - - /* substring longer than string */ - if (RSTR_LEN(ps) < len) return -1; - if (RSTR_LEN(ps) - pos < len) { - pos = RSTR_LEN(ps) - len; - } - sbeg = RSTR_PTR(ps); - s = RSTR_PTR(ps) + pos; - t = RSTRING_PTR(sub); - if (len) { - while (sbeg <= s) { - if (memcmp(s, t, len) == 0) { - return s - RSTR_PTR(ps); - } - s--; - } - return -1; - } - else { - return pos; - } -} - -static mrb_value -mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value indx) -{ - mrb_int idx; - - mrb_regexp_check(mrb, indx); - switch (mrb_type(indx)) { - case MRB_TT_FLOAT: - indx = mrb_flo_to_fixnum(mrb, indx); - /* fall through */ - case MRB_TT_FIXNUM: - idx = mrb_fixnum(indx); - -num_index: - str = str_substr(mrb, str, idx, 1); - if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value(); - return str; - - case MRB_TT_STRING: - if (str_index(mrb, str, indx, 0) != -1) - return mrb_str_dup(mrb, indx); - return mrb_nil_value(); - - case MRB_TT_RANGE: - /* check if indx is Range */ - { - mrb_int beg, len; - mrb_value tmp; - - len = RSTRING_LEN_UTF8(str); - if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) { - tmp = str_subseq(mrb, str, beg, len); - return tmp; - } - else { - return mrb_nil_value(); - } - } - default: - idx = mrb_fixnum(indx); - goto num_index; - } - return mrb_nil_value(); /* not reached */ -} - -static mrb_value -mrb_str_aref_m(mrb_state *mrb, mrb_value str) -{ - mrb_value a1, a2; - int argc; - - argc = mrb_get_args(mrb, "o|o", &a1, &a2); - if (argc == 2) { - mrb_regexp_check(mrb, a1); - return str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); - } - if (argc != 1) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc)); - } - return mrb_str_aref(mrb, str, a1); -} - -static mrb_value -mrb_str_index_m(mrb_state *mrb, mrb_value str) -{ - mrb_value *argv; - mrb_int argc; - - mrb_value sub; - mrb_int pos; - - mrb_get_args(mrb, "*", &argv, &argc); - if (argc == 2) { - pos = mrb_fixnum(argv[1]); - sub = argv[0]; - } - else { - pos = 0; - if (argc > 0) - sub = argv[0]; - else - sub = mrb_nil_value(); - - } - mrb_regexp_check(mrb, sub); - if (pos < 0) { - pos += RSTRING_LEN(str); - if (pos < 0) { - return mrb_nil_value(); - } - } - - if (mrb_type(sub) == MRB_TT_FIXNUM) { - sub = mrb_fixnum_chr(mrb, sub); - } - - switch (mrb_type(sub)) { - default: { - mrb_value tmp; - - tmp = mrb_check_string_type(mrb, sub); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub); - } - sub = tmp; - } - /* fall through */ - case MRB_TT_STRING: - pos = str_index(mrb, str, sub, pos); - break; - } - - if (pos == -1) return mrb_nil_value(); - return mrb_fixnum_value(mrb_utf8_strlen(str, pos)); -} - -static mrb_value -mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) -{ - mrb_int utf8_len = mrb_utf8_strlen(str, -1); - if (utf8_len > 1) { - mrb_int len; - char *buf; - unsigned char *p, *e, *r; - - mrb_str_modify(mrb, mrb_str_ptr(str)); - len = RSTRING_LEN(str); - buf = (char *)mrb_malloc(mrb, (size_t)len); - p = (unsigned char*)buf; - e = (unsigned char*)buf + len; - - memcpy(buf, RSTRING_PTR(str), len); - r = (unsigned char*)RSTRING_PTR(str) + len; - - while (p len) pos = len; - } - else { - pos = len; - if (argc > 0) - sub = argv[0]; - else - sub = mrb_nil_value(); - } - mrb_regexp_check(mrb, sub); - - if (mrb_type(sub) == MRB_TT_FIXNUM) { - sub = mrb_fixnum_chr(mrb, sub); - } - - switch (mrb_type(sub)) { - default: { - mrb_value tmp; - - tmp = mrb_check_string_type(mrb, sub); - if (mrb_nil_p(tmp)) { - mrb_raisef(mrb, E_TYPE_ERROR, "type mismatch: %S given", sub); - } - sub = tmp; - } - /* fall through */ - case MRB_TT_STRING: - pos = str_rindex(mrb, str, sub, pos); - break; - } - - if (pos == -1) return mrb_nil_value(); - return mrb_fixnum_value(mrb_utf8_strlen(str, pos)); -} - -static mrb_value -mrb_str_reverse(mrb_state *mrb, mrb_value str) -{ - return mrb_str_reverse_bang(mrb, mrb_str_dup(mrb, str)); -} - -static mrb_value -mrb_fixnum_chr(mrb_state *mrb, mrb_value num) -{ - mrb_int cp = mrb_fixnum(num); - char utf8[4]; - mrb_int len; - - if (cp < 0 || 0x10FFFF < cp) { - mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num); - } - if (cp < 0x80) { - utf8[0] = (char)cp; - len = 1; - } - else if (cp < 0x800) { - utf8[0] = (char)(0xC0 | (cp >> 6)); - utf8[1] = (char)(0x80 | (cp & 0x3F)); - len = 2; - } - else if (cp < 0x10000) { - utf8[0] = (char)(0xE0 | (cp >> 12)); - utf8[1] = (char)(0x80 | ((cp >> 6) & 0x3F)); - utf8[2] = (char)(0x80 | ( cp & 0x3F)); - len = 3; - } - else { - utf8[0] = (char)(0xF0 | (cp >> 18)); - utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F)); - utf8[2] = (char)(0x80 | ((cp >> 6) & 0x3F)); - utf8[3] = (char)(0x80 | ( cp & 0x3F)); - len = 4; - } - return mrb_str_new(mrb, utf8, len); -} - -static mrb_value -mrb_str_ord(mrb_state* mrb, mrb_value str) -{ - mrb_int len = RSTRING_LEN(str); - - if (len == 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); - return mrb_fixnum_value(utf8code((unsigned char*) RSTRING_PTR(str))); -} - -static mrb_value -mrb_str_split_m(mrb_state *mrb, mrb_value str) -{ - int argc; - mrb_value spat = mrb_nil_value(); - enum {awk, string, regexp} split_type = string; - long i = 0, lim_p; - mrb_int beg; - mrb_int end; - mrb_int lim = 0; - mrb_value result, tmp; - - argc = mrb_get_args(mrb, "|oi", &spat, &lim); - lim_p = (lim > 0 && argc == 2); - if (argc == 2) { - if (lim == 1) { - if (RSTRING_LEN(str) == 0) - return mrb_ary_new_capa(mrb, 0); - return mrb_ary_new_from_values(mrb, 1, &str); - } - i = 1; - } - - if (argc == 0 || mrb_nil_p(spat)) { - split_type = awk; - } - else { - if (mrb_string_p(spat)) { - split_type = string; - if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){ - split_type = awk; - } - } - else { - mrb_noregexp(mrb, str); - } - } - - result = mrb_ary_new(mrb); - beg = 0; - if (split_type == awk) { - char *ptr = RSTRING_PTR(str); - char *eptr = RSTRING_END(str); - char *bptr = ptr; - int skip = 1; - unsigned int c; - - end = beg; - while (ptr < eptr) { - int ai = mrb_gc_arena_save(mrb); - c = (unsigned char)*ptr++; - if (skip) { - if (ISSPACE(c)) { - beg = ptr - bptr; - } - else { - end = ptr - bptr; - skip = 0; - if (lim_p && lim <= i) break; - } - } - else if (ISSPACE(c)) { - mrb_ary_push(mrb, result, str_subseq(mrb, str, beg, end-beg)); - mrb_gc_arena_restore(mrb, ai); - skip = 1; - beg = ptr - bptr; - if (lim_p) ++i; - } - else { - end = ptr - bptr; - } - } - } - else if (split_type == string) { - char *ptr = RSTRING_PTR(str); // s->as.ary - char *temp = ptr; - char *eptr = RSTRING_END(str); - mrb_int slen = RSTRING_LEN(spat); - - if (slen == 0) { - int ai = mrb_gc_arena_save(mrb); - while (ptr < eptr) { - mrb_ary_push(mrb, result, str_subseq(mrb, str, ptr-temp, 1)); - mrb_gc_arena_restore(mrb, ai); - ptr++; - if (lim_p && lim <= ++i) break; - } - } - else { - char *sptr = RSTRING_PTR(spat); - int ai = mrb_gc_arena_save(mrb); - - while (ptr < eptr && - (end = mrb_memsearch(sptr, slen, ptr, eptr - ptr)) >= 0) { - /* mrb_ary_push(mrb, result, str_subseq(mrb, str, ptr - temp, end)); */ - mrb_ary_push(mrb, result, mrb_str_new(mrb, ptr, end)); - mrb_gc_arena_restore(mrb, ai); - ptr += end + slen; - if (lim_p && lim <= ++i) break; - } - } - beg = ptr - temp; - } - else { - mrb_noregexp(mrb, str); - } - if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) { - if (RSTRING_LEN(str) == beg) { - tmp = mrb_str_new_lit(mrb, ""); - } - else { - tmp = mrb_str_new(mrb, RSTRING_PTR(str)+beg, RSTRING_LEN(str)-beg); - } - mrb_ary_push(mrb, result, tmp); - } - if (!lim_p && lim == 0) { - mrb_int len; - while ((len = RARRAY_LEN(result)) > 0 && - (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0)) - mrb_ary_pop(mrb, result); - } - - return result; -} - -static mrb_value -mrb_str_chr(mrb_state *mrb, mrb_value self) -{ - return str_substr(mrb, self, 0, 1); -} - -static mrb_value -mrb_str_chars(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - mrb_value blk; - int ai; - mrb_int len; - mrb_value arg; - char *p = RSTRING_PTR(self); - char *e = p + RSTRING_LEN(self); - - mrb_get_args(mrb, "&", &blk); - - result = mrb_ary_new(mrb); - - if (!mrb_nil_p(blk)) { - while (p < e) { - len = utf8len((unsigned char*) p); - arg = mrb_str_new(mrb, p, len); - mrb_yield_argv(mrb, blk, 1, &arg); - p += len; - } - return self; - } - while (p < e) { - ai = mrb_gc_arena_save(mrb); - len = utf8len((unsigned char*) p); - mrb_ary_push(mrb, result, mrb_str_new(mrb, p, len)); - mrb_gc_arena_restore(mrb, ai); - p += len; - } - return result; -} - -static mrb_value -mrb_str_codepoints(mrb_state *mrb, mrb_value self) -{ - mrb_value result; - mrb_value blk; - int ai; - mrb_int len; - mrb_value arg; - char *p = RSTRING_PTR(self); - char *e = p + RSTRING_LEN(self); - - mrb_get_args(mrb, "&", &blk); - - result = mrb_ary_new(mrb); - - if (!mrb_nil_p(blk)) { - while (p < e) { - len = utf8len((unsigned char*) p); - arg = mrb_fixnum_value(utf8code((unsigned char*) p)); - mrb_yield_argv(mrb, blk, 1, &arg); - p += len; - } - return self; - } - while (p < e) { - ai = mrb_gc_arena_save(mrb); - len = utf8len((unsigned char*) p); - mrb_ary_push(mrb, result, mrb_fixnum_value(utf8code((unsigned char*) p))); - mrb_gc_arena_restore(mrb, ai); - p += len; - } - return result; -} - -void -mrb_mruby_string_utf8_gem_init(mrb_state* mrb) -{ - struct RClass * s = mrb->string_class; - - mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "length", mrb_str_size, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ANY()); - mrb_define_method(mrb, s, "[]", mrb_str_aref_m, MRB_ARGS_ANY()); - mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); - mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); - mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, MRB_ARGS_ANY()); - mrb_define_method(mrb, s, "chr", mrb_str_chr, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "chars", mrb_str_chars, MRB_ARGS_NONE()); - mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "each_char"), mrb_intern_lit(mrb, "chars")); - mrb_define_method(mrb, s, "codepoints", mrb_str_codepoints, MRB_ARGS_NONE()); - mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "each_codepoint"), mrb_intern_lit(mrb, "codepoints")); - - mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE()); -} - -void -mrb_mruby_string_utf8_gem_final(mrb_state* mrb) -{ -} diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-utf8/test/string.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-utf8/test/string.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-string-utf8/test/string.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-string-utf8/test/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -## -# String(utf8) Test - -assert('String#[]') do - assert_equal "ち", "こんにちは世界"[3] - assert_equal nil, "こんにちは世界"[20] - assert_equal "世", "こんにちは世界"[-2] - assert_equal "世界", "こんにちは世界"[-2..-1] - assert_equal "んに", "こんにちは世界"[1,2] - assert_equal "世", "こんにちは世界"["世"] - assert_equal 'b', 'abc'[1.1] -end - -assert('String#reverse', '15.2.10.5.29') do - a = 'こんにちは世界!' - a.reverse - - assert_equal 'こんにちは世界!', a - assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse -end - -assert('String#reverse!', '15.2.10.5.30') do - a = 'こんにちは世界!' - a.reverse! - - assert_equal '!界世はちにんこ', a - assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse! -end - -assert('Invalid sequence') do - assert_equal 5, "\xF8\x88\x80\x80\x80".size - assert_equal 6, "\xFC\x84\x80\x80\x80\x80".size -end - -assert('String#size') do - str = 'こんにちは世界!' - assert_equal 8, str.size - assert_not_equal str.bytesize, str.size - assert_equal 2, str[1, 2].size -end - -assert('String#index') do - str = "こんにちは世界!\nこんにちは世界!" - assert_nil str.index('さ') - assert_equal 3, str.index('ち') - assert_equal 12, str.index('ち', 10) - assert_equal nil, str.index("さ") -end - -assert('String#ord') do - got = "こんにちは世界!".split('').map {|x| x.ord} - expect = [0x3053,0x3093,0x306b,0x3061,0x306f,0x4e16,0x754c,0x21] - assert_equal expect, got -end - -assert('String#split') do - got = "こんにちは世界!".split('') - assert_equal ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'], got - got = "こんにちは世界!".split('に') - assert_equal ['こん', 'ちは世界!'], got -end - -assert('String#rindex') do - str = "こんにちは世界!\nこんにちは世界!" - assert_nil str.index('さ') - assert_equal 12, str.rindex('ち') - assert_equal 3, str.rindex('ち', 10) -end - -assert('String#chr(utf-8)') do - assert_equal "こ", "こんにちは世界!".chr -end - -assert('String#chars') do - expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'] - assert_equal expect, "こんにちは世界!".chars - s = "" - "こんにちは世界!".chars do |x| - s += x - end - assert_equal "こんにちは世界!", s -end - -assert('String#each_char') do - expect = ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'] - s = "" - "こんにちは世界!".each_char do |x| - s += x - end - assert_equal "こんにちは世界!", s -end -assert('String#codepoints') do - expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] - assert_equal expect, "こんにちは世界!".codepoints - cp = [] - "こんにちは世界!".codepoints do |x| - cp << x - end - assert_equal expect, cp -end - -assert('String#each_codepoint') do - expect = [12371, 12435, 12395, 12385, 12399, 19990, 30028, 33] - cp = [] - "こんにちは世界!".each_codepoint do |x| - cp << x - end - assert_equal expect, cp -end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-struct/mrblib/struct.rb mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-struct/mrblib/struct.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-struct/mrblib/struct.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-struct/mrblib/struct.rb 2016-03-14 00:35:53.000000000 +0000 @@ -47,7 +47,12 @@ end def _inspect - str = "# +#include +#include +#include +#include +#include +#include #define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len #define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr @@ -40,9 +40,9 @@ } static mrb_value -mrb_struct_s_members(mrb_state *mrb, mrb_value klass) +struct_s_members(mrb_state *mrb, struct RClass *klass) { - mrb_value members = struct_ivar_get(mrb, klass, mrb_intern_lit(mrb, "__members__")); + mrb_value members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__")); if (mrb_nil_p(members)) { mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct"); @@ -54,15 +54,16 @@ } static mrb_value -mrb_struct_members(mrb_state *mrb, mrb_value s) +struct_members(mrb_state *mrb, mrb_value s) { - mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s))); - if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) { - if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { - mrb_raisef(mrb, E_TYPE_ERROR, - "struct size differs (%S required %S given)", - mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); - } + mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s)); + if (!mrb_array_p(s)) { + mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); + } + if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { + mrb_raisef(mrb, E_TYPE_ERROR, + "struct size differs (%S required %S given)", + mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); } return members; } @@ -72,7 +73,7 @@ { mrb_value members, ary; - members = mrb_struct_s_members(mrb, klass); + members = struct_s_members(mrb, mrb_class_ptr(klass)); ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members)); mrb_ary_replace(mrb, ary, members); return ary; @@ -92,7 +93,7 @@ */ static mrb_value -mrb_struct_members_m(mrb_state *mrb, mrb_value obj) +mrb_struct_members(mrb_state *mrb, mrb_value obj) { return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj))); } @@ -105,7 +106,7 @@ mrb_int i, len; ptr = RSTRUCT_PTR(obj); - members = mrb_struct_members(mrb, obj); + members = struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); slot = mrb_symbol_value(id); len = RARRAY_LEN(members); @@ -183,7 +184,7 @@ name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen); mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */ - members = mrb_struct_members(mrb, obj); + members = struct_members(mrb, obj); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); ptr = RSTRUCT_PTR(obj); @@ -402,7 +403,7 @@ } static mrb_value -mrb_struct_initialize_m(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value self) +mrb_struct_initialize(mrb_state *mrb, mrb_value self) { mrb_value *argv; mrb_int argc; @@ -417,7 +418,6 @@ mrb_struct_init_copy(mrb_state *mrb, mrb_value copy) { mrb_value s; - mrb_int i, len; mrb_get_args(mrb, "o", &s); @@ -428,13 +428,7 @@ if (!mrb_array_p(s)) { mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct"); } - if (RSTRUCT_LEN(copy) != RSTRUCT_LEN(s)) { - mrb_raise(mrb, E_TYPE_ERROR, "struct size mismatch"); - } - len = RSTRUCT_LEN(copy); - for (i = 0; i < len; i++) { - mrb_ary_set(mrb, copy, i, RSTRUCT_PTR(s)[i]); - } + mrb_ary_replace(mrb, copy, s); return copy; } @@ -446,7 +440,7 @@ mrb_int i, len; ptr = RSTRUCT_PTR(s); - members = mrb_struct_members(mrb, s); + members = struct_members(mrb, s); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i", cc.inspect + assert_equal "#", cc.inspect end assert('Struct#length, Struct#size') do diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-symbol-ext/src/symbol.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-symbol-ext/src/symbol.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-symbol-ext/src/symbol.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-symbol-ext/src/symbol.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ -#include "mruby.h" -#include "mruby/khash.h" -#include "mruby/array.h" +#include +#include +#include typedef struct symbol_name { size_t len; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-test/driver.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-test/driver.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-test/driver.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-test/driver.c 2016-03-14 00:35:53.000000000 +0000 @@ -10,13 +10,13 @@ #include #include -#include "mruby.h" -#include "mruby/proc.h" -#include "mruby/data.h" -#include "mruby/compile.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/array.h" +#include +#include +#include +#include +#include +#include +#include void mrb_init_mrbtest(mrb_state *); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-test/init_mrbtest.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-test/init_mrbtest.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-test/init_mrbtest.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-test/init_mrbtest.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,10 +1,9 @@ #include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/variable.h" +#include +#include +#include extern const uint8_t mrbtest_assert_irep[]; -extern const uint8_t mrbtest_irep[]; void mrbgemtest_init(mrb_state* mrb); void mrb_init_test_driver(mrb_state* mrb, mrb_bool verbose); @@ -24,7 +23,6 @@ } mrb_init_test_driver(core_test, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose")))); mrb_load_irep(core_test, mrbtest_assert_irep); - mrb_load_irep(core_test, mrbtest_irep); mrb_t_pass_result(mrb, core_test); #ifndef DISABLE_GEMS diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-test/mrbgem.rake mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-test/mrbgem.rake --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-test/mrbgem.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-test/mrbgem.rake 2016-03-14 00:35:53.000000000 +0000 @@ -6,9 +6,10 @@ build.bins << 'mrbtest' spec.add_dependency('mruby-compiler', :core => 'mruby-compiler') + spec.test_rbfiles = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb") + clib = "#{build_dir}/mrbtest.c" mlib = clib.ext(exts.object) - mrbs = Dir.glob("#{MRUBY_ROOT}/test/t/*.rb") exec = exefile("#{build.build_dir}/bin/mrbtest") libmruby = libfile("#{build.build_dir}/lib/libmruby") @@ -26,7 +27,7 @@ mrbtest_objs << assert_lib file assert_lib => assert_c - file assert_c => [build.mrbcfile, assert_rb] do |t| + file assert_c => assert_rb do |t| open(t.name, 'w') do |f| mrbc.run f, assert_rb, 'mrbtest_assert_irep' end @@ -40,7 +41,7 @@ dep_list = build.gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions) file test_rbobj => g.test_rbireps - file g.test_rbireps => [g.test_rbfiles].flatten + [File.join(g.dir, 'mrbgem.rake'), g.build.mrbcfile, "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"] do |t| + file g.test_rbireps => [g.test_rbfiles].flatten do |t| FileUtils.mkdir_p File.dirname(t.name) open(t.name, 'w') do |f| g.print_gem_test_header(f) @@ -145,8 +146,21 @@ end init = "#{spec.dir}/init_mrbtest.c" + + # store the last gem selection and make the re-build + # of the test gem depending on a change to the gem + # selection + active_gems = "#{build_dir}/active_gems.lst" + FileUtils.mkdir_p File.dirname(active_gems) + open(active_gems, 'w+') do |f| + build.gems.each do |g| + f.puts g.name + end + end + file clib => active_gems + file mlib => clib - file clib => [build.mrbcfile, init] do |t| + file clib => init do |t| _pp "GEN", "*.rb", "#{clib.relative_path}" FileUtils.mkdir_p File.dirname(clib) open(clib, 'w') do |f| @@ -160,7 +174,6 @@ f.puts %Q[ */] f.puts %Q[] f.puts IO.read(init) - mrbc.run f, mrbs, 'mrbtest_irep' build.gems.each do |g| f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);] end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-time/src/time.c mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-time/src/time.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrbgems/mruby-time/src/time.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrbgems/mruby-time/src/time.c 2016-03-14 00:35:53.000000000 +0000 @@ -7,9 +7,19 @@ #include #include #include -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/data.h" +#include +#include +#include + +#if _MSC_VER < 1800 +double round(double x) { + if (x >= 0.0) { + return (double)((int)(x + 0.5)); + } else { + return (double)((int)(x - 0.5)); + } +} +#endif #if !defined(__MINGW64__) && defined(_WIN32) # define llround(x) round(x) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrblib/array.rb mruby-1.2.0+20160315+git4f20d58a/mrblib/array.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrblib/array.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrblib/array.rb 2016-03-14 00:35:53.000000000 +0000 @@ -12,15 +12,10 @@ def each(&block) return to_enum :each unless block_given? - idx, length = -1, self.length-1 - while idx < length and length <= self.length and length = self.length-1 - elm = self[idx += 1] - unless elm - if elm.nil? and length >= self.length - break - end - end - block.call(elm) + idx = 0 + while idx < length + block.call(self[idx]) + idx += 1 end self end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrblib/enum.rb mruby-1.2.0+20160315+git4f20d58a/mrblib/enum.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrblib/enum.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrblib/enum.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,17 +1,16 @@ ## # Enumerable # -# ISO 15.3.2 +# The Enumerable mixin provides collection classes with +# several traversal and searching methods, and with the ability to +# sort. The class must provide a method `each`, which +# yields successive members of the collection. If +# {Enumerable#max}, {#min}, or +# {#sort} is used, the objects in the collection must also +# implement a meaningful `<=>` operator, as these methods +# rely on an ordering between members of the collection. # -# The Enumerable mixin provides collection classes with -# several traversal and searching methods, and with the ability to -# sort. The class must provide a method each, which -# yields successive members of the collection. If -# Enumerable#max, #min, or -# #sort is used, the objects in the collection must also -# implement a meaningful <=> operator, as these methods -# rely on an ordering between members of the collection. - +# @ISO 15.3.2 module Enumerable ## @@ -384,7 +383,7 @@ h = 12347 i = 0 self.each do |e| - n = e.hash << (i % 16) + n = (e.hash & (0x7fffffff >> (i % 16))) << (i % 16) h ^= n i += 1 end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrblib/hash.rb mruby-1.2.0+20160315+git4f20d58a/mrblib/hash.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrblib/hash.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrblib/hash.rb 2016-03-14 00:35:53.000000000 +0000 @@ -74,8 +74,8 @@ # # If no block is given, an enumerator is returned instead. # - # h = { "a" => 100, "b" => 200 } - # h.each {|key, value| puts "#{key} is #{value}" } + # h = { "a" => 100, "b" => 200 } + # h.each {|key, value| puts "#{key} is #{value}" } # # produces: # @@ -154,6 +154,7 @@ # # ISO 15.2.13.4.23 def replace(hash) + raise TypeError, "can't convert argument into Hash" unless hash.respond_to?(:to_hash) self.clear hash = hash.to_hash hash.each_key{|k| @@ -319,6 +320,29 @@ h end + ## + # call-seq: + # hsh.rehash -> hsh + # + # Rebuilds the hash based on the current hash values for each key. If + # values of key objects have changed since they were inserted, this + # method will reindex hsh. + # + # h = {"AAA" => "b"} + # h.keys[0].chop! + # h #=> {"AA"=>"b"} + # h["AA"] #=> nil + # h.rehash #=> {"AA"=>"b"} + # h["AA"] #=> "b" + # + def rehash + h = {} + self.each{|k,v| + h[k] = v + } + self.replace(h) + end + def __update(h) h.each_key{|k| self[k] = h[k]} self diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrblib/init_mrblib.c mruby-1.2.0+20160315+git4f20d58a/mrblib/init_mrblib.c --- mruby-1.1.0+20150906+git1cbbb7e1/mrblib/init_mrblib.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrblib/init_mrblib.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,5 +1,5 @@ -#include "mruby.h" -#include "mruby/irep.h" +#include +#include extern const uint8_t mrblib_irep[]; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrblib/kernel.rb mruby-1.2.0+20160315+git4f20d58a/mrblib/kernel.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrblib/kernel.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrblib/kernel.rb 2016-03-14 00:35:53.000000000 +0000 @@ -30,8 +30,8 @@ while true yield end - rescue StopIteration - nil + rescue StopIteration => e + e.result end # 11.4.4 Step c) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mrblib/string.rb mruby-1.2.0+20160315+git4f20d58a/mrblib/string.rb --- mruby-1.1.0+20150906+git1cbbb7e1/mrblib/string.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mrblib/string.rb 2016-03-14 00:35:53.000000000 +0000 @@ -10,9 +10,8 @@ # # ISO 15.2.10.5.15 def each_line(&block) - # expect that str.index accepts an Integer for 1st argument as a byte data offset = 0 - while pos = self.index(0x0a, offset) + while pos = self.index("\n", offset) block.call(self[offset, pos + 1 - offset]) offset = pos + 1 end @@ -154,13 +153,48 @@ end ## - # Modify +self+ by replacing the content of +self+ - # at the position +pos+ with +value+. - def []=(pos, value) - pos += self.length if pos < 0 - b = self[0, pos] - a = self[pos + 1..-1] - self.replace([b, value, a].join('')) + # Modify +self+ by replacing the content of +self+. + # The portion of the string affected is determined using the same criteria as +String#[]+. + def []=(*args) + anum = args.size + if anum == 2 + pos, value = args + if pos.kind_of? String + posnum = self.index(pos) + if posnum + b = self[0, posnum.to_i] + a = self[(posnum + pos.length)..-1] + self.replace([b, value, a].join('')) + return value + else + raise IndexError, "string not matched" + end + else + pos += self.length if pos < 0 + if pos < 0 || pos > self.length + raise IndexError, "index #{args[0]} out of string" + end + b = self[0, pos.to_i] + a = self[pos + 1..-1] + self.replace([b, value, a].join('')) + return value + end + elsif anum == 3 + pos, len, value = args + pos += self.length if pos < 0 + if pos < 0 || pos > self.length + raise IndexError, "index #{args[0]} out of string" + end + if len < 0 + raise IndexError, "negative length #{len}" + end + b = self[0, pos.to_i] + a = self[pos + len..-1] + self.replace([b, value, a].join('')) + return value + else + raise ArgumentError, "wrong number of arguments (#{anum} for 2..3)" + end end ## diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/mruby-source.gemspec mruby-1.2.0+20160315+git4f20d58a/mruby-source.gemspec --- mruby-1.1.0+20150906+git1cbbb7e1/mruby-source.gemspec 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/mruby-source.gemspec 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,18 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'mruby/source' + +Gem::Specification.new do |spec| + spec.name = "mruby-source" + spec.version = MRuby::Source::MRUBY_VERSION + spec.authors = [ MRuby::Source::MRUBY_AUTHOR ] + + spec.summary = %q{MRuby source code wrapper.} + spec.description = %q{MRuby source code wrapper for use with Ruby libs.} + spec.homepage = "http://www.mruby.org/" + spec.license = "MIT" + + spec.files = `git ls-files -z`.split("\x0") + spec.require_paths = ["lib"] +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/Rakefile mruby-1.2.0+20160315+git4f20d58a/Rakefile --- mruby-1.1.0+20150906+git1cbbb7e1/Rakefile 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/Rakefile 2016-03-14 00:35:53.000000000 +0000 @@ -32,7 +32,7 @@ # generic build targets, rules task :default => :all -bin_path = "#{MRUBY_ROOT}/bin" +bin_path = ENV['INSTALL_DIR'] || "#{MRUBY_ROOT}/bin" FileUtils.mkdir_p bin_path, { :verbose => $verbose } depfiles = MRuby.targets['host'].bins.map do |bin| @@ -71,7 +71,7 @@ end if target == MRuby.targets['host'] - install_path = MRuby.targets['host'].exefile("#{MRUBY_ROOT}/bin/#{bin}") + install_path = MRuby.targets['host'].exefile("#{bin_path}/#{bin}") file install_path => exec do |t| FileUtils.rm_f t.name, { :verbose => $verbose } @@ -80,7 +80,7 @@ depfiles += [ install_path ] elsif target == MRuby.targets['host-debug'] unless MRuby.targets['host'].gems.map {|g| g.bins}.include?([bin]) - install_path = MRuby.targets['host-debug'].exefile("#{MRUBY_ROOT}/bin/#{bin}") + install_path = MRuby.targets['host-debug'].exefile("#{bin_path}/#{bin}") file install_path => exec do |t| FileUtils.rm_f t.name, { :verbose => $verbose } @@ -139,5 +139,10 @@ desc 'generate document' task :doc do - load "#{MRUBY_ROOT}/doc/language/generator.rb" + begin + sh "mrbdoc" + rescue + puts "ERROR: To generate documents, you should install yard-mruby gem." + puts " $ gem install yard-mruby" + end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/README.md mruby-1.2.0+20160315+git4f20d58a/README.md --- mruby-1.1.0+20150906+git1cbbb7e1/README.md 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/README.md 2016-03-14 00:35:53.000000000 +0000 @@ -1,9 +1,9 @@ [![Build Status][build-status-img]][travis-ci] -## What's mruby +## What is mruby mruby is the lightweight implementation of the Ruby language complying to (part -of) the [ISO standard][ISO-standard]. Its syntax is Ruby 1.9 compatible. +of) the [ISO standard][ISO-standard]. Its syntax is Ruby 1.9 compatible. mruby can be linked and embedded within your application. We provide the interpreter program "mruby" and the interactive mruby shell "mirb" as examples. @@ -15,39 +15,30 @@ This achievement was sponsored by the Regional Innovation Creation R&D Programs of the Ministry of Economy, Trade and Industry of Japan. - ## How to get mruby -The stable version 1.1.0 of mruby can be downloaded via the following URL: - - https://github.com/mruby/mruby/archive/1.1.0.zip +The stable version 1.2.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.2.0.zip](https://github.com/mruby/mruby/archive/1.2.0.zip) -The latest development version of mruby can be downloaded via the following URL: - - https://github.com/mruby/mruby/zipball/master +The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master) The trunk of the mruby source tree can be checked out with the following command: $ git clone https://github.com/mruby/mruby.git +You can also install and compile mruby using [ruby-install](https://github.com/postmodern/ruby-install), [ruby-build](https://github.com/rbenv/ruby-build) or [rvm](https://github.com/rvm/rvm). ## mruby home-page -The URL of the mruby home-page is: - - http://www.mruby.org/ - +The URL of the mruby home-page is: [http://www.mruby.org](http://www.mruby.org). ## Mailing list -We don't have mailing list, use GitHub forum . - +We don't have a mailing list, but you can use [GitHub issues](https://github.com/mruby/mruby). ## How to compile and install (mruby and gems) -See the [doc/compile/README.md](doc/compile/README.md) file. - +See the [doc/guides/compile.md](doc/guides/compile.md) file. ## Running Tests @@ -59,37 +50,16 @@ $ ruby ./minirake test - ## How to customize mruby (mrbgems) mruby contains a package manager called *mrbgems*. To create extensions in C and/or Ruby you should create a *GEM*. For a documentation of how to -use mrbgems consult the file [doc/mrbgems/README.md](doc/mrbgems/README.md). For example code of +use mrbgems consult the file [doc/guides/mrbgems.md](doc/guides/mrbgems.md). For example code of how to use mrbgems look into the folder *examples/mrbgems/*. - ## License -Copyright (c) 2015 mruby developers - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - +mruby is released under the [MIT License](MITL). ## Note for License @@ -108,17 +78,15 @@ Please ask us if you want to distribute your code under another license. - ## How to Contribute -See the [contribution guidelines][contribution-guidelines] then send a pull +See the [contribution guidelines][contribution-guidelines], and then send a pull request to . 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, please include an update to the AUTHORS file in your pull request. [ISO-standard]: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=59579 -[build-status-img]: https://travis-ci.org/mruby/mruby.png?branch=master -[contribution-guidelines]: https://github.com/mruby/mruby/blob/master/CONTRIBUTING.md +[build-status-img]: https://travis-ci.org/mruby/mruby.svg?branch=master +[contribution-guidelines]: CONTRIBUTING.md [travis-ci]: https://travis-ci.org/mruby/mruby - diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/array.c mruby-1.2.0+20160315+git4f20d58a/src/array.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/array.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/array.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,11 +4,11 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/string.h" -#include "mruby/range.h" +#include +#include +#include +#include +#include #include "value_array.h" #define ARY_DEFAULT_LEN 4 @@ -1068,7 +1068,7 @@ { struct RClass *a; - a = mrb->array_class = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */ + mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */ MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY); mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */ @@ -1101,4 +1101,5 @@ mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1)); mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */ } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/backtrace.c mruby-1.2.0+20160315+git4f20d58a/src/backtrace.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/backtrace.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/backtrace.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,28 +4,38 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/variable.h" -#include "mruby/proc.h" -#include "mruby/array.h" -#include "mruby/string.h" -#include "mruby/class.h" -#include "mruby/debug.h" -#include "mruby/error.h" -#include "mruby/numeric.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct backtrace_location_raw { + int i; + int lineno; + const char *filename; + mrb_sym method_id; + char sep; + struct RClass *klass; +}; struct backtrace_location { int i; int lineno; const char *filename; const char *method; - const char *sep; + char sep; const char *class_name; }; +typedef void (*each_backtrace_func)(mrb_state*, struct backtrace_location_raw*, void*); typedef void (*output_stream_func)(mrb_state*, struct backtrace_location*, void*); -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO struct print_backtrace_args { FILE *stream; @@ -48,7 +58,7 @@ if (loc->method) { if (loc->class_name) { - fprintf(args->stream, ":in %s%s%s", loc->class_name, loc->sep, loc->method); + fprintf(args->stream, ":in %s%c%s", loc->class_name, loc->sep, loc->method); } else { fprintf(args->stream, ":in %s", loc->method); @@ -78,7 +88,7 @@ if (loc->class_name) { mrb_str_cat_cstr(mrb, str, loc->class_name); - mrb_str_cat_cstr(mrb, str, loc->sep); + mrb_str_cat(mrb, str, &loc->sep, 1); } mrb_str_cat_cstr(mrb, str, loc->method); @@ -89,7 +99,7 @@ } static void -output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *data) +each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func func, void *data) { int i; @@ -97,7 +107,7 @@ ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { - struct backtrace_location loc; + struct backtrace_location_raw loc; mrb_callinfo *ci; mrb_irep *irep; mrb_code *pc; @@ -124,23 +134,53 @@ if (loc.lineno == -1) continue; if (ci->target_class == ci->proc->target_class) { - loc.sep = "."; + loc.sep = '.'; } else { - loc.sep = "#"; + loc.sep = '#'; } if (!loc.filename) { loc.filename = "(unknown)"; } - loc.method = mrb_sym2name(mrb, ci->mid); - loc.class_name = mrb_class_name(mrb, ci->proc->target_class); + loc.method_id = ci->mid; + loc.klass = ci->proc->target_class; loc.i = i; func(mrb, &loc, data); } } +struct output_backtrace_args { + output_stream_func func; + void *data; +}; + +static void +output_backtrace_i(mrb_state *mrb, struct backtrace_location_raw *loc_raw, void *data) +{ + struct backtrace_location loc; + struct output_backtrace_args *args = data; + + loc.i = loc_raw->i; + loc.lineno = loc_raw->lineno; + loc.filename = loc_raw->filename; + loc.method = mrb_sym2name(mrb, loc_raw->method_id); + loc.sep = loc_raw->sep; + loc.class_name = mrb_class_name(mrb, loc_raw->klass); + + args->func(mrb, &loc, args->data); +} + +static void +output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *data) +{ + struct output_backtrace_args args; + args.func = func; + args.data = data; + each_backtrace(mrb, ciidx, pc0, output_backtrace_i, &args); +} + static void exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream) { @@ -165,20 +205,78 @@ overwritten. So invoke these functions just after detecting exceptions. */ -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO + +static void +print_backtrace(mrb_state *mrb, mrb_value backtrace) +{ + int i, n; + FILE *stream = stderr; + + fprintf(stream, "trace:\n"); + + n = RARRAY_LEN(backtrace); + for (i = 0; i < n; i++) { + mrb_value entry = RARRAY_PTR(backtrace)[i]; + + fprintf(stream, "\t[%d] %.*s\n", i, (int)RSTRING_LEN(entry), RSTRING_PTR(entry)); + } +} + +static void +print_backtrace_saved(mrb_state *mrb) +{ + int i; + FILE *stream = stderr; + + fprintf(stream, "trace:\n"); + for (i = 0; i < mrb->backtrace.n; i++) { + mrb_backtrace_entry *entry; + + entry = &(mrb->backtrace.entries[i]); + fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno); + + if (entry->method_id != 0) { + const char *method_name; + + method_name = mrb_sym2name(mrb, entry->method_id); + if (entry->klass) { + fprintf(stream, ":in %s%c%s", + mrb_class_name(mrb, entry->klass), + entry->sep, + method_name); + } + else { + fprintf(stream, ":in %s", method_name); + } + } + + fprintf(stream, "\n"); + } +} MRB_API void mrb_print_backtrace(mrb_state *mrb) { - struct print_backtrace_args args; + mrb_value backtrace; if (!mrb->exc || mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_SYSSTACK_ERROR)) { return; } - args.stream = stderr; - args.tracehead = TRUE; - exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)&args); + backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace")); + if (!mrb_nil_p(backtrace)) { + print_backtrace(mrb, backtrace); + } + else if (mrb->backtrace.n > 0) { + print_backtrace_saved(mrb); + } + else { + struct print_backtrace_args args; + args.stream = stderr; + args.tracehead = TRUE; + exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)&args); + } } #else @@ -215,3 +313,112 @@ return ary; } + +void +mrb_free_backtrace(mrb_state *mrb) +{ + mrb->backtrace.exc = 0; + mrb->backtrace.n = 0; + mrb->backtrace.n_allocated = 0; + mrb_free(mrb, mrb->backtrace.entries); +} + +static void +save_backtrace_i(mrb_state *mrb, + struct backtrace_location_raw *loc_raw, + void *data) +{ + mrb_backtrace_entry *entry; + + if (mrb->backtrace.n >= mrb->backtrace.n_allocated) { + int new_n_allocated; + if (mrb->backtrace.n_allocated == 0) { + new_n_allocated = 8; + } + else { + new_n_allocated = mrb->backtrace.n_allocated * 2; + } + mrb->backtrace.entries = + mrb_realloc(mrb, + mrb->backtrace.entries, + sizeof(mrb_backtrace_entry) * new_n_allocated); + mrb->backtrace.n_allocated = new_n_allocated; + } + + entry = &mrb->backtrace.entries[mrb->backtrace.n]; + entry->filename = loc_raw->filename; + entry->lineno = loc_raw->lineno; + entry->klass = loc_raw->klass; + entry->sep = loc_raw->sep; + entry->method_id = loc_raw->method_id; + + mrb->backtrace.n++; +} + +void +mrb_save_backtrace(mrb_state *mrb) +{ + mrb_value lastpc; + mrb_code *code; + mrb_int ciidx; + + mrb->backtrace.n = 0; + mrb->backtrace.exc = 0; + + if (!mrb->exc) + return; + + mrb->backtrace.exc = mrb->exc; + + lastpc = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc")); + if (mrb_nil_p(lastpc)) { + code = NULL; + } + else { + code = (mrb_code*)mrb_cptr(lastpc); + } + + ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"))); + + each_backtrace(mrb, ciidx, code, save_backtrace_i, NULL); +} + +mrb_value +mrb_restore_backtrace(mrb_state *mrb) +{ + int i; + mrb_value backtrace; + + backtrace = mrb_ary_new(mrb); + for (i = 0; i < mrb->backtrace.n; i++) { + int ai; + mrb_backtrace_entry *entry; + mrb_value mrb_entry; + + ai = mrb_gc_arena_save(mrb); + entry = &(mrb->backtrace.entries[i]); + + mrb_entry = mrb_str_new_cstr(mrb, entry->filename); + mrb_str_cat_lit(mrb, mrb_entry, ":"); + mrb_str_concat(mrb, mrb_entry, + mrb_fixnum_to_str(mrb, + mrb_fixnum_value(entry->lineno), + 10)); + if (entry->method_id != 0) { + mrb_str_cat_lit(mrb, mrb_entry, ":in "); + + if (entry->klass) { + mrb_str_cat_cstr(mrb, mrb_entry, mrb_class_name(mrb, entry->klass)); + mrb_str_cat(mrb, mrb_entry, &entry->sep, 1); + } + + mrb_str_cat_cstr(mrb, mrb_entry, mrb_sym2name(mrb, entry->method_id)); + } + + mrb_ary_push(mrb, backtrace, mrb_entry); + + mrb_gc_arena_restore(mrb, ai); + } + + return backtrace; +} diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/class.c mruby-1.2.0+20160315+git4f20d58a/src/class.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/class.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/class.c 2016-03-14 00:35:53.000000000 +0000 @@ -5,15 +5,15 @@ */ #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/numeric.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" -#include "mruby/data.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal) @@ -429,6 +429,8 @@ else { mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0); mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj); + /* not reached */ + return 0; } } @@ -466,9 +468,10 @@ { char c; int i = 0; - mrb_value *sp = mrb->c->stack + 1; va_list ap; int argc = mrb->c->ci->argc; + int arg_i = 0; + mrb_bool array_argv; mrb_bool opt = FALSE; mrb_bool given = TRUE; @@ -477,8 +480,14 @@ struct RArray *a = mrb_ary_ptr(mrb->c->stack[1]); argc = a->len; - sp = a->ptr; + array_argv = TRUE; + } else { + array_argv = FALSE; } + +#define ARGV \ + (array_argv ? mrb_ary_ptr(mrb->c->stack[1])->ptr : (mrb->c->stack + 1)) + while ((c = *format++)) { switch (c) { case '|': case '*': case '&': case '?': @@ -502,7 +511,7 @@ p = va_arg(ap, mrb_value*); if (i < argc) { - *p = *sp++; + *p = ARGV[arg_i++]; i++; } } @@ -515,7 +524,7 @@ if (i < argc) { mrb_value ss; - ss = *sp++; + ss = ARGV[arg_i++]; switch (mrb_type(ss)) { case MRB_TT_CLASS: case MRB_TT_MODULE: @@ -537,14 +546,14 @@ p = va_arg(ap, mrb_value*); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { - *p = *sp++; + if (i < argc && mrb_nil_p(ARGV[arg_i])) { + *p = ARGV[arg_i++]; i++; break; } } if (i < argc) { - *p = to_str(mrb, *sp++); + *p = to_str(mrb, ARGV[arg_i++]); i++; } } @@ -556,14 +565,14 @@ p = va_arg(ap, mrb_value*); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { - *p = *sp++; + if (i < argc && mrb_nil_p(ARGV[arg_i])) { + *p = ARGV[arg_i++]; i++; break; } } if (i < argc) { - *p = to_ary(mrb, *sp++); + *p = to_ary(mrb, ARGV[arg_i++]); i++; } } @@ -575,14 +584,14 @@ p = va_arg(ap, mrb_value*); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { - *p = *sp++; + if (i < argc && mrb_nil_p(ARGV[arg_i])) { + *p = ARGV[arg_i++]; i++; break; } } if (i < argc) { - *p = to_hash(mrb, *sp++); + *p = to_hash(mrb, ARGV[arg_i++]); i++; } } @@ -597,7 +606,7 @@ pl = va_arg(ap, mrb_int*); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { + if (i < argc && mrb_nil_p(ARGV[arg_i])) { *ps = NULL; *pl = 0; i++; @@ -605,7 +614,7 @@ } } if (i < argc) { - ss = to_str(mrb, *sp++); + ss = to_str(mrb, ARGV[arg_i++]); *ps = RSTRING_PTR(ss); *pl = RSTRING_LEN(ss); i++; @@ -620,14 +629,14 @@ ps = va_arg(ap, const char**); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { + if (i < argc && mrb_nil_p(ARGV[arg_i])) { *ps = NULL; - i++; + i++; arg_i++; break; } } if (i < argc) { - ss = to_str(mrb, *sp++); + ss = to_str(mrb, ARGV[arg_i++]); *ps = mrb_string_value_cstr(mrb, &ss); i++; } @@ -644,15 +653,15 @@ pl = va_arg(ap, mrb_int*); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { + if (i < argc && mrb_nil_p(ARGV[arg_i])) { *pb = 0; *pl = 0; - i++; + i++; arg_i++; break; } } if (i < argc) { - aa = to_ary(mrb, *sp++); + aa = to_ary(mrb, ARGV[arg_i++]); a = mrb_ary_ptr(aa); *pb = a->ptr; *pl = a->len; @@ -666,8 +675,8 @@ p = va_arg(ap, mrb_float*); if (i < argc) { - *p = mrb_to_flo(mrb, *sp); - sp++; + *p = mrb_to_flo(mrb, ARGV[arg_i]); + arg_i++; i++; } } @@ -678,13 +687,13 @@ p = va_arg(ap, mrb_int*); if (i < argc) { - switch (mrb_type(*sp)) { + switch (mrb_type(ARGV[arg_i])) { case MRB_TT_FIXNUM: - *p = mrb_fixnum(*sp); + *p = mrb_fixnum(ARGV[arg_i]); break; case MRB_TT_FLOAT: { - mrb_float f = mrb_float(*sp); + mrb_float f = mrb_float(ARGV[arg_i]); if (!FIXABLE(f)) { mrb_raise(mrb, E_RANGE_ERROR, "float too big for int"); @@ -696,10 +705,10 @@ mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer"); break; default: - *p = mrb_fixnum(mrb_Integer(mrb, *sp)); + *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i])); break; } - sp++; + arg_i++; i++; } } @@ -709,7 +718,7 @@ mrb_bool *boolp = va_arg(ap, mrb_bool*); if (i < argc) { - mrb_value b = *sp++; + mrb_value b = ARGV[arg_i++]; *boolp = mrb_test(b); i++; } @@ -723,7 +732,7 @@ if (i < argc) { mrb_value ss; - ss = *sp++; + ss = ARGV[arg_i++]; *symp = to_sym(mrb, ss); i++; } @@ -738,14 +747,14 @@ type = va_arg(ap, struct mrb_data_type const*); if (*format == '!') { format++; - if (i < argc && mrb_nil_p(*sp)) { + if (i < argc && mrb_nil_p(ARGV[arg_i])) { *datap = 0; - i++; + i++; arg_i++; break; } } if (i < argc) { - *datap = mrb_data_get_ptr(mrb, *sp++, type); + *datap = mrb_data_get_ptr(mrb, ARGV[arg_i++], type); ++i; } } @@ -787,10 +796,10 @@ if (argc > i) { *pl = argc-i; if (*pl > 0) { - *var = sp; + *var = ARGV + arg_i; } i = argc; - sp += *pl; + arg_i += *pl; } else { *pl = 0; @@ -803,6 +812,9 @@ break; } } + +#undef ARGV + if (!c && argc > i) { mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments"); } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/codedump.c mruby-1.2.0+20160315+git4f20d58a/src/codedump.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/codedump.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/codedump.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,11 +1,11 @@ -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/debug.h" -#include "mruby/opcode.h" -#include "mruby/string.h" -#include "mruby/proc.h" +#include +#include +#include +#include +#include +#include -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO static int print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre) { @@ -53,7 +53,7 @@ static void codedump(mrb_state *mrb, mrb_irep *irep) { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO int i; int ai; mrb_code c; @@ -189,7 +189,7 @@ print_lv(mrb, irep, c, RA); break; case OP_JMP: - printf("OP_JMP\t\t%03d\n", i+GETARG_sBx(c)); + printf("OP_JMP\t%03d\n", i+GETARG_sBx(c)); break; case OP_JMPIF: printf("OP_JMPIF\tR%d\t%03d\n", GETARG_A(c), i+GETARG_sBx(c)); @@ -240,12 +240,11 @@ switch (GETARG_B(c)) { case OP_R_NORMAL: case OP_R_RETURN: - printf("\treturn"); break; + printf("\treturn\t"); break; case OP_R_BREAK: - printf("\tbreak"); break; + printf("\tbreak\t"); break; default: - printf("\tbroken"); break; - break; + printf("\tbroken\t"); break; } print_lv(mrb, irep, c, RA); break; @@ -323,7 +322,7 @@ GETARG_C(c)); break; case OP_EQ: - printf("OP_EQ\tR%d\t:%s\t%d\n", GETARG_A(c), + printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c), mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), GETARG_C(c)); break; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/compar.c mruby-1.2.0+20160315+git4f20d58a/src/compar.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/compar.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/compar.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,7 +4,7 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" +#include void mrb_init_comparable(mrb_state *mrb) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/debug.c mruby-1.2.0+20160315+git4f20d58a/src/debug.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/debug.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/debug.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,7 +1,7 @@ #include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/debug.h" +#include +#include +#include static mrb_irep_debug_info_file * get_file(mrb_irep_debug_info *info, uint32_t pc) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/dump.c mruby-1.2.0+20160315+git4f20d58a/src/dump.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/dump.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/dump.c 2016-03-14 00:35:53.000000000 +0000 @@ -6,11 +6,11 @@ #include #include -#include "mruby/dump.h" -#include "mruby/string.h" -#include "mruby/irep.h" -#include "mruby/numeric.h" -#include "mruby/debug.h" +#include +#include +#include +#include +#include #define FLAG_BYTEORDER_NATIVE 2 #define FLAG_BYTEORDER_NONATIVE 0 @@ -54,7 +54,7 @@ { uint8_t *cur = buf; - cur += uint32_to_bin(get_irep_record_size_1(mrb, irep), cur); /* record size */ + cur += uint32_to_bin((uint32_t)get_irep_record_size_1(mrb, irep), cur); /* record size */ cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */ cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */ cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */ @@ -989,7 +989,7 @@ return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size); } -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO int mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp) @@ -1092,4 +1092,4 @@ return result; } -#endif /* ENABLE_STDIO */ +#endif /* MRB_DISABLE_STDIO */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/enum.c mruby-1.2.0+20160315+git4f20d58a/src/enum.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/enum.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/enum.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,7 +4,7 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" +#include void mrb_init_enumerable(mrb_state *mrb) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/error.c mruby-1.2.0+20160315+git4f20d58a/src/error.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/error.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/error.c 2016-03-14 00:35:53.000000000 +0000 @@ -7,16 +7,16 @@ #include #include #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/debug.h" -#include "mruby/error.h" -#include "mruby/class.h" -#include "mruby/throw.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include MRB_API mrb_value mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, size_t len) @@ -174,6 +174,42 @@ return str; } +void mrb_save_backtrace(mrb_state *mrb); +mrb_value mrb_restore_backtrace(mrb_state *mrb); + +static mrb_value +exc_get_backtrace(mrb_state *mrb, mrb_value exc) +{ + mrb_sym attr_name; + mrb_value backtrace; + + attr_name = mrb_intern_lit(mrb, "backtrace"); + backtrace = mrb_iv_get(mrb, exc, attr_name); + if (mrb_nil_p(backtrace)) { + if (mrb_obj_ptr(exc) == mrb->backtrace.exc && mrb->backtrace.n > 0) { + backtrace = mrb_restore_backtrace(mrb); + mrb->backtrace.n = 0; + mrb->backtrace.exc = 0; + } + else { + backtrace = mrb_exc_backtrace(mrb, exc); + } + mrb_iv_set(mrb, exc, attr_name, backtrace); + } + + return backtrace; +} + +static mrb_value +exc_set_backtrace(mrb_state *mrb, mrb_value exc) +{ + mrb_value backtrace; + + mrb_get_args(mrb, "o", &backtrace); + mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace); + + return backtrace; +} static void exc_debug_info(mrb_state *mrb, struct RObject *exc) @@ -202,12 +238,57 @@ } } +static void +set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) +{ + mrb_funcall(mrb, info, "set_backtrace", 1, bt); +} + +static mrb_bool +have_backtrace(mrb_state *mrb, struct RObject *exc) +{ + return !mrb_nil_p(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "backtrace"))); +} + +void +mrb_exc_set(mrb_state *mrb, mrb_value exc) +{ + if (!mrb->gc.out_of_memory && mrb->backtrace.n > 0) { + mrb_value target_exc = mrb_nil_value(); + int ai; + + ai = mrb_gc_arena_save(mrb); + if ((mrb->exc && !have_backtrace(mrb, mrb->exc))) { + target_exc = mrb_obj_value(mrb->exc); + } + else if (!mrb_nil_p(exc) && mrb->backtrace.exc) { + target_exc = mrb_obj_value(mrb->backtrace.exc); + mrb_gc_protect(mrb, target_exc); + } + if (!mrb_nil_p(target_exc)) { + mrb_value backtrace; + backtrace = mrb_restore_backtrace(mrb); + set_backtrace(mrb, target_exc, backtrace); + } + mrb_gc_arena_restore(mrb, ai); + } + + mrb->backtrace.n = 0; + if (mrb_nil_p(exc)) { + mrb->exc = 0; + } + else { + mrb->exc = mrb_obj_ptr(exc); + } +} + MRB_API mrb_noreturn void mrb_exc_raise(mrb_state *mrb, mrb_value exc) { - mrb->exc = mrb_obj_ptr(exc); - if (!mrb->out_of_memory) { + mrb_exc_set(mrb, exc); + if (!mrb->gc.out_of_memory) { exc_debug_info(mrb, mrb->exc); + mrb_save_backtrace(mrb); } if (!mrb->jmp) { mrb_p(mrb, exc); @@ -309,7 +390,7 @@ MRB_API void mrb_warn(mrb_state *mrb, const char *fmt, ...) { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO va_list ap; mrb_value str; @@ -324,7 +405,7 @@ MRB_API mrb_noreturn void mrb_bug(mrb_state *mrb, const char *fmt, ...) { -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO va_list ap; mrb_value str; @@ -337,12 +418,6 @@ exit(EXIT_FAILURE); } -static void -set_backtrace(mrb_state *mrb, mrb_value info, mrb_value bt) -{ - mrb_funcall(mrb, info, "set_backtrace", 1, bt); -} - static mrb_value make_exception(mrb_state *mrb, int argc, const mrb_value *argv, mrb_bool isstr) { @@ -390,7 +465,7 @@ if (!mrb_obj_is_kind_of(mrb, mesg, mrb->eException_class)) mrb_raise(mrb, E_TYPE_ERROR, "exception object expected"); if (argc > 2) - set_backtrace(mrb, mesg, argv[2]); + set_backtrace(mrb, mesg, argv[2]); } return mesg; @@ -449,7 +524,8 @@ mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "message", exc_message, MRB_ARGS_NONE()); mrb_define_method(mrb, exception, "inspect", exc_inspect, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); + mrb_define_method(mrb, exception, "backtrace", exc_get_backtrace, MRB_ARGS_NONE()); + mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1)); mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ runtime_error = mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/error.h mruby-1.2.0+20160315+git4f20d58a/src/error.h --- mruby-1.1.0+20150906+git1cbbb7e1/src/error.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/error.h 2016-03-14 00:35:53.000000000 +0000 @@ -1,3 +1,3 @@ /* this header file is to be removed soon. added for compatibility purpose (1.0.0) */ -#include "mruby/error.h" +#include diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/etc.c mruby-1.2.0+20160315+git4f20d58a/src/etc.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/etc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/etc.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,12 +4,12 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/string.h" -#include "mruby/data.h" -#include "mruby/class.h" -#include "mruby/re.h" -#include "mruby/irep.h" +#include +#include +#include +#include +#include +#include MRB_API struct RData* mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb_data_type *type) @@ -179,7 +179,18 @@ MRB_API mrb_bool mrb_regexp_p(mrb_state *mrb, mrb_value v) { - return mrb_class_defined(mrb, REGEXP_CLASS) && mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS)); + if (mrb->flags & MRB_STATE_NO_REGEXP) { + return FALSE; + } + if ((mrb->flags & MRB_STATE_REGEXP) || mrb_class_defined(mrb, REGEXP_CLASS)) { + mrb->flags |= MRB_STATE_REGEXP; + return mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS)); + } + else { + mrb->flags |= MRB_STATE_REGEXP; + mrb->flags |= MRB_STATE_NO_REGEXP; + } + return FALSE; } #if defined _MSC_VER && _MSC_VER < 1900 diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/fmt_fp.c mruby-1.2.0+20160315+git4f20d58a/src/fmt_fp.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/fmt_fp.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/fmt_fp.c 2016-03-14 00:35:53.000000000 +0000 @@ -33,8 +33,8 @@ #include #include -#include "mruby.h" -#include "mruby/string.h" +#include +#include struct fmt_args { mrb_state *mrb; @@ -90,11 +90,6 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; #endif -#if ((defined(__CYGWIN__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__) -#undef frexpl -#define frexpl frexp -#endif - static int fmt_fp(struct fmt_args *f, long double y, int w, int p, int fl, int t) { @@ -127,7 +122,7 @@ return MAX(w, 3+pl); } - y = frexpl(y, &e2) * 2; + y = frexp((double)y, &e2) * 2; if (y) e2--; if ((t|32)=='a') { @@ -161,7 +156,7 @@ s=buf; do { - int x=y; + int x=(int)y; *s++=xdigits[x]|(t&32); y=16*(y-x); if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.'; @@ -189,7 +184,7 @@ else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1; do { - *z = y; + *z = (uint32_t)y; y = 1000000000*(y-*z++); } while (y); @@ -199,7 +194,7 @@ for (d=z-1; d>=a; d--) { uint64_t x = ((uint64_t)*d<a && !z[-1]) z--; diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/gc.c mruby-1.2.0+20160315+git4f20d58a/src/gc.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/gc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/gc.c 2016-03-14 00:35:53.000000000 +0000 @@ -6,17 +6,17 @@ #include #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/data.h" -#include "mruby/hash.h" -#include "mruby/proc.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/gc.h" -#include "mruby/error.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* = Tri-color Incremental Garbage Collection @@ -136,7 +136,7 @@ #define GC_INVOKE_TIME_REPORT(with) do {\ fprintf(stderr, "%s\n", with);\ fprintf(stderr, "gc_invoke: %19.3f\n", gettimeofday_time() - program_invoke_time);\ - fprintf(stderr, "is_generational: %d\n", is_generational(mrb));\ + fprintf(stderr, "is_generational: %d\n", is_generational(gc));\ fprintf(stderr, "is_major_gc: %d\n", is_major_gc(mrb));\ } while(0) @@ -147,10 +147,10 @@ #define GC_TIME_STOP_AND_REPORT do {\ gc_time = gettimeofday_time() - gc_time;\ gc_total_time += gc_time;\ - fprintf(stderr, "gc_state: %d\n", mrb->gc_state);\ - fprintf(stderr, "live: %zu\n", mrb->live);\ - fprintf(stderr, "majorgc_old_threshold: %zu\n", mrb->majorgc_old_threshold);\ - fprintf(stderr, "gc_threshold: %zu\n", mrb->gc_threshold);\ + fprintf(stderr, "gc_state: %d\n", gc->state);\ + fprintf(stderr, "live: %zu\n", gc->live);\ + fprintf(stderr, "majorgc_old_threshold: %zu\n", gc->majorgc_old_threshold);\ + fprintf(stderr, "gc_threshold: %zu\n", gc->threshold);\ fprintf(stderr, "gc_time: %30.20f\n", gc_time);\ fprintf(stderr, "gc_total_time: %30.20f\n\n", gc_total_time);\ } while(0) @@ -166,8 +166,32 @@ #define DEBUG(x) #endif +#ifndef MRB_HEAP_PAGE_SIZE +#define MRB_HEAP_PAGE_SIZE 1024 +#endif + #define GC_STEP_SIZE 1024 +/* white: 011, black: 100, gray: 000 */ +#define GC_GRAY 0 +#define GC_WHITE_A 1 +#define GC_WHITE_B (1 << 1) +#define GC_BLACK (1 << 2) +#define GC_WHITES (GC_WHITE_A | GC_WHITE_B) +#define GC_COLOR_MASK 7 + +#define paint_gray(o) ((o)->color = GC_GRAY) +#define paint_black(o) ((o)->color = GC_BLACK) +#define paint_white(o) ((o)->color = GC_WHITES) +#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part) +#define is_gray(o) ((o)->color == GC_GRAY) +#define is_white(o) ((o)->color & GC_WHITES) +#define is_black(o) ((o)->color & GC_BLACK) +#define flip_white_part(s) ((s)->current_white_part = other_white_part(s)) +#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES) +#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE) + +#define objects(p) ((RVALUE *)p->objects) MRB_API void* mrb_realloc_simple(mrb_state *mrb, void *p, size_t len) @@ -175,7 +199,7 @@ void *p2; p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud); - if (!p2 && len > 0 && mrb->heaps) { + if (!p2 && len > 0 && mrb->gc.heaps) { mrb_full_gc(mrb); p2 = (mrb->allocf)(mrb, p, len, mrb->allocf_ud); } @@ -183,7 +207,6 @@ return p2; } - MRB_API void* mrb_realloc(mrb_state *mrb, void *p, size_t len) { @@ -191,16 +214,17 @@ p2 = mrb_realloc_simple(mrb, p, len); if (!p2 && len) { - if (mrb->out_of_memory) { + if (mrb->gc.out_of_memory) { + mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); /* mrb_panic(mrb); */ } else { - mrb->out_of_memory = TRUE; + mrb->gc.out_of_memory = TRUE; mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err)); } } else { - mrb->out_of_memory = FALSE; + mrb->gc.out_of_memory = FALSE; } return p2; @@ -244,101 +268,98 @@ (mrb->allocf)(mrb, p, 0, mrb->allocf_ud); } -#ifndef MRB_HEAP_PAGE_SIZE -#define MRB_HEAP_PAGE_SIZE 1024 -#endif - -struct heap_page { - struct RBasic *freelist; - struct heap_page *prev; - struct heap_page *next; - struct heap_page *free_next; - struct heap_page *free_prev; - mrb_bool old:1; - RVALUE objects[MRB_HEAP_PAGE_SIZE]; -}; +MRB_API mrb_bool +mrb_object_dead_p(mrb_state *mrb, struct RBasic *object) { + return is_dead(&mrb->gc, object); +} static void -link_heap_page(mrb_state *mrb, struct heap_page *page) +link_heap_page(mrb_gc *gc, mrb_heap_page *page) { - page->next = mrb->heaps; - if (mrb->heaps) - mrb->heaps->prev = page; - mrb->heaps = page; + page->next = gc->heaps; + if (gc->heaps) + gc->heaps->prev = page; + gc->heaps = page; } static void -unlink_heap_page(mrb_state *mrb, struct heap_page *page) +unlink_heap_page(mrb_gc *gc, mrb_heap_page *page) { if (page->prev) page->prev->next = page->next; if (page->next) page->next->prev = page->prev; - if (mrb->heaps == page) - mrb->heaps = page->next; + if (gc->heaps == page) + gc->heaps = page->next; page->prev = NULL; page->next = NULL; } static void -link_free_heap_page(mrb_state *mrb, struct heap_page *page) +link_free_heap_page(mrb_gc *gc, mrb_heap_page *page) { - page->free_next = mrb->free_heaps; - if (mrb->free_heaps) { - mrb->free_heaps->free_prev = page; + page->free_next = gc->free_heaps; + if (gc->free_heaps) { + gc->free_heaps->free_prev = page; } - mrb->free_heaps = page; + gc->free_heaps = page; } static void -unlink_free_heap_page(mrb_state *mrb, struct heap_page *page) +unlink_free_heap_page(mrb_gc *gc, mrb_heap_page *page) { if (page->free_prev) page->free_prev->free_next = page->free_next; if (page->free_next) page->free_next->free_prev = page->free_prev; - if (mrb->free_heaps == page) - mrb->free_heaps = page->free_next; + if (gc->free_heaps == page) + gc->free_heaps = page->free_next; page->free_prev = NULL; page->free_next = NULL; } static void -add_heap(mrb_state *mrb) +add_heap(mrb_state *mrb, mrb_gc *gc) { - struct heap_page *page = (struct heap_page *)mrb_calloc(mrb, 1, sizeof(struct heap_page)); + mrb_heap_page *page = (mrb_heap_page *)mrb_calloc(mrb, 1, sizeof(mrb_heap_page) + MRB_HEAP_PAGE_SIZE * sizeof(RVALUE)); RVALUE *p, *e; struct RBasic *prev = NULL; - for (p = page->objects, e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt = MRB_TT_FREE; p->as.free.next = prev; prev = &p->as.basic; } page->freelist = prev; - link_heap_page(mrb, page); - link_free_heap_page(mrb, page); + link_heap_page(gc, page); + link_free_heap_page(gc, page); } #define DEFAULT_GC_INTERVAL_RATIO 200 #define DEFAULT_GC_STEP_RATIO 200 #define DEFAULT_MAJOR_GC_INC_RATIO 200 -#define is_generational(mrb) ((mrb)->is_generational_gc_mode) -#define is_major_gc(mrb) (is_generational(mrb) && (mrb)->gc_full) -#define is_minor_gc(mrb) (is_generational(mrb) && !(mrb)->gc_full) +#define is_generational(gc) ((gc)->generational) +#define is_major_gc(gc) (is_generational(gc) && (gc)->full) +#define is_minor_gc(gc) (is_generational(gc) && !(gc)->full) void -mrb_init_heap(mrb_state *mrb) +mrb_gc_init(mrb_state *mrb, mrb_gc *gc) { - 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; +#ifndef MRB_GC_FIXED_ARENA + gc->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE); + gc->arena_capa = MRB_GC_ARENA_SIZE; +#endif + + gc->current_white_part = GC_WHITE_A; + gc->heaps = NULL; + gc->free_heaps = NULL; + add_heap(mrb, gc); + gc->interval_ratio = DEFAULT_GC_INTERVAL_RATIO; + gc->step_ratio = DEFAULT_GC_STEP_RATIO; #ifndef MRB_GC_TURN_OFF_GENERATIONAL - mrb->is_generational_gc_mode = TRUE; - mrb->gc_full = TRUE; + gc->generational = TRUE; + gc->full = TRUE; #endif #ifdef GC_PROFILE @@ -349,16 +370,16 @@ static void obj_free(mrb_state *mrb, struct RBasic *obj); void -mrb_free_heap(mrb_state *mrb) +free_heap(mrb_state *mrb, mrb_gc *gc) { - struct heap_page *page = mrb->heaps; - struct heap_page *tmp; + mrb_heap_page *page = gc->heaps; + mrb_heap_page *tmp; RVALUE *p, *e; while (page) { tmp = page; page = page->next; - for (p = tmp->objects, e=p+MRB_HEAP_PAGE_SIZE; pas.free.tt != MRB_TT_FREE) obj_free(mrb, &p->as.basic); } @@ -366,30 +387,87 @@ } } +void +mrb_gc_destroy(mrb_state *mrb, mrb_gc *gc) +{ + free_heap(mrb, gc); +#ifndef MRB_GC_FIXED_ARENA + mrb_free(mrb, gc->arena); +#endif +} + static void -gc_protect(mrb_state *mrb, struct RBasic *p) +gc_protect(mrb_state *mrb, mrb_gc *gc, struct RBasic *p) { #ifdef MRB_GC_FIXED_ARENA - if (mrb->arena_idx >= MRB_GC_ARENA_SIZE) { + if (gc->arena_idx >= MRB_GC_ARENA_SIZE) { /* arena overflow error */ - mrb->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ + gc->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */ mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); } #else - if (mrb->arena_idx >= mrb->arena_capa) { + if (gc->arena_idx >= gc->arena_capa) { /* extend arena */ - mrb->arena_capa = (int)(mrb->arena_capa * 1.5); - mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*mrb->arena_capa); + gc->arena_capa = (int)(gc->arena_capa * 1.5); + gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*gc->arena_capa); } #endif - mrb->arena[mrb->arena_idx++] = p; + gc->arena[gc->arena_idx++] = p; } +/* mrb_gc_protect() leaves the object in the arena */ MRB_API void mrb_gc_protect(mrb_state *mrb, mrb_value obj) { if (mrb_immediate_p(obj)) return; - gc_protect(mrb, mrb_basic_ptr(obj)); + gc_protect(mrb, &mrb->gc, mrb_basic_ptr(obj)); +} + +#define GC_ROOT_NAME "_gc_root_" + +/* mrb_gc_register() keeps the object from GC. + + Register your object when it's exported to C world, + without reference from Ruby world, e.g. callback + arguments. Don't forget to remove the obejct using + mrb_gc_unregister, otherwise your object will leak. +*/ + +MRB_API void +mrb_gc_register(mrb_state *mrb, mrb_value obj) +{ + mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME); + mrb_value table = mrb_gv_get(mrb, root); + + if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) { + table = mrb_ary_new(mrb); + mrb_gv_set(mrb, root, table); + } + mrb_ary_push(mrb, table, obj); +} + +/* mrb_gc_unregister() removes the object from GC root. */ +MRB_API void +mrb_gc_unregister(mrb_state *mrb, mrb_value obj) +{ + mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME); + mrb_value table = mrb_gv_get(mrb, root); + struct RArray *a; + mrb_int i, j; + + if (mrb_nil_p(table)) return; + if (mrb_type(table) != MRB_TT_ARRAY) { + mrb_gv_set(mrb, root, mrb_nil_value()); + return; + } + a = mrb_ary_ptr(table); + mrb_ary_modify(mrb, a); + for (i=j=0; ilen; i++) { + if (!mrb_obj_eq(mrb, a->ptr[i], obj)) { + a->ptr[j++] = a->ptr[i]; + } + } + a->len = j; } MRB_API struct RBasic* @@ -397,34 +475,35 @@ { struct RBasic *p; static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } }; + mrb_gc *gc = &mrb->gc; #ifdef MRB_GC_STRESS mrb_full_gc(mrb); #endif - if (mrb->gc_threshold < mrb->live) { + if (gc->threshold < gc->live) { mrb_incremental_gc(mrb); } - if (mrb->free_heaps == NULL) { - add_heap(mrb); + if (gc->free_heaps == NULL) { + add_heap(mrb, gc); } - p = mrb->free_heaps->freelist; - mrb->free_heaps->freelist = ((struct free_obj*)p)->next; - if (mrb->free_heaps->freelist == NULL) { - unlink_free_heap_page(mrb, mrb->free_heaps); + p = gc->free_heaps->freelist; + gc->free_heaps->freelist = ((struct free_obj*)p)->next; + if (gc->free_heaps->freelist == NULL) { + unlink_free_heap_page(gc, gc->free_heaps); } - mrb->live++; - gc_protect(mrb, p); + gc->live++; + gc_protect(mrb, gc, p); *(RVALUE *)p = RVALUE_zero; p->tt = ttype; p->c = cls; - paint_partial_white(mrb, p); + paint_partial_white(gc, p); return p; } static inline void -add_gray_list(mrb_state *mrb, struct RBasic *obj) +add_gray_list(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) { #ifdef MRB_GC_STRESS if (obj->tt > MRB_TT_MAXDEFINE) { @@ -432,8 +511,8 @@ } #endif paint_gray(obj); - obj->gcnext = mrb->gray_list; - mrb->gray_list = obj; + obj->gcnext = gc->gray_list; + gc->gray_list = obj; } static void @@ -490,11 +569,11 @@ } static void -gc_mark_children(mrb_state *mrb, struct RBasic *obj) +gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) { mrb_assert(is_gray(obj)); paint_black(obj); - mrb->gray_list = obj->gcnext; + gc->gray_list = obj->gcnext; mrb_gc_mark(mrb, (struct RBasic*)obj->c); switch (obj->tt) { case MRB_TT_ICLASS: @@ -535,14 +614,11 @@ case MRB_TT_ENV: { struct REnv *e = (struct REnv*)obj; + mrb_int i, len; - if (!MRB_ENV_STACK_SHARED_P(e)) { - mrb_int i, len; - - len = MRB_ENV_STACK_LEN(e); - for (i=0; istack[i]); - } + len = MRB_ENV_STACK_LEN(e); + for (i=0; istack[i]); } } break; @@ -596,7 +672,7 @@ if (obj == 0) return; if (!is_white(obj)) return; mrb_assert((obj)->tt != MRB_TT_FREE); - add_gray_list(mrb, obj); + add_gray_list(mrb, &mrb->gc, obj); } static void @@ -619,8 +695,13 @@ #endif case MRB_TT_OBJECT: + mrb_gc_free_iv(mrb, (struct RObject*)obj); + break; + case MRB_TT_EXCEPTION: mrb_gc_free_iv(mrb, (struct RObject*)obj); + if ((struct RObject*)obj == mrb->backtrace.exc) + mrb->backtrace.exc = 0; break; case MRB_TT_CLASS: @@ -647,9 +728,19 @@ case MRB_TT_FIBER: { struct mrb_context *c = ((struct RFiber*)obj)->cxt; - - if (c != mrb->root_c) + if (c && c != mrb->root_c) { + mrb_callinfo *ci = c->ci; + mrb_callinfo *ce = c->cibase; + + while (ce <= ci) { + struct REnv *e = ci->env; + if (e && !is_dead(&mrb->gc, e) && MRB_ENV_STACK_SHARED_P(e)) { + mrb_env_unshare(mrb, e); + } + ci--; + } mrb_free_context(mrb, c); + } } break; @@ -700,19 +791,19 @@ } static void -root_scan_phase(mrb_state *mrb) +root_scan_phase(mrb_state *mrb, mrb_gc *gc) { size_t i, e; - if (!is_minor_gc(mrb)) { - mrb->gray_list = NULL; - mrb->atomic_gray_list = NULL; + if (!is_minor_gc(gc)) { + gc->gray_list = NULL; + gc->atomic_gray_list = NULL; } mrb_gc_mark_gv(mrb); /* mark arena */ - for (i=0,e=mrb->arena_idx; iarena[i]); + for (i=0,e=gc->arena_idx; iarena[i]); } /* mark class hierarchy */ mrb_gc_mark(mrb, (struct RBasic*)mrb->object_class); @@ -733,11 +824,11 @@ } static size_t -gc_gray_mark(mrb_state *mrb, struct RBasic *obj) +gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) { size_t children = 0; - gc_mark_children(mrb, obj); + gc_mark_children(mrb, gc, obj); switch (obj->tt) { case MRB_TT_ICLASS: @@ -816,68 +907,68 @@ 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); +gc_mark_gray_list(mrb_state *mrb, mrb_gc *gc) { + while (gc->gray_list) { + if (is_gray(gc->gray_list)) + gc_mark_children(mrb, gc, gc->gray_list); else - mrb->gray_list = mrb->gray_list->gcnext; + gc->gray_list = gc->gray_list->gcnext; } } static size_t -incremental_marking_phase(mrb_state *mrb, size_t limit) +incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) { size_t tried_marks = 0; - while (mrb->gray_list && tried_marks < limit) { - tried_marks += gc_gray_mark(mrb, mrb->gray_list); + while (gc->gray_list && tried_marks < limit) { + tried_marks += gc_gray_mark(mrb, gc, gc->gray_list); } return tried_marks; } static void -final_marking_phase(mrb_state *mrb) +final_marking_phase(mrb_state *mrb, mrb_gc *gc) { 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); + gc_mark_gray_list(mrb, gc); + mrb_assert(gc->gray_list == NULL); + gc->gray_list = gc->atomic_gray_list; + gc->atomic_gray_list = NULL; + gc_mark_gray_list(mrb, gc); + mrb_assert(gc->gray_list == NULL); } static void -prepare_incremental_sweep(mrb_state *mrb) +prepare_incremental_sweep(mrb_state *mrb, mrb_gc *gc) { - mrb->gc_state = GC_STATE_SWEEP; - mrb->sweeps = mrb->heaps; - mrb->gc_live_after_mark = mrb->live; + gc->state = MRB_GC_STATE_SWEEP; + gc->sweeps = gc->heaps; + gc->live_after_mark = gc->live; } static size_t -incremental_sweep_phase(mrb_state *mrb, size_t limit) +incremental_sweep_phase(mrb_state *mrb, mrb_gc *gc, size_t limit) { - struct heap_page *page = mrb->sweeps; + mrb_heap_page *page = gc->sweeps; size_t tried_sweep = 0; while (page && (tried_sweep < limit)) { - RVALUE *p = page->objects; + RVALUE *p = objects(page); RVALUE *e = p + MRB_HEAP_PAGE_SIZE; size_t freed = 0; mrb_bool dead_slot = TRUE; mrb_bool full = (page->freelist == NULL); - if (is_minor_gc(mrb) && page->old) { + if (is_minor_gc(gc) && page->old) { /* skip a slot which doesn't contain any young object */ p = e; dead_slot = FALSE; } while (pas.basic)) { + if (is_dead(gc, &p->as.basic)) { if (p->as.basic.tt != MRB_TT_FREE) { obj_free(mrb, &p->as.basic); p->as.free.next = page->freelist; @@ -886,8 +977,8 @@ } } else { - if (!is_generational(mrb)) - paint_partial_white(mrb, &p->as.basic); /* next gc target */ + if (!is_generational(gc)) + paint_partial_white(gc, &p->as.basic); /* next gc target */ dead_slot = 0; } p++; @@ -895,54 +986,54 @@ /* free dead slot */ if (dead_slot && freed < MRB_HEAP_PAGE_SIZE) { - struct heap_page *next = page->next; + mrb_heap_page *next = page->next; - unlink_heap_page(mrb, page); - unlink_free_heap_page(mrb, page); + unlink_heap_page(gc, page); + unlink_free_heap_page(gc, page); mrb_free(mrb, page); page = next; } else { if (full && freed > 0) { - link_free_heap_page(mrb, page); + link_free_heap_page(gc, page); } - if (page->freelist == NULL && is_minor_gc(mrb)) + if (page->freelist == NULL && is_minor_gc(gc)) page->old = TRUE; else page->old = FALSE; page = page->next; } tried_sweep += MRB_HEAP_PAGE_SIZE; - mrb->live -= freed; - mrb->gc_live_after_mark -= freed; + gc->live -= freed; + gc->live_after_mark -= freed; } - mrb->sweeps = page; + gc->sweeps = page; return tried_sweep; } static size_t -incremental_gc(mrb_state *mrb, size_t limit) +incremental_gc(mrb_state *mrb, mrb_gc *gc, size_t limit) { - switch (mrb->gc_state) { - case GC_STATE_ROOT: - root_scan_phase(mrb); - mrb->gc_state = GC_STATE_MARK; - flip_white_part(mrb); + switch (gc->state) { + case MRB_GC_STATE_ROOT: + root_scan_phase(mrb, gc); + gc->state = MRB_GC_STATE_MARK; + flip_white_part(gc); return 0; - case GC_STATE_MARK: - if (mrb->gray_list) { - return incremental_marking_phase(mrb, limit); + case MRB_GC_STATE_MARK: + if (gc->gray_list) { + return incremental_marking_phase(mrb, gc, limit); } else { - final_marking_phase(mrb); - prepare_incremental_sweep(mrb); + final_marking_phase(mrb, gc); + prepare_incremental_sweep(mrb, gc); return 0; } - case GC_STATE_SWEEP: { + case MRB_GC_STATE_SWEEP: { size_t tried_sweep = 0; - tried_sweep = incremental_sweep_phase(mrb, limit); + tried_sweep = incremental_sweep_phase(mrb, gc, limit); if (tried_sweep == 0) - mrb->gc_state = GC_STATE_ROOT; + gc->state = MRB_GC_STATE_ROOT; return tried_sweep; } default: @@ -953,79 +1044,81 @@ } static void -incremental_gc_until(mrb_state *mrb, enum gc_state to_state) +incremental_gc_until(mrb_state *mrb, mrb_gc *gc, mrb_gc_state to_state) { do { - incremental_gc(mrb, SIZE_MAX); - } while (mrb->gc_state != to_state); + incremental_gc(mrb, gc, SIZE_MAX); + } while (gc->state != to_state); } static void -incremental_gc_step(mrb_state *mrb) +incremental_gc_step(mrb_state *mrb, mrb_gc *gc) { size_t limit = 0, result = 0; - limit = (GC_STEP_SIZE/100) * mrb->gc_step_ratio; + limit = (GC_STEP_SIZE/100) * gc->step_ratio; while (result < limit) { - result += incremental_gc(mrb, limit); - if (mrb->gc_state == GC_STATE_ROOT) + result += incremental_gc(mrb, gc, limit); + if (gc->state == MRB_GC_STATE_ROOT) break; } - mrb->gc_threshold = mrb->live + GC_STEP_SIZE; + gc->threshold = gc->live + GC_STEP_SIZE; } static void -clear_all_old(mrb_state *mrb) +clear_all_old(mrb_state *mrb, mrb_gc *gc) { - mrb_bool origin_mode = mrb->is_generational_gc_mode; + mrb_bool origin_mode = gc->generational; - mrb_assert(is_generational(mrb)); - if (is_major_gc(mrb)) { + mrb_assert(is_generational(gc)); + if (is_major_gc(gc)) { /* finish the half baked GC */ - incremental_gc_until(mrb, GC_STATE_ROOT); + incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); } /* Sweep the dead objects, then reset all the live objects * (including all the old objects, of course) to white. */ - mrb->is_generational_gc_mode = FALSE; - prepare_incremental_sweep(mrb); - incremental_gc_until(mrb, GC_STATE_ROOT); - mrb->is_generational_gc_mode = origin_mode; + gc->generational = FALSE; + prepare_incremental_sweep(mrb, gc); + incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); + gc->generational = origin_mode; /* The gray objects have already been painted as white */ - mrb->atomic_gray_list = mrb->gray_list = NULL; + gc->atomic_gray_list = gc->gray_list = NULL; } MRB_API void mrb_incremental_gc(mrb_state *mrb) { - if (mrb->gc_disabled) return; + mrb_gc *gc = &mrb->gc; + + if (gc->disabled) return; GC_INVOKE_TIME_REPORT("mrb_incremental_gc()"); GC_TIME_START; - if (is_minor_gc(mrb)) { - incremental_gc_until(mrb, GC_STATE_ROOT); + if (is_minor_gc(gc)) { + incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); } else { - incremental_gc_step(mrb); + incremental_gc_step(mrb, gc); } - if (mrb->gc_state == GC_STATE_ROOT) { - 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 (gc->state == MRB_GC_STATE_ROOT) { + mrb_assert(gc->live >= gc->live_after_mark); + gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio; + if (gc->threshold < GC_STEP_SIZE) { + 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; + if (is_major_gc(gc)) { + gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; + gc->full = FALSE; } - else if (is_minor_gc(mrb)) { - if (mrb->live > mrb->majorgc_old_threshold) { - clear_all_old(mrb); - mrb->gc_full = TRUE; + else if (is_minor_gc(gc)) { + if (gc->live > gc->majorgc_old_threshold) { + clear_all_old(mrb, gc); + gc->full = TRUE; } } } @@ -1037,26 +1130,29 @@ MRB_API void mrb_full_gc(mrb_state *mrb) { - if (mrb->gc_disabled) return; + mrb_gc *gc = &mrb->gc; + + if (gc->disabled) return; + GC_INVOKE_TIME_REPORT("mrb_full_gc()"); GC_TIME_START; - if (is_generational(mrb)) { + if (is_generational(gc)) { /* clear all the old objects back to young */ - clear_all_old(mrb); - mrb->gc_full = TRUE; + clear_all_old(mrb, gc); + gc->full = TRUE; } - else if (mrb->gc_state != GC_STATE_ROOT) { + else if (gc->state != MRB_GC_STATE_ROOT) { /* finish half baked GC cycle */ - incremental_gc_until(mrb, GC_STATE_ROOT); + incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); } - incremental_gc_until(mrb, GC_STATE_ROOT); - mrb->gc_threshold = (mrb->gc_live_after_mark/100) * mrb->gc_interval_ratio; + incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); + gc->threshold = (gc->live_after_mark/100) * gc->interval_ratio; - if (is_generational(mrb)) { - mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; - mrb->gc_full = FALSE; + if (is_generational(gc)) { + gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; + gc->full = FALSE; } GC_TIME_STOP_AND_REPORT; @@ -1071,27 +1167,29 @@ MRB_API int mrb_gc_arena_save(mrb_state *mrb) { - return mrb->arena_idx; + return mrb->gc.arena_idx; } MRB_API void mrb_gc_arena_restore(mrb_state *mrb, int idx) { + mrb_gc *gc = &mrb->gc; + #ifndef MRB_GC_FIXED_ARENA - int capa = mrb->arena_capa; + int capa = gc->arena_capa; if (idx < capa / 2) { capa = (int)(capa * 0.66); if (capa < MRB_GC_ARENA_SIZE) { capa = MRB_GC_ARENA_SIZE; } - if (capa != mrb->arena_capa) { - mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*capa); - mrb->arena_capa = capa; + if (capa != gc->arena_capa) { + gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa); + gc->arena_capa = capa; } } #endif - mrb->arena_idx = idx; + gc->arena_idx = idx; } /* @@ -1102,18 +1200,20 @@ MRB_API void mrb_field_write_barrier(mrb_state *mrb, struct RBasic *obj, struct RBasic *value) { + mrb_gc *gc = &mrb->gc; + if (!is_black(obj)) return; if (!is_white(value)) return; - mrb_assert(!is_dead(mrb, value) && !is_dead(mrb, obj)); - mrb_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_ROOT); + mrb_assert(gc->state == MRB_GC_STATE_MARK || (!is_dead(gc, value) && !is_dead(gc, obj))); + mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT); - if (is_generational(mrb) || mrb->gc_state == GC_STATE_MARK) { - add_gray_list(mrb, value); + if (is_generational(gc) || gc->state == MRB_GC_STATE_MARK) { + add_gray_list(mrb, gc, value); } else { - mrb_assert(mrb->gc_state == GC_STATE_SWEEP); - paint_partial_white(mrb, obj); /* for never write barriers */ + mrb_assert(gc->state == MRB_GC_STATE_SWEEP); + paint_partial_white(gc, obj); /* for never write barriers */ } } @@ -1129,13 +1229,15 @@ MRB_API void mrb_write_barrier(mrb_state *mrb, struct RBasic *obj) { + mrb_gc *gc = &mrb->gc; + if (!is_black(obj)) return; - mrb_assert(!is_dead(mrb, obj)); - mrb_assert(is_generational(mrb) || mrb->gc_state != GC_STATE_ROOT); + mrb_assert(!is_dead(gc, obj)); + mrb_assert(is_generational(gc) || gc->state != MRB_GC_STATE_ROOT); paint_gray(obj); - obj->gcnext = mrb->atomic_gray_list; - mrb->atomic_gray_list = obj; + obj->gcnext = gc->atomic_gray_list; + gc->atomic_gray_list = obj; } /* @@ -1169,9 +1271,9 @@ static mrb_value gc_enable(mrb_state *mrb, mrb_value obj) { - mrb_bool old = mrb->gc_disabled; + mrb_bool old = mrb->gc.disabled; - mrb->gc_disabled = FALSE; + mrb->gc.disabled = FALSE; return mrb_bool_value(old); } @@ -1191,9 +1293,9 @@ static mrb_value gc_disable(mrb_state *mrb, mrb_value obj) { - mrb_bool old = mrb->gc_disabled; + mrb_bool old = mrb->gc.disabled; - mrb->gc_disabled = TRUE; + mrb->gc.disabled = TRUE; return mrb_bool_value(old); } @@ -1209,7 +1311,7 @@ static mrb_value gc_interval_ratio_get(mrb_state *mrb, mrb_value obj) { - return mrb_fixnum_value(mrb->gc_interval_ratio); + return mrb_fixnum_value(mrb->gc.interval_ratio); } /* @@ -1227,7 +1329,7 @@ mrb_int ratio; mrb_get_args(mrb, "i", &ratio); - mrb->gc_interval_ratio = ratio; + mrb->gc.interval_ratio = ratio; return mrb_nil_value(); } @@ -1242,7 +1344,7 @@ static mrb_value gc_step_ratio_get(mrb_state *mrb, mrb_value obj) { - return mrb_fixnum_value(mrb->gc_step_ratio); + return mrb_fixnum_value(mrb->gc.step_ratio); } /* @@ -1260,24 +1362,24 @@ mrb_int ratio; mrb_get_args(mrb, "i", &ratio); - mrb->gc_step_ratio = ratio; + mrb->gc.step_ratio = ratio; return mrb_nil_value(); } static void -change_gen_gc_mode(mrb_state *mrb, mrb_bool enable) +change_gen_gc_mode(mrb_state *mrb, mrb_gc *gc, mrb_bool enable) { - if (is_generational(mrb) && !enable) { - clear_all_old(mrb); - mrb_assert(mrb->gc_state == GC_STATE_ROOT); - mrb->gc_full = FALSE; - } - else if (!is_generational(mrb) && enable) { - incremental_gc_until(mrb, GC_STATE_ROOT); - mrb->majorgc_old_threshold = mrb->gc_live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; - mrb->gc_full = FALSE; + if (is_generational(gc) && !enable) { + clear_all_old(mrb, gc); + mrb_assert(gc->state == MRB_GC_STATE_ROOT); + gc->full = FALSE; + } + else if (!is_generational(gc) && enable) { + incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT); + gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO; + gc->full = FALSE; } - mrb->is_generational_gc_mode = enable; + gc->generational = enable; } /* @@ -1291,7 +1393,7 @@ static mrb_value gc_generational_mode_get(mrb_state *mrb, mrb_value self) { - return mrb_bool_value(mrb->is_generational_gc_mode); + return mrb_bool_value(mrb->gc.generational); } /* @@ -1308,21 +1410,22 @@ mrb_bool enable; mrb_get_args(mrb, "b", &enable); - if (mrb->is_generational_gc_mode != enable) - change_gen_gc_mode(mrb, enable); + if (mrb->gc.generational != enable) + change_gen_gc_mode(mrb, &mrb->gc, enable); return mrb_bool_value(enable); } -void -mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data) + +static void +gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void *data) { - struct heap_page* page = mrb->heaps; + mrb_heap_page* page = gc->heaps; while (page != NULL) { RVALUE *p, *pend; - p = page->objects; + p = objects(page); pend = p + MRB_HEAP_PAGE_SIZE; for (;p < pend; p++) { (*callback)(mrb, &p->as.basic, data); @@ -1332,6 +1435,12 @@ } } +void +mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data) +{ + gc_each_objects(mrb, &mrb->gc, callback, data); +} + #ifdef GC_TEST #ifdef GC_DEBUG static mrb_value gc_test(mrb_state *, mrb_value); @@ -1368,42 +1477,43 @@ { mrb_state *mrb = mrb_open(); struct RBasic *obj, *value; + mrb_gc *gc = &mrb->gc; puts("test_mrb_field_write_barrier"); - mrb->is_generational_gc_mode = FALSE; + gc->generational = FALSE; obj = mrb_basic_ptr(mrb_ary_new(mrb)); value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value")); paint_black(obj); - paint_partial_white(mrb, value); + paint_partial_white(gc, value); - puts(" in GC_STATE_MARK"); - mrb->gc_state = GC_STATE_MARK; + puts(" in MRB_GC_STATE_MARK"); + gc->state = MRB_GC_STATE_MARK; mrb_field_write_barrier(mrb, obj, value); mrb_assert(is_gray(value)); - puts(" in GC_STATE_SWEEP"); - paint_partial_white(mrb, value); - mrb->gc_state = GC_STATE_SWEEP; + puts(" in MRB_GC_STATE_SWEEP"); + paint_partial_white(gc, value); + gc->state = MRB_GC_STATE_SWEEP; mrb_field_write_barrier(mrb, obj, value); - mrb_assert(obj->color & mrb->current_white_part); - mrb_assert(value->color & mrb->current_white_part); + mrb_assert(obj->color & gc->current_white_part); + mrb_assert(value->color & gc->current_white_part); puts(" fail with black"); - mrb->gc_state = GC_STATE_MARK; + gc->state = MRB_GC_STATE_MARK; paint_white(obj); - paint_partial_white(mrb, value); + paint_partial_white(gc, value); mrb_field_write_barrier(mrb, obj, value); - mrb_assert(obj->color & mrb->current_white_part); + mrb_assert(obj->color & gc->current_white_part); puts(" fail with gray"); - mrb->gc_state = GC_STATE_MARK; + gc->state = MRB_GC_STATE_MARK; paint_black(obj); paint_gray(value); mrb_field_write_barrier(mrb, obj, value); @@ -1416,9 +1526,9 @@ obj = mrb_basic_ptr(mrb_ary_new(mrb)); mrb_value value = mrb_str_new_lit(mrb, "value"); paint_black(obj); - paint_partial_white(mrb, mrb_basic_ptr(value)); + paint_partial_white(gc, mrb_basic_ptr(value)); - mrb->gc_state = GC_STATE_MARK; + gc->state = MRB_GC_STATE_MARK; mrb_field_write_barrier_value(mrb, obj, value); mrb_assert(is_gray(mrb_basic_ptr(value))); @@ -1432,17 +1542,18 @@ { mrb_state *mrb = mrb_open(); struct RBasic *obj; + mrb_gc *gc = &mrb->gc; puts("test_mrb_write_barrier"); obj = mrb_basic_ptr(mrb_ary_new(mrb)); paint_black(obj); - puts(" in GC_STATE_MARK"); - mrb->gc_state = GC_STATE_MARK; + puts(" in MRB_GC_STATE_MARK"); + gc->state = MRB_GC_STATE_MARK; mrb_write_barrier(mrb, obj); mrb_assert(is_gray(obj)); - mrb_assert(mrb->atomic_gray_list == obj); + mrb_assert(gc->atomic_gray_list == obj); puts(" fail with gray"); @@ -1459,19 +1570,20 @@ { mrb_state *mrb = mrb_open(); struct RBasic *obj1, *obj2; + mrb_gc *gc = &mrb->gc; puts("test_add_gray_list"); - change_gen_gc_mode(mrb, FALSE); - mrb_assert(mrb->gray_list == NULL); + change_gen_gc_mode(mrb, gc, FALSE); + mrb_assert(gc->gray_list == NULL); obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); - add_gray_list(mrb, obj1); - mrb_assert(mrb->gray_list == obj1); + add_gray_list(mrb, gc, obj1); + mrb_assert(gc->gray_list == obj1); mrb_assert(is_gray(obj1)); obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test")); - add_gray_list(mrb, obj2); - mrb_assert(mrb->gray_list == obj2); - mrb_assert(mrb->gray_list->gcnext == obj1); + add_gray_list(mrb, gc, obj2); + mrb_assert(gc->gray_list == obj2); + mrb_assert(gc->gray_list->gcnext == obj1); mrb_assert(is_gray(obj2)); mrb_close(mrb); @@ -1484,13 +1596,14 @@ mrb_value obj_v, value_v; struct RBasic *obj; size_t gray_num = 0; + mrb_gc *gc = &mrb->gc; puts("test_gc_gray_mark"); puts(" in MRB_TT_CLASS"); obj = (struct RBasic*)mrb->object_class; paint_gray(obj); - gray_num = gc_gray_mark(mrb, obj); + gray_num = gc_gray_mark(mrb, gc, obj); mrb_assert(is_black(obj)); mrb_assert(gray_num > 1); @@ -1498,9 +1611,9 @@ obj_v = mrb_ary_new(mrb); value_v = mrb_str_new_lit(mrb, "test"); paint_gray(mrb_basic_ptr(obj_v)); - paint_partial_white(mrb, mrb_basic_ptr(value_v)); + paint_partial_white(gc, mrb_basic_ptr(value_v)); mrb_ary_push(mrb, obj_v, value_v); - gray_num = gc_gray_mark(mrb, mrb_basic_ptr(obj_v)); + gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v)); mrb_assert(is_black(mrb_basic_ptr(obj_v))); mrb_assert(is_gray(mrb_basic_ptr(value_v))); mrb_assert(gray_num == 1); @@ -1514,32 +1627,33 @@ mrb_state *mrb = mrb_open(); size_t max = ~0, live = 0, total = 0, freed = 0; RVALUE *free; - struct heap_page *page; + mrb_heap_page *page; + mrb_gc *gc = &mrb->gc; puts("test_incremental_gc"); - change_gen_gc_mode(mrb, FALSE); + change_gen_gc_mode(mrb, gc, FALSE); puts(" in mrb_full_gc"); mrb_full_gc(mrb); - mrb_assert(mrb->gc_state == GC_STATE_ROOT); - puts(" in GC_STATE_ROOT"); - incremental_gc(mrb, max); - mrb_assert(mrb->gc_state == GC_STATE_MARK); - puts(" in GC_STATE_MARK"); - incremental_gc_until(mrb, GC_STATE_SWEEP); - mrb_assert(mrb->gc_state == GC_STATE_SWEEP); + mrb_assert(gc->state == MRB_GC_STATE_ROOT); + puts(" in MRB_GC_STATE_ROOT"); + incremental_gc(mrb, gc, max); + mrb_assert(gc->state == MRB_GC_STATE_MARK); + puts(" in MRB_GC_STATE_MARK"); + incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP); + mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - puts(" in GC_STATE_SWEEP"); - page = mrb->heaps; + puts(" in MRB_GC_STATE_SWEEP"); + page = gc->heaps; while (page) { - RVALUE *p = page->objects; + RVALUE *p = objects(page); RVALUE *e = p + MRB_HEAP_PAGE_SIZE; while (pas.basic)) { live++; } - if (is_gray(&p->as.basic) && !is_dead(mrb, &p->as.basic)) { + if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) { printf("%p\n", &p->as.basic); } p++; @@ -1548,44 +1662,44 @@ total += MRB_HEAP_PAGE_SIZE; } - mrb_assert(mrb->gray_list == NULL); + mrb_assert(gc->gray_list == NULL); - incremental_gc(mrb, max); - mrb_assert(mrb->gc_state == GC_STATE_SWEEP); + incremental_gc(mrb, gc, max); + mrb_assert(gc->state == MRB_GC_STATE_SWEEP); - incremental_gc(mrb, max); - mrb_assert(mrb->gc_state == GC_STATE_ROOT); + incremental_gc(mrb, gc, max); + mrb_assert(gc->state == MRB_GC_STATE_ROOT); - free = (RVALUE*)mrb->heaps->freelist; + free = (RVALUE*)gc->heaps->freelist; while (free) { freed++; free = (RVALUE*)free->as.free.next; } - mrb_assert(mrb->live == live); - mrb_assert(mrb->live == total-freed); + mrb_assert(gc->live == live); + mrb_assert(gc->live == total-freed); puts("test_incremental_gc(gen)"); - incremental_gc_until(mrb, GC_STATE_SWEEP); - change_gen_gc_mode(mrb, TRUE); + incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP); + change_gen_gc_mode(mrb, gc, TRUE); - mrb_assert(mrb->gc_full == FALSE); - mrb_assert(mrb->gc_state == GC_STATE_ROOT); + mrb_assert(gc->full == FALSE); + mrb_assert(gc->state == MRB_GC_STATE_ROOT); puts(" in minor"); - mrb_assert(is_minor_gc(mrb)); - mrb_assert(mrb->majorgc_old_threshold > 0); - mrb->majorgc_old_threshold = 0; + mrb_assert(is_minor_gc(gc)); + mrb_assert(gc->majorgc_old_threshold > 0); + gc->majorgc_old_threshold = 0; mrb_incremental_gc(mrb); - mrb_assert(mrb->gc_full == TRUE); - mrb_assert(mrb->gc_state == GC_STATE_ROOT); + mrb_assert(gc->full == TRUE); + mrb_assert(gc->state == MRB_GC_STATE_ROOT); puts(" in major"); - mrb_assert(is_major_gc(mrb)); + mrb_assert(is_major_gc(gc)); do { mrb_incremental_gc(mrb); - } while (mrb->gc_state != GC_STATE_ROOT); - mrb_assert(mrb->gc_full == FALSE); + } while (gc->state != MRB_GC_STATE_ROOT); + mrb_assert(gc->full == FALSE); mrb_close(mrb); } @@ -1594,18 +1708,19 @@ test_incremental_sweep_phase(void) { mrb_state *mrb = mrb_open(); + mrb_gc *gc = &mrb->gc; puts("test_incremental_sweep_phase"); - add_heap(mrb); - mrb->sweeps = mrb->heaps; + add_heap(mrb, gc); + gc->sweeps = gc->heaps; - mrb_assert(mrb->heaps->next->next == NULL); - mrb_assert(mrb->free_heaps->next->next == NULL); - incremental_sweep_phase(mrb, MRB_HEAP_PAGE_SIZE*3); + mrb_assert(gc->heaps->next->next == NULL); + mrb_assert(gc->free_heaps->next->next == NULL); + incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3); - mrb_assert(mrb->heaps->next == NULL); - mrb_assert(mrb->heaps == mrb->free_heaps); + mrb_assert(gc->heaps->next == NULL); + mrb_assert(gc->heaps == gc->free_heaps); mrb_close(mrb); } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/hash.c mruby-1.2.0+20160315+git4f20d58a/src/hash.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/hash.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/hash.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,13 +4,13 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/hash.h" -#include "mruby/khash.h" -#include "mruby/string.h" -#include "mruby/variable.h" +#include +#include +#include +#include +#include +#include +#include /* a function to get hash value of a float number */ mrb_int mrb_float_id(mrb_float f); @@ -91,12 +91,6 @@ } } -typedef struct { - mrb_value v; - mrb_int n; -} mrb_hash_value; - -KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE) KHASH_DEFINE (ht, mrb_value, mrb_hash_value, TRUE, mrb_hash_ht_hash_func, mrb_hash_ht_hash_equal) static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); @@ -104,10 +98,11 @@ static inline mrb_value mrb_hash_ht_key(mrb_state *mrb, mrb_value key) { - if (mrb_string_p(key)) - return mrb_str_dup(mrb, key); - else - return key; + if (mrb_string_p(key) && !RSTR_FROZEN_P(mrb_str_ptr(key))) { + key = mrb_str_dup(mrb, key); + RSTR_SET_FROZEN_FLAG(mrb_str_ptr(key)); + } + return key; } #define KEY(key) mrb_hash_ht_key(mrb, key) @@ -177,10 +172,13 @@ } /* not found */ - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + if (MRB_RHASH_DEFAULT_P(hash)) { + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + } + return RHASH_IFNONE(hash); } - return RHASH_IFNONE(hash); + return mrb_nil_value(); } MRB_API mrb_value @@ -293,22 +291,22 @@ * default value. It is the block's responsibility to store the value * in the hash if required. * - * h = Hash.new("Go Fish") - * h["a"] = 100 - * h["b"] = 200 - * h["a"] #=> 100 - * h["c"] #=> "Go Fish" - * # The following alters the single default object - * h["c"].upcase! #=> "GO FISH" - * h["d"] #=> "GO FISH" - * h.keys #=> ["a", "b"] - * - * # While this creates a new default object each time - * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" } - * h["c"] #=> "Go Fish: c" - * h["c"].upcase! #=> "GO FISH: C" - * h["d"] #=> "Go Fish: d" - * h.keys #=> ["c", "d"] + * h = Hash.new("Go Fish") + * h["a"] = 100 + * h["b"] = 200 + * h["a"] #=> 100 + * h["c"] #=> "Go Fish" + * # The following alters the single default object + * h["c"].upcase! #=> "GO FISH" + * h["d"] #=> "GO FISH" + * h.keys #=> ["a", "b"] + * + * # While this creates a new default object each time + * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" } + * h["c"] #=> "Go Fish: c" + * h["c"].upcase! #=> "GO FISH: C" + * h["d"] #=> "Go Fish: d" + * h.keys #=> ["c", "d"] * */ @@ -328,7 +326,10 @@ RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; ifnone = block; } - mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); + if (!mrb_nil_p(ifnone)) { + RHASH(hash)->flags |= MRB_HASH_DEFAULT; + mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); + } return hash; } @@ -422,8 +423,13 @@ mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); - RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT); - + RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT; + if (!mrb_nil_p(ifnone)) { + RHASH(hash)->flags |= MRB_HASH_DEFAULT; + } + else { + RHASH(hash)->flags &= ~MRB_HASH_DEFAULT; + } return ifnone; } @@ -473,7 +479,14 @@ mrb_get_args(mrb, "o", &ifnone); mrb_hash_modify(mrb, hash); mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone); - RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; + if (!mrb_nil_p(ifnone)) { + RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT; + RHASH(hash)->flags |= MRB_HASH_DEFAULT; + } + else { + RHASH(hash)->flags &= ~MRB_HASH_DEFAULT; + RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT; + } return ifnone; } @@ -516,10 +529,10 @@ * key is not found, pass in the key and return the result of * block. * - * h = { "a" => 100, "b" => 200 } - * h.delete("a") #=> 100 - * h.delete("z") #=> nil - * h.delete("z") { |el| "#{el} not found" } #=> "z not found" + * h = { "a" => 100, "b" => 200 } + * h.delete("a") #=> 100 + * h.delete("z") #=> nil + * h.delete("z") { |el| "#{el} not found" } #=> "z not found" * */ static mrb_value @@ -540,9 +553,9 @@ * two-item array [ key, value ], or * the hash's default value if the hash is empty. * - * h = { 1 => "a", 2 => "b", 3 => "c" } - * h.shift #=> [1, "a"] - * h #=> {2=>"b", 3=>"c"} + * h = { 1 => "a", 2 => "b", 3 => "c" } + * h.shift #=> [1, "a"] + * h #=> {2=>"b", 3=>"c"} */ static mrb_value @@ -566,12 +579,15 @@ } } - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value()); - } - else { - return RHASH_IFNONE(hash); + if (MRB_RHASH_DEFAULT_P(hash)) { + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, mrb_nil_value()); + } + else { + return RHASH_IFNONE(hash); + } } + return mrb_nil_value(); } /* 15.2.13.4.4 */ @@ -579,10 +595,10 @@ * call-seq: * hsh.clear -> hsh * - * Removes all key-value pairs from hsh. + * Removes all key-value pairs from `hsh`. * - * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200} - * h.clear #=> {} + * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200} + * h.clear #=> {} * */ @@ -608,10 +624,10 @@ * use as a key (a String passed as a key will be * duplicated and frozen). * - * h = { "a" => 100, "b" => 200 } - * h["a"] = 9 - * h["c"] = 4 - * h #=> {"a"=>9, "b"=>200, "c"=>4} + * h = { "a" => 100, "b" => 200 } + * h["a"] = 9 + * h["c"] = 4 + * h #=> {"a"=>9, "b"=>200, "c"=>4} * */ static mrb_value @@ -826,7 +842,7 @@ { struct RClass *h; - h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */ + mrb->hash_class = h = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */ MRB_SET_INSTANCE_TT(h, MRB_TT_HASH); mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/init.c mruby-1.2.0+20160315+git4f20d58a/src/init.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/init.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/init.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,7 +4,7 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" +#include void mrb_init_symtbl(mrb_state*); void mrb_init_class(mrb_state*); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/kernel.c mruby-1.2.0+20160315+git4f20d58a/src/kernel.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/kernel.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/kernel.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,13 +4,13 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" +#include +#include +#include +#include +#include +#include +#include typedef enum { NOEX_PUBLIC = 0x00, @@ -654,13 +654,13 @@ { khint_t i; mrb_value ary; - mrb_bool prepended; + mrb_bool prepended = FALSE; struct RClass* oldklass; khash_t(st)* set = kh_init(st, mrb); if (!recur && (klass->flags & MRB_FLAG_IS_PREPENDED)) { MRB_CLASS_ORIGIN(klass); - prepended = 1; + prepended = TRUE; } oldklass = 0; @@ -1097,7 +1097,7 @@ { struct RClass *krn; - krn = mrb->kernel_module = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */ + mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */ mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */ mrb_define_class_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.2.4 */ mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/load.c mruby-1.2.0+20160315+git4f20d58a/src/load.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/load.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/load.c 2016-03-14 00:35:53.000000000 +0000 @@ -7,12 +7,12 @@ #include #include #include -#include "mruby/dump.h" -#include "mruby/irep.h" -#include "mruby/proc.h" -#include "mruby/string.h" -#include "mruby/debug.h" -#include "mruby/error.h" +#include +#include +#include +#include +#include +#include #if SIZE_MAX < UINT32_MAX # error size_t must be at least 32 bits wide @@ -614,10 +614,12 @@ return read_irep(mrb, bin, flags); } +void mrb_exc_set(mrb_state *mrb, mrb_value exc); + static void irep_error(mrb_state *mrb) { - mrb->exc = mrb_obj_ptr(mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error")); + mrb_exc_set(mrb, mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error")); } MRB_API mrb_value @@ -633,7 +635,7 @@ proc = mrb_proc_new(mrb, irep); mrb_irep_decref(mrb, irep); if (c && c->no_exec) return mrb_obj_value(proc); - return mrb_toplevel_run(mrb, proc); + return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0); } MRB_API mrb_value @@ -642,7 +644,7 @@ return mrb_load_irep_cxt(mrb, bin, NULL); } -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO MRB_API mrb_irep* mrb_read_irep_file(mrb_state *mrb, FILE* fp) @@ -695,7 +697,7 @@ mrb_irep_decref(mrb, irep); if (c && c->dump_result) mrb_codedump_all(mrb, proc); if (c && c->no_exec) return mrb_obj_value(proc); - val = mrb_toplevel_run(mrb, proc); + val = mrb_top_run(mrb, proc, mrb_top_self(mrb), 0); return val; } @@ -704,4 +706,4 @@ { return mrb_load_irep_file_cxt(mrb, fp, NULL); } -#endif /* ENABLE_STDIO */ +#endif /* MRB_DISABLE_STDIO */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/numeric.c mruby-1.2.0+20160315+git4f20d58a/src/numeric.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/numeric.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/numeric.c 2016-03-14 00:35:53.000000000 +0000 @@ -9,10 +9,10 @@ #include #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/numeric.h" -#include "mruby/string.h" +#include +#include +#include +#include #ifdef MRB_USE_FLOAT #define floor(f) floorf(f) @@ -821,14 +821,28 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width) { mrb_assert(width > 0); - if (width > NUMERIC_SHIFT_WIDTH_MAX) { + if (val > 0) { + if ((width > NUMERIC_SHIFT_WIDTH_MAX) || + (val > (MRB_INT_MAX >> width))) { + goto bit_overflow; + } + } else { + if ((width > NUMERIC_SHIFT_WIDTH_MAX) || + (val < (MRB_INT_MIN >> width))) { + goto bit_overflow; + } + } + + return mrb_fixnum_value(val << width); + +bit_overflow: + { mrb_float f = (mrb_float)val; while (width--) { f *= 2; } return mrb_float_value(mrb, f); } - return mrb_fixnum_value(val << width); } static mrb_value @@ -856,7 +870,7 @@ /* 15.2.8.3.12 */ /* * call-seq: - * fix << count -> integer + * fix << count -> integer or float * * Shifts _fix_ left _count_ positions (right if _count_ is negative). */ @@ -881,7 +895,7 @@ /* 15.2.8.3.13 */ /* * call-seq: - * fix >> count -> integer + * fix >> count -> integer or float * * Shifts _fix_ right _count_ positions (left if _count_ is negative). */ @@ -950,7 +964,12 @@ if (isnan(d)) { mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); } - z = (mrb_int)d; + if (FIXABLE(d)) { + z = (mrb_int)d; + } + else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x); + } } return mrb_fixnum_value(z); } @@ -1161,7 +1180,7 @@ mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); /* Fixnum Class */ - fixnum = mrb->fixnum_class = mrb_define_class(mrb, "Fixnum", integer); + mrb->fixnum_class = fixnum = mrb_define_class(mrb, "Fixnum", integer); mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ @@ -1181,7 +1200,7 @@ mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */ /* Float Class */ - fl = mrb->float_class = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ + mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ mrb_undef_class_method(mrb, fl, "new"); mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/object.c mruby-1.2.0+20160315+git4f20d58a/src/object.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/object.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/object.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,10 +4,10 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/numeric.h" -#include "mruby/string.h" +#include +#include +#include +#include MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value v1, mrb_value v2) @@ -264,7 +264,7 @@ struct RClass *t; struct RClass *f; - n = mrb->nil_class = mrb_define_class(mrb, "NilClass", mrb->object_class); + mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class); mrb_undef_class_method(mrb, n, "new"); mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ @@ -273,7 +273,7 @@ mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */ mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE()); - t = mrb->true_class = mrb_define_class(mrb, "TrueClass", mrb->object_class); + mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class); mrb_undef_class_method(mrb, t, "new"); mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ @@ -281,7 +281,7 @@ mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */ mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE()); - f = mrb->false_class = mrb_define_class(mrb, "FalseClass", mrb->object_class); + mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class); mrb_undef_class_method(mrb, f, "new"); mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ @@ -481,6 +481,7 @@ case MRB_TT_MODULE: case MRB_TT_CLASS: case MRB_TT_ICLASS: + case MRB_TT_SCLASS: break; default: diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/opcode.h mruby-1.2.0+20160315+git4f20d58a/src/opcode.h --- mruby-1.1.0+20150906+git1cbbb7e1/src/opcode.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/opcode.h 2016-03-14 00:35:53.000000000 +0000 @@ -1,2 +1,2 @@ /* this header file is to be removed soon. */ -#include "mruby/opcode.h" +#include diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/pool.c mruby-1.2.0+20160315+git4f20d58a/src/pool.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/pool.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/pool.c 2016-03-14 00:35:53.000000000 +0000 @@ -7,7 +7,7 @@ #include #include #include -#include "mruby.h" +#include /* configuration section */ /* allocated memory address should be multiple of POOL_ALIGNMENT */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/print.c mruby-1.2.0+20160315+git4f20d58a/src/print.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/print.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/print.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,11 +4,11 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/string.h" -#include "mruby/variable.h" +#include +#include +#include -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO static void printstr(mrb_value obj, FILE *stream) { @@ -24,35 +24,24 @@ MRB_API void mrb_p(mrb_state *mrb, mrb_value obj) { - mrb_value val = mrb_inspect(mrb, obj); - - printstr(val, stdout); + printstr(mrb_inspect(mrb, obj), stdout); } MRB_API void mrb_print_error(mrb_state *mrb) { - mrb_value s; - mrb_print_backtrace(mrb); - s = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); - printstr(s, stderr); + printstr(mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0), stderr); } MRB_API void mrb_show_version(mrb_state *mrb) { - mrb_value msg; - - msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")); - printstr(msg, stdout); + printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_DESCRIPTION")), stdout); } MRB_API void mrb_show_copyright(mrb_state *mrb) { - mrb_value msg; - - msg = mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")); - printstr(msg, stdout); + printstr(mrb_const_get(mrb, mrb_obj_value(mrb->object_class), mrb_intern_lit(mrb, "MRUBY_COPYRIGHT")), stdout); } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/proc.c mruby-1.2.0+20160315+git4f20d58a/src/proc.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/proc.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/proc.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,10 +4,10 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/opcode.h" +#include +#include +#include +#include static mrb_code call_iseq[] = { MKOP_A(OP_CALL, 0), diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/range.c mruby-1.2.0+20160315+git4f20d58a/src/range.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/range.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/range.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,11 +4,11 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/class.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/array.h" +#include +#include +#include +#include +#include #define RANGE_CLASS (mrb_class_get(mrb, "Range")) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/state.c mruby-1.2.0+20160315+git4f20d58a/src/state.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/state.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/state.c 2016-03-14 00:35:53.000000000 +0000 @@ -6,16 +6,18 @@ #include #include -#include "mruby.h" -#include "mruby/irep.h" -#include "mruby/variable.h" -#include "mruby/debug.h" -#include "mruby/string.h" +#include +#include +#include +#include +#include -void mrb_init_heap(mrb_state*); void mrb_init_core(mrb_state*); void mrb_init_mrbgems(mrb_state*); +void mrb_gc_init(mrb_state*, mrb_gc *gc); +void mrb_gc_destroy(mrb_state*, mrb_gc *gc); + static mrb_value inspect_main(mrb_state *mrb, mrb_value mod) { @@ -35,15 +37,9 @@ *mrb = mrb_state_zero; mrb->allocf_ud = ud; mrb->allocf = f; - mrb->current_white_part = MRB_GC_WHITE_A; mrb->atexit_stack_len = 0; -#ifndef MRB_GC_FIXED_ARENA - mrb->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE); - mrb->arena_capa = MRB_GC_ARENA_SIZE; -#endif - - mrb_init_heap(mrb); + mrb_gc_init(mrb, &mrb->gc); mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); *mrb->c = mrb_context_zero; mrb->root_c = mrb->c; @@ -122,7 +118,6 @@ } void mrb_free_symtbl(mrb_state *mrb); -void mrb_free_heap(mrb_state *mrb); void mrb_irep_incref(mrb_state *mrb, mrb_irep *irep) @@ -220,6 +215,8 @@ return mrb_obj_value(ns); } +void mrb_free_backtrace(mrb_state *mrb); + MRB_API void mrb_free_context(mrb_state *mrb, struct mrb_context *c) { @@ -234,6 +231,7 @@ MRB_API void mrb_close(mrb_state *mrb) { + if (!mrb) return; if (mrb->atexit_stack_len > 0) { mrb_int i; for (i = mrb->atexit_stack_len; i > 0; --i) { @@ -246,13 +244,11 @@ /* free */ mrb_gc_free_gv(mrb); + mrb_free_backtrace(mrb); mrb_free_context(mrb, mrb->root_c); mrb_free_symtbl(mrb); - mrb_free_heap(mrb); mrb_alloca_free(mrb); -#ifndef MRB_GC_FIXED_ARENA - mrb_free(mrb, mrb->arena); -#endif + mrb_gc_destroy(mrb, &mrb->gc); mrb_free(mrb, mrb); } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/string.c mruby-1.2.0+20160315+git4f20d58a/src/string.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/string.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/string.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,19 +4,21 @@ ** See Copyright Notice in mruby.h */ +#ifdef _MSC_VER +# define _CRT_NONSTDC_NO_DEPRECATE +#endif + #include #include #include #include #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/re.h" - -const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +#include +#include +#include +#include +#include +#include typedef struct mrb_shared_string { mrb_bool nofree : 1; @@ -25,135 +27,7 @@ mrb_int len; } mrb_shared_string; -static mrb_value str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2); -static mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len); - -MRB_API mrb_int -mrb_str_strlen(mrb_state *mrb, struct RString *s) -{ - mrb_int i, max = RSTR_LEN(s); - char *p = RSTR_PTR(s); - - if (!p) return 0; - for (i=0; ias.ary, len); - RSTR_UNSET_EMBED_FLAG(s); - s->as.heap.ptr = tmp; - s->as.heap.len = len; - s->as.heap.aux.capa = capacity; - } - } - else { - s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); - s->as.heap.aux.capa = capacity; - } -} - -static void -str_decref(mrb_state *mrb, mrb_shared_string *shared) -{ - shared->refcnt--; - if (shared->refcnt == 0) { - if (!shared->nofree) { - mrb_free(mrb, shared->ptr); - } - mrb_free(mrb, shared); - } -} - -static void -check_frozen(mrb_state *mrb, struct RString *s) -{ - if (RSTR_FROZEN_P(s)) { - mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); - } -} - -MRB_API void -mrb_str_modify(mrb_state *mrb, struct RString *s) -{ - check_frozen(mrb, s); - if (RSTR_SHARED_P(s)) { - mrb_shared_string *shared = s->as.heap.aux.shared; - - if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) { - s->as.heap.ptr = shared->ptr; - s->as.heap.aux.capa = shared->len; - RSTR_PTR(s)[s->as.heap.len] = '\0'; - mrb_free(mrb, shared); - } - else { - char *ptr, *p; - mrb_int len; - - p = RSTR_PTR(s); - len = s->as.heap.len; - ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); - if (p) { - memcpy(ptr, p, len); - } - ptr[len] = '\0'; - s->as.heap.ptr = ptr; - s->as.heap.aux.capa = len; - str_decref(mrb, shared); - } - RSTR_UNSET_SHARED_FLAG(s); - return; - } - if (RSTR_NOFREE_P(s)) { - char *p = s->as.heap.ptr; - - s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1); - if (p) { - memcpy(RSTR_PTR(s), p, s->as.heap.len); - } - RSTR_PTR(s)[s->as.heap.len] = '\0'; - s->as.heap.aux.capa = s->as.heap.len; - RSTR_UNSET_NOFREE_FLAG(s); - return; - } -} - -static mrb_value -mrb_str_freeze(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - - RSTR_SET_FROZEN_FLAG(s); - return str; -} - -MRB_API mrb_value -mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) -{ - mrb_int slen; - struct RString *s = mrb_str_ptr(str); - - mrb_str_modify(mrb, s); - slen = RSTR_LEN(s); - if (len != slen) { - if (slen < len || slen - len > 256) { - resize_capa(mrb, s, len); - } - RSTR_SET_LEN(s, len); - RSTR_PTR(s)[len] = '\0'; /* sentinel */ - } - return str; -} +const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; #define mrb_obj_alloc_string(mrb) ((struct RString*)mrb_obj_alloc((mrb), MRB_TT_STRING, (mrb)->string_class)) @@ -244,6 +118,26 @@ return mrb_obj_value(s); } +static inline void +resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity) +{ + if (RSTR_EMBED_P(s)) { + if (RSTRING_EMBED_LEN_MAX < capacity) { + char *const tmp = (char *)mrb_malloc(mrb, capacity+1); + const mrb_int len = RSTR_EMBED_LEN(s); + memcpy(tmp, s->as.ary, len); + RSTR_UNSET_EMBED_FLAG(s); + s->as.heap.ptr = tmp; + s->as.heap.len = len; + s->as.heap.aux.capa = capacity; + } + } + else { + s->as.heap.ptr = (char *)mrb_realloc(mrb, RSTR_PTR(s), capacity+1); + s->as.heap.aux.capa = capacity; + } +} + static void str_buf_cat(mrb_state *mrb, struct RString *s, const char *ptr, size_t len) { @@ -257,81 +151,580 @@ off = ptr - RSTR_PTR(s); } - if (RSTR_EMBED_P(s)) - capa = RSTRING_EMBED_LEN_MAX; - else - capa = s->as.heap.aux.capa; + if (RSTR_EMBED_P(s)) + capa = RSTRING_EMBED_LEN_MAX; + else + capa = s->as.heap.aux.capa; + + if (RSTR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); + } + total = RSTR_LEN(s)+len; + if (capa <= total) { + while (total > capa) { + if (capa + 1 >= MRB_INT_MAX / 2) { + capa = (total + 4095) / 4096; + break; + } + capa = (capa + 1) * 2; + } + resize_capa(mrb, s, capa); + } + if (off != -1) { + ptr = RSTR_PTR(s) + off; + } + memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len); + mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX); + RSTR_SET_LEN(s, total); + RSTR_PTR(s)[total] = '\0'; /* sentinel */ +} + +MRB_API mrb_value +mrb_str_new(mrb_state *mrb, const char *p, size_t len) +{ + return mrb_obj_value(str_new(mrb, p, len)); +} + +/* + * call-seq: (Caution! NULL string) + * String.new(str="") => new_str + * + * Returns a new string object containing a copy of str. + */ + +MRB_API mrb_value +mrb_str_new_cstr(mrb_state *mrb, const char *p) +{ + struct RString *s; + size_t len; + + if (p) { + len = strlen(p); + } + else { + len = 0; + } + + s = str_new(mrb, p, len); + + return mrb_obj_value(s); +} + +MRB_API mrb_value +mrb_str_new_static(mrb_state *mrb, const char *p, size_t len) +{ + struct RString *s = str_new_static(mrb, p, len); + return mrb_obj_value(s); +} + +static void +str_decref(mrb_state *mrb, mrb_shared_string *shared) +{ + shared->refcnt--; + if (shared->refcnt == 0) { + if (!shared->nofree) { + mrb_free(mrb, shared->ptr); + } + mrb_free(mrb, shared); + } +} + +void +mrb_gc_free_str(mrb_state *mrb, struct RString *str) +{ + if (RSTR_EMBED_P(str)) + /* no code */; + else if (RSTR_SHARED_P(str)) + str_decref(mrb, str->as.heap.aux.shared); + else if (!RSTR_NOFREE_P(str)) + mrb_free(mrb, str->as.heap.ptr); +} + +#ifdef MRB_UTF8_STRING +static const char utf8len_codepage[256] = +{ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1, +}; + +static mrb_int +utf8len(const char* p, const char* e) +{ + mrb_int len; + mrb_int i; + + len = utf8len_codepage[(unsigned char)*p]; + if (p + len > e) return 1; + for (i = 1; i < len; ++i) + if ((p[i] & 0xc0) != 0x80) + return 1; + return len; +} + +static mrb_int +utf8_strlen(mrb_value str, mrb_int len) +{ + mrb_int total = 0; + char* p = RSTRING_PTR(str); + char* e = p; + if (RSTRING(str)->flags & MRB_STR_NO_UTF) { + return RSTRING_LEN(str); + } + e += len < 0 ? RSTRING_LEN(str) : len; + while (pflags |= MRB_STR_NO_UTF; + } + return total; +} + +#define RSTRING_CHAR_LEN(s) utf8_strlen(s, -1) + +/* map character index to byte offset index */ +static mrb_int +chars2bytes(mrb_value s, mrb_int off, mrb_int idx) +{ + mrb_int i, b, n; + const char *p = RSTRING_PTR(s) + off; + const char *e = RSTRING_END(s); + + for (b=i=0; p n) return -1; + else if (m == n) { + return memcmp(x0, y0, m) == 0 ? 0 : -1; + } + else if (m < 1) { + return 0; + } + else if (m == 1) { + const unsigned char *ys = memchr(y, *x, n); + + if (ys) + return ys - y; + else + return -1; + } + return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n); +} + +static void +str_make_shared(mrb_state *mrb, struct RString *s) +{ + if (!RSTR_SHARED_P(s)) { + mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string)); + + shared->refcnt = 1; + if (RSTR_EMBED_P(s)) { + const mrb_int len = RSTR_EMBED_LEN(s); + char *const tmp = (char *)mrb_malloc(mrb, len+1); + memcpy(tmp, s->as.ary, len); + tmp[len] = '\0'; + RSTR_UNSET_EMBED_FLAG(s); + s->as.heap.ptr = tmp; + s->as.heap.len = len; + shared->nofree = FALSE; + shared->ptr = s->as.heap.ptr; + } + else if (RSTR_NOFREE_P(s)) { + shared->nofree = TRUE; + shared->ptr = s->as.heap.ptr; + RSTR_UNSET_NOFREE_FLAG(s); + } + else { + shared->nofree = FALSE; + if (s->as.heap.aux.capa > s->as.heap.len) { + s->as.heap.ptr = shared->ptr = (char *)mrb_realloc(mrb, s->as.heap.ptr, s->as.heap.len+1); + } + else { + shared->ptr = s->as.heap.ptr; + } + } + shared->len = s->as.heap.len; + s->as.heap.aux.shared = shared; + RSTR_SET_SHARED_FLAG(s); + } +} + +static mrb_value +byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) +{ + struct RString *orig, *s; + mrb_shared_string *shared; + + orig = mrb_str_ptr(str); + if (RSTR_EMBED_P(orig)) { + s = str_new(mrb, orig->as.ary+beg, len); + } + else { + str_make_shared(mrb, orig); + shared = orig->as.heap.aux.shared; + s = mrb_obj_alloc_string(mrb); + s->as.heap.ptr = orig->as.heap.ptr + beg; + s->as.heap.len = len; + s->as.heap.aux.shared = shared; + RSTR_SET_SHARED_FLAG(s); + shared->refcnt++; + } + + return mrb_obj_value(s); +} +#ifdef MRB_UTF8_STRING +static inline mrb_value +str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) +{ + beg = chars2bytes(str, 0, beg); + len = chars2bytes(str, beg, len); + + return byte_subseq(mrb, str, beg, len); +} +#else +#define str_subseq(mrb, str, beg, len) byte_subseq(mrb, str, beg, len) +#endif + +static mrb_value +str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) +{ + mrb_int clen = RSTRING_CHAR_LEN(str); + + if (len < 0) return mrb_nil_value(); + if (clen == 0) { + len = 0; + } + else if (beg < 0) { + beg = clen + beg; + } + if (beg > clen) return mrb_nil_value(); + if (beg < 0) { + beg += clen; + if (beg < 0) return mrb_nil_value(); + } + if (beg + len > clen) + len = clen - beg; + if (len <= 0) { + len = 0; + } + return str_subseq(mrb, str, beg, len); +} + +static mrb_int +str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) +{ + mrb_int pos; + char *s, *sptr; + mrb_int len, slen; + + len = RSTRING_LEN(str); + slen = RSTRING_LEN(sub); + if (offset < 0) { + offset += len; + if (offset < 0) return -1; + } + if (len - offset < slen) return -1; + s = RSTRING_PTR(str); + if (offset) { + s += offset; + } + if (slen == 0) return offset; + /* need proceed one character at a time */ + sptr = RSTRING_PTR(sub); + slen = RSTRING_LEN(sub); + len = RSTRING_LEN(str) - offset; + pos = mrb_memsearch(sptr, slen, s, len); + if (pos < 0) return pos; + return pos + offset; +} + +static void +check_frozen(mrb_state *mrb, struct RString *s) +{ + if (RSTR_FROZEN_P(s)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); + } +} + +static mrb_value +str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2) +{ + long len; + + check_frozen(mrb, s1); + len = RSTR_LEN(s2); + if (RSTR_SHARED_P(s1)) { + str_decref(mrb, s1->as.heap.aux.shared); + } + else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) { + mrb_free(mrb, s1->as.heap.ptr); + } + + RSTR_UNSET_NOFREE_FLAG(s1); + + if (RSTR_SHARED_P(s2)) { +L_SHARE: + RSTR_UNSET_EMBED_FLAG(s1); + s1->as.heap.ptr = s2->as.heap.ptr; + s1->as.heap.len = len; + s1->as.heap.aux.shared = s2->as.heap.aux.shared; + RSTR_SET_SHARED_FLAG(s1); + s1->as.heap.aux.shared->refcnt++; + } + else { + if (len <= RSTRING_EMBED_LEN_MAX) { + RSTR_UNSET_SHARED_FLAG(s1); + RSTR_SET_EMBED_FLAG(s1); + memcpy(s1->as.ary, RSTR_PTR(s2), len); + RSTR_SET_EMBED_LEN(s1, len); + } + else { + str_make_shared(mrb, s2); + goto L_SHARE; + } + } + + return mrb_obj_value(s1); +} - if (RSTR_LEN(s) >= MRB_INT_MAX - (mrb_int)len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big"); +static mrb_int +str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) +{ + char *s, *sbeg, *t; + struct RString *ps = mrb_str_ptr(str); + mrb_int len = RSTRING_LEN(sub); + + /* substring longer than string */ + if (RSTR_LEN(ps) < len) return -1; + if (RSTR_LEN(ps) - pos < len) { + pos = RSTR_LEN(ps) - len; } - total = RSTR_LEN(s)+len; - if (capa <= total) { - while (total > capa) { - if (capa + 1 >= MRB_INT_MAX / 2) { - capa = (total + 4095) / 4096; - break; + sbeg = RSTR_PTR(ps); + s = RSTR_PTR(ps) + pos; + t = RSTRING_PTR(sub); + if (len) { + while (sbeg <= s) { + if (memcmp(s, t, len) == 0) { + return s - RSTR_PTR(ps); } - capa = (capa + 1) * 2; + s--; } - resize_capa(mrb, s, capa); + return -1; } - if (off != -1) { - ptr = RSTR_PTR(s) + off; + else { + return pos; } - memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len); - mrb_assert_int_fit(size_t, total, mrb_int, MRB_INT_MAX); - RSTR_SET_LEN(s, total); - RSTR_PTR(s)[total] = '\0'; /* sentinel */ } -MRB_API mrb_value -mrb_str_new(mrb_state *mrb, const char *p, size_t len) +MRB_API mrb_int +mrb_str_strlen(mrb_state *mrb, struct RString *s) { - return mrb_obj_value(str_new(mrb, p, len)); + mrb_int i, max = RSTR_LEN(s); + char *p = RSTR_PTR(s); + + if (!p) return 0; + for (i=0; i new_str - * - * Returns a new string object containing a copy of str. - */ +#ifdef _WIN32 +#include -MRB_API mrb_value -mrb_str_new_cstr(mrb_state *mrb, const char *p) +char* +mrb_utf8_from_locale(const char *str, size_t len) { - struct RString *s; - size_t len; + wchar_t* wcsp; + char* mbsp; + size_t mbssize, wcssize; + + if (len == 0) + return strdup(""); + if (len == -1) + len = strlen(str); + wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0); + wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t)); + if (!wcsp) + return NULL; + wcssize = MultiByteToWideChar(GetACP(), 0, str, len, wcsp, wcssize + 1); + wcsp[wcssize] = 0; + + mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL); + mbsp = (char*) malloc((mbssize + 1)); + if (!mbsp) { + free(wcsp); + return NULL; + } + mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL); + mbsp[mbssize] = 0; + free(wcsp); + return mbsp; +} + +char* +mrb_locale_from_utf8(const char *utf8, size_t len) +{ + wchar_t* wcsp; + char* mbsp; + size_t mbssize, wcssize; + + if (len == 0) + return strdup(""); + if (len == -1) + len = strlen(utf8); + wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0); + wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t)); + if (!wcsp) + return NULL; + wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1); + wcsp[wcssize] = 0; + mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL); + mbsp = (char*) malloc((mbssize + 1)); + if (!mbsp) { + free(wcsp); + return NULL; + } + mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL); + mbsp[mbssize] = 0; + free(wcsp); + return mbsp; +} +#endif - if (p) { - len = strlen(p); +MRB_API void +mrb_str_modify(mrb_state *mrb, struct RString *s) +{ + check_frozen(mrb, s); + s->flags &= ~MRB_STR_NO_UTF; + if (RSTR_SHARED_P(s)) { + mrb_shared_string *shared = s->as.heap.aux.shared; + + if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) { + s->as.heap.ptr = shared->ptr; + s->as.heap.aux.capa = shared->len; + RSTR_PTR(s)[s->as.heap.len] = '\0'; + mrb_free(mrb, shared); + } + else { + char *ptr, *p; + mrb_int len; + + p = RSTR_PTR(s); + len = s->as.heap.len; + ptr = (char *)mrb_malloc(mrb, (size_t)len + 1); + if (p) { + memcpy(ptr, p, len); + } + ptr[len] = '\0'; + s->as.heap.ptr = ptr; + s->as.heap.aux.capa = len; + str_decref(mrb, shared); + } + RSTR_UNSET_SHARED_FLAG(s); + return; } - else { - len = 0; + if (RSTR_NOFREE_P(s)) { + char *p = s->as.heap.ptr; + + s->as.heap.ptr = (char *)mrb_malloc(mrb, (size_t)s->as.heap.len+1); + if (p) { + memcpy(RSTR_PTR(s), p, s->as.heap.len); + } + RSTR_PTR(s)[s->as.heap.len] = '\0'; + s->as.heap.aux.capa = s->as.heap.len; + RSTR_UNSET_NOFREE_FLAG(s); + return; } +} - s = str_new(mrb, p, len); +static mrb_value +mrb_str_freeze(mrb_state *mrb, mrb_value str) +{ + struct RString *s = mrb_str_ptr(str); - return mrb_obj_value(s); + RSTR_SET_FROZEN_FLAG(s); + return str; } MRB_API mrb_value -mrb_str_new_static(mrb_state *mrb, const char *p, size_t len) +mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) { - struct RString *s = str_new_static(mrb, p, len); - return mrb_obj_value(s); -} + mrb_int slen; + struct RString *s = mrb_str_ptr(str); -void -mrb_gc_free_str(mrb_state *mrb, struct RString *str) -{ - if (RSTR_EMBED_P(str)) - /* no code */; - else if (RSTR_SHARED_P(str)) - str_decref(mrb, str->as.heap.aux.shared); - else if (!RSTR_NOFREE_P(str)) - mrb_free(mrb, str->as.heap.ptr); + mrb_str_modify(mrb, s); + slen = RSTR_LEN(s); + if (len != slen) { + if (slen < len || slen - len > 256) { + resize_capa(mrb, s, len); + } + RSTR_SET_LEN(s, len); + RSTR_PTR(s)[len] = '\0'; /* sentinel */ + } + return str; } MRB_API char* @@ -350,44 +743,6 @@ return RSTR_PTR(s); } -static void -str_make_shared(mrb_state *mrb, struct RString *s) -{ - if (!RSTR_SHARED_P(s)) { - mrb_shared_string *shared = (mrb_shared_string *)mrb_malloc(mrb, sizeof(mrb_shared_string)); - - shared->refcnt = 1; - if (RSTR_EMBED_P(s)) { - const mrb_int len = RSTR_EMBED_LEN(s); - char *const tmp = (char *)mrb_malloc(mrb, len+1); - memcpy(tmp, s->as.ary, len); - tmp[len] = '\0'; - RSTR_UNSET_EMBED_FLAG(s); - s->as.heap.ptr = tmp; - s->as.heap.len = len; - shared->nofree = FALSE; - shared->ptr = s->as.heap.ptr; - } - else if (RSTR_NOFREE_P(s)) { - shared->nofree = TRUE; - shared->ptr = s->as.heap.ptr; - RSTR_UNSET_NOFREE_FLAG(s); - } - else { - shared->nofree = FALSE; - if (s->as.heap.aux.capa > s->as.heap.len) { - s->as.heap.ptr = shared->ptr = (char *)mrb_realloc(mrb, s->as.heap.ptr, s->as.heap.len+1); - } - else { - shared->ptr = s->as.heap.ptr; - } - } - shared->len = s->as.heap.len; - s->as.heap.aux.shared = shared; - RSTR_SET_SHARED_FLAG(s); - } -} - /* * call-seq: (Caution! String("abcd") change) * String("abcdefg") = String("abcd") + String("efg") @@ -456,15 +811,22 @@ /* 15.2.10.5.33 */ /* * call-seq: - * len = strlen(String("abcd")) + * "abcd".size => int * * Returns the length of string. */ static mrb_value mrb_str_size(mrb_state *mrb, mrb_value self) { - struct RString *s = mrb_str_ptr(self); - return mrb_fixnum_value(RSTR_LEN(s)); + mrb_int len = RSTRING_CHAR_LEN(self); + return mrb_fixnum_value(len); +} + +static mrb_value +mrb_str_bytesize(mrb_state *mrb, mrb_value self) +{ + mrb_int len = RSTRING_LEN(self); + return mrb_fixnum_value(len); } /* 15.2.10.5.1 */ @@ -655,99 +1017,35 @@ } return s; } - return str; -} - -MRB_API const char* -mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr) -{ - mrb_value str = mrb_str_to_str(mrb, ptr); - return RSTRING_PTR(str); -} - -void -mrb_noregexp(mrb_state *mrb, mrb_value self) -{ - mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented"); -} - -void -mrb_regexp_check(mrb_state *mrb, mrb_value obj) -{ - if (mrb_regexp_p(mrb, obj)) { - mrb_noregexp(mrb, obj); - } -} - -static inline mrb_int -mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n) -{ - const unsigned char *x = xs, *xe = xs + m; - const unsigned char *y = ys; - int i, qstable[256]; - - /* Preprocessing */ - for (i = 0; i < 256; ++i) - qstable[i] = m + 1; - for (; x < xe; ++x) - qstable[*x] = xe - x; - /* Searching */ - for (; y + m <= ys + n; y += *(qstable + y[m])) { - if (*xs == *y && memcmp(xs, y, m) == 0) - return y - ys; - } - return -1; -} - -static mrb_int -mrb_memsearch(const void *x0, mrb_int m, const void *y0, mrb_int n) -{ - const unsigned char *x = (const unsigned char *)x0, *y = (const unsigned char *)y0; - - if (m > n) return -1; - else if (m == n) { - return memcmp(x0, y0, m) == 0 ? 0 : -1; - } - else if (m < 1) { - return 0; - } - else if (m == 1) { - const unsigned char *ys = y, *ye = ys + n; - for (; y < ye; ++y) { - if (*x == *y) - return y - ys; - } - return -1; - } - return mrb_memsearch_qs((const unsigned char *)x0, m, (const unsigned char *)y0, n); + return str; } -static mrb_int -mrb_str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) +MRB_API const char* +mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr) { - mrb_int pos; - char *s, *sptr; - mrb_int len, slen; + mrb_value str = mrb_str_to_str(mrb, ptr); + return RSTRING_PTR(str); +} - len = RSTRING_LEN(str); - slen = RSTRING_LEN(sub); - if (offset < 0) { - offset += len; - if (offset < 0) return -1; - } - if (len - offset < slen) return -1; - s = RSTRING_PTR(str); - if (offset) { - s += offset; +MRB_API mrb_int +mrb_string_value_len(mrb_state *mrb, mrb_value ptr) +{ + mrb_value str = mrb_str_to_str(mrb, ptr); + return RSTRING_LEN(str); +} + +void +mrb_noregexp(mrb_state *mrb, mrb_value self) +{ + mrb_raise(mrb, E_NOTIMP_ERROR, "Regexp class not implemented"); +} + +void +mrb_regexp_check(mrb_state *mrb, mrb_value obj) +{ + if (mrb_regexp_p(mrb, obj)) { + mrb_noregexp(mrb, obj); } - if (slen == 0) return offset; - /* need proceed one character at a time */ - sptr = RSTRING_PTR(sub); - slen = RSTRING_LEN(sub); - len = RSTRING_LEN(str) - offset; - pos = mrb_memsearch(sptr, slen, s, len); - if (pos < 0) return pos; - return pos + offset; } MRB_API mrb_value @@ -771,12 +1069,12 @@ idx = mrb_fixnum(indx); num_index: - str = mrb_str_substr(mrb, str, idx, 1); + str = str_substr(mrb, str, idx, 1); if (!mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value(); return str; case MRB_TT_STRING: - if (mrb_str_index(mrb, str, indx, 0) != -1) + if (str_index(mrb, str, indx, 0) != -1) return mrb_str_dup(mrb, indx); return mrb_nil_value(); @@ -785,9 +1083,9 @@ { mrb_int beg, len; - len = RSTRING_LEN(str); + len = RSTRING_CHAR_LEN(str); if (mrb_range_beg_len(mrb, indx, &beg, &len, len)) { - return mrb_str_subseq(mrb, str, beg, len); + return str_subseq(mrb, str, beg, len); } else { return mrb_nil_value(); @@ -854,7 +1152,7 @@ argc = mrb_get_args(mrb, "o|o", &a1, &a2); if (argc == 2) { mrb_regexp_check(mrb, a1); - return mrb_str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); + return str_substr(mrb, str, mrb_fixnum(a1), mrb_fixnum(a2)); } if (argc != 1) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(argc)); @@ -924,7 +1222,7 @@ /* 15.2.10.5.10 */ /* * call-seq: - * str.chomp!(separator=$/) => str or nil + * str.chomp!(separator="\n") => str or nil * * Modifies str in place as described for String#chomp, * returning str, or nil if no modifications were made. @@ -998,7 +1296,7 @@ /* 15.2.10.5.9 */ /* * call-seq: - * str.chomp(separator=$/) => new_str + * str.chomp(separator="\n") => new_str * * Returns a new String with the given record separator removed * from the end of str (if present). If $/ has not been @@ -1041,7 +1339,18 @@ mrb_str_modify(mrb, s); if (RSTR_LEN(s) > 0) { mrb_int len; +#ifdef MRB_UTF8_STRING + const char* t = RSTR_PTR(s), *p = t; + const char* e = p + RSTR_LEN(s); + while (p=e) break; + p += clen; + } + len = p - t; +#else len = RSTR_LEN(s) - 1; +#endif if (RSTR_PTR(s)[len] == '\n') { if (len > 0 && RSTR_PTR(s)[len-1] == '\r') { @@ -1169,47 +1478,10 @@ return mrb_bool_value(eql_p); } -static mrb_value -mrb_str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) -{ - struct RString *orig, *s; - mrb_shared_string *shared; - - orig = mrb_str_ptr(str); - if (RSTR_EMBED_P(orig)) { - s = str_new(mrb, orig->as.ary+beg, len); - } else { - str_make_shared(mrb, orig); - shared = orig->as.heap.aux.shared; - s = mrb_obj_alloc_string(mrb); - s->as.heap.ptr = orig->as.heap.ptr + beg; - s->as.heap.len = len; - s->as.heap.aux.shared = shared; - RSTR_SET_SHARED_FLAG(s); - shared->refcnt++; - } - - return mrb_obj_value(s); -} - MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len) { - if (len < 0) return mrb_nil_value(); - if (!RSTRING_LEN(str)) { - len = 0; - } - if (beg > RSTRING_LEN(str)) return mrb_nil_value(); - if (beg < 0) { - beg += RSTRING_LEN(str); - if (beg < 0) return mrb_nil_value(); - } - if (beg + len > RSTRING_LEN(str)) - len = RSTRING_LEN(str) - beg; - if (len <= 0) { - len = 0; - } - return mrb_str_subseq(mrb, str, beg, len); + return str_substr(mrb, str, beg, len); } mrb_int @@ -1268,7 +1540,7 @@ } else { str2 = mrb_str_to_str(mrb, str2); - i = mrb_str_index(mrb, self, str2, 0); + i = str_index(mrb, self, str2, 0); include_p = (i != -1); } @@ -1298,12 +1570,12 @@ * "hello".index(/[aeiou]/, -3) #=> 4 */ static mrb_value -mrb_str_index_m(mrb_state *mrb, mrb_value str) +mrb_str_index(mrb_state *mrb, mrb_value str) { mrb_value *argv; mrb_int argc; mrb_value sub; - mrb_int pos; + mrb_int pos, clen; mrb_get_args(mrb, "*", &argv, &argc); if (argc == 2) { @@ -1318,25 +1590,17 @@ sub = mrb_nil_value(); } mrb_regexp_check(mrb, sub); + clen = RSTRING_CHAR_LEN(str); if (pos < 0) { - pos += RSTRING_LEN(str); + pos += clen; if (pos < 0) { return mrb_nil_value(); } } + if (pos >= clen) return mrb_nil_value(); + pos = chars2bytes(str, 0, pos); switch (mrb_type(sub)) { - case MRB_TT_FIXNUM: { - mrb_int c = mrb_fixnum(sub); - mrb_int len = RSTRING_LEN(str); - unsigned char *p = (unsigned char*)RSTRING_PTR(str); - - for (;posas.heap.aux.shared); - } - else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1)) { - mrb_free(mrb, s1->as.heap.ptr); - } - - RSTR_UNSET_NOFREE_FLAG(s1); - - if (RSTR_SHARED_P(s2)) { -L_SHARE: - RSTR_UNSET_EMBED_FLAG(s1); - s1->as.heap.ptr = s2->as.heap.ptr; - s1->as.heap.len = len; - s1->as.heap.aux.shared = s2->as.heap.aux.shared; - RSTR_SET_SHARED_FLAG(s1); - s1->as.heap.aux.shared->refcnt++; - } - else { - if (len <= RSTRING_EMBED_LEN_MAX) { - RSTR_UNSET_SHARED_FLAG(s1); - RSTR_SET_EMBED_FLAG(s1); - memcpy(s1->as.ary, RSTR_PTR(s2), len); - RSTR_SET_EMBED_LEN(s1, len); - } - else { - str_make_shared(mrb, s2); - goto L_SHARE; - } - } - - return mrb_obj_value(s1); -} - /* 15.2.10.5.24 */ /* 15.2.10.5.28 */ /* @@ -1518,107 +1743,81 @@ return mrb_check_convert_type(mrb, str, MRB_TT_STRING, "String", "to_str"); } -/* ---------------------------------- */ -/* 15.2.10.5.29 */ +/* 15.2.10.5.30 */ /* * call-seq: - * str.reverse => new_str - * - * Returns a new string with the characters from str in reverse order. + * str.reverse! => str * - * "stressed".reverse #=> "desserts" + * Reverses str in place. */ static mrb_value -mrb_str_reverse(mrb_state *mrb, mrb_value str) +mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) { - struct RString *s2; - char *s, *e, *p; +#ifdef MRB_UTF8_STRING + mrb_int utf8_len = RSTRING_CHAR_LEN(str); + mrb_int len = RSTRING_LEN(str); + + if (utf8_len == len) goto bytes; + if (utf8_len > 1) { + char *buf; + char *p, *e, *r; - if (RSTRING_LEN(str) <= 1) return mrb_str_dup(mrb, str); + mrb_str_modify(mrb, mrb_str_ptr(str)); + len = RSTRING_LEN(str); + buf = mrb_malloc(mrb, (size_t)len); + p = buf; + e = buf + len; - s2 = str_new(mrb, 0, RSTRING_LEN(str)); - str_with_class(mrb, s2, str); - s = RSTRING_PTR(str); e = RSTRING_END(str) - 1; - p = RSTR_PTR(s2); + memcpy(buf, RSTRING_PTR(str), len); + r = RSTRING_PTR(str) + len; - while (e >= s) { - *p++ = *e--; + while (p str - * - * Reverses str in place. - */ -static mrb_value -mrb_str_reverse_bang(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - char *p, *e; - char c; + bytes: +#endif + { + struct RString *s = mrb_str_ptr(str); + char *p, *e; + char c; - mrb_str_modify(mrb, s); - if (RSTR_LEN(s) > 1) { - p = RSTR_PTR(s); - e = p + RSTR_LEN(s) - 1; - while (p < e) { + mrb_str_modify(mrb, s); + if (RSTR_LEN(s) > 1) { + p = RSTR_PTR(s); + e = p + RSTR_LEN(s) - 1; + while (p < e) { c = *p; *p++ = *e; *e-- = c; + } } + return str; } - return str; } +/* ---------------------------------- */ +/* 15.2.10.5.29 */ /* * call-seq: - * str.rindex(substring [, fixnum]) => fixnum or nil - * str.rindex(fixnum [, fixnum]) => fixnum or nil - * str.rindex(regexp [, fixnum]) => fixnum or nil + * str.reverse => new_str * - * Returns the index of the last occurrence of the given substring, - * character (fixnum), or pattern (regexp) in str. Returns - * nil if not found. If the second parameter is present, it - * specifies the position in the string to end the search---characters beyond - * this point will not be considered. + * Returns a new string with the characters from str in reverse order. * - * "hello".rindex('e') #=> 1 - * "hello".rindex('l') #=> 3 - * "hello".rindex('a') #=> nil - * "hello".rindex(101) #=> 1 - * "hello".rindex(/[aeiou]/, -2) #=> 1 + * "stressed".reverse #=> "desserts" */ -static mrb_int -mrb_str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos) +static mrb_value +mrb_str_reverse(mrb_state *mrb, mrb_value str) { - char *s, *sbeg, *t; - struct RString *ps = mrb_str_ptr(str); - mrb_int len = RSTRING_LEN(sub); - - /* substring longer than string */ - if (RSTR_LEN(ps) < len) return -1; - if (RSTR_LEN(ps) - pos < len) { - pos = RSTR_LEN(ps) - len; - } - sbeg = RSTR_PTR(ps); - s = RSTR_PTR(ps) + pos; - t = RSTRING_PTR(sub); - if (len) { - while (sbeg <= s) { - if (memcmp(s, t, len) == 0) { - return s - RSTR_PTR(ps); - } - s--; - } - return -1; - } - else { - return pos; - } + mrb_value str2 = mrb_str_dup(mrb, str); + mrb_str_reverse_bang(mrb, str2); + return str2; } /* 15.2.10.5.31 */ @@ -1641,13 +1840,13 @@ * "hello".rindex(/[aeiou]/, -2) #=> 1 */ static mrb_value -mrb_str_rindex_m(mrb_state *mrb, mrb_value str) +mrb_str_rindex(mrb_state *mrb, mrb_value str) { mrb_value *argv; mrb_int argc; mrb_value sub; mrb_value vpos; - mrb_int pos, len = RSTRING_LEN(str); + mrb_int pos, len = RSTRING_CHAR_LEN(str); mrb_get_args(mrb, "*", &argv, &argc); if (argc == 2) { @@ -1670,19 +1869,10 @@ else sub = mrb_nil_value(); } + pos = chars2bytes(str, 0, pos); mrb_regexp_check(mrb, sub); switch (mrb_type(sub)) { - case MRB_TT_FIXNUM: { - mrb_int c = mrb_fixnum(sub); - unsigned char *p = (unsigned char*)RSTRING_PTR(str); - - for (pos=len-1;pos>=0;pos--) { - if (p[pos] == c) return mrb_fixnum_value(pos); - } - return mrb_nil_value(); - } - default: { mrb_value tmp; @@ -1694,8 +1884,12 @@ } /* fall through */ case MRB_TT_STRING: - pos = mrb_str_rindex(mrb, str, sub, pos); - if (pos >= 0) return mrb_fixnum_value(pos); + pos = str_rindex(mrb, str, sub, pos); + if (pos >= 0) { + pos = bytes2chars(RSTRING_PTR(str), pos); + BYTES_ALIGN_CHECK(pos); + return mrb_fixnum_value(pos); + } break; } /* end of switch (TYPE(sub)) */ @@ -1706,7 +1900,7 @@ /* * call-seq: - * str.split(pattern=$;, [limit]) => anArray + * str.split(pattern="\n", [limit]) => anArray * * Divides str into substrings based on a delimiter, returning an array * of these substrings. @@ -1804,7 +1998,7 @@ } } else if (ISSPACE(c)) { - mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, beg, end-beg)); + mrb_ary_push(mrb, result, byte_subseq(mrb, str, beg, end-beg)); mrb_gc_arena_restore(mrb, ai); skip = TRUE; beg = idx; @@ -1826,9 +2020,9 @@ end = mrb_memsearch(RSTRING_PTR(spat), pat_len, RSTRING_PTR(str)+idx, str_len - idx); if (end < 0) break; } else { - end = 1; + end = chars2bytes(str, idx, 1); } - mrb_ary_push(mrb, result, mrb_str_subseq(mrb, str, idx, end)); + mrb_ary_push(mrb, result, byte_subseq(mrb, str, idx, end)); mrb_gc_arena_restore(mrb, ai); idx += end + pat_len; if (lim_p && lim <= ++i) break; @@ -1843,7 +2037,7 @@ tmp = mrb_str_new_empty(mrb, str); } else { - tmp = mrb_str_subseq(mrb, str, beg, RSTRING_LEN(str)-beg); + tmp = byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg); } mrb_ary_push(mrb, result, tmp); } @@ -1858,11 +2052,12 @@ } MRB_API mrb_value -mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) +mrb_str_len_to_inum(mrb_state *mrb, const char *str, size_t len, int base, int badcheck) { - const char *p; + const char *p = str; + const char *pend = str + len; char sign = 1; - int c, uscore; + int c; uint64_t n = 0; mrb_int val; @@ -1872,26 +2067,23 @@ ISUPPER(c) ? ((c) - 'A' + 10) : \ -1) - if (!str) { + if (!p) { if (badcheck) goto bad; return mrb_fixnum_value(0); } - while (ISSPACE(*str)) str++; + while (p=pend) { + if (badcheck) goto bad; + return mrb_fixnum_value(0); + } + if (*p == '0') { /* squeeze preceding 0s */ + p++; + while (p= 2) + if (p= base) { + if (p == pend) { if (badcheck) goto bad; return mrb_fixnum_value(0); } - - uscore = 0; - for (p=str;*p;p++) { + for ( ;p= base) { - if (badcheck) goto bad; break; } n *= base; n += c; - if (n > MRB_INT_MAX) { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str)); + if (n > (uint64_t)MRB_INT_MAX + (sign ? 0 : 1)) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", + mrb_str_new(mrb, str, pend-str)); } } - val = n; + val = (mrb_int)n; if (badcheck) { if (p == str) goto bad; /* no number */ - while (*p && ISSPACE(*p)) p++; - if (*p) goto bad; /* trailing garbage */ + while (p 1) { + mrb_int i; + for (i=0; istring_class = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */ + mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */ MRB_SET_INSTANCE_TT(s, MRB_TT_STRING); - mrb_define_method(mrb, s, "bytesize", mrb_str_size, MRB_ARGS_NONE()); + mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */ mrb_define_method(mrb, s, "==", mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.2 */ @@ -2511,7 +2732,7 @@ mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 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, "index", mrb_str_index, 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 */ @@ -2519,7 +2740,7 @@ 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, "rindex", mrb_str_rindex, MRB_ARGS_ANY()); /* 15.2.10.5.31 */ mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.33 */ 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 */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/symbol.c mruby-1.2.0+20160315+git4f20d58a/src/symbol.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/symbol.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/symbol.c 2016-03-14 00:35:53.000000000 +0000 @@ -6,10 +6,10 @@ #include #include -#include "mruby.h" -#include "mruby/khash.h" -#include "mruby/string.h" -#include "mruby/dump.h" +#include +#include +#include +#include /* ------------------------------------------------------ */ typedef struct symbol_name { @@ -354,7 +354,9 @@ if (*++m == '*') ++m; break; case '!': - if (*++m == '=') ++m; + switch (*++m) { + case '=': case '~': ++m; + } break; case '+': case '-': if (*++m == '@') ++m; @@ -478,7 +480,7 @@ { struct RClass *sym; - sym = mrb->symbol_class = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ + mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ mrb_define_method(mrb, sym, "===", sym_equal, MRB_ARGS_REQ(1)); /* 15.2.11.3.1 */ mrb_define_method(mrb, sym, "id2name", mrb_sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.2 */ diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/value_array.h mruby-1.2.0+20160315+git4f20d58a/src/value_array.h --- mruby-1.1.0+20150906+git1cbbb7e1/src/value_array.h 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/value_array.h 2016-03-14 00:35:53.000000000 +0000 @@ -1,7 +1,7 @@ #ifndef MRB_VALUE_ARRAY_H__ #define MRB_VALUE_ARRAY_H__ -#include "mruby.h" +#include static inline void value_move(mrb_value *s1, const mrb_value *s2, size_t n) diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/variable.c mruby-1.2.0+20160315+git4f20d58a/src/variable.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/variable.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/variable.c 2016-03-14 00:35:53.000000000 +0000 @@ -4,11 +4,11 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/proc.h" -#include "mruby/string.h" +#include +#include +#include +#include +#include typedef int (iv_foreach_func)(mrb_state*,mrb_sym,mrb_value,void*); @@ -282,7 +282,7 @@ #else -#include "mruby/khash.h" +#include #ifndef MRB_IVHASH_INIT_SIZE #define MRB_IVHASH_INIT_SIZE 8 @@ -759,17 +759,29 @@ mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) { struct RClass * cls = c; + mrb_value v; while (c) { - if (c->iv) { - iv_tbl *t = c->iv; - mrb_value v; - - if (iv_get(mrb, t, sym, &v)) - return v; + if (c->iv && iv_get(mrb, c->iv, sym, &v)) { + return v; } c = c->super; } + if (cls && cls->tt == MRB_TT_SCLASS) { + mrb_value klass; + + klass = mrb_obj_iv_get(mrb, (struct RObject *)cls, + mrb_intern_lit(mrb, "__attached__")); + c = mrb_class_ptr(klass); + if (c->tt == MRB_TT_CLASS || c->tt == MRB_TT_MODULE) { + while (c) { + if (c->iv && iv_get(mrb, c->iv, sym, &v)) { + return v; + } + c = c->super; + } + } + } mrb_name_error(mrb, sym, "uninitialized class variable %S in %S", mrb_sym2str(mrb, sym), mrb_obj_value(cls)); /* not reached */ @@ -914,6 +926,14 @@ if (c->iv && iv_get(mrb, c->iv, sym, &v)) { return v; } + if (c->tt == MRB_TT_SCLASS) { + mrb_value klass; + klass = mrb_obj_iv_get(mrb, (struct RObject *)c, + mrb_intern_lit(mrb, "__attached__")); + c2 = mrb_class_ptr(klass); + if (c2->tt == MRB_TT_CLASS) + c = c2; + } c2 = c; for (;;) { c2 = mrb_class_outer_module(mrb, c2); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/version.c mruby-1.2.0+20160315+git4f20d58a/src/version.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/version.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/version.c 2016-03-14 00:35:53.000000000 +0000 @@ -1,11 +1,14 @@ -#include "mruby.h" -#include "mruby/variable.h" +#include +#include void mrb_init_version(mrb_state* mrb) { + mrb_value mruby_version = mrb_str_new_lit(mrb, MRUBY_VERSION); + mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION)); mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE)); + mrb_define_global_const(mrb, "RUBY_ENGINE_VERSION", mruby_version); mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION)); mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO)); mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE)); diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/src/vm.c mruby-1.2.0+20160315+git4f20d58a/src/vm.c --- mruby-1.1.0+20150906+git1cbbb7e1/src/vm.c 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/src/vm.c 2016-03-14 00:35:53.000000000 +0000 @@ -7,22 +7,22 @@ #include #include #include -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/hash.h" -#include "mruby/irep.h" -#include "mruby/numeric.h" -#include "mruby/proc.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" -#include "mruby/opcode.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "value_array.h" -#include "mruby/throw.h" +#include -#ifndef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO #if defined(__cplusplus) extern "C" { #endif @@ -52,7 +52,7 @@ # define DEBUG(x) #endif -#define ARENA_RESTORE(mrb,ai) (mrb)->arena_idx = (ai) +#define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai) static inline void stack_clear(mrb_value *from, size_t count) @@ -209,6 +209,7 @@ #define CI_ACC_SKIP -1 #define CI_ACC_DIRECT -2 +#define CI_ACC_RESUMED -3 static mrb_callinfo* cipush(mrb_state *mrb) @@ -237,27 +238,35 @@ return ci; } +MRB_API void +mrb_env_unshare(mrb_state *mrb, struct REnv *e) +{ + size_t len = (size_t)MRB_ENV_STACK_LEN(e); + mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); + + MRB_ENV_UNSHARE_STACK(e); + if (len > 0) { + stack_copy(p, e->stack, len); + } + e->stack = p; + mrb_write_barrier(mrb, (struct RBasic *)e); +} + static void cipop(mrb_state *mrb) { struct mrb_context *c = mrb->c; - - if (c->ci->env) { - struct REnv *e = c->ci->env; - size_t len = (size_t)MRB_ENV_STACK_LEN(e); - mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); - - MRB_ENV_UNSHARE_STACK(e); - if (len > 0) { - stack_copy(p, e->stack, len); - } - e->stack = p; - mrb_write_barrier(mrb, (struct RBasic *)e); - } + struct REnv *env = c->ci->env; c->ci--; + + if (env) { + mrb_env_unshare(mrb, env); + } } +void mrb_exc_set(mrb_state *mrb, mrb_value exc); + static void ecall(mrb_state *mrb, int i) { @@ -496,21 +505,32 @@ { struct RProc *p; mrb_callinfo *ci; + mrb_int max = 3; if (mrb_nil_p(blk)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); } ci = mrb->c->ci; if (ci->acc == CI_ACC_DIRECT) { - return mrb_yield_with_class(mrb, blk, 0, 0, self, c); + return mrb_yield_with_class(mrb, blk, 1, &self, self, c); } ci->target_class = c; p = mrb_proc_ptr(blk); ci->proc = p; + ci->argc = 1; if (MRB_PROC_CFUNC_P(p)) { + stack_extend(mrb, 3, 0); + mrb->c->stack[0] = self; + mrb->c->stack[1] = self; + mrb->c->stack[2] = mrb_nil_value(); return p->body.func(mrb, self); } ci->nregs = p->body.irep->nregs; + if (max < ci->nregs) max = ci->nregs; + stack_extend(mrb, max, 0); + mrb->c->stack[0] = self; + mrb->c->stack[1] = self; + mrb->c->stack[2] = mrb_nil_value(); ci = cipush(mrb); ci->nregs = 0; ci->target_class = 0; @@ -669,7 +689,7 @@ mrb_str_cat(mrb, msg, lead, sizeof(lead) - 1); mrb_str_cat(mrb, msg, kind_str[kind], kind_str_len[kind]); exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); } static void @@ -688,12 +708,12 @@ mrb_fixnum_value(mrb->c->ci->argc), mrb_fixnum_value(num)); } exc = mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str); - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); } #define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc; #define ERR_PC_CLR(mrb) mrb->c->ci->err = 0; -#ifdef ENABLE_DEBUG +#ifdef MRB_ENABLE_DEBUG_HOOK #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs)); #else #define CODE_FETCH_HOOK(mrb, irep, pc, regs) @@ -727,11 +747,23 @@ void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); MRB_API mrb_value -mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) +mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) +{ + mrb_irep *irep = proc->body.irep; + + if (!mrb->c->stack) { + stack_init(mrb); + } + stack_extend(mrb, irep->nregs, stack_keep); + mrb->c->stack[0] = self; + return mrb_vm_exec(mrb, proc, irep->iseq); +} + +MRB_API mrb_value +mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) { /* mrb_assert(mrb_proc_cfunc_p(proc)) */ mrb_irep *irep = proc->body.irep; - mrb_code *pc = irep->iseq; mrb_value *pool = irep->pool; mrb_sym *syms = irep->syms; mrb_value *regs = NULL; @@ -775,14 +807,9 @@ goto L_RAISE; } mrb->jmp = &c_jmp; - if (!mrb->c->stack) { - stack_init(mrb); - } - stack_extend(mrb, irep->nregs, stack_keep); mrb->c->ci->proc = proc; mrb->c->ci->nregs = irep->nregs; regs = mrb->c->stack; - regs[0] = self; INIT_DISPATCH { CASE(OP_NOP) { @@ -1007,7 +1034,7 @@ CASE(OP_RAISE) { /* A raise(R(A)) */ - mrb->exc = mrb_obj_ptr(regs[GETARG_A(i)]); + mrb_exc_set(mrb, regs[GETARG_A(i)]); goto L_RAISE; } @@ -1124,19 +1151,24 @@ ci->nregs = n + 2; } result = m->body.func(mrb, recv); - mrb->c->stack[0] = result; mrb_gc_arena_restore(mrb, ai); if (mrb->exc) goto L_RAISE; /* pop stackpos */ ci = mrb->c->ci; if (!ci->target_class) { /* return from context modifying method (resume/yield) */ - if (!MRB_PROC_CFUNC_P(ci[-1].proc)) { + if (ci->acc == CI_ACC_RESUMED) { + mrb->jmp = prev_jmp; + return result; + } + else { + mrb_assert(!MRB_PROC_CFUNC_P(ci[-1].proc)); proc = ci[-1].proc; irep = proc->body.irep; pool = irep->pool; syms = irep->syms; } } + mrb->c->stack[0] = result; regs = mrb->c->stack = ci->stackent; pc = ci->pc; cipop(mrb); @@ -1241,7 +1273,7 @@ mrb_value exc; exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); goto L_RAISE; } recv = regs[0]; @@ -1331,7 +1363,7 @@ mrb_value exc; exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); goto L_RAISE; } stack = e->stack + 1; @@ -1561,7 +1593,7 @@ } if (mrb->c->prev->ci == mrb->c->prev->cibase) { mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume"); - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); goto L_RAISE; } /* automatic yield at the end */ @@ -1601,14 +1633,19 @@ while (eidx > mrb->c->ci[-1].eidx) { ecall(mrb, --eidx); } + if (mrb->c->vmexec && !mrb->c->ci->target_class) { + mrb->c->vmexec = FALSE; + mrb->jmp = prev_jmp; + return v; + } cipop(mrb); acc = ci->acc; - pc = ci->pc; regs = mrb->c->stack = ci->stackent; if (acc == CI_ACC_SKIP) { mrb->jmp = prev_jmp; return v; } + pc = ci->pc; DEBUG(printf("from :%s\n", mrb_sym2name(mrb, ci->mid))); proc = mrb->c->ci->proc; irep = proc->body.irep; @@ -2178,6 +2215,7 @@ CASE(OP_STRCAT) { /* A B R(A).concat(R(B)) */ mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); + regs = mrb->c->stack; NEXT; } @@ -2207,15 +2245,6 @@ } else { p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]); - if (c & OP_L_METHOD) { - if (p->target_class->tt == MRB_TT_SCLASS) { - mrb_value klass; - klass = mrb_obj_iv_get(mrb, - (struct RObject *)p->target_class, - mrb_intern_lit(mrb, "__attached__")); - p->target_class = mrb_class_ptr(klass); - } - } } if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; regs[GETARG_A(i)] = mrb_obj_value(p); @@ -2331,7 +2360,7 @@ /* A R(A) := target_class */ if (!mrb->c->ci->target_class) { mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); goto L_RAISE; } regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class); @@ -2348,10 +2377,10 @@ CASE(OP_DEBUG) { /* A B C debug print R(A),R(B),R(C) */ -#ifdef ENABLE_DEBUG +#ifdef MRB_ENABLE_DEBUG_HOOK mrb->debug_op_hook(mrb, irep, pc, regs); #else -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); #else abort(); @@ -2389,7 +2418,7 @@ else { exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); } - mrb->exc = mrb_obj_ptr(exc); + mrb_exc_set(mrb, exc); goto L_RAISE; } } @@ -2406,30 +2435,24 @@ MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { - return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + return mrb_vm_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ } MRB_API mrb_value -mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_keep) +mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { mrb_callinfo *ci; mrb_value v; if (!mrb->c->cibase || mrb->c->ci == mrb->c->cibase) { - return mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); + return mrb_vm_run(mrb, proc, self, stack_keep); } ci = cipush(mrb); ci->nregs = 1; /* protect the receiver */ ci->acc = CI_ACC_SKIP; ci->target_class = mrb->object_class; - v = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); + v = mrb_vm_run(mrb, proc, self, stack_keep); cipop(mrb); return v; } - -MRB_API mrb_value -mrb_toplevel_run(mrb_state *mrb, struct RProc *proc) -{ - return mrb_toplevel_run_keep(mrb, proc, 0); -} diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/mrbgem_spec.rake mruby-1.2.0+20160315+git4f20d58a/tasks/mrbgem_spec.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/mrbgem_spec.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/mrbgem_spec.rake 2016-03-14 00:35:53.000000000 +0000 @@ -52,7 +52,7 @@ MRuby::Build::COMMANDS.each do |command| instance_variable_set("@#{command}", @build.send(command).clone) end - @linker = LinkerConfig.new([], [], [], []) + @linker = LinkerConfig.new([], [], [], [], []) @rbfiles = Dir.glob("#{dir}/mrblib/**/*.rb").sort @objs = Dir.glob("#{dir}/src/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f| @@ -103,6 +103,10 @@ @dependencies << {:gem => name, :requirements => requirements, :default => default_gem} end + def add_test_dependency(*args) + add_dependency(*args) if build.test_enabled? + end + def add_conflict(name, *req) @conflicts << {:gem => name, :requirements => req.empty? ? nil : req} end @@ -177,18 +181,18 @@ def print_gem_init_header(f) print_gem_comment(f) f.puts %Q[#include ] unless rbfiles.empty? - f.puts %Q[#include "mruby.h"] - f.puts %Q[#include "mruby/irep.h"] unless rbfiles.empty? + f.puts %Q[#include ] + f.puts %Q[#include ] unless rbfiles.empty? end def print_gem_test_header(f) print_gem_comment(f) f.puts %Q[#include ] f.puts %Q[#include ] - f.puts %Q[#include "mruby.h"] - f.puts %Q[#include "mruby/irep.h"] - f.puts %Q[#include "mruby/variable.h"] - f.puts %Q[#include "mruby/hash.h"] unless test_args.empty? + f.puts %Q[#include ] + f.puts %Q[#include ] + f.puts %Q[#include ] + f.puts %Q[#include ] unless test_args.empty? end def test_dependencies @@ -409,9 +413,12 @@ # as circular dependency has already detected in the caller. import_include_paths(dep_g) + dep_g.export_include_paths.uniq! g.compilers.each do |compiler| compiler.include_paths += dep_g.export_include_paths g.export_include_paths += dep_g.export_include_paths + compiler.include_paths.uniq! + g.export_include_paths.uniq! end end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/mrbgems.rake mruby-1.2.0+20160315+git4f20d58a/tasks/mrbgems.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/mrbgems.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/mrbgems.rake 2016-03-14 00:35:53.000000000 +0000 @@ -31,7 +31,7 @@ f.puts %Q[ * All manual changes will get lost.] f.puts %Q[ */] f.puts %Q[] - f.puts %Q[#include "mruby.h"] + f.puts %Q[#include ] f.puts %Q[] f.write gem_func_decls f.puts %Q[] diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/mruby_build_gem.rake mruby-1.2.0+20160315+git4f20d58a/tasks/mruby_build_gem.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/mruby_build_gem.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/mruby_build_gem.rake 2016-03-14 00:35:53.000000000 +0000 @@ -106,7 +106,7 @@ git.run_checkout gemdir, params[:checksum_hash] else # Jump to the top of the branch - git.run_checkout gemdir, branch + git.run_checkout gemdir, branch if $pull_gems end else fail "unknown gem option #{params}" diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/mruby_build.rake mruby-1.2.0+20160315+git4f20d58a/tasks/mruby_build.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/mruby_build.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/mruby_build.rake 2016-03-14 00:35:53.000000000 +0000 @@ -26,8 +26,8 @@ MRuby::Toolchain.toolchains[@name] = self end - def setup(conf) - conf.instance_eval(&@initializer) + def setup(conf,params={}) + conf.instance_exec(conf, params, &@initializer) end def self.load @@ -158,10 +158,10 @@ @enable_bintest end - def toolchain(name) + def toolchain(name, params={}) tc = Toolchain.toolchains[name.to_s] fail "Unknown #{name} toolchain" unless tc - tc.setup(self) + tc.setup(self, params) @toolchains.unshift name.to_s end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/androideabi.rake mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/androideabi.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/androideabi.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/androideabi.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,132 +0,0 @@ -# Download and unarchive latest Android NDK from https://developer.android.com/tools/sdk/ndk/index.html -# Make custom standalone toolchain as described here (android_ndk/docs/STANDALONE-TOOLCHAIN.html) -# Please export custom standalone toolchain path -# export ANDROID_STANDALONE_TOOLCHAIN=/tmp/android-14-toolchain - -# Add to your build_config.rb -# MRuby::CrossBuild.new('androideabi') do |conf| -# toolchain :androideabi -# end - -MRuby::Toolchain.new(:androideabi) do |conf| - toolchain :gcc - - DEFAULT_ANDROID_TOOLCHAIN = 'gcc' - DEFAULT_ANDROID_TARGET_ARCH = 'arm' - DEFAULT_ANDROID_TARGET_ARCH_ABI = 'armeabi' - DEFAULT_ANDROID_TARGET_PLATFORM = 'android-14' - DEFAULT_GCC_VERSION = '4.6' - DEFAULT_CLANG_VERSION = '3.1' - GCC_COMMON_CFLAGS = %W(-ffunction-sections -funwind-tables -fstack-protector) - GCC_COMMON_LDFLAGS = %W() - - # 'ANDROID_STANDALONE_TOOLCHAIN' or 'ANDROID_NDK_HOME' must be set. - ANDROID_STANDALONE_TOOLCHAIN = ENV['ANDROID_STANDALONE_TOOLCHAIN'] - ANDROID_NDK_HOME = ENV['ANDROID_NDK_HOME'] - - ANDROID_TARGET_ARCH = ENV['ANDROID_TARGET_ARCH'] || DEFAULT_ANDROID_TARGET_ARCH - ANDROID_TARGET_ARCH_ABI = ENV['ANDROID_TARGET_ARCH_ABI'] || DEFAULT_ANDROID_TARGET_ARCH_ABI - ANDROID_TOOLCHAIN = ENV['ANDROID_TOOLCHAIN'] || DEFAULT_ANDROID_TOOLCHAIN - GCC_VERSION = ENV['GCC_VERSION'] || DEFAULT_GCC_VERSION - CLANG_VERSION = ENV['CLANG_VERSION'] || DEFAULT_CLANG_VERSION - - case ANDROID_TARGET_ARCH.downcase - when 'arch-arm', 'arm' then - toolchain_prefix = 'arm-linux-androideabi-' - when 'arch-x86', 'x86' then - toolchain_prefix = 'i686-linux-android-' - when 'arch-mips', 'mips' then - toolchain_prefix = 'mipsel-linux-android-' - else - # Any other architectures are not supported by Android NDK. - # Notify error. - end - - if ANDROID_STANDALONE_TOOLCHAIN == nil then - case RUBY_PLATFORM - when /cygwin|mswin|mingw|bccwin|wince|emx/i - HOST_PLATFORM = 'windows' - when /x86_64-darwin/i - HOST_PLATFORM = 'darwin-x86_64' - when /darwin/i - HOST_PLATFORM = 'darwin-x86' - when /x86_64-linux/i - HOST_PLATFORM = 'linux-x86_64' - when /linux/i - HOST_PLATFORM = 'linux-x86' - else - # 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 - if ANDROID_TOOLCHAIN.downcase == 'gcc' then - case ANDROID_TARGET_ARCH.downcase - when 'arch-arm', 'arm' then - path_to_toolchain += 'arm-linux-androideabi-' - path_to_sysroot += '/arch-arm' - when 'arch-x86', 'x86' then - path_to_toolchain += 'x86-' - path_to_sysroot += '/arch-x86' - when 'arch-mips', 'mips' then - path_to_toolchain += 'mipsel-linux-android-' - path_to_sysroot += '/arch-mips' - else - # Any other architecture are not supported by Android NDK. - end - path_to_toolchain += GCC_VERSION + '/prebuilt/' + HOST_PLATFORM - else - path_to_toolchain += 'llvm-' + CLANG_VERSION + '/prebuilt/' + HOST_PLATFORM - end - else - path_to_toolchain = ANDROID_STANDALONE_TOOLCHAIN - path_to_sysroot = ANDROID_STANDALONE_TOOLCHAIN + '/sysroot' - end - - SYSROOT = path_to_sysroot - - case ANDROID_TARGET_ARCH.downcase - when 'arch-arm', 'arm' then - if ANDROID_TARGET_ARCH_ABI.downcase == 'armeabi-v7a' then - ARCH_CFLAGS = %W(-march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16) - ARCH_LDFLAGS = %W(-march=armv7-a -Wl,--fix-cortex-a8) - else - ARCH_CFLAGS = %W(-march=armv5te -mtune=xscale -msoft-float) - ARCH_LDFLAGS = %W() - end - when 'arch-x86', 'x86' then - ARCH_CFLAGS = %W() - ARCH_LDFLAGS = %W() - when 'arch-mips', 'mips' then - ARCH_CFLAGS = %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers) - ARCH_LDFLAGS = %W() - else - # Notify error - end - - case ANDROID_TOOLCHAIN.downcase - when 'gcc' then - ANDROID_CC = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc' - ANDROID_LD = path_to_toolchain + '/bin/' + toolchain_prefix + 'gcc' - ANDROID_AR = path_to_toolchain + '/bin/' + toolchain_prefix + 'ar' - ANDROID_CFLAGS = GCC_COMMON_CFLAGS + %W(-D__android__ -mandroid --sysroot="#{SYSROOT}") + ARCH_CFLAGS - ANDROID_LDFLAGS = GCC_COMMON_LDFLAGS + %W(-D__android__ -mandroid --sysroot="#{SYSROOT}") + ARCH_LDFLAGS - when 'clang' then - # clang is not supported yet. - when 'clang31', 'clang3.1' then - # clang is not supported yet. - else - # Any other toolchains are not supported by Android NDK. - # Notify error. - end - - [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc| - cc.command = ENV['CC'] || ANDROID_CC - cc.flags = [ENV['CFLAGS'] || ANDROID_CFLAGS] - end - conf.linker.command = ENV['LD'] || ANDROID_LD - conf.linker.flags = [ENV['LDFLAGS'] || ANDROID_LDFLAGS] - conf.archiver.command = ENV['AR'] || ANDROID_AR -end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/android.rake mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/android.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/android.rake 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/android.rake 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,216 @@ +class MRuby::Toolchain::Android + DEFAULT_ARCH = 'armeabi' + DEFAULT_PLATFORM = 'android-14' + DEFAULT_TOOLCHAIN = :gcc + DEFAULT_NDK_HOMES = %w{ + /usr/local/opt/android-ndk + } + TOOLCHAINS = [:gcc, :clang] + ARCHITECTURES = %w{ + armeabi armeabi-v7a arm64-v8a + mips mips64 + x86 x86_64 + } + + class AndroidNDKHomeNotFound < StandardError + def message + <<-EOM +Couldn't find Android NDK Home. +Set ANDROID_NDK_HOME environment variable or set :ndk_home parameter + EOM + end + end + + attr_reader :params + + def initialize(params) + @params = params + end + + def home_path + @home_path ||= Pathname( + params[:ndk_home] || + ENV['ANDROID_NDK_HOME'] || + DEFAULT_NDK_HOMES.find{ |path| File.directory?(path) } || + raise(AndroidNDKHomeNotFound) + ) + end + + def arch + params.fetch(:arch){ DEFAULT_ARCH } + end + + def platform + params.fetch(:platform){ DEFAULT_PLATFORM } + end + + def toolchain + params.fetch(:toolchain){ DEFAULT_TOOLCHAIN } + end + + def toolchain_version + params.fetch(:toolchain_version) do + test = case toolchain + when :gcc + case arch + when /armeabi/ + 'arm-linux-androideabi-*' + when /arm64/ + 'aarch64-linux-android-*' + when /mips64/ + 'mips64el-linux-android-*' + when /mips/ + 'mipsel-linux-android-*' + when /x86_64/ + 'x86_64-*' + when /x86/ + 'x86-*' + end + when :clang + 'llvm-*' + end + + Dir[home_path.join('toolchains',test)].map{|t| t.match(/-(\d+\.\d+)$/); $1.to_f }.max + end + end + + def toolchain_path + prefix = case toolchain + when :clang then 'llvm-' + when :gcc + case arch + when /armeabi/ then 'arm-linux-androideabi-' + when /arm64/ then 'aarch64-linux-android-' + when /x86_64/ then 'x86_64-' + when /x86/ then 'x86-' + when /mips64/ then 'mips64el-linux-android-' + when /mips/ then 'mipsel-linux-android-' + end + end + home_path.join('toolchains', prefix + toolchain_version.to_s, 'prebuilt', host_platform) + end + + def sysroot + path = case arch + when /armeabi/ then 'arch-arm' + when /arm64/ then 'arch-arm64' + when /x86_64/ then 'arch-x86_64' + when /x86/ then 'arch-x86' + when /mips64/ then 'arch-mips64' + when /mips/ then 'arch-mips' + end + + home_path.join('platforms', platform, path).to_s + end + + def bin(command) + command = command.to_s + + if toolchain == :gcc + command = case arch + when /armeabi/ then 'arm-linux-androideabi-' + when /arm64/ then 'aarch64-linux-android-' + when /x86_64/ then 'x86_64-linux-android-' + when /x86/ then 'i686-linux-android-' + when /mips64/ then 'mips64el-linux-android-' + when /mips/ then 'mipsel-linux-android-' + end + command + end + + toolchain_path.join('bin',command).to_s + end + + def cc + case toolchain + when :gcc then bin(:gcc) + when :clang then bin(:clang) + end + end + + def cflags + flags = [] + + case toolchain + when :gcc + flags += %W(-ffunction-sections -funwind-tables -no-canonical-prefixes) + flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}") + case arch + when /arm64/ + flags += %W(-fpic -fstack-protector-strong) + when 'armeabi-v7a-hard' + flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mhard-float -D_NDK_MATH_NO_SOFTFP=1 -mfpu=vfpv3-d16) + when 'armeabi-v7a' + flags += %W(-fpic -fstack-protector-strong -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16) + when /arm/ + flags += %W(-fpic -fstack-protector-strong -march=armv5te -mtune=xscale -msoft-float) + when /mips/ + flags += %W(-fpic -fno-strict-aliasing -finline-functions -fmessage-length=0 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers) + when /x86/ + flags += %W(-fstack-protector-strong) + end + when :clang + end + + flags + end + + def ld + cc + end + + def ldflags + flags = [] + case toolchain + when :gcc + flags += %W(-no-canonical-prefixes) + flags += %W(-D__android__ -mandroid --sysroot="#{sysroot}") + case arch + when 'armeabi-v7a-hard' + flags += %W(-march=armv7-a -Wl,--fix-cortex-a8 -Wl,--no-warn-mismatch -lm_hard) + when 'armeabi-v7a' + flags += %W(-march=armv7-a -Wl,--fix-cortex-a8) + end + end + + flags + end + + def ar + case toolchain + when :gcc then bin(:ar) + when :clang then bin('llvm-ar') + end + end + + def host_platform + case RUBY_PLATFORM + when /cygwin|mswin|mingw|bccwin|wince|emx/i + 'windows' + when /x86_64-darwin/i + 'darwin-x86_64' + when /darwin/i + 'darwin-x86' + when /x86_64-linux/i + 'linux-x86_64' + when /linux/i + 'linux-x86' + else + raise NotImplementedError, "Unknown host platform (#{RUBY_PLATFORM})" + end + end +end + +MRuby::Toolchain.new(:android) do |conf, params| + ndk = MRuby::Toolchain::Android.new(params) + + toolchain ndk.toolchain + + [conf.cc, conf.cxx, conf.objc, conf.asm].each do |cc| + cc.command = ndk.cc + cc.flags = ndk.cflags + end + conf.linker.command = ndk.ld + conf.linker.flags = ndk.ldflags + conf.archiver.command = ndk.ar +end + diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/clang.rake mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/clang.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/clang.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/clang.rake 2016-03-14 00:35:53.000000000 +0000 @@ -1,4 +1,4 @@ -MRuby::Toolchain.new(:clang) do |conf| +MRuby::Toolchain.new(:clang) do |conf, _params| toolchain :gcc [conf.cc, conf.objc, conf.asm].each do |cc| diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/gcc.rake mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/gcc.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/gcc.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/gcc.rake 2016-03-14 00:35:53.000000000 +0000 @@ -1,4 +1,4 @@ -MRuby::Toolchain.new(:gcc) do |conf| +MRuby::Toolchain.new(:gcc) do |conf, _params| [conf.cc, conf.objc, conf.asm].each do |cc| cc.command = ENV['CC'] || 'gcc' cc.flags = [ENV['CFLAGS'] || %w(-g -std=gnu99 -O3 -Wall -Werror-implicit-function-declaration -Wdeclaration-after-statement -Wwrite-strings)] diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/openwrt.rake mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/openwrt.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/openwrt.rake 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/openwrt.rake 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,38 @@ +# usage of environmental variables to set the +# cross compiling toolchain proper +MRuby::Toolchain.new(:openwrt) do |conf| + [conf.cc, conf.objc, conf.asm].each do |cc| + cc.command = ENV['TARGET_CC'] + cc.flags = ENV['TARGET_CFLAGS'] + cc.include_paths = ["#{MRUBY_ROOT}/include"] + cc.defines = %w(DISABLE_GEMS) + cc.option_include_path = '-I%s' + cc.option_define = '-D%s' + cc.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' + end + + [conf.cxx].each do |cxx| + cxx.command = ENV['TARGET_CXX'] + cxx.flags = ENV['TARGET_CXXFLAGS'] + cxx.include_paths = ["#{MRUBY_ROOT}/include"] + cxx.defines = %w(DISABLE_GEMS) + cxx.option_include_path = '-I%s' + cxx.option_define = '-D%s' + cxx.compile_options = '%{flags} -MMD -o %{outfile} -c %{infile}' + end + + conf.linker do |linker| + linker.command = ENV['TARGET_CC'] + linker.flags = ENV['TARGET_LDFLAGS'] + linker.libraries = %w(m) + linker.library_paths = [] + linker.option_library = '-l%s' + linker.option_library_path = '-L%s' + linker.link_options = '%{flags} -o %{outfile} %{objs} %{flags_before_libraries} %{libs} %{flags_after_libraries}' + end + + conf.archiver do |archiver| + archiver.command = ENV['TARGET_AR'] + archiver.archive_options = 'rs %{outfile} %{objs}' + end +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/visualcpp.rake mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/visualcpp.rake --- mruby-1.1.0+20150906+git1cbbb7e1/tasks/toolchains/visualcpp.rake 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/tasks/toolchains/visualcpp.rake 2016-03-14 00:35:53.000000000 +0000 @@ -1,4 +1,4 @@ -MRuby::Toolchain.new(:visualcpp) do |conf| +MRuby::Toolchain.new(:visualcpp) do |conf, _params| [conf.cc].each do |cc| cc.command = ENV['CC'] || 'cl.exe' # C4013: implicit function declaration diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/assert.rb mruby-1.2.0+20160315+git4f20d58a/test/assert.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/assert.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/assert.rb 2016-03-14 00:35:53.000000000 +0000 @@ -10,11 +10,7 @@ len = args.size while i < len str = args[i].to_s - begin - __printstr__ str - rescue NoMethodError - __t_printstr__ str rescue print str - end + __t_printstr__ str rescue print str i += 1 end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/bintest.rb mruby-1.2.0+20160315+git4f20d58a/test/bintest.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/bintest.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/bintest.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,24 @@ $:.unshift File.dirname(File.dirname(File.expand_path(__FILE__))) require 'test/assert.rb' +def cmd(s) + case RbConfig::CONFIG['host_os'] + when /mswin(?!ce)|mingw|cygwin|bccwin/ + "bin\\#{s}.exe" + else + "bin/#{s}" + end +end + +def shellquote(s) + case RbConfig::CONFIG['host_os'] + when /mswin(?!ce)|mingw|cygwin|bccwin/ + "\"#{s}\"" + else + "'#{s}'" + end +end + ARGV.each do |gem| Dir["#{gem}/bintest/**/*.rb"].each do |file| load file diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/class.rb mruby-1.2.0+20160315+git4f20d58a/test/t/class.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/class.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/class.rb 2016-03-14 00:35:53.000000000 +0000 @@ -384,6 +384,19 @@ assert_equal("value", ClassVariableTest.class_variable) end +assert('class variable in module and class << self style class method') do + module ClassVariableInModuleTest + @@class_variable = "value" + class << self + def class_variable + @@class_variable + end + end + end + + assert_equal("value", ClassVariableInModuleTest.class_variable) +end + assert('class with non-class/module outer raises TypeError') do assert_raise(TypeError) { class 0::C1; end } assert_raise(TypeError) { class []::C2; end } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/exception.rb mruby-1.2.0+20160315+git4f20d58a/test/t/exception.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/exception.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/exception.rb 2016-03-14 00:35:53.000000000 +0000 @@ -373,12 +373,47 @@ end end -assert('Raise in rescue') do - assert_raise(ArgumentError) do - begin - raise "" # RuntimeError - rescue - raise ArgumentError +def backtrace_avaialble? + begin + raise "XXX" + rescue => exception + not exception.backtrace.empty? + end +end + +assert('GC in rescue') do + skip "backtrace isn't avaialble" unless backtrace_avaialble? + + line = nil + begin + [1].each do + [2].each do + [3].each do + line = __LINE__; raise "XXX" + end + end + end + rescue => exception + GC.start + assert_equal("#{__FILE__}:#{line}:in Object.call", + exception.backtrace.first) + end +end + +assert('Method call in rescue') do + skip "backtrace isn't avaialble" unless backtrace_avaialble? + + line = nil + begin + [1].each do + [2].each do + line = __LINE__; raise "XXX" + end + end + rescue => exception + [3].each do end + assert_equal("#{__FILE__}:#{line}:in Object.call", + exception.backtrace.first) end end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/float.rb mruby-1.2.0+20160315+git4f20d58a/test/t/float.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/float.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/float.rb 2016-03-14 00:35:53.000000000 +0000 @@ -198,5 +198,5 @@ assert_equal 0, 23.0 >> 128 # Don't raise on large Right Shift - assert_equal -1, -23.0 >> 128 + assert_equal(-1, -23.0 >> 128) end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/hash.rb mruby-1.2.0+20160315+git4f20d58a/test/t/hash.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/hash.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/hash.rb 2016-03-14 00:35:53.000000000 +0000 @@ -239,6 +239,10 @@ a = Hash.new{|h,x| x} b.replace(a) assert_equal(127, b[127]) + + assert_raise(TypeError) do + { 'abc_key' => 'abc_value' }.replace "a" + end end assert('Hash#shift', '15.2.13.4.24') do @@ -342,3 +346,12 @@ assert_include ret, '"a"=>100' assert_include ret, '"d"=>400' end + +assert('Hash#rehash') do + h = {[:a] => "b"} + # hash key modified + h.keys[0][0] = :b + # h[[:b]] => nil + h.rehash + assert_equal("b", h[[:b]]) +end diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/integer.rb mruby-1.2.0+20160315+git4f20d58a/test/t/integer.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/integer.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/integer.rb 2016-03-14 00:35:53.000000000 +0000 @@ -147,6 +147,12 @@ # Left Shift by a negative is Right Shift assert_equal 23, 46 << -1 + + # Left Shift by 31 is bitShift overflow to SignedInt + assert_equal 2147483648, 1 << 31 + + # -3 Left Shift by 30 is bitShift overflow to SignedInt + assert_equal(-3221225472, -3 << 30) end assert('Integer#>>', '15.2.8.3.13') do diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/string.rb mruby-1.2.0+20160315+git4f20d58a/test/t/string.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/string.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/string.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,9 @@ +# coding: utf-8 ## # String ISO Test +UTF8STRING = ("\343\201\202".size == 1) + assert('String', '15.2.10') do assert_equal Class, String.class end @@ -60,23 +63,32 @@ a3 = 'abc'['bc'] b3 = 'abc'['XX'] - assert_equal 'a', a - assert_equal 'c', b - assert_nil c - assert_nil d - assert_equal 'b', e - assert_nil a1 - assert_nil b1 - assert_nil c1 - assert_equal '', d1 - assert_equal 'bc', e1 - assert_equal 'bc', a3 - assert_nil b3 - - assert_raise(TypeError) do - a[nil] - end -end + assert_equal 'a', 'a' + # assert_equal 'c', b + # assert_nil c + # assert_nil d + # assert_equal 'b', e + # assert_nil a1 + # assert_nil b1 + # assert_nil c1 + # assert_equal '', d1 + # assert_equal 'bc', e1 + # assert_equal 'bc', a3 + # assert_nil b3 + + # assert_raise(TypeError) do + # a[nil] + # end +end + +assert('String#[](UTF-8)', '15.2.10.5.6') do + assert_equal "ち", "こんにちは世界"[3] + assert_equal nil, "こんにちは世界"[20] + assert_equal "世", "こんにちは世界"[-2] + assert_equal "世界", "こんにちは世界"[-2..-1] + assert_equal "んに", "こんにちは世界"[1,2] + assert_equal "世", "こんにちは世界"["世"] +end if UTF8STRING assert('String#[] with Range') do a1 = 'abc'[1..0] @@ -122,6 +134,69 @@ assert_equal 'bc', j2 end +assert('String#[]=') do + # length of args is 1 + a = 'abc' + a[0] = 'X' + assert_equal 'Xbc', a + + b = 'abc' + b[-1] = 'X' + assert_equal 'abX', b + + c = 'abc' + assert_raise(IndexError) do + c[10] = 'X' + end + + d = 'abc' + assert_raise(IndexError) do + d[-10] = 'X' + end + + e = 'abc' + e[1.1] = 'X' + assert_equal 'aXc', e + + + # length of args is 2 + a1 = 'abc' + assert_raise(IndexError) do + a1[0, -1] = 'X' + end + + b1 = 'abc' + assert_raise(IndexError) do + b1[10, 0] = 'X' + end + + c1 = 'abc' + assert_raise(IndexError) do + c1[-10, 0] = 'X' + end + + d1 = 'abc' + d1[0, 0] = 'X' + assert_equal 'Xabc', d1 + + e1 = 'abc' + e1[1, 3] = 'X' + assert_equal 'aX', e1 + + # args is RegExp + # It will be tested in mrbgems. + + # args is String + a3 = 'abc' + a3['bc'] = 'X' + assert_equal a3, 'aX' + + b3 = 'abc' + assert_raise(IndexError) do + b3['XX'] = 'Y' + end +end + assert('String#capitalize', '15.2.10.5.7') do a = 'abc' a.capitalize @@ -188,6 +263,16 @@ assert_equal 'abc', c end +assert('String#chop(UTF-8)', '15.2.10.5.11') do + a = ''.chop + b = 'あいう'.chop + c = "あ\nい".chop.chop + + assert_equal '', a + assert_equal 'あい', b + assert_equal 'あ', c +end if UTF8STRING + assert('String#chop!', '15.2.10.5.12') do a = '' b = 'abc' @@ -199,6 +284,21 @@ assert_equal b, 'ab' end +assert('String#chop!(UTF-8)', '15.2.10.5.12') do + a = '' + b = "あいうえ\n" + c = "あいうえ\n" + + a.chop! + b.chop! + c.chop! + c.chop! + + assert_equal a, '' + assert_equal b, 'あいうえ' + assert_equal c, 'あいう' +end if UTF8STRING + assert('String#downcase', '15.2.10.5.13') do a = 'ABC'.downcase b = 'ABC' @@ -348,6 +448,15 @@ assert_equal 'cba', 'abc'.reverse end +assert('String#reverse(UTF-8)', '15.2.10.5.29') do + assert_equal "ち", "こんにちは世界"[3] + assert_equal nil, "こんにちは世界"[20] + assert_equal "世", "こんにちは世界"[-2] + assert_equal "世界", "こんにちは世界"[-2..-1] + assert_equal "んに", "こんにちは世界"[1,2] + assert_equal "世", "こんにちは世界"["世"] +end if UTF8STRING + assert('String#reverse!', '15.2.10.5.30') do a = 'abc' a.reverse! @@ -356,22 +465,42 @@ assert_equal 'cba', 'abc'.reverse! end +assert('String#reverse!(UTF-8)', '15.2.10.5.30') do + a = 'こんにちは世界!' + a.reverse! + + assert_equal '!界世はちにんこ', a + assert_equal '!界世はちにんこ', 'こんにちは世界!'.reverse! +end if UTF8STRING + assert('String#rindex', '15.2.10.5.31') do assert_equal 0, 'abc'.rindex('a') assert_nil 'abc'.rindex('d') assert_equal 0, 'abcabc'.rindex('a', 1) assert_equal 3, 'abcabc'.rindex('a', 4) - - assert_equal 3, 'abcabc'.rindex(97) - assert_equal nil, 'abcabc'.rindex(0) end +assert('String#rindex(UTF-8)', '15.2.10.5.31') do + str = "こんにちは世界!\nこんにちは世界!" + assert_nil str.index('さ') + assert_equal 3, str.index('ち') + assert_equal 12, str.index('ち', 10) + assert_equal nil, str.index("さ") +end if UTF8STRING + # 'String#scan', '15.2.10.5.32' will be tested in mrbgems. assert('String#size', '15.2.10.5.33') do assert_equal 3, 'abc'.size end +assert('String#size(UTF-8)', '15.2.10.5.33') do + str = 'こんにちは世界!' + assert_equal 8, str.size + assert_not_equal str.bytesize, str.size + assert_equal 2, str[1, 2].size +end if UTF8STRING + assert('String#slice', '15.2.10.5.34') do # length of args is 1 a = 'abc'.slice(0) @@ -419,6 +548,13 @@ assert_equal ['a', 'b', 'c'], 'abc'.split("") end +assert('String#split(UTF-8)', '15.2.10.5.35') do + got = "こんにちは世界!".split('') + assert_equal ['こ', 'ん', 'に', 'ち', 'は', '世', '界', '!'], got + got = "こんにちは世界!".split('に') + assert_equal ['こん', 'ちは世界!'], got +end if UTF8STRING + assert('String#sub', '15.2.10.5.36') do assert_equal 'aBcabc', 'abcabc'.sub('b', 'B') assert_equal 'aBcabc', 'abcabc'.sub('b') { |w| w.capitalize } diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/test/t/syntax.rb mruby-1.2.0+20160315+git4f20d58a/test/t/syntax.rb --- mruby-1.1.0+20150906+git1cbbb7e1/test/t/syntax.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/test/t/syntax.rb 2016-03-14 00:35:53.000000000 +0000 @@ -1,6 +1,6 @@ assert('__FILE__') do - file = __FILE__.split('test/')[1] - assert_true 't/syntax.rb' == file || 't\syntax.rb' == file + file = __FILE__[-9, 9] + assert_equal 'syntax.rb', file end assert('__LINE__') do diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/TODO mruby-1.2.0+20160315+git4f20d58a/TODO --- mruby-1.1.0+20150906+git1cbbb7e1/TODO 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/TODO 2016-03-14 00:35:53.000000000 +0000 @@ -1,11 +1,10 @@ Things to do (Things that are not done yet) -* Special variables ($1,$2..) +* special variables ($1,$2..) * super in aliased methods +* multi-assignment decomposing +* keyword arguments in def statement Things to improve (Done but things to fix) -* Hash (Reduce size. Use khash or save the order) -* stringEx (Delete encoding、delete CODERANGE、delete everything except UTF-8 or ASCII) * Make additions as they are noticed. - diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/travis_config.rb mruby-1.2.0+20160315+git4f20d58a/travis_config.rb --- mruby-1.1.0+20150906+git1cbbb7e1/travis_config.rb 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/travis_config.rb 2016-03-14 00:35:53.000000000 +0000 @@ -12,6 +12,17 @@ build_mrbc_exec end +MRuby::Build.new('full-debug') do |conf| + toolchain :gcc + enable_debug + + # include all core GEMs + conf.gembox 'full-core' + conf.cc.defines = %w(MRB_ENABLE_DEBUG_HOOK) + + conf.enable_test +end + MRuby::Build.new do |conf| toolchain :gcc diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/.travis.yml mruby-1.2.0+20160315+git4f20d58a/.travis.yml --- mruby-1.1.0+20150906+git1cbbb7e1/.travis.yml 2015-09-04 17:04:20.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/.travis.yml 2016-03-14 00:35:53.000000000 +0000 @@ -1,14 +1,18 @@ language: c +sudo: false + matrix: include: - os: linux sudo: 9000 - os: osx - osx_image: xcod6.4 + osx_image: xcode7.1 -install: - - if [ $TRAVIS_OS_NAME = 'linux' ]; then sudo apt-get update -qq; sudo apt-get -q install gperf; fi +addons: + apt: + packages: + - gperf env: MRUBY_CONFIG=travis_config.rb script: "./minirake all test" diff -Nru mruby-1.1.0+20150906+git1cbbb7e1/.yardopts mruby-1.2.0+20160315+git4f20d58a/.yardopts --- mruby-1.1.0+20150906+git1cbbb7e1/.yardopts 1970-01-01 00:00:00.000000000 +0000 +++ mruby-1.2.0+20160315+git4f20d58a/.yardopts 2016-03-14 00:35:53.000000000 +0000 @@ -0,0 +1,17 @@ +--markup markdown +--plugin mruby +--plugin coderay +--output-dir doc/api + +src/**/*.c +mrblib/**/*.rb +include/**/*.h + +mrbgems/*/src/**/*.c +mrbgems/*/mrblib/**/*.rb +mrbgems/*/include/**/*.h +- +AUTHORS +MITL +CONTRIBUTING.md +doc/guides/*.md