Merge remote-tracking branch 'mruby/master'

This commit is contained in:
Asmod4n
2015-09-17 13:24:17 +02:00
126 changed files with 3307 additions and 815 deletions
+9 -2
View File
@@ -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"
+1
View File
@@ -26,6 +26,7 @@ Original Authors "mruby developers" are:
Hiroshi Mimaki
Satoshi Odawara
Mitsubishi Electric Micro-Computer Application Software Co.,Ltd.
Ralph Desir(Mav7)
Hiroyuki Matsuzaki
Yuhei Okazaki
Manycolors, Inc.
+1 -1
View File
@@ -45,7 +45,7 @@ on-demand.
#### Don't use C++ style comments
/* This is the prefered comment style */
/* This is the preferred comment style */
Use C++ style comments only for temporary comment e.g. commenting out some code lines.
+6 -9
View File
@@ -3,6 +3,7 @@
# basic build file for mruby
MRUBY_ROOT = File.dirname(File.expand_path(__FILE__))
MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd')
# load build systems
load "#{MRUBY_ROOT}/tasks/ruby_ext.rake"
@@ -21,21 +22,17 @@ end
# load custom rules
load "#{MRUBY_ROOT}/src/mruby_core.rake"
load "#{MRUBY_ROOT}/mrblib/mrblib.rake"
load "#{MRUBY_ROOT}/tools/mrbc/mrbc.rake"
load "#{MRUBY_ROOT}/tasks/mrbgems.rake"
load "#{MRUBY_ROOT}/tasks/libmruby.rake"
load "#{MRUBY_ROOT}/tasks/mrbgems_test.rake"
load "#{MRUBY_ROOT}/test/mrbtest.rake"
load "#{MRUBY_ROOT}/tasks/benchmark.rake"
##############################
# 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|
@@ -74,7 +71,7 @@ MRuby.each_target do |target|
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 }
@@ -83,7 +80,7 @@ MRuby.each_target do |target|
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 }
@@ -117,9 +114,9 @@ task :all => depfiles do
end
desc "run all mruby tests"
task :test => ["all"] + MRuby.targets.values.map { |t| t.build_mrbtest_lib_only? ? t.libfile("#{t.build_dir}/test/mrbtest") : t.exefile("#{t.build_dir}/test/mrbtest") } do
task :test => ["all"] do
MRuby.each_target do
run_test unless build_mrbtest_lib_only?
run_test if test_enabled?
end
end
+10
View File
@@ -108,6 +108,16 @@ MRuby::Build.new('host-debug') do |conf|
# conf.enable_bintest
end
MRuby::Build.new('test') do |conf|
toolchain :gcc
enable_debug
conf.enable_bintest
conf.enable_test
conf.gembox 'default'
end
# Define cross build settings
# MRuby::CrossBuild.new('32bit') do |conf|
# toolchain :gcc
+20 -20
View File
@@ -8,23 +8,23 @@ 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.
[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.
+156 -8
View File
@@ -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`|
@@ -67,3 +69,149 @@ char|mruby type|retrieve types|note
`?`|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.
+250
View File
@@ -0,0 +1,250 @@
### 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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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]
```
+380
View File
@@ -0,0 +1,380 @@
### 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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 {}
```
+47
View File
@@ -0,0 +1,47 @@
#### 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 <stdio.h>
#include <mruby.h>
#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
```
+3
View File
@@ -0,0 +1,3 @@
### Macros
#### REGEXP_CLASS
A string with the name of the REGEXP class.
+91
View File
@@ -0,0 +1,91 @@
## 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.
+238
View File
@@ -0,0 +1,238 @@
### 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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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 <stdio.h>
#include <mruby.h>
#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
```
+33
View File
@@ -0,0 +1,33 @@
### 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.
+1 -1
View File
@@ -13,7 +13,7 @@ This file documents the mruby debugger ('mrdb') methods.
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-Forum/mruby.git
$ git clone https://github.com/mruby/mruby.git
```
To run the `make` command:
+19 -6
View File
@@ -26,6 +26,15 @@ 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```.
@@ -142,7 +151,7 @@ MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec|
# 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 ignored)
# Use latest mruby-onig-regexp from github. (version requirements can be omitted)
spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp')
end
```
@@ -189,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.
+16 -10
View File
@@ -192,10 +192,13 @@ typedef struct mrb_state {
# 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);
@@ -203,6 +206,7 @@ MRB_API struct RClass *mrb_define_class(mrb_state *, const char*, struct RClass*
MRB_API struct RClass *mrb_define_module(mrb_state *, const char*);
MRB_API mrb_value mrb_singleton_class(mrb_state*, mrb_value);
MRB_API void mrb_include_module(mrb_state*, struct RClass*, struct RClass*);
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);
MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *, mrb_func_t, mrb_aspec);
@@ -250,16 +254,6 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
/* accept no arguments */
#define MRB_ARGS_NONE() ((mrb_aspec)0)
/* compatibility macros; will be removed */
#define ARGS_REQ(n) MRB_ARGS_REQ(n)
#define ARGS_OPT(n) MRB_ARGS_OPT(n)
#define ARGS_REST() MRB_ARGS_REST()
#define ARGS_POST(n) MRB_ARGS_POST()
#define ARGS_KEY(n1,n2) MRB_ARGS_KEY(n1,n2)
#define ARGS_BLOCK() MRB_ARGS_BLOCK()
#define ARGS_ANY() MRB_ARGS_ANY()
#define ARGS_NONE() MRB_ARGS_NONE()
MRB_API mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...);
/* `strlen` for character string literals (use with caution or `strlen` instead)
@@ -298,6 +292,18 @@ 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
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);
+14 -2
View File
@@ -48,8 +48,20 @@ mrb_class(mrb_state *mrb, mrb_value v)
}
}
#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~0xff) | (char)tt)
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & 0xff)
// TODO: figure out where to put user flags
#define MRB_FLAG_IS_PREPENDED (1 << 19)
#define MRB_FLAG_IS_ORIGIN (1 << 20)
#define MRB_CLASS_ORIGIN(c) do {\
if (c->flags & MRB_FLAG_IS_PREPENDED) {\
c = c->super;\
while (!(c->flags & MRB_FLAG_IS_ORIGIN)) {\
c = c->super;\
}\
}\
} while (0)
#define MRB_INSTANCE_TT_MASK (0xFF)
#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt)
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK)
MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
+2 -2
View File
@@ -55,8 +55,8 @@ enum mrb_lex_state_enum {
EXPR_CMDARG, /* newline significant, +/- is an operator. */
EXPR_MID, /* newline significant, +/- is an operator. */
EXPR_FNAME, /* ignore newline, no reserved words. */
EXPR_DOT, /* right after `.' or `::', no reserved words. */
EXPR_CLASS, /* immediate after `class', no here document. */
EXPR_DOT, /* right after '.' or '::', no reserved words. */
EXPR_CLASS, /* immediate after 'class', no here document. */
EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */
EXPR_MAX_STATE
};
+2 -2
View File
@@ -17,8 +17,8 @@ extern "C" {
#define DUMP_DEBUG_INFO 1
#define DUMP_ENDIAN_BIG 2
#define DUMP_ENDIAN_LIL 4
#define DUMP_ENDIAN_NAT 6
#define DUMP_ENDIAN_MASK 6
#define DUMP_ENDIAN_NAT 6
#define DUMP_ENDIAN_MASK 6
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
#ifdef ENABLE_STDIO
+11 -1
View File
@@ -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
+2
View File
@@ -14,6 +14,8 @@
struct RClass *c;\
struct RBasic *gcnext
#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
+1 -1
View File
@@ -8,7 +8,7 @@
#define MRUBY_OPCODE_H
#define MAXARG_Bx (0xffff)
#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
/* instructions: packed 32 bit */
/* ------------------------------- */
+8 -3
View File
@@ -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*);
+7 -5
View File
@@ -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 \
+14 -11
View File
@@ -14,34 +14,34 @@ MRuby::GemBox.new do |conf|
# Use standard Struct class
conf.gem :core => "mruby-struct"
# Use extensional Enumerable module
# Use Enumerable module extension
conf.gem :core => "mruby-enum-ext"
# Use extensional String class
# Use String class extension
conf.gem :core => "mruby-string-ext"
# Use extensional Numeric class
# Use Numeric class extension
conf.gem :core => "mruby-numeric-ext"
# Use extensional Array class
# Use Array class extension
conf.gem :core => "mruby-array-ext"
# Use extensional Hash class
# Use Hash class extension
conf.gem :core => "mruby-hash-ext"
# Use extensional Range class
# Use Range class extension
conf.gem :core => "mruby-range-ext"
# Use extensional Proc class
# Use Proc class extension
conf.gem :core => "mruby-proc-ext"
# Use extensional Symbol class
# Use Symbol class extension
conf.gem :core => "mruby-symbol-ext"
# Use Random class
conf.gem :core => "mruby-random"
# Use extensional Object class
# Use Object class extension
conf.gem :core => "mruby-object-ext"
# Use ObjectSpace class
@@ -56,7 +56,7 @@ MRuby::GemBox.new do |conf|
# Use Enumerable::Lazy class (require mruby-enumerator)
conf.gem :core => "mruby-enum-lazy"
# Use extended toplevel object (main) methods
# Use toplevel object (main) methods extension
conf.gem :core => "mruby-toplevel-ext"
# Generate mirb command
@@ -68,6 +68,9 @@ MRuby::GemBox.new do |conf|
# Generate mruby-strip command
conf.gem :core => "mruby-bin-strip"
# Use extensional Kernel module
# Use Kernel module extension
conf.gem :core => "mruby-kernel-ext"
# Use mruby-compiler to build other mrbgems
conf.gem :core => "mruby-compiler"
end
+1 -1
View File
@@ -4,6 +4,6 @@ MRuby::GemBox.new do |conf|
Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x|
g = File.basename File.dirname x
conf.gem :core => g unless g =~ /^mruby-(print|sprintf|bin-debugger)$/
conf.gem :core => g unless g =~ /^mruby-(print|sprintf|bin-debugger|test)$/
end
end
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Array class'
spec.summary = 'Array class extension'
end
+12 -12
View File
@@ -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
+1 -1
View File
@@ -1,7 +1,7 @@
MRuby::Gem::Specification.new('mruby-bin-debugger') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'mruby debuggeer command'
spec.summary = 'mruby debugger command'
spec.add_dependency('mruby-eval', :core => 'mruby-eval')
@@ -33,7 +33,7 @@ static help_msg help_msg_list[] = {
"\n"
"Continue program stopped by a breakpoint.\n"
"If N, which is non negative value, is passed,\n"
"proceed program until the N-th breakpoint is comming.\n"
"proceed program until the N-th breakpoint is coming.\n"
"If N is not passed, N is assumed 1.\n"
},
{
+2 -2
View File
@@ -222,9 +222,9 @@ mrb_debug_context_free(mrb_state *mrb)
static mrdb_state*
mrdb_state_new(mrb_state *mrb)
{
mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrb_state));
mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state));
memset(mrdb, 0, sizeof(mrb_state));
memset(mrdb, 0, sizeof(mrdb_state));
mrdb->dbg = mrb_debug_context_get(mrb);
mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1);
+12 -4
View File
@@ -6,20 +6,28 @@ MRuby::Gem::Specification.new('mruby-bin-mirb') do |spec|
if spec.build.cc.search_header_path 'readline/readline.h'
spec.cc.defines << "ENABLE_READLINE"
if spec.build.cc.search_header_path 'termcap.h'
if MRUBY_BUILD_HOST_IS_CYGWIN then
spec.linker.libraries << 'ncurses'
else
spec.linker.libraries << 'termcap'
if MRUBY_BUILD_HOST_IS_CYGWIN || MRUBY_BUILD_HOST_IS_OPENBSD
if spec.build.cc.search_header_path 'termcap.h'
if MRUBY_BUILD_HOST_IS_CYGWIN then
spec.linker.libraries << 'ncurses'
else
spec.linker.libraries << 'termcap'
end
end
end
end
if RUBY_PLATFORM.include?('netbsd')
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"
end
spec.bins = %w(mirb)
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
end
+8 -2
View File
@@ -366,6 +366,8 @@ main(int argc, char **argv)
ai = mrb_gc_arena_save(mrb);
while (TRUE) {
char *utf8;
#ifndef ENABLE_READLINE
print_cmdline(code_block_open);
@@ -415,17 +417,21 @@ main(int argc, char **argv)
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 */
+16
View File
@@ -0,0 +1,16 @@
MRuby::Gem::Specification.new 'mruby-bin-mrbc' do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'mruby compiler executable'
spec.add_dependency 'mruby-compiler', :core => 'mruby-compiler'
exec = exefile("#{build.build_dir}/bin/mrbc")
mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten
file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t|
build.linker.run t.name, t.prerequisites
end
build.bins << 'mrbc' unless build.bins.find { |v| v == 'mrbc' }
end
@@ -119,10 +119,10 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
args->flags |= DUMP_DEBUG_INFO;
break;
case 'E':
args->flags = DUMP_ENDIAN_BIG | (args->flags & DUMP_DEBUG_INFO);
args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
break;
case 'e':
args->flags = DUMP_ENDIAN_LIL | (args->flags & DUMP_DEBUG_INFO);
args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
break;
case 'h':
return -1;
@@ -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);
}
+1
View File
@@ -3,4 +3,5 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
spec.author = 'mruby developers'
spec.summary = 'mruby command'
spec.bins = %w(mruby)
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
end
+12 -10
View File
@@ -11,12 +11,8 @@
static void
p(mrb_state *mrb, mrb_value obj)
{
mrb_value val;
mrb_value val = mrb_inspect(mrb, obj);
val = mrb_funcall(mrb, obj, "inspect", 0);
if (!mrb_string_p(val)) {
val = mrb_obj_as_string(mrb, obj);
}
fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
putc('\n', stdout);
}
@@ -163,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);
}
@@ -196,7 +191,11 @@ main(int argc, char **argv)
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);
@@ -227,7 +226,10 @@ main(int argc, char **argv)
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);
@@ -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))
@@ -957,13 +973,6 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
gen_vmassignment(s, tree->car, sp, val);
break;
push();
gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL);
pop();
if (val) {
genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
}
break;
/* splat without assignment */
case NODE_NIL:
break;
@@ -1008,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 */
@@ -1622,8 +1633,14 @@ codegen(codegen_scope *s, node *tree, int val)
}
}
if (t->car) { /* rest (len - pre - post) */
int rn = len - post - n;
int rn;
if (len < post + n) {
rn = 0;
}
else {
rn = len - post - n;
}
genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
gen_assignment(s, t->car, cursp(), NOVAL);
n += rn;
@@ -1912,7 +1929,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_GVAR:
{
if (val) {
int sym = new_sym(s, sym(tree));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
@@ -1921,7 +1938,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_IVAR:
{
if (val) {
int sym = new_sym(s, sym(tree));
genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
@@ -1930,7 +1947,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_CVAR:
{
if (val) {
int sym = new_sym(s, sym(tree));
genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
@@ -1943,7 +1960,9 @@ codegen(codegen_scope *s, node *tree, int val)
int sym = new_sym(s, sym(tree));
genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
push();
if (val) {
push();
}
}
break;
@@ -1952,7 +1971,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_BACK_REF:
{
if (val) {
char buf[2] = { '$' };
mrb_value str;
int sym;
@@ -1966,7 +1985,7 @@ codegen(codegen_scope *s, node *tree, int val)
break;
case NODE_NTH_REF:
{
if (val) {
int sym;
mrb_state *mrb = s->mrb;
mrb_value fix = mrb_fixnum_value((intptr_t)tree);
@@ -2651,13 +2670,17 @@ loop_break(codegen_scope *s, node *tree)
}
loop = s->loop;
while (loop->type == LOOP_BEGIN) {
while (loop && loop->type == LOOP_BEGIN) {
genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
loop = loop->prev;
}
while (loop->type == LOOP_RESCUE) {
while (loop && loop->type == LOOP_RESCUE) {
loop = loop->prev;
}
if (!loop) {
codegen_error(s, "unexpected break");
}
if (loop->type == LOOP_NORMAL) {
int tmp;
@@ -1,5 +1,5 @@
/* ANSI-C code produced by gperf version 3.0.3 */
/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' src/keywords */
/* ANSI-C code produced by gperf version 3.0.4 */
/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' /home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -28,13 +28,13 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
#endif
#line 1 "src/keywords"
#line 1 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
const struct kwtable *mrb_reserved_word(const char *, unsigned int);
static const struct kwtable *reserved_word(const char *, unsigned int);
#define mrb_reserved_word(str, len) reserved_word(str, len)
#line 8 "src/keywords"
#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
struct kwtable;
#define TOTAL_KEYWORDS 40
@@ -100,7 +100,7 @@ hash (register const char *str, register unsigned int len)
#ifdef __GNUC__
__inline
#ifdef __GNUC_STDC_INLINE__
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif
@@ -110,87 +110,87 @@ mrb_reserved_word (register const char *str, register unsigned int len)
static const struct kwtable wordlist[] =
{
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
#line 18 "src/keywords"
#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"break", {keyword_break, keyword_break}, EXPR_MID},
#line 23 "src/keywords"
#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"else", {keyword_else, keyword_else}, EXPR_BEG},
#line 33 "src/keywords"
#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"nil", {keyword_nil, keyword_nil}, EXPR_END},
#line 26 "src/keywords"
#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"ensure", {keyword_ensure, keyword_ensure}, EXPR_BEG},
#line 25 "src/keywords"
#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"end", {keyword_end, keyword_end}, EXPR_END},
#line 42 "src/keywords"
#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"then", {keyword_then, keyword_then}, EXPR_BEG},
#line 34 "src/keywords"
#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"not", {keyword_not, keyword_not}, EXPR_ARG},
#line 27 "src/keywords"
#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"false", {keyword_false, keyword_false}, EXPR_END},
#line 40 "src/keywords"
#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"self", {keyword_self, keyword_self}, EXPR_END},
#line 24 "src/keywords"
#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"elsif", {keyword_elsif, keyword_elsif}, EXPR_VALUE},
#line 37 "src/keywords"
#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"rescue", {keyword_rescue, modifier_rescue}, EXPR_MID},
#line 43 "src/keywords"
#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"true", {keyword_true, keyword_true}, EXPR_END},
#line 46 "src/keywords"
#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"until", {keyword_until, modifier_until}, EXPR_VALUE},
#line 45 "src/keywords"
#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"unless", {keyword_unless, modifier_unless}, EXPR_VALUE},
#line 39 "src/keywords"
#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"return", {keyword_return, keyword_return}, EXPR_MID},
#line 21 "src/keywords"
#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"def", {keyword_def, keyword_def}, EXPR_FNAME},
#line 16 "src/keywords"
#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"and", {keyword_and, keyword_and}, EXPR_VALUE},
#line 22 "src/keywords"
#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"do", {keyword_do, keyword_do}, EXPR_BEG},
#line 49 "src/keywords"
#line 49 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"yield", {keyword_yield, keyword_yield}, EXPR_ARG},
#line 28 "src/keywords"
#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"for", {keyword_for, keyword_for}, EXPR_VALUE},
#line 44 "src/keywords"
#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"undef", {keyword_undef, keyword_undef}, EXPR_FNAME},
#line 35 "src/keywords"
#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"or", {keyword_or, keyword_or}, EXPR_VALUE},
#line 30 "src/keywords"
#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"in", {keyword_in, keyword_in}, EXPR_VALUE},
#line 47 "src/keywords"
#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"when", {keyword_when, keyword_when}, EXPR_VALUE},
#line 38 "src/keywords"
#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"retry", {keyword_retry, keyword_retry}, EXPR_END},
#line 29 "src/keywords"
#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"if", {keyword_if, modifier_if}, EXPR_VALUE},
#line 19 "src/keywords"
#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"case", {keyword_case, keyword_case}, EXPR_VALUE},
#line 36 "src/keywords"
#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"redo", {keyword_redo, keyword_redo}, EXPR_END},
#line 32 "src/keywords"
#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"next", {keyword_next, keyword_next}, EXPR_MID},
#line 41 "src/keywords"
#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"super", {keyword_super, keyword_super}, EXPR_ARG},
#line 31 "src/keywords"
#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"module", {keyword_module, keyword_module}, EXPR_VALUE},
#line 17 "src/keywords"
#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"begin", {keyword_begin, keyword_begin}, EXPR_BEG},
#line 12 "src/keywords"
#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"__LINE__", {keyword__LINE__, keyword__LINE__}, EXPR_END},
#line 11 "src/keywords"
#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"__FILE__", {keyword__FILE__, keyword__FILE__}, EXPR_END},
#line 10 "src/keywords"
#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
#line 14 "src/keywords"
#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"END", {keyword_END, keyword_END}, EXPR_END},
#line 15 "src/keywords"
#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"alias", {keyword_alias, keyword_alias}, EXPR_FNAME},
#line 13 "src/keywords"
#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"BEGIN", {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
{""},
#line 20 "src/keywords"
#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"class", {keyword_class, keyword_class}, EXPR_CLASS},
{""}, {""},
#line 48 "src/keywords"
#line 48 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
{"while", {keyword_while, modifier_while}, EXPR_VALUE}
};
@@ -208,5 +208,5 @@ mrb_reserved_word (register const char *str, register unsigned int len)
}
return 0;
}
#line 50 "src/keywords"
#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
@@ -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
@@ -3604,10 +3605,13 @@ toklast(parser_state *p)
static void
tokfix(parser_state *p)
{
if (p->bidx >= MRB_PARSER_BUF_SIZE) {
int i = p->bidx, imax = MRB_PARSER_BUF_SIZE - 1;
if (i > imax) {
i = imax;
yyerror(p, "string too long (truncated)");
}
p->buf[p->bidx] = '\0';
p->buf[i] = '\0';
}
static const char*
@@ -4204,7 +4208,7 @@ parser_yylex(parser_state *p)
}
pushback(p, c);
if (IS_SPCARG(c)) {
yywarning(p, "`*' interpreted as argument prefix");
yywarning(p, "'*' interpreted as argument prefix");
c = tSTAR;
}
else if (IS_BEG()) {
@@ -4455,7 +4459,7 @@ parser_yylex(parser_state *p)
}
pushback(p, c);
if (IS_SPCARG(c)) {
yywarning(p, "`&' interpreted as argument prefix");
yywarning(p, "'&' interpreted as argument prefix");
c = tAMPER;
}
else if (IS_BEG()) {
@@ -4761,7 +4765,7 @@ parser_yylex(parser_state *p)
nondigit = c;
break;
case '_': /* `_' in number just ignored */
case '_': /* '_' in number just ignored */
if (nondigit) goto decode_num;
nondigit = c;
break;
@@ -4776,7 +4780,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
if (nondigit) {
trailing_uc:
yyerror_i(p, "trailing `%c' in number", nondigit);
yyerror_i(p, "trailing '%c' in number", nondigit);
}
tokfix(p);
if (is_float) {
@@ -4802,6 +4806,7 @@ parser_yylex(parser_state *p)
case ')':
case ']':
p->paren_nest--;
/* fall through */
case '}':
COND_LEXPOP();
CMDARG_LEXPOP();
@@ -5133,6 +5138,7 @@ parser_yylex(parser_state *p)
pushback(p, c);
return '$';
}
/* fall through */
case '0':
tokadd(p, '$');
}
@@ -5157,10 +5163,10 @@ parser_yylex(parser_state *p)
}
else if (isdigit(c)) {
if (p->bidx == 1) {
yyerror_i(p, "`@%c' is not allowed as an instance variable name", c);
yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
}
else {
yyerror_i(p, "`@@%c' is not allowed as a class variable name", c);
yyerror_i(p, "'@@%c' is not allowed as a class variable name", c);
}
return 0;
}
@@ -5176,7 +5182,7 @@ parser_yylex(parser_state *p)
default:
if (!identchar(c)) {
yyerror_i(p, "Invalid char `\\x%02X' in expression", c);
yyerror_i(p, "Invalid char '\\x%02X' in expression", c);
goto retry;
}
+40
View File
@@ -0,0 +1,40 @@
MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'mruby compiler library'
current_dir = spec.dir
current_build_dir = spec.build_dir
lex_def = "#{current_dir}/core/lex.def"
core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f|
next nil if build.cxx_abi_enabled? and f =~ /(codegen).c$/
objfile(f.pathmap("#{current_build_dir}/core/%n"))
}.compact
if build.cxx_abi_enabled?
core_objs <<
build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx",
objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) <<
build.compile_as_cxx("#{current_dir}/core/codegen.c", "#{current_build_dir}/core/codegen.cxx")
else
core_objs << objfile("#{current_build_dir}/core/y.tab")
file objfile("#{current_build_dir}/core/y.tab") => "#{current_build_dir}/core/y.tab.c" do |t|
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
end
end
file objfile("#{current_build_dir}/core/y.tab") => lex_def
# Parser
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t|
yacc.run t.name, t.prerequisites.first
end
# Lexical analyzer
file lex_def => "#{current_dir}/core/keywords" do |t|
gperf.run t.name, t.prerequisites.first
end
file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs
build.libmruby << core_objs
end
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-enum-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Enumerable module'
spec.summary = 'Enumerable module extension'
end
+3 -3
View File
@@ -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)
+10
View File
@@ -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
+100
View File
@@ -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)
{
}
+59
View File
@@ -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));
}
+55
View File
@@ -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
+2
View File
@@ -2,4 +2,6 @@ MRuby::Gem::Specification.new('mruby-eval') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'standard Kernel#eval method'
add_dependency 'mruby-compiler', :core => 'mruby-compiler'
end
+3 -3
View File
@@ -235,12 +235,12 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
mrb_int len;
char *file = NULL;
mrb_int line = 1;
mrb_value cv;
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;
}
cv = mrb_singleton_class(mrb, self);
c->ci->target_class = mrb_class_ptr(cv);
return mrb_run(mrb, create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line), self);
}
else {
+3 -3
View File
@@ -167,7 +167,7 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
}
}
if (resume && c->status == MRB_FIBER_TRANSFERRED) {
mrb_raise(mrb, E_FIBER_ERROR, "resuming transfered fiber");
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");
@@ -265,8 +265,8 @@ fiber_eq(mrb_state *mrb, mrb_value self)
* call-seq:
* fiber.transfer(args, ...) -> obj
*
* Transfers control to reciever fiber of the method call.
* Unlike <code>resume</code> the reciever wouldn't be pushed to call
* Transfers control to receiver fiber of the method call.
* Unlike <code>resume</code> the receiver wouldn't be pushed to call
* stack of fibers. Instead it will switch to the call stack of
* transferring fiber.
* When resuming a fiber that was transferred to another fiber it would
+1 -1
View File
@@ -1,7 +1,7 @@
MRuby::Gem::Specification.new('mruby-hash-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Hash class'
spec.summary = 'Hash class extension'
spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext'
end
+2 -2
View File
@@ -119,14 +119,14 @@ class Hash
#
# <em>produces:</em>
#
# prog.rb:2:in `fetch': key not found (KeyError)
# prog.rb:2:in 'fetch': key not found (KeyError)
# from prog.rb:2
#
def fetch(key, none=NONE, &block)
unless self.key?(key)
if block
block.call
block.call(key)
elsif none != NONE
none
else
+1
View File
@@ -75,6 +75,7 @@ assert('Hash#fetch') do
assert_equal "feline", h.fetch("cat")
assert_equal "mickey", h.fetch("mouse", "mickey")
assert_equal "minny", h.fetch("mouse"){"minny"}
assert_equal "mouse", h.fetch("mouse"){|k| k}
begin
h.fetch("gnu")
rescue => e
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-kernel-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Kernel module'
spec.summary = 'Kernel module extension'
end
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-numeric-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Numeric class'
spec.summary = 'Numeric class extension'
end
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-object-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Object class'
spec.summary = 'Object class extension'
end
+7 -6
View File
@@ -1,17 +1,18 @@
#include "mruby.h"
#include "mruby/string.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
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);
char* ptr = mrb_locale_from_utf8(RSTRING_PTR(obj), RSTRING_LEN(obj));
if (ptr) {
fwrite(ptr, strlen(ptr), 1, stdout);
mrb_locale_free(ptr);
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-proc-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Proc class'
spec.summary = 'Proc class extension'
end
+3 -1
View File
@@ -13,9 +13,11 @@ class Proc
end
def curry(arity=self.arity)
type = :proc
abs = lambda {|a| a < 0 ? -a - 1 : a}
arity = abs[arity]
if lambda?
type = :lambda
self_arity = self.arity
if (self_arity >= 0 && arity != self_arity) ||
(self_arity < 0 && abs[self_arity] > arity)
@@ -25,7 +27,7 @@ class Proc
pproc = self
make_curry = proc do |given_args=[]|
proc do |*args|
send(type) do |*args|
new_args = given_args + args
if new_args.size >= arity
pproc[*new_args]
+3
View File
@@ -41,6 +41,9 @@ assert('Proc#curry') do
assert_raise(ArgumentError) { b.curry[1, 2][3, 4] }
assert_raise(ArgumentError) { b.curry(5) }
assert_raise(ArgumentError) { b.curry(1) }
assert_false(proc{}.curry.lambda?)
assert_true(lambda{}.curry.lambda?)
end
assert('Proc#parameters') do
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-range-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Range class'
spec.summary = 'Range class extension'
end
+41 -41
View File
@@ -73,7 +73,7 @@ mrb_fix2binstr(mrb_state *mrb, mrb_value x, int base)
{
char buf[64], *b = buf + sizeof buf;
mrb_int num = mrb_fixnum(x);
unsigned long val = (unsigned long)num;
uint64_t val = (uint64_t)num;
char d;
if (base != 2) {
@@ -234,20 +234,20 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* ------+--------------------------------------------------------------
* b | Convert argument as a binary number.
* | Negative numbers will be displayed as a two's complement
* | prefixed with `..1'.
* B | Equivalent to `b', but uses an uppercase 0B for prefix
* | prefixed with '..1'.
* B | Equivalent to 'b', but uses an uppercase 0B for prefix
* | in the alternative format by #.
* d | Convert argument as a decimal number.
* i | Identical to `d'.
* i | Identical to 'd'.
* o | Convert argument as an octal number.
* | Negative numbers will be displayed as a two's complement
* | prefixed with `..7'.
* u | Identical to `d'.
* | prefixed with '..7'.
* u | Identical to 'd'.
* x | Convert argument as a hexadecimal number.
* | Negative numbers will be displayed as a two's complement
* | prefixed with `..f' (representing an infinite string of
* | prefixed with '..f' (representing an infinite string of
* | leading 'ff's).
* X | Equivalent to `x', but uses uppercase letters.
* X | Equivalent to 'x', but uses uppercase letters.
*
* Field | Float Format
* ------+--------------------------------------------------------------
@@ -255,7 +255,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* | with one digit before the decimal point as [-]d.dddddde[+-]dd.
* | The precision specifies the number of digits after the decimal
* | point (defaulting to six).
* E | Equivalent to `e', but uses an uppercase E to indicate
* E | Equivalent to 'e', but uses an uppercase E to indicate
* | the exponent.
* f | Convert floating point argument as [-]ddd.dddddd,
* | where the precision specifies the number of digits after
@@ -264,11 +264,11 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* | if the exponent is less than -4 or greater than or
* | equal to the precision, or in dd.dddd form otherwise.
* | The precision specifies the number of significant digits.
* G | Equivalent to `g', but use an uppercase `E' in exponent form.
* G | Equivalent to 'g', but use an uppercase 'E' in exponent form.
* a | Convert floating point argument as [-]0xh.hhhhp[+-]dd,
* | which is consisted from optional sign, "0x", fraction part
* | as hexadecimal, "p", and exponential part as decimal.
* A | Equivalent to `a', but use uppercase `X' and `P'.
* A | Equivalent to 'a', but use uppercase 'X' and 'P'.
*
* Field | Other Format
* ------+--------------------------------------------------------------
@@ -287,7 +287,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* ---------+---------------+-----------------------------------------
* space | bBdiouxX | Leave a space at the start of
* | aAeEfgG | non-negative numbers.
* | (numeric fmt) | For `o', `x', `X', `b' and `B', use
* | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use
* | | a minus sign with absolute value for
* | | negative values.
* ---------+---------------+-----------------------------------------
@@ -297,27 +297,27 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* | | sprintf string.
* ---------+---------------+-----------------------------------------
* # | bBoxX | Use an alternative format.
* | aAeEfgG | For the conversions `o', increase the precision
* | | until the first digit will be `0' if
* | aAeEfgG | For the conversions 'o', increase the precision
* | | until the first digit will be '0' if
* | | it is not formatted as complements.
* | | For the conversions `x', `X', `b' and `B'
* | | on non-zero, prefix the result with ``0x'',
* | | ``0X'', ``0b'' and ``0B'', respectively.
* | | For `a', `A', `e', `E', `f', `g', and 'G',
* | | For the conversions 'x', 'X', 'b' and 'B'
* | | on non-zero, prefix the result with "0x",
* | | "0X", "0b" and "0B", respectively.
* | | For 'a', 'A', 'e', 'E', 'f', 'g', and 'G',
* | | force a decimal point to be added,
* | | even if no digits follow.
* | | For `g' and 'G', do not remove trailing zeros.
* | | For 'g' and 'G', do not remove trailing zeros.
* ---------+---------------+-----------------------------------------
* + | bBdiouxX | Add a leading plus sign to non-negative
* | aAeEfgG | numbers.
* | (numeric fmt) | For `o', `x', `X', `b' and `B', use
* | (numeric fmt) | For 'o', 'x', 'X', 'b' and 'B', use
* | | a minus sign with absolute value for
* | | negative values.
* ---------+---------------+-----------------------------------------
* - | all | Left-justify the result of this conversion.
* ---------+---------------+-----------------------------------------
* 0 (zero) | bBdiouxX | Pad with zeros, not spaces.
* | aAeEfgG | For `o', `x', `X', `b' and `B', radix-1
* | aAeEfgG | For 'o', 'x', 'X', 'b' and 'B', radix-1
* | (numeric fmt) | is used for negative numbers formatted as
* | | complements.
* ---------+---------------+-----------------------------------------
@@ -328,21 +328,21 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
*
* Examples of flags:
*
* # `+' and space flag specifies the sign of non-negative numbers.
* # '+' and space flag specifies the sign of non-negative numbers.
* sprintf("%d", 123) #=> "123"
* sprintf("%+d", 123) #=> "+123"
* sprintf("% d", 123) #=> " 123"
*
* # `#' flag for `o' increases number of digits to show `0'.
* # `+' and space flag changes format of negative numbers.
* # '#' flag for 'o' increases number of digits to show '0'.
* # '+' and space flag changes format of negative numbers.
* sprintf("%o", 123) #=> "173"
* sprintf("%#o", 123) #=> "0173"
* sprintf("%+o", -123) #=> "-173"
* sprintf("%o", -123) #=> "..7605"
* sprintf("%#o", -123) #=> "..7605"
*
* # `#' flag for `x' add a prefix `0x' for non-zero numbers.
* # `+' and space flag disables complements for negative numbers.
* # '#' flag for 'x' add a prefix '0x' for non-zero numbers.
* # '+' and space flag disables complements for negative numbers.
* sprintf("%x", 123) #=> "7b"
* sprintf("%#x", 123) #=> "0x7b"
* sprintf("%+x", -123) #=> "-7b"
@@ -350,12 +350,12 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* sprintf("%#x", -123) #=> "0x..f85"
* sprintf("%#x", 0) #=> "0"
*
* # `#' for `X' uses the prefix `0X'.
* # '#' for 'X' uses the prefix '0X'.
* sprintf("%X", 123) #=> "7B"
* sprintf("%#X", 123) #=> "0X7B"
*
* # `#' flag for `b' add a prefix `0b' for non-zero numbers.
* # `+' and space flag disables complements for negative numbers.
* # '#' flag for 'b' add a prefix '0b' for non-zero numbers.
* # '+' and space flag disables complements for negative numbers.
* sprintf("%b", 123) #=> "1111011"
* sprintf("%#b", 123) #=> "0b1111011"
* sprintf("%+b", -123) #=> "-1111011"
@@ -363,19 +363,19 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* sprintf("%#b", -123) #=> "0b..10000101"
* sprintf("%#b", 0) #=> "0"
*
* # `#' for `B' uses the prefix `0B'.
* # '#' for 'B' uses the prefix '0B'.
* sprintf("%B", 123) #=> "1111011"
* sprintf("%#B", 123) #=> "0B1111011"
*
* # `#' for `e' forces to show the decimal point.
* # '#' for 'e' forces to show the decimal point.
* sprintf("%.0e", 1) #=> "1e+00"
* sprintf("%#.0e", 1) #=> "1.e+00"
*
* # `#' for `f' forces to show the decimal point.
* # '#' for 'f' forces to show the decimal point.
* sprintf("%.0f", 1234) #=> "1234"
* sprintf("%#.0f", 1234) #=> "1234."
*
* # `#' for `g' forces to show the decimal point.
* # '#' for 'g' forces to show the decimal point.
* # It also disables stripping lowest zeros.
* sprintf("%g", 123.4) #=> "123.4"
* sprintf("%#g", 123.4) #=> "123.400"
@@ -409,7 +409,7 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
*
* Examples of precisions:
*
* # precision for `d', 'o', 'x' and 'b' is
* # precision for 'd', 'o', 'x' and 'b' is
* # minimum number of digits <------>
* sprintf("%20.8d", 123) #=> " 00000123"
* sprintf("%20.8o", 123) #=> " 00000173"
@@ -420,8 +420,8 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* sprintf("%20.8x", -123) #=> " ..ffff85"
* sprintf("%20.8b", -11) #=> " ..110101"
*
* # "0x" and "0b" for `#x' and `#b' is not counted for
* # precision but "0" for `#o' is counted. <------>
* # "0x" and "0b" for '#x' and '#b' is not counted for
* # precision but "0" for '#o' is counted. <------>
* sprintf("%#20.8d", 123) #=> " 00000123"
* sprintf("%#20.8o", 123) #=> " 00000173"
* sprintf("%#20.8x", 123) #=> " 0x0000007b"
@@ -431,22 +431,22 @@ get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
* sprintf("%#20.8x", -123) #=> " 0x..ffff85"
* sprintf("%#20.8b", -11) #=> " 0b..110101"
*
* # precision for `e' is number of
* # precision for 'e' is number of
* # digits after the decimal point <------>
* sprintf("%20.8e", 1234.56789) #=> " 1.23456789e+03"
*
* # precision for `f' is number of
* # precision for 'f' is number of
* # digits after the decimal point <------>
* sprintf("%20.8f", 1234.56789) #=> " 1234.56789000"
*
* # precision for `g' is number of
* # precision for 'g' is number of
* # significant digits <------->
* sprintf("%20.8g", 1234.56789) #=> " 1234.5679"
*
* # <------->
* sprintf("%20.8g", 123456789) #=> " 1.2345679e+08"
*
* # precision for `s' is
* # precision for 's' is
* # maximum number of characters <------>
* sprintf("%20.8s", "string test") #=> " string t"
*
@@ -539,7 +539,7 @@ mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
if (t >= end)
goto sprint_exit; /* end of fmt string */
p = t + 1; /* skip `%' */
p = t + 1; /* skip '%' */
width = prec = -1;
nextvalue = mrb_undef_value();
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-string-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional String class'
spec.summary = 'String class extension'
end
+6 -6
View File
@@ -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
+56
View File
@@ -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));
+16
View File
@@ -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
+1
View File
@@ -259,6 +259,7 @@ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value 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);
+4 -4
View File
@@ -114,7 +114,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
return ptr[i];
}
}
mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, id));
mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
return mrb_nil_value(); /* not reached */
}
@@ -193,7 +193,7 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val)
return ptr[i] = val;
}
}
mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, mid));
mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, mid));
return mrb_nil_value(); /* not reached */
}
@@ -749,8 +749,8 @@ mrb_struct_values_at(mrb_state *mrb, mrb_value self)
* The <code>Struct</code> class is a generator of specific classes,
* each one of which is defined to hold a set of variables and their
* accessors. In these examples, we'll call the generated class
* ``<i>Customer</i>Class,'' and we'll show an example instance of that
* class as ``<i>Customer</i>Inst.''
* "<i>Customer</i>Class," and we'll show an example instance of that
* class as "<i>Customer</i>Inst."
*
* In the descriptions that follow, the parameter <i>symbol</i> refers
* to a symbol, which is either a quoted string or a
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-symbol-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extensional Symbol class'
spec.summary = 'Symbol class extension'
end
@@ -1,13 +1,46 @@
MRuby.each_target do
gem_table = gems.generate_gem_table self
MRuby::Gem::Specification.new('mruby-test') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'mruby test'
gems.each do |g|
build.bins << 'mrbtest'
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
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")
libmruby_core = libfile("#{build.build_dir}/lib/libmruby_core")
mrbtest_lib = libfile("#{build_dir}/mrbtest")
mrbtest_objs = []
driver_obj = objfile("#{build_dir}/driver")
driver = "#{spec.dir}/driver.c"
assert_c = "#{build_dir}/assert.c"
assert_rb = "#{MRUBY_ROOT}/test/assert.rb"
assert_lib = assert_c.ext(exts.object)
mrbtest_objs << assert_lib
file assert_lib => assert_c
file assert_c => [build.mrbcfile, assert_rb] do |t|
open(t.name, 'w') do |f|
mrbc.run f, assert_rb, 'mrbtest_assert_irep'
end
end
gem_table = build.gems.generate_gem_table build
build.gems.each do |g|
test_rbobj = g.test_rbireps.ext(exts.object)
g.test_objs << test_rbobj
dep_list = gems.tsort_dependencies(g.test_dependencies, gem_table).select(&:generate_functions)
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, __FILE__, "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"] do |t|
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|
FileUtils.mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
g.print_gem_test_header(f)
@@ -91,4 +124,51 @@ MRuby.each_target do
end
end
end
build.gems.each do |v|
mrbtest_objs.concat v.test_objs
end
file mrbtest_lib => mrbtest_objs do |t|
build.archiver.run t.name, t.prerequisites
end
unless build.build_mrbtest_lib_only?
file exec => [driver_obj, mlib, mrbtest_lib, libmruby_core, libmruby] do |t|
gem_flags = build.gems.map { |g| g.linker.flags }
gem_flags_before_libraries = build.gems.map { |g| g.linker.flags_before_libraries }
gem_flags_after_libraries = build.gems.map { |g| g.linker.flags_after_libraries }
gem_libraries = build.gems.map { |g| g.linker.libraries }
gem_library_paths = build.gems.map { |g| g.linker.library_paths }
build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries
end
end
init = "#{spec.dir}/init_mrbtest.c"
file mlib => clib
file clib => [build.mrbcfile, init] do |t|
_pp "GEN", "*.rb", "#{clib.relative_path}"
FileUtils.mkdir_p File.dirname(clib)
open(clib, 'w') do |f|
f.puts %Q[/*]
f.puts %Q[ * This file contains a list of all]
f.puts %Q[ * test functions.]
f.puts %Q[ *]
f.puts %Q[ * IMPORTANT:]
f.puts %Q[ * This file was generated!]
f.puts %Q[ * All manual changes will get lost.]
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
f.puts %Q[void mrbgemtest_init(mrb_state* mrb) {]
build.gems.each do |g|
f.puts %Q[ GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb);]
end
f.puts %Q[}]
end
end
end
+12 -4
View File
@@ -4,12 +4,17 @@
** See Copyright Notice in mruby.h
*/
#include <math.h>
#include <stdio.h>
#include <time.h>
#include "mruby.h"
#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
@@ -200,20 +205,23 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
struct mrb_time *tm;
tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
tm->sec = (time_t)sec;
if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) {
goto out_of_range;
}
else if ((sec > 0 && tm->sec < 0) || (sec < 0 && (double)tm->sec > sec)) {
if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) {
goto out_of_range;
}
tm->sec = (time_t)sec;
if ((sec > 0 && tm->sec < 0) || (sec < 0 && (double)tm->sec > sec)) {
out_of_range:
mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec));
}
tm->usec = (time_t)((sec - tm->sec) * 1.0e6 + usec);
tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec);
while (tm->usec < 0) {
tm->sec--;
tm->usec += 1000000;
}
while (tm->usec > 1000000) {
while (tm->usec >= 1000000) {
tm->sec++;
tm->usec -= 1000000;
}
+8
View File
@@ -203,3 +203,11 @@ assert('day of week methods') do
assert_false t.friday?
assert_false t.saturday?
end
assert('2000 times 500us make a second') do
t = Time.utc 2015
2000.times do
t += 0.0005
end
t.usec == 0
end
+1 -1
View File
@@ -1,5 +1,5 @@
MRuby::Gem::Specification.new('mruby-toplevel-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'extended toplevel object (main) methods'
spec.summary = 'toplevel object (main) methods extension'
end
+12 -23
View File
@@ -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
@@ -34,7 +34,7 @@ class Array
return to_enum :each_index unless block_given?
idx = 0
while(idx < length)
while idx < length
block.call(idx)
idx += 1
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,10 +70,10 @@ class Array
self.clear
if size > 0
self[size - 1] = nil # allocate
self[size - 1] = nil # allocate
idx = 0
while(idx < size)
while idx < size
self[idx] = (block)? block.call(idx): obj
idx += 1
end
@@ -146,7 +144,7 @@ class Array
# equal, then that inequality is the return value. If all the
# values found are equal, then the return is based on a
# comparison of the array lengths. Thus, two arrays are
# ``equal'' according to <code>Array#<=></code> if and only if they have
# "equal" according to <code>Array#<=></code> if and only if they have
# the same length and the value of each element is equal to the
# value of the corresponding element in the other array.
#
@@ -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
+10 -27
View File
@@ -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
-15
View File
@@ -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
+25 -2
View File
@@ -10,7 +10,7 @@ class Hash
# hash.
#
# ISO 15.2.13.4.1
def == (hash)
def ==(hash)
return true if self.equal?(hash)
begin
hash = hash.to_hash
@@ -54,7 +54,7 @@ class Hash
#
# ISO 15.2.13.4.8
def delete(key, &block)
if block && ! self.has_key?(key)
if block && !self.has_key?(key)
block.call(key)
else
self.__delete(key)
@@ -319,6 +319,29 @@ class Hash
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 <i>hsh</i>.
#
# 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
+1 -1
View File
@@ -27,7 +27,7 @@ module Kernel
def loop(&block)
return to_enum :loop unless block
while(true)
while true
yield
end
rescue StopIteration
+27 -13
View File
@@ -48,7 +48,7 @@ module Integral
return to_enum(:downto, num) unless block_given?
i = self.to_i
while(i >= num)
while i >= num
block.call(i)
i -= 1
end
@@ -89,7 +89,7 @@ module Integral
return to_enum(:upto, num) unless block_given?
i = self.to_i
while(i <= num)
while i <= num
block.call(i)
i += 1
end
@@ -100,18 +100,18 @@ 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?
i = if num.kind_of? Float then self.to_f else self end
if step > 0
while(i <= num)
while i <= num
block.call(i)
i += step
end
else
while(i >= num)
while i >= num
block.call(i)
i += step
end
@@ -165,16 +165,30 @@ class Float
# floats should be compatible to integers.
def >> other
n = self.to_i
other.to_i.times {
n /= 2
}
n
other = other.to_i
if other < 0
n << -other
else
other.times { n /= 2 }
if n.abs < 1
if n >= 0
0
else
-1
end
else
n.to_i
end
end
end
def << other
n = self.to_i
other.to_i.times {
n *= 2
}
n.to_i
other = other.to_i
if other < 0
n >> -other
else
other.times { n *= 2 }
n
end
end
end
+4 -10
View File
@@ -26,29 +26,23 @@ 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
while((val <=> last) < 0)
while (val <=> last) < 0
block.call(val)
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
+87 -28
View File
@@ -12,7 +12,7 @@ class String
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(0x0a, offset)
block.call(self[offset, pos + 1 - offset])
offset = pos + 1
end
@@ -20,6 +20,30 @@ class String
self
end
# private method for gsub/sub
def __sub_replace(pre, m, post)
s = ""
i = 0
while j = index("\\", i)
break if j == length-1
t = case self[j+1]
when "\\"
"\\"
when "`"
pre
when "&", "0"
m
when "'"
post
else
self[j, 2]
end
s += self[i, j-i] + t
i = j + 2
end
s + self[i, length-i]
end
##
# Replace all matches of +pattern+ with +replacement+.
# Call block (if given) for each match and replace
@@ -29,7 +53,17 @@ class String
# ISO 15.2.10.5.18
def gsub(*args, &block)
if args.size == 2
split(args[0], -1).join(args[1])
s = ""
i = 0
while j = index(args[0], i)
seplen = args[0].length
k = j + seplen
pre = self[0, j]
post = self[k, length-k]
s += self[i, j-i] + args[1].__sub_replace(pre, args[0], post)
i = k
end
s + self[i, length-i]
elsif args.size == 1 && block
split(args[0], -1).join(block.call(args[0]))
else
@@ -46,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
##
@@ -76,7 +106,9 @@ class String
# ISO 15.2.10.5.36
def sub(*args, &block)
if args.size == 2
split(args[0], 2).join(args[1])
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]))
else
@@ -93,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
##
@@ -106,7 +134,7 @@ class String
# +self+.
def each_char(&block)
pos = 0
while(pos < self.size)
while pos < self.size
block.call(self[pos])
pos += 1
end
@@ -118,7 +146,7 @@ class String
def each_byte(&block)
bytes = self.bytes
pos = 0
while(pos < bytes.size)
while pos < bytes.size
block.call(bytes[pos])
pos += 1
end
@@ -126,23 +154,54 @@ class String
end
##
# Modify +self+ by replacing the content of +self+
# at the position +pos+ with +value+.
def []=(pos, value)
if pos < 0
pos += self.length
# 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
b = self[0, pos]
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
+15 -23
View File
@@ -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();
}
@@ -88,15 +87,12 @@ array_copy(mrb_value *dst, const mrb_value *src, mrb_int size)
MRB_API mrb_value
mrb_ary_new_from_values(mrb_state *mrb, mrb_int size, const mrb_value *vals)
{
mrb_value ary;
struct RArray *a;
struct RArray *a = ary_new_capa(mrb, size);
ary = mrb_ary_new_capa(mrb, size);
a = mrb_ary_ptr(ary);
array_copy(a->ptr, vals, size);
a->len = size;
return ary;
return mrb_obj_value(a);
}
MRB_API mrb_value
@@ -293,18 +289,19 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
{
struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2;
mrb_value ary;
mrb_value *ptr;
mrb_int blen;
mrb_get_args(mrb, "a", &ptr, &blen);
ary = mrb_ary_new_capa(mrb, a1->len + blen);
a2 = mrb_ary_ptr(ary);
if (ARY_MAX_SIZE - blen < a1->len) {
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);
array_copy(a2->ptr + a1->len, ptr, blen);
a2->len = a1->len + blen;
return ary;
return mrb_obj_value(a2);
}
static void
@@ -342,7 +339,6 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
{
struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2;
mrb_value ary;
mrb_value *ptr;
mrb_int times;
@@ -351,9 +347,10 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
}
if (times == 0) return mrb_ary_new(mrb);
ary = mrb_ary_new_capa(mrb, a1->len * times);
a2 = mrb_ary_ptr(ary);
if (ARY_MAX_SIZE / times < a1->len) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
a2 = ary_new_capa(mrb, a1->len * times);
ptr = a2->ptr;
while (times--) {
array_copy(ptr, a1->ptr, a1->len);
@@ -361,7 +358,7 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
a2->len += a1->len;
}
return ary;
return mrb_obj_value(a2);
}
static mrb_value
@@ -388,11 +385,8 @@ mrb_ary_reverse_bang(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_ary_reverse(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self), *b;
mrb_value ary;
struct RArray *a = mrb_ary_ptr(self), *b = ary_new_capa(mrb, a->len);
ary = mrb_ary_new_capa(mrb, a->len);
b = mrb_ary_ptr(ary);
if (a->len > 0) {
mrb_value *p1, *p2, *e;
@@ -404,7 +398,7 @@ mrb_ary_reverse(mrb_state *mrb, mrb_value self)
}
b->len = a->len;
}
return ary;
return mrb_obj_value(b);
}
MRB_API void
@@ -1036,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);
}
@@ -1047,7 +1041,6 @@ mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
mrb_get_args(mrb, "o", &ary2);
if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
if (mrb_immediate_p(ary2)) return mrb_false_value();
if (!mrb_array_p(ary2)) {
return mrb_false_value();
}
@@ -1063,7 +1056,6 @@ mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
mrb_get_args(mrb, "o", &ary2);
if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0);
if (mrb_immediate_p(ary2)) return mrb_nil_value();
if (!mrb_array_p(ary2)) {
return mrb_nil_value();
}
+258 -88
View File
@@ -76,7 +76,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
if (o->c->tt == MRB_TT_SCLASS) return;
sc = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_SCLASS, mrb->class_class);
sc->mt = 0;
sc->mt = kh_init(mt, mrb);
sc->iv = 0;
if (o->tt == MRB_TT_CLASS) {
c = (struct RClass*)o;
@@ -131,6 +131,19 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
return mrb_class_ptr(outer);
}
static void
check_if_class_or_module(mrb_state *mrb, mrb_value obj)
{
switch (mrb_type(obj)) {
case MRB_TT_CLASS:
case MRB_TT_SCLASS:
case MRB_TT_MODULE:
return;
default:
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj));
}
}
static struct RClass*
define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
{
@@ -160,6 +173,7 @@ mrb_define_module(mrb_state *mrb, const char *name)
MRB_API struct RClass*
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
{
check_if_class_or_module(mrb, outer);
return define_module(mrb, id, mrb_class_ptr(outer));
}
@@ -173,6 +187,13 @@ mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
return c;
}
static struct RClass*
find_origin(struct RClass *c)
{
MRB_CLASS_ORIGIN(c);
return c;
}
static struct RClass*
define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
{
@@ -180,6 +201,7 @@ define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *
if (mrb_const_defined_at(mrb, mrb_obj_value(outer), name)) {
c = class_from_sym(mrb, outer, name);
MRB_CLASS_ORIGIN(c);
if (super && mrb_class_real(c->super) != super) {
mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
mrb_sym2str(mrb, name),
@@ -198,7 +220,7 @@ MRB_API struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
{
if (!super) {
mrb_warn(mrb, "no super class for `%S', Object assumed", mrb_sym2str(mrb, name));
mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name));
}
return define_class(mrb, name, super, mrb->object_class);
}
@@ -232,15 +254,7 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
else {
s = 0;
}
switch (mrb_type(outer)) {
case MRB_TT_CLASS:
case MRB_TT_SCLASS:
case MRB_TT_MODULE:
break;
default:
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer);
break;
}
check_if_class_or_module(mrb, outer);
c = define_class(mrb, id, s, mrb_class_ptr(outer));
mrb_class_inherited(mrb, mrb_class_real(c->super), c);
@@ -305,7 +319,7 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
#if 0
if (!super) {
mrb_warn(mrb, "no super class for `%S::%S', Object assumed",
mrb_warn(mrb, "no super class for '%S::%S', Object assumed",
mrb_obj_value(outer), mrb_sym2str(mrb, id));
}
#endif
@@ -317,8 +331,10 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
MRB_API void
mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RProc *p)
{
khash_t(mt) *h = c->mt;
khash_t(mt) *h;
khiter_t k;
MRB_CLASS_ORIGIN(c);
h = c->mt;
if (!h) h = c->mt = kh_init(mt, mrb);
k = kh_put(mt, mrb, h, mid);
@@ -429,12 +445,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]
@@ -519,6 +535,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++;
@@ -530,6 +554,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++;
@@ -541,6 +573,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++;
@@ -555,6 +595,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);
@@ -569,6 +618,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);
@@ -585,6 +642,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);
@@ -670,6 +736,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;
@@ -753,47 +827,130 @@ boot_defclass(mrb_state *mrb, struct RClass *super)
return c;
}
MRB_API void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
static void
boot_initmod(mrb_state *mrb, struct RClass *mod)
{
struct RClass *ins_pos;
mod->mt = kh_init(mt, mrb);
}
static struct RClass*
include_class_new(mrb_state *mrb, struct RClass *m, struct RClass *super)
{
struct RClass *ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
if (m->tt == MRB_TT_ICLASS) {
m = m->c;
}
MRB_CLASS_ORIGIN(m);
ic->iv = m->iv;
ic->mt = m->mt;
ic->super = super;
if (m->tt == MRB_TT_ICLASS) {
ic->c = m->c;
} else {
ic->c = m;
}
return ic;
}
static int
include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, struct RClass *m, int search_super)
{
struct RClass *p, *ic;
void *klass_mt = find_origin(c)->mt;
ins_pos = c;
while (m) {
struct RClass *p = c, *ic;
int superclass_seen = 0;
if (c->mt && c->mt == m->mt) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
}
while (p) {
if (c != p && p->tt == MRB_TT_CLASS) {
superclass_seen = 1;
}
else if (p->mt == m->mt) {
if (p->tt == MRB_TT_ICLASS && !superclass_seen) {
ins_pos = p;
if (m->flags & MRB_FLAG_IS_PREPENDED)
goto skip;
if (klass_mt && klass_mt == m->mt)
return -1;
p = c->super;
while(p) {
if (p->tt == MRB_TT_ICLASS) {
if (p->mt == m->mt) {
if (!superclass_seen) {
ins_pos = p; // move insert point
}
goto skip;
}
goto skip;
} else if (p->tt == MRB_TT_CLASS) {
if (!search_super) break;
superclass_seen = 1;
}
p = p->super;
}
ic = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, mrb->class_class);
if (m->tt == MRB_TT_ICLASS) {
ic->c = m->c;
}
else {
ic->c = m;
}
ic->mt = m->mt;
ic->iv = m->iv;
ic->super = ins_pos->super;
ic = include_class_new(mrb, m, ins_pos->super);
ins_pos->super = ic;
mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ic);
mrb_field_write_barrier(mrb, (struct RBasic*)ins_pos, (struct RBasic*)ins_pos->super);
ins_pos = ic;
skip:
m = m->super;
}
return 0;
}
MRB_API void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
int changed = include_module_at(mrb, c, find_origin(c), m, 1);
if (changed < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
}
}
MRB_API void
mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
struct RClass *origin;
int changed = 0;
if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
origin->flags |= MRB_FLAG_IS_ORIGIN;
origin->super = c->super;
c->super = origin;
origin->mt = c->mt;
c->mt = kh_init(mt, mrb);
mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)origin);
c->flags |= MRB_FLAG_IS_PREPENDED;
}
changed = include_module_at(mrb, c, c, m, 0);
if (changed < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic prepend detected");
}
}
static mrb_value
mrb_mod_prepend_features(mrb_state *mrb, mrb_value mod)
{
mrb_value klass;
mrb_check_type(mrb, mod, MRB_TT_MODULE);
mrb_get_args(mrb, "C", &klass);
mrb_prepend_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
return mod;
}
static mrb_value
mrb_mod_prepend(mrb_state *mrb, mrb_value klass)
{
mrb_value *argv;
mrb_int argc, i;
mrb_get_args(mrb, "*", &argv, &argc);
for (i=0; i<argc; i++) {
mrb_check_type(mrb, argv[i], MRB_TT_MODULE);
}
while (argc--) {
mrb_funcall(mrb, argv[argc], "prepend_features", 1, klass);
mrb_funcall(mrb, argv[argc], "prepended", 1, klass);
}
return klass;
}
static mrb_value
@@ -867,15 +1024,12 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
{
mrb_value result;
struct RClass *c = mrb_class_ptr(self);
result = mrb_ary_new(mrb);
mrb_ary_push(mrb, result, mrb_obj_value(c));
c = c->super;
while (c) {
if (c->tt == MRB_TT_ICLASS) {
mrb_ary_push(mrb, result, mrb_obj_value(c->c));
}
else if (c->tt != MRB_TT_SCLASS) {
else if (!(c->flags & MRB_FLAG_IS_PREPENDED)) {
mrb_ary_push(mrb, result, mrb_obj_value(c));
}
c = c->super;
@@ -900,11 +1054,15 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
{
mrb_value result;
struct RClass *c = mrb_class_ptr(self);
struct RClass *origin = c;
MRB_CLASS_ORIGIN(origin);
result = mrb_ary_new(mrb);
while (c) {
if (c->tt == MRB_TT_ICLASS) {
mrb_ary_push(mrb, result, mrb_obj_value(c->c));
if (c != origin && c->tt == MRB_TT_ICLASS) {
if (c->c->tt == MRB_TT_MODULE) {
mrb_ary_push(mrb, result, mrb_obj_value(c->c));
}
}
c = c->super;
}
@@ -916,10 +1074,11 @@ static mrb_value
mrb_mod_initialize(mrb_state *mrb, mrb_value mod)
{
mrb_value b;
mrb_get_args(mrb, "&", &b);
struct RClass *m = mrb_class_ptr(mod);
boot_initmod(mrb, m); // bootstrap a newly initialized module
mrb_get_args(mrb, "|&", &b);
if (!mrb_nil_p(b)) {
mrb_yield_with_class(mrb, b, 1, &mod, mod, mrb_class_ptr(mod));
mrb_yield_with_class(mrb, b, 1, &mod, mod, m);
}
return mod;
}
@@ -1168,11 +1327,11 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
* call-seq:
* class.new(args, ...) -> obj
*
* Calls <code>allocate</code> to create a new object of
* <i>class</i>'s class, then invokes that object's
* <code>initialize</code> method, passing it <i>args</i>.
* This is the method that ends up getting called whenever
* an object is constructed using .new.
* Creates a new object of <i>class</i>'s class, then
* invokes that object's <code>initialize</code> method,
* passing it <i>args</i>. This is the method that ends
* up getting called whenever an object is constructed using
* `.new`.
*
*/
@@ -1236,9 +1395,9 @@ mrb_class_superclass(mrb_state *mrb, mrb_value klass)
struct RClass *c;
c = mrb_class_ptr(klass);
c = c->super;
c = find_origin(c)->super;
while (c && c->tt == MRB_TT_ICLASS) {
c = c->super;
c = find_origin(c)->super;
}
if (!c) return mrb_nil_value();
return mrb_obj_value(c);
@@ -1256,6 +1415,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:
@@ -1295,27 +1479,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();
}
@@ -1469,8 +1635,7 @@ MRB_API struct RClass*
mrb_module_new(mrb_state *mrb)
{
struct RClass *m = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_MODULE, mrb->module_class);
m->mt = kh_init(mt, mrb);
boot_initmod(mrb, m);
return m;
}
@@ -1537,10 +1702,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, ">");
@@ -1652,7 +1817,7 @@ check_cv_name_str(mrb_state *mrb, mrb_value str)
mrb_int len = RSTRING_LEN(str);
if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str);
mrb_name_error(mrb, mrb_intern_str(mrb, str), "'%S' is not allowed as a class variable name", str);
}
}
@@ -1829,18 +1994,19 @@ static void
remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
{
struct RClass *c = mrb_class_ptr(mod);
khash_t(mt) *h = c->mt;
khash_t(mt) *h = find_origin(c)->mt;
khiter_t k;
if (h) {
k = kh_get(mt, mrb, h, mid);
if (k != kh_end(h)) {
kh_del(mt, mrb, h, k);
mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid));
return;
}
}
mrb_name_error(mrb, mid, "method `%S' not defined in %S",
mrb_name_error(mrb, mid, "method '%S' not defined in %S",
mrb_sym2str(mrb, mid), mod);
}
@@ -2069,6 +2235,9 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "class_variable_set", mrb_mod_cvar_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.18 */
mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
mrb_define_method(mrb, mod, "prepend", mrb_mod_prepend, MRB_ARGS_ANY());
mrb_define_method(mrb, mod, "prepended", mrb_bob_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "prepend_features", mrb_mod_prepend_features, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "include", mrb_mod_include, MRB_ARGS_ANY()); /* 15.2.2.4.27 */
mrb_define_method(mrb, mod, "include?", mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */
mrb_define_method(mrb, mod, "append_features", mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */
@@ -2085,6 +2254,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */
mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
mrb_define_method(mrb, mod, "method_removed", mrb_bob_init, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */
mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */
mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE());
+3 -8
View File
@@ -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
@@ -819,7 +819,6 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8
uint32_t offset;
switch (flags & DUMP_ENDIAN_NAT) {
default:
endian_big:
case DUMP_ENDIAN_BIG:
memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
@@ -979,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;
}
+4 -5
View File
@@ -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);
}
+6 -8
View File
@@ -26,7 +26,7 @@ mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const mrb
MRB_API void
mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
{
if (mrb_immediate_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
if (mrb_type(obj) != MRB_TT_DATA) {
mrb_check_type(mrb, obj, MRB_TT_DATA);
}
if (DATA_TYPE(obj) != type) {
@@ -48,7 +48,7 @@ mrb_data_check_type(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
MRB_API void*
mrb_data_check_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
{
if (mrb_immediate_p(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
if (mrb_type(obj) != MRB_TT_DATA) {
return NULL;
}
if (DATA_TYPE(obj) != type) {
@@ -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);
+3 -6
View File
@@ -90,12 +90,9 @@ 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)
static long double
frexpl (long double x, int *eptr)
{
return frexp(x, eptr);
}
#if ((defined(__CYGWIN__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__)
#undef frexpl
#define frexpl frexp
#endif
static int
+10 -2
View File
@@ -498,7 +498,12 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
mrb_gc_mark(mrb, (struct RBasic*)obj->c);
switch (obj->tt) {
case MRB_TT_ICLASS:
mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super);
{
struct RClass *c = (struct RClass*)obj;
if (MRB_FLAG_TEST(c, MRB_FLAG_IS_ORIGIN))
mrb_gc_mark_mt(mrb, c);
mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super);
}
break;
case MRB_TT_CLASS:
@@ -624,7 +629,10 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
mrb_gc_free_mt(mrb, (struct RClass*)obj);
mrb_gc_free_iv(mrb, (struct RObject*)obj);
break;
case MRB_TT_ICLASS:
if (MRB_FLAG_TEST(obj, MRB_FLAG_IS_ORIGIN))
mrb_gc_free_mt(mrb, (struct RClass*)obj);
break;
case MRB_TT_ENV:
{
struct REnv *e = (struct REnv*)obj;
+5 -4
View File
@@ -104,10 +104,11 @@ static void mrb_hash_modify(mrb_state *mrb, mrb_value hash);
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)
+29 -4
View File
@@ -240,14 +240,12 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
/* copy singleton(unnamed) class */
struct RClass *clone = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, mrb->class_class);
if ((mrb_type(obj) == MRB_TT_CLASS) ||
(mrb_type(obj) == MRB_TT_SCLASS)) { /* BUILTIN_TYPE(obj) == T_CLASS */
if ((mrb_type(obj) == MRB_TT_CLASS) || (mrb_type(obj) == MRB_TT_SCLASS)) {
clone->c = clone;
}
else {
clone->c = mrb_singleton_class_clone(mrb, mrb_obj_value(klass));
}
clone->super = klass->super;
if (klass->iv) {
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
@@ -269,6 +267,21 @@ copy_class(mrb_state *mrb, mrb_value dst, mrb_value src)
{
struct RClass *dc = mrb_class_ptr(dst);
struct RClass *sc = mrb_class_ptr(src);
/* if the origin is not the same as the class, then the origin and
the current class need to be copied */
if (sc->flags & MRB_FLAG_IS_PREPENDED) {
struct RClass *c0 = sc->super;
struct RClass *c1 = dc;
/* copy prepended iclasses */
while (!(c0->flags & MRB_FLAG_IS_ORIGIN)) {
c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
c1 = c1->super;
c0 = c0->super;
}
c1->super = mrb_class_ptr(mrb_obj_dup(mrb, mrb_obj_value(c0)));
c1->super->flags |= MRB_FLAG_IS_ORIGIN;
}
dc->mt = kh_copy(mt, mrb, sc->mt);
dc->super = sc->super;
}
@@ -330,6 +343,9 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
if (mrb_immediate_p(self)) {
mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %S", self);
}
if (mrb_type(self) == MRB_TT_SCLASS) {
mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
}
p = (struct RObject*)mrb_obj_alloc(mrb, mrb_type(self), mrb_obj_class(mrb, self));
p->c = mrb_singleton_class_clone(mrb, self);
clone = mrb_obj_value(p);
@@ -366,6 +382,9 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
if (mrb_immediate_p(obj)) {
mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %S", obj);
}
if (mrb_type(obj) == MRB_TT_SCLASS) {
mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
}
p = mrb_obj_alloc(mrb, mrb_type(obj), mrb_obj_class(mrb, obj));
dup = mrb_obj_value(p);
init_copy(mrb, dup, obj);
@@ -635,13 +654,19 @@ mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* kl
{
khint_t i;
mrb_value ary;
mrb_bool prepended;
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;
}
oldklass = 0;
while (klass && (klass != oldklass)) {
method_entry_loop(mrb, klass, set);
if ((klass->tt == MRB_TT_ICLASS) ||
if ((klass->tt == MRB_TT_ICLASS && !prepended) ||
(klass->tt == MRB_TT_SCLASS)) {
}
else {
+1 -1
View File
@@ -529,7 +529,7 @@ read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t
else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) {
if (bigendian_p())
*flags |= FLAG_BYTEORDER_LIL;
else
else
*flags |= FLAG_BYTEORDER_NATIVE;
}
else {
+2 -61
View File
@@ -3,76 +3,17 @@ MRuby.each_target do
relative_from_root = File.dirname(__FILE__).relative_path_from(MRUBY_ROOT)
current_build_dir = "#{build_dir}/#{relative_from_root}"
lex_def = "#{current_dir}/lex.def"
objs = Dir.glob("#{current_dir}/*.c").map { |f|
next nil if cxx_abi_enabled? and f =~ /(codegen|error|vm).c$/
next nil if cxx_abi_enabled? and f =~ /(error|vm).c$/
objfile(f.pathmap("#{current_build_dir}/%n"))
}.compact
if cxx_abi_enabled?
cxx_abi_dependency = %w(codegen error vm)
cxx_abi_objs = cxx_abi_dependency.map { |v|
src = "#{current_build_dir}/#{v}.cxx"
file src => ["#{current_dir}/#{v}.c", __FILE__] do |t|
File.open(t.name, 'w') do |f|
f.write <<EOS
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
extern "C" {
#include "#{MRUBY_ROOT}/#{t.prerequisites.first}"
}
#{v == 'error'? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''}
EOS
end
end
file objfile(src) => src do |t|
cxx.run t.name, t.prerequisites.first, [], [current_dir]
end
objfile src
}
cxx_abi_objs << objfile("#{current_build_dir}/y.tab")
file "#{current_build_dir}/y.tab.cxx" => ["#{current_build_dir}/y.tab.c", __FILE__] do |t|
File.open(t.name, 'w') do |f|
f.write <<EOS
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
extern "C" {
#include "#{t.prerequisites.first}"
}
EOS
end
end
file objfile("#{current_build_dir}/y.tab") => ["#{current_build_dir}/y.tab.cxx", lex_def] do |t|
cxx.run t.name, t.prerequisites.first, [], [current_dir]
end
objs += cxx_abi_objs
else
objs += [objfile("#{current_build_dir}/y.tab")]
file objfile("#{current_build_dir}/y.tab") => ["#{current_build_dir}/y.tab.c", lex_def] do |t|
cc.run t.name, t.prerequisites.first, [], [current_dir]
end
objs += %w(vm error).map { |v| compile_as_cxx "#{current_dir}/#{v}.c", "#{current_build_dir}/#{v}.cxx" }
end
self.libmruby << objs
file libfile("#{build_dir}/lib/libmruby_core") => objs do |t|
archiver.run t.name, t.prerequisites
end
# Parser
file "#{current_build_dir}/y.tab.c" => ["#{current_dir}/parse.y"] do |t|
yacc.run t.name, t.prerequisites.first
end
# Lexical analyzer
file lex_def => "#{current_dir}/keywords" do |t|
gperf.run t.name, t.prerequisites.first
end
end
+13 -10
View File
@@ -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);
}
@@ -110,8 +111,8 @@ num_div(mrb_state *mrb, mrb_value x)
*
* Returns a string containing a representation of self. As well as a
* fixed or exponential form of the number, the call may return
* ``<code>NaN</code>'', ``<code>Infinity</code>'', and
* ``<code>-Infinity</code>''.
* "<code>NaN</code>", "<code>Infinity</code>", and
* "<code>-Infinity</code>".
*/
static mrb_value
@@ -436,7 +437,7 @@ flo_round(mrb_state *mrb, mrb_value num)
{
double number, f;
mrb_int ndigits = 0;
int i;
mrb_int i;
mrb_get_args(mrb, "|i", &ndigits);
number = mrb_float(num);
@@ -451,7 +452,7 @@ flo_round(mrb_state *mrb, mrb_value num)
}
f = 1.0;
i = abs(ndigits);
i = ndigits >= 0 ? ndigits : -ndigits;
while (--i >= 0)
f = f*10.0;
@@ -819,11 +820,13 @@ fix_xor(mrb_state *mrb, mrb_value x)
static mrb_value
lshift(mrb_state *mrb, mrb_int val, mrb_int width)
{
mrb_assert(width >= 0);
mrb_assert(width > 0);
if (width > NUMERIC_SHIFT_WIDTH_MAX) {
mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)",
mrb_fixnum_value(width),
mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX));
mrb_float f = (mrb_float)val;
while (width--) {
f *= 2;
}
return mrb_float_value(mrb, f);
}
return mrb_fixnum_value(val << width);
}
@@ -831,7 +834,7 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width)
static mrb_value
rshift(mrb_int val, mrb_int width)
{
mrb_assert(width >= 0);
mrb_assert(width > 0);
if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
if (val < 0) {
return mrb_fixnum_value(-1);

Some files were not shown because too many files have changed in this diff Show More