diff options
49 files changed, 879 insertions, 488 deletions
diff --git a/.travis.yml b/.travis.yml index f7be58c8a..bcfce3984 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,14 @@ -# no installation... +language: c + +matrix: + include: + - os: linux + sudo: 9000 + - os: osx + osx_image: xcod6.4 install: - - sudo apt-get -q install gperf + - if [ $TRAVIS_OS_NAME = 'linux' ]; then sudo apt-get update -qq; sudo apt-get -q install gperf; fi env: MRUBY_CONFIG=travis_config.rb script: "./minirake all test" diff --git a/doc/api/mruby.h.md b/doc/api/mruby.h.md index 8862fee2c..06bab2d56 100644 --- a/doc/api/mruby.h.md +++ b/doc/api/mruby.h.md @@ -43,20 +43,22 @@ Deletes `mrb_state`. 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 number of function retrieved. -`format` is a list of following format specifier: +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`| -`A`|`Array`|`mrb_value`| -`H`|`Hash`|`mrb_value`| -`s`|`String`|`char*`, `mrb_int`| -`z`|`String`|`char*`| -`a`|`Array`|`mrb_value*`, `mrb_int`| +`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`| @@ -118,7 +120,7 @@ mrb_value example_method(mrb_state* mrb, mrb_value 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()); + mrb_define_method(mrb, example_class, "example_method", example_method, MRB_ARGS_NONE()); } void mrb_example_gem_final(mrb_state* mrb) { diff --git a/doc/api/mruby/array.h.md b/doc/api/mruby/array.h.md index e1fb0003d..36c253cec 100644 --- a/doc/api/mruby/array.h.md +++ b/doc/api/mruby/array.h.md @@ -12,28 +12,27 @@ In this example we read from a Ruby file inside C. The Ruby code will print what #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;
+{
+ 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
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -52,32 +51,32 @@ In this example we read from a Ruby file inside C. The Ruby code will print what #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;
+{
+ 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
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -103,37 +102,37 @@ called pop_ary that will return the array alone(just to be clean) and you should #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;
+{
+ 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
+ def method_name(a)
+ puts a
+ puts a.class
+ end
+ def pop_ary(a)
+ puts a
+ end
end
Example_Class.new
```
@@ -158,35 +157,35 @@ In this example we read from a Ruby file inside C. The Ruby code will print what #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;
+{
+ 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
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -211,36 +210,36 @@ In this example we read from a Ruby file inside C. The Ruby code will print what #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;
+{
+ 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
+ def method_name(a)
+ puts a
+ puts a.class
+ end
+ def before_after(a)
+ puts a
+ end
end
Example_Class.new
```
diff --git a/doc/api/mruby/hash.h.md b/doc/api/mruby/hash.h.md index b7962696c..fa12ea670 100644 --- a/doc/api/mruby/hash.h.md +++ b/doc/api/mruby/hash.h.md @@ -17,19 +17,18 @@ to Hash.new. #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;
+{
+ 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;
}
```
@@ -37,10 +36,10 @@ int main(int argc, char *argv[]) ``` Ruby
class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -67,22 +66,21 @@ a = {:da_key => 80} #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;
+{
+ 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;
}
```
@@ -90,10 +88,10 @@ int main(int argc, char *argv[]) ```Ruby
class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -131,25 +129,25 @@ a[:da_key] #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;
+{
+ 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;
}
```
@@ -157,10 +155,10 @@ int main(int argc, char *argv[]) ```Ruby
class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -198,26 +196,27 @@ a.delete(:da_key2) #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.
- 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;
+{
+ 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;
}
```
@@ -225,14 +224,14 @@ int main(int argc, char *argv[]) ```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
+ 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
```
@@ -265,25 +264,25 @@ and what class the passed in value is. This example gets an array of keys from a #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;
+{
+ 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;
}
```
@@ -291,10 +290,10 @@ int main(int argc, char *argv[]) ```Ruby
class Example_Class
- def method_name(a)
- puts a
- puts a.class
- end
+ def method_name(a)
+ puts a
+ puts a.class
+ end
end
Example_Class.new
```
@@ -332,26 +331,26 @@ a.clear #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;
+{
+ 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;
}
```
@@ -359,14 +358,14 @@ int main(int argc, char *argv[]) ```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
+ 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
```
diff --git a/doc/api/mruby/value.h.md b/doc/api/mruby/value.h.md index f3ae2d421..fbf2dadf1 100644 --- a/doc/api/mruby/value.h.md +++ b/doc/api/mruby/value.h.md @@ -38,10 +38,10 @@ main(void) test.rb
```Ruby
class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
+ def method_name(s)
+ puts s
+ puts s.class
+ end
end
a = My_Class.new
```
@@ -86,10 +86,10 @@ main(void) test.rb
```Ruby
class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
+ def method_name(s)
+ puts s
+ puts s.class
+ end
end
a = My_Class.new
```
@@ -134,10 +134,10 @@ main(void) test.rb
```Ruby
class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
+ def method_name(s)
+ puts s
+ puts s.class
+ end
end
a = My_Class.new
```
@@ -181,10 +181,10 @@ main(void) test.rb
```Ruby
class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
+ def method_name(s)
+ puts s
+ puts s.class
+ end
end
a = My_Class.new
```
@@ -229,10 +229,10 @@ main(void) test.rb
```Ruby
class My_Class
- def method_name(s)
- puts s
- puts s.class
- end
+ def method_name(s)
+ puts s
+ puts s.class
+ end
end
a = My_Class.new
```
diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md index e0c60daf2..f75231f71 100644 --- a/doc/mrbgems/README.md +++ b/doc/mrbgems/README.md @@ -198,17 +198,21 @@ end In case your GEM has more complex build requirements you can use the following options additionally inside of your GEM specification: -* `spec.cflags` (C compiler flags) -* `spec.mruby_cflags` (global C compiler flags for everything) -* `spec.mruby_ldflags` (global linker flags for everything) -* `spec.mruby_libs` (global libraries for everything) -* `spec.mruby_includes` (global includes for everything) +* `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. diff --git a/include/mruby/error.h b/include/mruby/error.h index 52f6772bd..e3e2b25e2 100644 --- a/include/mruby/error.h +++ b/include/mruby/error.h @@ -24,11 +24,21 @@ MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value st MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv); MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb); -MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, const char *fmt, ...); +MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...); /* declaration for fail method */ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value); +/* functions defined in mruby-error mrbgem */ +MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state); +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); +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); +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 diff --git a/include/mruby/string.h b/include/mruby/string.h index 5228dcbca..c4b31216e 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -59,6 +59,10 @@ struct RString { #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) +#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN) +#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) +#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) + #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)) @@ -70,9 +74,10 @@ mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 -#define MRB_STR_EMBED 4 -#define MRB_STR_EMBED_LEN_MASK 0xf8 -#define MRB_STR_EMBED_LEN_SHIFT 3 +#define MRB_STR_FROZEN 4 +#define MRB_STR_EMBED 8 +#define MRB_STR_EMBED_LEN_MASK 0x1f0 +#define MRB_STR_EMBED_LEN_SHIFT 4 void mrb_gc_free_str(mrb_state*, struct RString*); MRB_API void mrb_str_modify(mrb_state*, struct RString*); diff --git a/include/mruby/version.h b/include/mruby/version.h index ea044d6da..b3e4df029 100644 --- a/include/mruby/version.h +++ b/include/mruby/version.h @@ -7,25 +7,27 @@ #ifndef MRUBY_VERSION_H #define MRUBY_VERSION_H +#define MRB_STRINGIZE0(expr) #expr +#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr) + #define MRUBY_RUBY_VERSION "1.9" #define MRUBY_RUBY_ENGINE "mruby" -#define MRUBY_VERSION "1.1.0" #define MRUBY_RELEASE_MAJOR 1 #define MRUBY_RELEASE_MINOR 1 #define MRUBY_RELEASE_TEENY 1 -#define MRUBY_RELEASE_NO 10101 -#define MRUBY_RELEASE_DATE "2014-11-19" + +#define MRUBY_VERSION MRB_STRINGIZE(MRUBY_RELEASE_MAJOR)"."MRB_STRINGIZE(MRUBY_RELEASE_MINOR)"."MRB_STRINGIZE(MRUBY_RELEASE_TEENY) +#define MRUBY_RELEASE_NO (MRUBY_RELEASE_MAJOR * 100 * 100 + MRUBY_RELEASE_MINOR * 100 + MRUBY_RELEASE_TEENY) #define MRUBY_RELEASE_YEAR 2014 #define MRUBY_RELEASE_MONTH 11 #define MRUBY_RELEASE_DAY 19 +#define MRUBY_RELEASE_DATE MRB_STRINGIZE(MRUBY_RELEASE_YEAR)"-"MRB_STRINGIZE(MRUBY_RELEASE_MONTH)"-"MRB_STRINGIZE(MRUBY_RELEASE_DAY) #define MRUBY_BIRTH_YEAR 2010 #define MRUBY_AUTHOR "mruby developers" -#define MRB_STRINGIZE0(expr) #expr -#define MRB_STRINGIZE(expr) MRB_STRINGIZE0(expr) #define MRUBY_DESCRIPTION \ "mruby " MRUBY_VERSION \ diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb index fd80fa0bb..1f1d97376 100644 --- a/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mrbgems/mruby-array-ext/mrblib/array.rb @@ -217,7 +217,7 @@ class Array # [ "a", "b", "c" ].compact! #=> nil # def compact! - result = self.select { |e| e != nil } + result = self.select { |e| !e.nil? } if result.size == self.size nil else @@ -262,7 +262,7 @@ class Array # def fetch(n=nil, ifnone=NONE, &block) - warn "block supersedes default value argument" if n != nil && ifnone != NONE && block + warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block idx = n if idx < 0 @@ -312,51 +312,51 @@ class Array # def fill(arg0=nil, arg1=nil, arg2=nil, &block) - if arg0 == nil && arg1 == nil && arg2 == nil && !block + if arg0.nil? && arg1.nil? && arg2.nil? && !block raise ArgumentError, "wrong number of arguments (0 for 1..3)" end beg = len = 0 ary = [] if block - if arg0 == nil && arg1 == nil && arg2 == nil + if arg0.nil? && arg1.nil? && arg2.nil? # ary.fill { |index| block } -> ary beg = 0 len = self.size - elsif arg0 != nil && arg0.kind_of?(Range) + elsif !arg0.nil? && arg0.kind_of?(Range) # ary.fill(range) { |index| block } -> ary beg = arg0.begin beg += self.size if beg < 0 len = arg0.end len += self.size if len < 0 len += 1 unless arg0.exclude_end? - elsif arg0 != nil + elsif !arg0.nil? # ary.fill(start [, length] ) { |index| block } -> ary beg = arg0 beg += self.size if beg < 0 - if arg1 == nil + if arg1.nil? len = self.size else len = arg0 + arg1 end end else - if arg0 != nil && arg1 == nil && arg2 == nil + if !arg0.nil? && arg1.nil? && arg2.nil? # ary.fill(obj) -> ary beg = 0 len = self.size - elsif arg0 != nil && arg1 != nil && arg1.kind_of?(Range) + elsif !arg0.nil? && !arg1.nil? && arg1.kind_of?(Range) # ary.fill(obj, range ) -> ary beg = arg1.begin beg += self.size if beg < 0 len = arg1.end len += self.size if len < 0 len += 1 unless arg1.exclude_end? - elsif arg0 != nil && arg1 != nil + elsif !arg0.nil? && !arg1.nil? # ary.fill(obj, start [, length]) -> ary beg = arg1 beg += self.size if beg < 0 - if arg2 == nil + if arg2.nil? len = self.size else len = beg + arg2 @@ -582,7 +582,7 @@ class Array elsif v == true satisfied = true smaller = true - elsif v == false || v == nil + elsif v == false || v.nil? smaller = false end if smaller diff --git a/mrbgems/mruby-bin-mirb/mrbgem.rake b/mrbgems/mruby-bin-mirb/mrbgem.rake index 7d45409c9..a74871d81 100644 --- a/mrbgems/mruby-bin-mirb/mrbgem.rake +++ b/mrbgems/mruby-bin-mirb/mrbgem.rake @@ -20,6 +20,9 @@ MRuby::Gem::Specification.new('mruby-bin-mirb') do |spec| spec.linker.libraries << 'edit' else spec.linker.libraries << 'readline' + if spec.build.cc.search_header_path 'curses.h' + spec.linker.libraries << 'ncurses' + end end elsif spec.build.cc.search_header_path 'linenoise.h' spec.cc.defines << "ENABLE_LINENOISE" diff --git a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c index f27f87a5d..301dde1c6 100644 --- a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +++ b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c @@ -161,8 +161,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args) static void cleanup(mrb_state *mrb, struct mrbc_args *args) { - if (args->outfile) - mrb_free(mrb, (void*)args->outfile); + mrb_free(mrb, (void*)args->outfile); mrb_close(mrb); } diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c index 141ea151b..5ca744388 100644 --- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c @@ -159,10 +159,9 @@ cleanup(mrb_state *mrb, struct _args *args) { if (args->rfp && args->rfp != stdin) fclose(args->rfp); - if (args->cmdline && !args->fname) + if (!args->fname) mrb_free(mrb, args->cmdline); - if (args->argv) - mrb_free(mrb, args->argv); + mrb_free(mrb, args->argv); mrb_close(mrb); } diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index cefde8b7b..3853814ec 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -188,6 +188,11 @@ genop_peep(codegen_scope *s, mrb_code i, int val) if (val) break; switch (c0) { case OP_MOVE: + if (GETARG_A(i) == GETARG_A(i0)) { + /* skip overriden OP_MOVE */ + s->pc--; + s->iseq[s->pc] = i; + } if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) { /* skip swapping OP_MOVE */ return 0; @@ -406,7 +411,18 @@ push_(codegen_scope *s) nregs_update; } +static void +push_n_(codegen_scope *s, size_t n) +{ + if (s->sp+n > 511) { + codegen_error(s, "too complex expression"); + } + s->sp+=n; + nregs_update; +} + #define push() push_(s) +#define push_n(n) push_n_(s,n) #define pop_(s) ((s)->sp--) #define pop() pop_(s) #define pop_n(n) (s->sp-=(n)) @@ -1001,6 +1017,8 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val) else { pop(); } + push_n(post); + pop_n(post); genop(s, MKOP_ABC(OP_APOST, cursp(), n, post)); n = 1; if (t->car) { /* rest */ diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index b057cac17..097d63ac4 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -2154,6 +2154,7 @@ primary : literal $$ = new_lambda(p, $3, $5); local_unnest(p); p->cmdarg_stack = $<stack>4; + CMDARG_LEXPOP(); } | keyword_if expr_value then compstmt @@ -2941,7 +2942,7 @@ backref : tNTH_REF | tBACK_REF ; -superclass : term +superclass : /* term */ { $$ = 0; } @@ -2953,12 +2954,12 @@ superclass : term expr_value term { $$ = $3; - } + } /* | error term { yyerrok; $$ = 0; - } + } */ ; f_arglist : '(' f_args rparen diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index f6629ed79..6fef0c077 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -515,7 +515,7 @@ module Enumerable # def each_with_object(obj=nil, &block) - raise ArgumentError, "wrong number of arguments (0 for 1)" if obj == nil + raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil? return to_enum(:each_with_object, obj) unless block @@ -574,10 +574,10 @@ module Enumerable # def cycle(n=nil, &block) - return to_enum(:cycle, n) if !block && n == nil + return to_enum(:cycle, n) if !block && n.nil? ary = [] - if n == nil + if n.nil? self.each do|*val| ary.push val block.call(*val) diff --git a/mrbgems/mruby-error/mrbgem.rake b/mrbgems/mruby-error/mrbgem.rake new file mode 100644 index 000000000..b8281b17e --- /dev/null +++ b/mrbgems/mruby-error/mrbgem.rake @@ -0,0 +1,10 @@ +MRuby::Gem::Specification.new('mruby-error') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'extensional error handling' + + if build.cxx_abi_enabled? + @objs << build.compile_as_cxx("#{spec.dir}/src/exception.c", "#{spec.build_dir}/src/exception.cxx") + @objs.delete_if { |v| v == objfile("#{spec.build_dir}/src/exception") } + end +end diff --git a/mrbgems/mruby-error/src/exception.c b/mrbgems/mruby-error/src/exception.c new file mode 100644 index 000000000..911fde0be --- /dev/null +++ b/mrbgems/mruby-error/src/exception.c @@ -0,0 +1,100 @@ +#include "mruby.h" +#include "mruby/throw.h" +#include "mruby/error.h" + +MRB_API mrb_value +mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state) +{ + struct mrb_jmpbuf *prev_jmp = mrb->jmp; + struct mrb_jmpbuf c_jmp; + mrb_value result = mrb_nil_value(); + + if (state) { *state = FALSE; } + + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + result = body(mrb, data); + mrb->jmp = prev_jmp; + } MRB_CATCH(&c_jmp) { + mrb->jmp = prev_jmp; + result = mrb_obj_value(mrb->exc); + mrb->exc = NULL; + if (state) { *state = TRUE; } + } MRB_END_EXC(&c_jmp); + + mrb_gc_protect(mrb, result); + return result; +} + +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) +{ + struct mrb_jmpbuf *prev_jmp = mrb->jmp; + struct mrb_jmpbuf c_jmp; + mrb_value result; + + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + result = body(mrb, b_data); + mrb->jmp = prev_jmp; + } MRB_CATCH(&c_jmp) { + mrb->jmp = prev_jmp; + ensure(mrb, e_data); + MRB_THROW(mrb->jmp); /* rethrow catched exceptions */ + } MRB_END_EXC(&c_jmp); + + ensure(mrb, e_data); + mrb_gc_protect(mrb, result); + return result; +} + +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) +{ + return mrb_rescue_exceptions(mrb, body, b_data, rescue, r_data, 1, &mrb->eStandardError_class); +} + +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) +{ + struct mrb_jmpbuf *prev_jmp = mrb->jmp; + struct mrb_jmpbuf c_jmp; + mrb_value result; + mrb_bool error_matched = FALSE; + mrb_int i; + + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; + result = body(mrb, b_data); + mrb->jmp = prev_jmp; + } MRB_CATCH(&c_jmp) { + mrb->jmp = prev_jmp; + + for (i = 0; i < len; ++i) { + if (mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), classes[i])) { + error_matched = TRUE; + break; + } + } + + if (!error_matched) { MRB_THROW(mrb->jmp); } + + mrb->exc = NULL; + result = rescue(mrb, r_data); + } MRB_END_EXC(&c_jmp); + + mrb_gc_protect(mrb, result); + return result; +} + +void +mrb_mruby_error_gem_init(mrb_state *mrb) +{ +} + +void +mrb_mruby_error_gem_final(mrb_state *mrb) +{ +} diff --git a/mrbgems/mruby-error/test/exception.c b/mrbgems/mruby-error/test/exception.c new file mode 100644 index 000000000..2a943aaae --- /dev/null +++ b/mrbgems/mruby-error/test/exception.c @@ -0,0 +1,59 @@ +#include "mruby.h" +#include "mruby/error.h" +#include "mruby/array.h" + +static mrb_value +protect_cb(mrb_state *mrb, mrb_value b) +{ + return mrb_yield_argv(mrb, b, 0, NULL); +} + +static mrb_value +run_protect(mrb_state *mrb, mrb_value self) +{ + mrb_value b; + mrb_value ret[2]; + mrb_bool state; + mrb_get_args(mrb, "&", &b); + ret[0] = mrb_protect(mrb, protect_cb, b, &state); + ret[1] = mrb_bool_value(state); + return mrb_ary_new_from_values(mrb, 2, ret); +} + +static mrb_value +run_ensure(mrb_state *mrb, mrb_value self) +{ + mrb_value b, e; + mrb_get_args(mrb, "oo", &b, &e); + return mrb_ensure(mrb, protect_cb, b, protect_cb, e); +} + +static mrb_value +run_rescue(mrb_state *mrb, mrb_value self) +{ + mrb_value b, r; + mrb_get_args(mrb, "oo", &b, &r); + return mrb_rescue(mrb, protect_cb, b, protect_cb, r); +} + +static mrb_value +run_rescue_exceptions(mrb_state *mrb, mrb_value self) +{ + mrb_value b, r; + struct RClass *cls[1]; + mrb_get_args(mrb, "oo", &b, &r); + cls[0] = E_TYPE_ERROR; + return mrb_rescue_exceptions(mrb, protect_cb, b, protect_cb, r, 1, cls); +} + +void +mrb_mruby_error_gem_test(mrb_state *mrb) +{ + struct RClass *cls; + + cls = mrb_define_class(mrb, "ExceptionTest", mrb->object_class); + mrb_define_module_function(mrb, cls, "mrb_protect", run_protect, MRB_ARGS_NONE() | MRB_ARGS_BLOCK()); + mrb_define_module_function(mrb, cls, "mrb_ensure", run_ensure, MRB_ARGS_REQ(2)); + mrb_define_module_function(mrb, cls, "mrb_rescue", run_rescue, MRB_ARGS_REQ(2)); + mrb_define_module_function(mrb, cls, "mrb_rescue_exceptions", run_rescue_exceptions, MRB_ARGS_REQ(2)); +} diff --git a/mrbgems/mruby-error/test/exception.rb b/mrbgems/mruby-error/test/exception.rb new file mode 100644 index 000000000..0bbc2a0e7 --- /dev/null +++ b/mrbgems/mruby-error/test/exception.rb @@ -0,0 +1,55 @@ +assert 'mrb_protect' do + # no failure in protect returns [result, false] + assert_equal ['test', false] do + ExceptionTest.mrb_protect { 'test' } + end + # failure in protect returns [exception, true] + result = ExceptionTest.mrb_protect { raise 'test' } + assert_kind_of RuntimeError, result[0] + assert_true result[1] +end + +assert 'mrb_ensure' do + a = false + assert_equal 'test' do + ExceptionTest.mrb_ensure Proc.new { 'test' }, Proc.new { a = true } + end + assert_true a + + a = false + assert_raise RuntimeError do + ExceptionTest.mrb_ensure Proc.new { raise 'test' }, Proc.new { a = true } + end + assert_true a +end + +assert 'mrb_rescue' do + assert_equal 'test' do + ExceptionTest.mrb_rescue Proc.new { 'test' }, Proc.new {} + end + + class CustomExp < Exception + end + + assert_raise CustomExp do + ExceptionTest.mrb_rescue Proc.new { raise CustomExp.new 'test' }, Proc.new { 'rescue' } + end + + assert_equal 'rescue' do + ExceptionTest.mrb_rescue Proc.new { raise 'test' }, Proc.new { 'rescue' } + end +end + +assert 'mrb_rescue_exceptions' do + assert_equal 'test' do + ExceptionTest.mrb_rescue_exceptions Proc.new { 'test' }, Proc.new {} + end + + assert_raise RangeError do + ExceptionTest.mrb_rescue_exceptions Proc.new { raise RangeError.new 'test' }, Proc.new { 'rescue' } + end + + assert_equal 'rescue' do + ExceptionTest.mrb_rescue_exceptions Proc.new { raise TypeError.new 'test' }, Proc.new { 'rescue' } + end +end diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 2b61fdb48..7d9bc00b9 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -164,9 +164,9 @@ class String # string #=> "thsa sting" # def slice!(arg1, arg2=nil) - raise "wrong number of arguments (for 1..2)" if arg1 == nil && arg2 == nil + raise "wrong number of arguments (for 1..2)" if arg1.nil? && arg2.nil? - if arg1 != nil && arg2 != nil + if !arg1.nil? && !arg2.nil? idx = arg1 idx += self.size if arg1 < 0 if idx >= 0 && idx <= self.size && arg2 > 0 @@ -196,8 +196,8 @@ class String return nil end end - unless str == nil || str == "" - if arg1 != nil && arg2 !=nil + unless str.nil? || str == "" + if !arg1.nil? && !arg2.nil? idx = arg1 >= 0 ? arg1 : self.size+arg1 str2 = self[0...idx] + self[idx+arg2..-1].to_s else @@ -207,13 +207,13 @@ class String str2 = self[0...idx] + self[idx2+1..-1].to_s elsif arg1.kind_of?(String) idx = self.index(arg1) - str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx == nil + str2 = self[0...idx] + self[idx+arg1.size..-1] unless idx.nil? else idx = arg1 >= 0 ? arg1 : self.size+arg1 str2 = self[0...idx] + self[idx+1..-1].to_s end end - self.replace(str2) unless str2 == nil + self.replace(str2) unless str2.nil? end str end diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index e925a82a7..12657e129 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -3,6 +3,7 @@ #include "mruby/array.h" #include "mruby/class.h" #include "mruby/string.h" +#include "mruby/range.h" static mrb_value mrb_str_getbyte(mrb_state *mrb, mrb_value str) @@ -18,6 +19,59 @@ mrb_str_getbyte(mrb_state *mrb, mrb_value str) return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]); } +static mrb_value +mrb_str_setbyte(mrb_state *mrb, mrb_value str) +{ + mrb_int pos, byte; + long len = RSTRING_LEN(str); + + mrb_get_args(mrb, "ii", &pos, &byte); + + if (pos < -len || len <= pos) + mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos)); + if (pos < 0) + pos += len; + + mrb_str_modify(mrb, mrb_str_ptr(str)); + byte &= 0xff; + RSTRING_PTR(str)[pos] = byte; + return mrb_fixnum_value((unsigned char)byte); +} + +static mrb_value +mrb_str_byteslice(mrb_state *mrb, mrb_value str) +{ + mrb_value a1; + mrb_int len; + int argc; + + argc = mrb_get_args(mrb, "o|i", &a1, &len); + if (argc == 2) { + return mrb_str_substr(mrb, str, mrb_fixnum(a1), len); + } + switch (mrb_type(a1)) { + case MRB_TT_RANGE: + { + mrb_int beg; + + len = RSTRING_LEN(str); + if (mrb_range_beg_len(mrb, a1, &beg, &len, len)) { + return mrb_str_substr(mrb, str, beg, len); + } + return mrb_nil_value(); + } + case MRB_TT_FLOAT: + a1 = mrb_fixnum_value((mrb_int)mrb_float(a1)); + /* fall through */ + case MRB_TT_FIXNUM: + return mrb_str_substr(mrb, str, mrb_fixnum(a1), 1); + default: + mrb_raise(mrb, E_TYPE_ERROR, "wrong type of argument"); + } + /* not reached */ + return mrb_nil_value(); +} + /* * call-seq: * str.swapcase! -> str or nil @@ -375,6 +429,8 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "dump", mrb_str_dump, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "setbyte", mrb_str_setbyte, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_method(mrb, s, "swapcase!", mrb_str_swapcase_bang, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "swapcase", mrb_str_swapcase, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "concat", mrb_str_concat2, MRB_ARGS_REQ(1)); diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 14e00428e..5e4847f05 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -13,6 +13,22 @@ assert('String#getbyte') do assert_equal bytes2[0], str2.getbyte(0) end +assert('String#setbyte') do + str1 = "hello" + h = "H".getbyte(0) + str1.setbyte(0, h) + assert_equal(h, str1.getbyte(0)) + assert_equal("Hello", str1) +end + +assert('String#byteslice') do + str1 = "hello" + assert_equal("e", str1.byteslice(1)) + assert_equal("o", str1.byteslice(-1)) + assert_equal("ell", str1.byteslice(1..3)) + assert_equal("el", str1.byteslice(1...3)) +end + assert('String#dump') do ("\1" * 100).dump # should not raise an exception - regress #1210 "\0".inspect == "\"\\000\"" and diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c index 081e84c1c..c18ac7568 100644 --- a/mrbgems/mruby-time/src/time.c +++ b/mrbgems/mruby-time/src/time.c @@ -11,6 +11,10 @@ #include "mruby/class.h" #include "mruby/data.h" +#if !defined(__MINGW64__) && defined(_WIN32) +# define llround(x) round(x) +#endif + #if defined(__MINGW64__) || defined(__MINGW32__) # include <sys/time.h> #endif diff --git a/mrblib/array.rb b/mrblib/array.rb index 933f822db..65dd0d665 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -16,7 +16,7 @@ class Array 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 + if elm.nil? and length >= self.length break end end @@ -50,9 +50,7 @@ class Array def collect!(&block) return to_enum :collect! unless block_given? - self.each_index{|idx| - self[idx] = block.call(self[idx]) - } + self.each_index { |idx| self[idx] = block.call(self[idx]) } self end @@ -72,7 +70,7 @@ class Array self.clear if size > 0 - self[size - 1] = nil # allocate + self[size - 1] = nil # allocate idx = 0 while idx < size @@ -158,14 +156,11 @@ class Array len = self.size n = other.size - if len > n - len = n - end + len = n if len > n i = 0 while i < len n = (self[i] <=> other[i]) - return n if n == nil - return n if n != 0 + return n if n.nil? || n != 0 i += 1 end len = self.size - other.size @@ -185,20 +180,14 @@ class Array self.delete_at(i) ret = key end - if ret == nil && block - block.call - else - ret - end + return block.call if ret.nil? && block + ret end # internal method to convert multi-value to single value def __svalue - if self.size < 2 - self.first - else - self - end + return self.first if self.size < 2 + self end end diff --git a/mrblib/enum.rb b/mrblib/enum.rb index 6bf219283..f0c9a4884 100644 --- a/mrblib/enum.rb +++ b/mrblib/enum.rb @@ -24,17 +24,9 @@ module Enumerable # ISO 15.3.2.2.1 def all?(&block) if block - self.each{|*val| - unless block.call(*val) - return false - end - } + self.each{|*val| return false unless block.call(*val)} else - self.each{|*val| - unless val.__svalue - return false - end - } + self.each{|*val| return false unless val.__svalue} end true end @@ -49,17 +41,9 @@ module Enumerable # ISO 15.3.2.2.2 def any?(&block) if block - self.each{|*val| - if block.call(*val) - return true - end - } + self.each{|*val| return true if block.call(*val)} else - self.each{|*val| - if val.__svalue - return true - end - } + self.each{|*val| return true if val.__svalue} end false end @@ -75,9 +59,7 @@ module Enumerable return to_enum :collect unless block ary = [] - self.each{|*val| - ary.push(block.call(*val)) - } + self.each{|*val| ary.push(block.call(*val))} ary end @@ -183,9 +165,7 @@ module Enumerable # ISO 15.3.2.2.10 def include?(obj) self.each{|*val| - if val.__svalue == obj - return true - end + return true if val.__svalue == obj } false end @@ -402,8 +382,11 @@ module Enumerable # redefine #hash 15.3.1.3.15 def hash h = 12347 + i = 0 self.each do |e| - h ^= e.hash + n = e.hash << (i % 16) + h ^= n + i += 1 end h end diff --git a/mrblib/error.rb b/mrblib/error.rb index d76dd9c56..2674af7a2 100644 --- a/mrblib/error.rb +++ b/mrblib/error.rb @@ -1,18 +1,3 @@ -## -# Exception -# -# ISO 15.2.22 -class Exception - - ## - # Raise an exception. - # - # ISO 15.2.22.4.1 - def self.exception(*args, &block) - self.new(*args, &block) - end -end - # ISO 15.2.24 class ArgumentError < StandardError end diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index cf608b04b..206185e78 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -100,7 +100,7 @@ module Integral # Calls the given block from +self+ to +num+ # incremented by +step+ (default 1). # - def step(num, step=1, &block) + def step(num, step = 1, &block) raise ArgumentError, "step can't be 0" if step == 0 return to_enum(:step, num, step) unless block_given? @@ -165,16 +165,12 @@ class Float # floats should be compatible to integers. def >> other n = self.to_i - other.to_i.times { - n /= 2 - } + other.to_i.times { n /= 2 } n end def << other n = self.to_i - other.to_i.times { - n *= 2 - } + other.to_i.times { n *= 2 } n.to_i end end diff --git a/mrblib/range.rb b/mrblib/range.rb index 64fa0cb6c..5e5fd9bdc 100644 --- a/mrblib/range.rb +++ b/mrblib/range.rb @@ -26,9 +26,7 @@ class Range return self end - unless val.respond_to? :succ - raise TypeError, "can't iterate" - end + raise TypeError, "can't iterate" unless val.respond_to? :succ return self if (val <=> last) > 0 @@ -37,18 +35,14 @@ class Range val = val.succ end - if not exclude_end? and (val <=> last) == 0 - block.call(val) - end + block.call(val) if !exclude_end? && (val <=> last) == 0 self end # redefine #hash 15.3.1.3.15 def hash h = first.hash ^ last.hash - if self.exclude_end? - h += 1 - end + h += 1 if self.exclude_end? h end end diff --git a/mrblib/string.rb b/mrblib/string.rb index ee097ad6d..05b13cb43 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -80,12 +80,8 @@ class String # ISO 15.2.10.5.19 def gsub!(*args, &block) str = self.gsub(*args, &block) - if str != self - self.replace(str) - self - else - nil - end + return nil if str == self + self.replace(str) end ## @@ -111,6 +107,7 @@ class String def sub(*args, &block) if args.size == 2 pre, post = split(args[0], 2) + return self unless post # The sub target wasn't found in the string pre + args[1].__sub_replace(pre, args[0], post) + post elsif args.size == 1 && block split(args[0], 2).join(block.call(args[0])) @@ -128,12 +125,8 @@ class String # ISO 15.2.10.5.37 def sub!(*args, &block) str = self.sub(*args, &block) - if str != self - self.replace(str) - self - else - nil - end + return nil if str == self + self.replace(str) end ## @@ -164,20 +157,16 @@ class String # Modify +self+ by replacing the content of +self+ # at the position +pos+ with +value+. def []=(pos, value) - if pos < 0 - pos += self.length - end + pos += self.length if pos < 0 b = self[0, pos] - a = self[pos+1..-1] + a = self[pos + 1..-1] self.replace([b, value, a].join('')) end ## # ISO 15.2.10.5.3 def =~(re) - if re.respond_to? :to_str - raise TypeError, "type mismatch: String given" - end + raise TypeError, "type mismatch: String given" if re.respond_to? :to_str re =~ self end diff --git a/src/array.c b/src/array.c index f48719310..2622ee528 100644 --- a/src/array.c +++ b/src/array.c @@ -19,7 +19,6 @@ static inline mrb_value ary_elt(mrb_value ary, mrb_int offset) { - if (RARRAY_LEN(ary) == 0) return mrb_nil_value(); if (offset < 0 || RARRAY_LEN(ary) <= offset) { return mrb_nil_value(); } @@ -295,7 +294,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self) mrb_get_args(mrb, "a", &ptr, &blen); if (ARY_MAX_SIZE - blen < a1->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a2 = ary_new_capa(mrb, a1->len + blen); array_copy(a2->ptr, a1->ptr, a1->len); @@ -349,7 +348,7 @@ mrb_ary_times(mrb_state *mrb, mrb_value self) } if (times == 0) return mrb_ary_new(mrb); if (ARY_MAX_SIZE / times < a1->len) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); + mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big"); } a2 = ary_new_capa(mrb, a1->len * times); ptr = a2->ptr; @@ -1031,7 +1030,7 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary) { mrb_value sep = mrb_nil_value(); - mrb_get_args(mrb, "|S", &sep); + mrb_get_args(mrb, "|S!", &sep); return mrb_ary_join(mrb, ary, sep); } diff --git a/src/class.c b/src/class.c index e9cbc592d..33fb61211 100644 --- a/src/class.c +++ b/src/class.c @@ -435,12 +435,12 @@ to_sym(mrb_state *mrb, mrb_value ss) ---------------------------------------------------------------------------------------------- o: Object [mrb_value] C: class/module [mrb_value] - S: String [mrb_value] - A: Array [mrb_value] - H: Hash [mrb_value] - s: String [char*,mrb_int] Receive two arguments. - z: String [char*] NUL terminated string. - a: Array [mrb_value*,mrb_int] Receive two arguments. + 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] @@ -525,6 +525,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_str(mrb, *sp++); i++; @@ -536,6 +544,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_ary(mrb, *sp++); i++; @@ -547,6 +563,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) mrb_value *p; p = va_arg(ap, mrb_value*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *p = *sp++; + i++; + break; + } + } if (i < argc) { *p = to_hash(mrb, *sp++); i++; @@ -561,6 +585,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) ps = va_arg(ap, char**); pl = va_arg(ap, mrb_int*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *ps = NULL; + *pl = 0; + i++; + break; + } + } if (i < argc) { ss = to_str(mrb, *sp++); *ps = RSTRING_PTR(ss); @@ -575,6 +608,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) const char **ps; ps = va_arg(ap, const char**); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *ps = NULL; + i++; + break; + } + } if (i < argc) { ss = to_str(mrb, *sp++); *ps = mrb_string_value_cstr(mrb, &ss); @@ -591,6 +632,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) pb = va_arg(ap, mrb_value**); pl = va_arg(ap, mrb_int*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *pb = 0; + *pl = 0; + i++; + break; + } + } if (i < argc) { aa = to_ary(mrb, *sp++); a = mrb_ary_ptr(aa); @@ -676,6 +726,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) datap = va_arg(ap, void**); type = va_arg(ap, struct mrb_data_type const*); + if (*format == '!') { + format++; + if (i < argc && mrb_nil_p(*sp)) { + *datap = 0; + i++; + break; + } + } if (i < argc) { *datap = mrb_data_get_ptr(mrb, *sp++, type); ++i; @@ -1262,6 +1320,31 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv) return mrb_bool_value(!mrb_test(cv)); } +void +mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args) +{ + mrb_sym inspect; + mrb_value repr; + + inspect = mrb_intern_lit(mrb, "inspect"); + if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { + /* method missing in inspect; avoid recursion */ + repr = mrb_any_to_s(mrb, self); + } + else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) { + repr = mrb_funcall_argv(mrb, self, inspect, 0, 0); + if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { + repr = mrb_any_to_s(mrb, self); + } + } + else { + repr = mrb_any_to_s(mrb, self); + } + + mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S", + mrb_sym2str(mrb, name), repr); +} + /* 15.3.1.3.30 */ /* * call-seq: @@ -1301,27 +1384,9 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_sym name; mrb_value *a; mrb_int alen; - mrb_sym inspect; - mrb_value repr; mrb_get_args(mrb, "n*", &name, &a, &alen); - - inspect = mrb_intern_lit(mrb, "inspect"); - if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { - /* method missing in inspect; avoid recursion */ - repr = mrb_any_to_s(mrb, mod); - } - else if (mrb_respond_to(mrb, mod, inspect) && mrb->c->ci - mrb->c->cibase < 64) { - repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0); - if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) { - repr = mrb_any_to_s(mrb, mod); - } - } - else { - repr = mrb_any_to_s(mrb, mod); - } - - mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr); + mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a)); /* not reached */ return mrb_nil_value(); } @@ -1543,10 +1608,10 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass) case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: - mrb_str_append(mrb, str, mrb_inspect(mrb, v)); + mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v)); break; default: - mrb_str_append(mrb, str, mrb_any_to_s(mrb, v)); + mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v)); break; } return mrb_str_cat_lit(mrb, str, ">"); diff --git a/src/dump.c b/src/dump.c index 2f2e5edcb..734f38043 100644 --- a/src/dump.c +++ b/src/dump.c @@ -16,7 +16,7 @@ #define FLAG_BYTEORDER_NONATIVE 0 #ifdef MRB_USE_FLOAT -#define MRB_FLOAT_FMT "%.9e" +#define MRB_FLOAT_FMT "%.8e" #else #define MRB_FLOAT_FMT "%.16e" #endif @@ -978,12 +978,8 @@ error_exit: mrb_free(mrb, *bin); *bin = NULL; } - if (lv_syms) { - mrb_free(mrb, lv_syms); - } - if (filenames) { - mrb_free(mrb, filenames); - } + mrb_free(mrb, lv_syms); + mrb_free(mrb, filenames); return result; } diff --git a/src/error.c b/src/error.c index a800f77f9..359e5737b 100644 --- a/src/error.c +++ b/src/error.c @@ -152,7 +152,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) mrb_str_append(mrb, str, line); mrb_str_cat_lit(mrb, str, ": "); if (append_mesg) { - mrb_str_append(mrb, str, mesg); + mrb_str_cat_str(mrb, str, mesg); mrb_str_cat_lit(mrb, str, " ("); } mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc)); @@ -165,7 +165,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc) str = mrb_str_new_cstr(mrb, cname); mrb_str_cat_lit(mrb, str, ": "); if (append_mesg) { - mrb_str_append(mrb, str, mesg); + mrb_str_cat_str(mrb, str, mesg); } else { mrb_str_cat_cstr(mrb, str, cname); @@ -424,15 +424,14 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg) } MRB_API mrb_noreturn void -mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...) +mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...) { mrb_value exc; va_list ap; va_start(ap, fmt); exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3, - mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), - mrb_ary_new_from_values(mrb, argc, argv)); + mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args); va_end(ap); mrb_exc_raise(mrb, exc); } @@ -67,17 +67,15 @@ mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type) MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name) { - mrb_value tmp; mrb_sym id; switch (mrb_type(name)) { default: - tmp = mrb_check_string_type(mrb, name); - if (mrb_nil_p(tmp)) { - tmp = mrb_inspect(mrb, name); - mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); + name = mrb_check_string_type(mrb, name); + if (mrb_nil_p(name)) { + name = mrb_inspect(mrb, name); + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", name); } - name = tmp; /* fall through */ case MRB_TT_STRING: name = mrb_str_intern(mrb, name); diff --git a/src/fmt_fp.c b/src/fmt_fp.c index b467435a3..b27ebd6e9 100644 --- a/src/fmt_fp.c +++ b/src/fmt_fp.c @@ -90,7 +90,7 @@ fmt_u(uint32_t x, char *s) typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)]; #endif -#if ((defined(__CYGWIN32__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__) +#if ((defined(__CYGWIN__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__) #undef frexpl #define frexpl frexp #endif diff --git a/src/numeric.c b/src/numeric.c index b9aef51d9..14c0b76a6 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -55,7 +55,8 @@ num_pow(mrb_state *mrb, mrb_value x) mrb_get_args(mrb, "o", &y); yv = mrb_to_flo(mrb, y); d = pow(mrb_to_flo(mrb, x), yv); - if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0) + if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0 && + (d < 0 || (d > 0 && (mrb_int)d > 0))) return mrb_fixnum_value((mrb_int)d); return mrb_float_value(mrb, d); } diff --git a/src/range.c b/src/range.c index b427dc1b7..b58b6a1c8 100644 --- a/src/range.c +++ b/src/range.c @@ -290,7 +290,7 @@ range_to_s(mrb_state *mrb, mrb_value range) str2 = mrb_obj_as_string(mrb, r->edges->end); str = mrb_str_dup(mrb, str); mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_append(mrb, str, str2); + mrb_str_cat_str(mrb, str, str2); return str; } @@ -315,7 +315,7 @@ range_inspect(mrb_state *mrb, mrb_value range) str2 = mrb_inspect(mrb, r->edges->end); str = mrb_str_dup(mrb, str); mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2); - mrb_str_append(mrb, str, str2); + mrb_str_cat_str(mrb, str, str2); return str; } diff --git a/src/string.c b/src/string.c index 45ba38c9d..e5f446bde 100644 --- a/src/string.c +++ b/src/string.c @@ -75,9 +75,18 @@ str_decref(mrb_state *mrb, mrb_shared_string *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; @@ -119,6 +128,15 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } } +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) { @@ -1345,6 +1363,7 @@ 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); @@ -2514,4 +2533,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); + + mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } diff --git a/src/variable.c b/src/variable.c index 1b2ad56a7..efe6fad12 100644 --- a/src/variable.c +++ b/src/variable.c @@ -609,7 +609,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) else { ins = mrb_inspect(mrb, v); } - mrb_str_append(mrb, str, ins); + mrb_str_cat_str(mrb, str, ins); return 0; } diff --git a/src/version.c b/src/version.c index 7aac44d62..fc3b2fc7a 100644 --- a/src/version.c +++ b/src/version.c @@ -7,6 +7,7 @@ mrb_init_version(mrb_state* mrb) 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, "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)); mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION)); mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT)); @@ -266,6 +266,7 @@ ecall(mrb_state *mrb, int i) mrb_value *self = mrb->c->stack; struct RObject *exc; + if (i<0) return; p = mrb->c->ensure[i]; if (!p) return; if (mrb->c->ci->eidx > i) @@ -723,6 +724,8 @@ argnum_error(mrb_state *mrb, mrb_int num) #define CALL_MAXARGS 127 +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) { @@ -1030,7 +1033,7 @@ RETRY_TRY_BLOCK: mrb_callinfo *ci = mrb->c->ci; int n, eidx = ci->eidx; - for (n=0; n<a && eidx > ci[-1].eidx; n++) { + for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) { ecall(mrb, --eidx); ARENA_RESTORE(mrb, ai); } @@ -1078,8 +1081,15 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &c, missing); if (!m) { - mrb_no_method_error(mrb, mid, n, regs+a+1, - "undefined method '%S' for %S", mrb_sym2str(mrb, mid), recv); + mrb_value args; + + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); } mid = missing; if (n == CALL_MAXARGS) { @@ -1488,6 +1498,9 @@ RETRY_TRY_BLOCK: MRB_THROW(prev_jmp); } if (ci == mrb->c->cibase) { + while (eidx > 0) { + ecall(mrb, --eidx); + } if (ci->ridx == 0) { if (mrb->c == mrb->root_c) { regs = mrb->c->stack = mrb->c->stbase; diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index 04a9c39f0..d13e7733f 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -130,7 +130,7 @@ module MRuby end def define_gem_init_builder - file objfile("#{build_dir}/gem_init") => "#{build_dir}/gem_init.c" + file objfile("#{build_dir}/gem_init") => [ "#{build_dir}/gem_init.c", File.join(dir, "mrbgem.rake") ] file "#{build_dir}/gem_init.c" => [build.mrbcfile, __FILE__] + [rbfiles].flatten do |t| FileUtils.mkdir_p build_dir generate_gem_init("#{build_dir}/gem_init.c") diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake index 947b4ba77..9f8b4eda5 100644 --- a/tasks/mruby_build.rake +++ b/tasks/mruby_build.rake @@ -127,8 +127,8 @@ module MRuby obj = objfile(cxx_src) if obj.nil? file cxx_src => [src, __FILE__] do |t| - File.open(t.name, 'w') do |f| - f.write <<EOS + FileUtils.mkdir_p File.dirname t.name + IO.write t.name, <<EOS #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS @@ -136,9 +136,8 @@ extern "C" { #include "#{src}" } -#{File.basename(src) == 'error.c'? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''} +#{src == "#{MRUBY_ROOT}/src/error.c"? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''} EOS - end end file obj => cxx_src do |t| diff --git a/tasks/mruby_build_commands.rake b/tasks/mruby_build_commands.rake index 4fbfaa785..f4805f46d 100644 --- a/tasks/mruby_build_commands.rake +++ b/tasks/mruby_build_commands.rake @@ -92,6 +92,8 @@ module MRuby def define_rules(build_dir, source_dir='') @out_ext = build.exts.object + gemrake = File.join(source_dir, "mrbgem.rake") + rakedep = File.exist?(gemrake) ? [ gemrake ] : [] if build_dir.include? "mrbgems/" generated_file_matcher = Regexp.new("^#{Regexp.escape build_dir}/(.*)#{Regexp.escape out_ext}$") @@ -104,7 +106,7 @@ module MRuby file.sub(generated_file_matcher, "#{source_dir}/\\1#{ext}") }, proc { |file| - get_dependencies(file) + get_dependencies(file) + rakedep } ] do |t| run t.name, t.prerequisites.first @@ -115,7 +117,7 @@ module MRuby file.sub(generated_file_matcher, "#{build_dir}/\\1#{ext}") }, proc { |file| - get_dependencies(file) + get_dependencies(file) + rakedep } ] do |t| run t.name, t.prerequisites.first diff --git a/tasks/mruby_build_gem.rake b/tasks/mruby_build_gem.rake index 26990a380..896aeb147 100644 --- a/tasks/mruby_build_gem.rake +++ b/tasks/mruby_build_gem.rake @@ -59,7 +59,7 @@ module MRuby git.run_pull mgem_list_dir, mgem_list_url if $pull_gems else FileUtils.mkdir_p mgem_list_dir - git.run_clone mgem_list_dir, mgem_list_url + git.run_clone mgem_list_dir, mgem_list_url, "--depth 1" end require 'yaml' @@ -76,6 +76,9 @@ module MRuby if params[:core] gemdir = "#{root}/mrbgems/#{params[:core]}" + elsif params[:path] + require 'pathname' + gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}" elsif params[:git] url = params[:git] gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}" diff --git a/tasks/toolchains/androideabi.rake b/tasks/toolchains/androideabi.rake index 7cdb9e43a..272e802f7 100644 --- a/tasks/toolchains/androideabi.rake +++ b/tasks/toolchains/androideabi.rake @@ -27,6 +27,8 @@ MRuby::Toolchain.new(:androideabi) do |conf| 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 @@ -74,9 +76,9 @@ MRuby::Toolchain.new(:androideabi) do |conf| else # Any other architecture are not supported by Android NDK. end - path_to_toolchain += DEFAULT_GCC_VERSION + '/prebuilt/' + HOST_PLATFORM + path_to_toolchain += GCC_VERSION + '/prebuilt/' + HOST_PLATFORM else - path_to_toolchain += 'llvm-' + DEFAULT_CLANG_VERSION + '/prebuilt/' + HOST_PLATFORM + path_to_toolchain += 'llvm-' + CLANG_VERSION + '/prebuilt/' + HOST_PLATFORM end else path_to_toolchain = ANDROID_STANDALONE_TOOLCHAIN diff --git a/test/bintest.rb b/test/bintest.rb index 0ff3341a0..49990abb9 100644 --- a/test/bintest.rb +++ b/test/bintest.rb @@ -2,7 +2,7 @@ $:.unshift File.dirname(File.dirname(File.expand_path(__FILE__))) require 'test/assert.rb' ARGV.each do |gem| - Dir["#{gem}/bintest/*.rb"].each do |file| + Dir["#{gem}/bintest/**/*.rb"].each do |file| load file end end diff --git a/test/t/string.rb b/test/t/string.rb index ee6fe0848..7326adce9 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -542,3 +542,11 @@ assert('String#each_byte') do assert_equal bytes1, bytes2 end + +assert('String#freeze') do + str = "hello" + str.freeze + + assert_raise(RuntimeError) { str.upcase! } +end + |
