mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge remote-tracking branch 'mruby/master'
This commit is contained in:
+9
-2
@@ -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"
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
```
|
||||
@@ -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 {}
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
### Macros
|
||||
#### REGEXP_CLASS
|
||||
A string with the name of the REGEXP class.
|
||||
@@ -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.
|
||||
@@ -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
|
||||
```
|
||||
@@ -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.
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
/* ------------------------------- */
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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,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"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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,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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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,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,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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user