diff options
38 files changed, 511 insertions, 296 deletions
diff --git a/doc/compile/README.md b/doc/compile/README.md index 4309dcdc4..2d3bec367 100644 --- a/doc/compile/README.md +++ b/doc/compile/README.md @@ -1,6 +1,6 @@ # Compile -mruby is using Rake to compile and cross-compile all libraries and +mruby uses Rake to compile and cross-compile all libraries and binaries. ## Prerequisites @@ -22,10 +22,11 @@ Optional: Inside of the root directory of the mruby source a file exists called *build_config.rb*. This file contains the build configuration of mruby and looks like this for example: - - MRuby::Build.new do |conf| - toolchain :gcc - end +```ruby +MRuby::Build.new do |conf| + toolchain :gcc +end +``` All tools necessary to compile mruby can be set or modified here. In case you want to maintain an additional *build_config.rb* you can define a @@ -49,29 +50,33 @@ configure the build environment for specific compiler infrastructures. #### GCC Toolchain configuration for the GNU C Compiler. - - toolchain :gcc +```ruby +toolchain :gcc +``` #### clang Toolchain configuration for the LLVM C Compiler clang. Mainly equal to the GCC toolchain. - - toolchain :clang +```ruby +toolchain :clang +``` #### Visual Studio 2010, 2012 and 2013 Toolchain configuration for Visual Studio on Windows. If you use the [Visual Studio Command Prompt](http://msdn.microsoft.com/en-us/library/ms229859\(v=vs.110\).aspx), you normally do not have to specify this manually, since it gets automatically detected by our build process. - - toolchain :visualcpp +``` +toolchain :visualcpp +``` #### Android Toolchain configuration for Android. - - toolchain :androideabi +```ruby +toolchain :androideabi +``` Requires the custom standalone Android NDK and the toolchain path in ```ANDROID_STANDALONE_TOOLCHAIN```. @@ -84,123 +89,132 @@ process. The following tools can be selected: * mirb (mruby interactive shell) To select them declare conf.gem as follows: - - conf.gem "#{root}/mrbgems/mruby-bin-mruby" - - conf.gem "#{root}/mrbgems/mruby-bin-mirb" +```ruby +conf.gem "#{root}/mrbgems/mruby-bin-mruby" +conf.gem "#{root}/mrbgems/mruby-bin-mirb" +``` ### File Separator Some environments require a different file separator character. It is possible to set the character via ```conf.file_separator```. - - conf.file_separator = '/' +```ruby +conf.file_separator = '/' +``` ### C Compiler Configuration of the C compiler binary, flags and include paths. - - conf.cc do |cc| - cc.command = ... - cc.flags = ... - cc.include_paths = ... - cc.defines = ... - cc.option_include_path = ... - cc.option_define = ... - cc.compile_options = ... - end +```ruby +conf.cc do |cc| + cc.command = ... + cc.flags = ... + cc.include_paths = ... + cc.defines = ... + cc.option_include_path = ... + cc.option_define = ... + cc.compile_options = ... +end +``` C Compiler has header searcher to detect installed library. If you need a include path of header file use ```search_header_path```: - - # Searches ```iconv.h```. - # If found it will return include path of the header file. - # Otherwise it will return nil . - fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h' +```ruby +# Searches ```iconv.h```. +# If found it will return include path of the header file. +# Otherwise it will return nil . +fail 'iconv.h not found' unless conf.cc.search_header_path 'iconv.h' +``` If you need a full file name of header file use ```search_header```: - - # Searches ```iconv.h```. - # If found it will return full path of the header file. - # Otherwise it will return nil . - iconv_h = conf.cc.search_header 'iconv.h' - print "iconv.h found: #{iconv_h}\n" +```ruby +# Searches ```iconv.h```. +# If found it will return full path of the header file. +# Otherwise it will return nil . +iconv_h = conf.cc.search_header 'iconv.h' +print "iconv.h found: #{iconv_h}\n" +``` Header searcher uses compiler's ```include_paths``` by default. When you are using GCC toolchain (including clang toolchain since its base is gcc toolchain) it will use compiler specific include paths too. (For example ```/usr/local/include```, ```/usr/include```) If you need a special header search paths define a singleton method ```header_search_paths``` to C compiler: - - def conf.cc.header_search_paths - ['/opt/local/include'] + include_paths - end - +```ruby +def conf.cc.header_search_paths + ['/opt/local/include'] + include_paths +end +``` ### Linker Configuration of the Linker binary, flags and library paths. - - conf.linker do |linker| - linker.command = ... - linker.flags = ... - linker.flags_before_libraries = ... - linker.libraries = ... - linker.flags_after_libraries = ... - linker.library_paths = .... - linker.option_library = ... - linker.option_library_path = ... - linker.link_options = ... - end +```ruby +conf.linker do |linker| + linker.command = ... + linker.flags = ... + linker.flags_before_libraries = ... + linker.libraries = ... + linker.flags_after_libraries = ... + linker.library_paths = .... + linker.option_library = ... + linker.option_library_path = ... + linker.link_options = ... +end +``` ### Archiver Configuration of the Archiver binary and flags. - - conf.archiver do |archiver| - archiver.command = ... - archiver.archive_options = ... - end +```ruby +conf.archiver do |archiver| + archiver.command = ... + archiver.archive_options = ... +end +``` ### Parser Generator Configuration of the Parser Generator binary and flags. - - conf.yacc do |yacc| - yacc.command = ... - yacc.compile_options = ... - end +```ruby +conf.yacc do |yacc| + yacc.command = ... + yacc.compile_options = ... +end +``` ### GPerf Configuration of the GPerf binary and flags. - - conf.gperf do |gperf| - gperf.command = ... - gperf.compile_options = ... - end +```ruby +conf.gperf do |gperf| + gperf.command = ... + gperf.compile_options = ... +end +``` ### File Extensions - - conf.exts do |exts| - exts.object = ... - exts.executable = ... - exts.library = ... - end +```ruby +conf.exts do |exts| + exts.object = ... + exts.executable = ... + exts.library = ... +end +``` ### Mrbgems Integrate GEMs in the build process. - - # Integrate GEM with additional configuration - conf.gem 'path/to/gem' do |g| - g.cc.flags << ... - end - - # Integrate GEM without additional configuration - conf.gem 'path/to/another/gem' - +```ruby +# Integrate GEM with additional configuration +conf.gem 'path/to/gem' do |g| + g.cc.flags << ... +end + +# Integrate GEM without additional configuration +conf.gem 'path/to/another/gem' +``` See doc/mrbgems/README.md for more option about mrbgems. @@ -209,8 +223,9 @@ See doc/mrbgems/README.md for more option about mrbgems. Configuration Mrbtest build process. If you want mrbtest.a only, You should set ```conf.build_mrbtest_lib_only``` - - conf.build_mrbtest_lib_only +```ruby +conf.build_mrbtest_lib_only +``` ### Bintest @@ -220,8 +235,9 @@ See ```mruby-bin-*/bintest/*.rb``` if you need examples. If you want a temporary files use `tempfile` module of CRuby instead of ```/tmp/```. You can enable it with following: - - conf.enable_bintest +```ruby +conf.enable_bintest +``` ### C++ ABI @@ -230,24 +246,27 @@ It is called C++ ABI mode. By using C++ exception it can release C++ stack object correctly. Whenever you mix C++ code C++ ABI mode would be enabled automatically. If you need to enable C++ ABI mode explicity add the following: - - conf.enable_cxx_abi +```ruby +conf.enable_cxx_abi +``` #### C++ exception disabling. If you need to force C++ exception disable (For example using a compiler option to disable C++ exception) add following: - - conf.disable_cxx_exception +```ruby +conf.disable_cxx_exception +``` Note that it must be called before ```enable_cxx_abi``` or ```gem``` method. ### Debugging mode To enable debugging mode add the following: - - conf.enable_debug +```ruby +conf.enable_debug +``` When debugging mode is enabled * Macro ```MRB_DEBUG``` would be defined. @@ -263,13 +282,14 @@ achieve this the *build_config.rb* needs to contain an instance of ```MRuby::CrossBuild```. This instance defines the compilation tools and flags for the target platform. An example could look like this: +```ruby +MRuby::CrossBuild.new('32bit') do |conf| + toolchain :gcc - MRuby::CrossBuild.new('32bit') do |conf| - toolchain :gcc - - conf.cc.flags << "-m32" - conf.linker.flags << "-m32" - end + conf.cc.flags << "-m32" + conf.linker.flags << "-m32" +end +``` All configuration options of ```MRuby::Build``` can also be used in ```MRuby::CrossBuild```. @@ -278,15 +298,16 @@ in ```MRuby::CrossBuild```. In cross compilation, you can run ```mrbtest``` on emulator if you have it by changing configuration of test runner. - - conf.test_runner do |t| - t.command = ... # set emulator. this value must be non nil or false - t.flags = ... # set flags of emulator - - def t.run(bin) # override `run` if you need to change the behavior of it - ... # `bin` is the full path of mrbtest - end - end +```ruby +conf.test_runner do |t| + t.command = ... # set emulator. this value must be non nil or false + t.flags = ... # set flags of emulator + + def t.run(bin) # override `run` if you need to change the behavior of it + ... # `bin` is the full path of mrbtest + end +end +``` ## Build process @@ -438,12 +459,14 @@ To build a minimal mruby library you need to use the Cross Compiling feature due to the reason that there are functions (i.e. stdio) which can't be disabled for the main build. - MRuby::CrossBuild.new('Minimal') do |conf| - toolchain :gcc +```ruby +MRuby::CrossBuild.new('Minimal') do |conf| + toolchain :gcc - conf.cc.defines = %w(DISABLE_STDIO) - conf.bins = [] - end + conf.cc.defines = %w(DISABLE_STDIO) + conf.bins = [] +end +``` This configuration defines a cross compile build called 'Minimal' which is using the GCC and compiles for the host machine. It also disables diff --git a/doc/mrbconf/README.md b/doc/mrbconf/README.md new file mode 100644 index 000000000..813b80839 --- /dev/null +++ b/doc/mrbconf/README.md @@ -0,0 +1,83 @@ +# mruby configuration macros. + +## How to use these macros. +You can use mrbconfs with following ways: +* Write them in `mrbconf.h`. + * Using compiler flags is prefered when building a cross binaries or multiple mruby binaries + since it's easier to use different mrbconf per each `MRuby::Build`. + * Most flags can be enabled by just commenting in. +* Pass them as compiler flags. + * Make sure you pass the same flags to all compilers since some mrbconf(e.g., `MRB_GC_FIXED_ARENA`) + changes `struct` layout and cause memory access error when C and other language(e.g., C++) is mixed. + +## stdio setting. +`ENABLE_STDIO` +* Will be defined automatically if `DISABLE_STDIO` isn't defined. +* Uses `<stdio.h>` functions. + +`DISABLE_STDIO` +* When defined `<stdio.h>` functions won't be used. + +## Debug macros. +`ENABLE_DEBUG` +* When defined code fetch hook and debug OP hook will be enabled. +* When using any of the hook set function pointer `code_fetch_hook` and/or `debug_op_hook` of `mrb_state`. +* Fetch hook will be called before any OP. +* Debug OP hook will be called when dispatching `OP_DEBUG`. + +`DISABLE_DEBUG` +* Will be define automatically if `ENABLE_DEBUG` isn't defined. + +`MRB_DEBUG` +* When defined `mrb_assert*` macro will be defined with macros from `<assert.h>`. +* Could be enabled via `enable_debug` method of `MRuby::Build`. + +## Stack configuration + +`MRB_STACK_EXTEND_DOUBLING` +* If defined doubles the stack size when extending it. +* Else extends stack with `MRB_STACK_GROWTH`. + +`MRB_STACK_GROWTH` +* Default value is `128`. +* Used in stack extending. +* Ignored when `MRB_STACK_EXTEND_DOUBLING` is defined. + +`MRB_STACK_MAX` +* Default value is `0x40000 - MRB_STACK_GROWTH`. +* Raises `RuntimeError` when stack size exceeds this value. + +## Primitive type configuration. + +`MRB_USE_FLOAT` +* When defined single precision floating point type(C type `float`) is used as `mrb_float`. +* Else double precision floating point type(C type `double`) is used as `mrb_float`. + +`MRB_INT16` +* When defined `int16_t` will be defined as `mrb_int`. +* Conflicts with `MRB_INT64`. + +`MRB_INT64` +* When defined `int64_t` will be defined as `mrb_int`. +* Conflicts with `MRB_INT16`. +* When `MRB_INT16` or `MRB_INT64` isn't defined `int`(most of the times 32-bit integer) +will be defined as `mrb_int`. + +## Garbage collector configuration. + +`MRB_GC_STRESS` +* When defined full GC is emitted per each `RBasic` allocation. +* Mainly used in memory manager debugging. + +`MRB_GC_TURN_OFF_GENERATIONAL` +* When defined turns generational GC by default. + +`MRB_GC_FIXED_ARENA` +* When defined used fixed size GC arena. +* Raises `RuntimeError` when this is defined and GC arena size exceeds `MRB_GC_ARENA_SIZE`. +* Useful tracking unnecessary mruby object allocation. + +`MRB_GC_ARENA_SIZE` +* Default value is 100. +* Ignored when `MRB_GC_FIXED_ARENA` isn't defined. +* Defines fixed GC arena size. diff --git a/doc/mrbgems/README.md b/doc/mrbgems/README.md index 231914905..040687333 100644 --- a/doc/mrbgems/README.md +++ b/doc/mrbgems/README.md @@ -10,20 +10,21 @@ build configuration (i.e. *build_config.rb*), mrbgems will be activated and the extension integrated. To add a GEM into the *build_config.rb* add the following line for example: - - conf.gem '/path/to/your/gem/dir' +```ruby +conf.gem '/path/to/your/gem/dir' +``` You can also use a relative path which would be relative from the mruby root: - - conf.gem 'examples/mrbgems/ruby_extension_example' +```ruby +conf.gem 'examples/mrbgems/ruby_extension_example' +``` A remote GIT repository location for a GEM is also supported: - - conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master' - - conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' - - conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' +```ruby +conf.gem :git => 'https://github.com/masuidrive/mrbgems-example.git', :branch => 'master' +conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master' +conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master' +``` To pull all gems from remote GIT repository on build, call ```./minirake -p```, or ```./minirake --pull-gems```. @@ -41,11 +42,12 @@ via `config.gem`, but wrapped in an `MRuby::GemBox` object. GemBoxes are loaded into mruby via `config.gembox 'boxname'`. Below we have created a GemBox containing *mruby-time* and *mrbgems-example*: - - MRuby::GemBox.new do |conf| - conf.gem "#{root}/mrbgems/mruby-time" - conf.gem :github => 'masuidrive/mrbgems-example' - end +```ruby +MRuby::GemBox.new do |conf| + conf.gem "#{root}/mrbgems/mruby-time" + conf.gem :github => 'masuidrive/mrbgems-example' +end +``` As mentioned, the GemBox uses the same conventions as `MRuby::Build`. The GemBox must be saved with a *.gembox* extension inside the *mrbgems* directory to to be @@ -54,16 +56,17 @@ picked up by mruby. To use this example GemBox, we save it as `custom.gembox` inside the *mrbgems* directory in mruby, and add the following to our *build_config.rb* file inside the build block: - - conf.gembox 'custom' - +```ruby +conf.gembox 'custom' +``` This will cause the *custom* GemBox to be read in during the build process, adding *mruby-time* and *mrbgems-example* to the build. If you want, you can put GemBox outside of mruby directory. In that case you must -specify absolute path like below. - - conf.gembox "#{ENV["HOME"]}/mygemboxes/custom" +specify an absolute path like below. +```ruby +conf.gembox "#{ENV["HOME"]}/mygemboxes/custom" +``` There are two GemBoxes that ship with mruby: [default](../../mrbgems/default.gembox) and [full-core](../../mrbgems/full-core.gembox). The [default](../../mrbgems/default.gembox) GemBox @@ -98,11 +101,13 @@ to compile C and Ruby files. *README.md* is a short description of your GEM. mrbgems expects a specification file called *mrbgem.rake* inside of your GEM directory. A typical GEM specification could look like this for example: - - MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - end +```ruby +MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Example mrbgem using C and ruby' +end +``` The mrbgems build process will use this specification to compile Object and Ruby files. The compilation results will be added to *lib/libmruby.a*. This file exposes @@ -115,29 +120,32 @@ information purpose: * `spec.author` or `spec.authors` (Developer name or a list of them) * `spec.version` (Current version) * `spec.description` (Detailed description) -* `spec.summary` (Short summary) +* `spec.summary` + * One line short description of mrbgem. + * Printed in build summary of rake when set. * `spec.homepage` (Homepage) * `spec.requirements` (External requirements as information for user) -The license and author properties are required in every GEM! +The `license` and `author` properties are required in every GEM! In case your GEM is depending on other GEMs please use `spec.add_dependency(gem, *requirements[, default_get_info])` like: +```ruby +MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' - MRuby::Gem::Specification.new('c_and_ruby_extension_example') do |spec| - spec.license = 'MIT' - spec.author = 'mruby developers' - - # Add GEM dependency mruby-parser. - # The version must be between 1.0.0 and 1.5.2 . - spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2') + # Add GEM dependency mruby-parser. + # The version must be between 1.0.0 and 1.5.2 . + spec.add_dependency('mruby-parser', '>= 1.0.0', '<= 1.5.2') - # Use any version of mruby-uv from github. - spec.add_dependency('mruby-uv', '>= 0.0.0', :github => 'mattn/mruby-uv') + # Use 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) - spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp') - end + # Use latest mruby-onig-regexp from github. (version requirements can be ignored) + spec.add_dependency('mruby-onig-regexp', :github => 'mattn/mruby-onig-regexp') +end +``` The version requirements and default gem information are optional. @@ -166,16 +174,17 @@ If you have conflicting GEMs use the following method: * The `requirements` argument is same as in `add_dependency` method. like following code: - - MRuby::Gem::Specification.new 'some-regexp-binding' do |spec| - spec.license = 'BSD' - spec.author = 'John Doe' - - spec.add_conflict 'mruby-onig-regexp', '> 0.0.0' - spec.add_conflict 'mruby-hs-regexp' - spec.add_conflict 'mruby-pcre-regexp' - spec.add_conflict 'mruby-regexp-pcre' - end +```ruby +MRuby::Gem::Specification.new 'some-regexp-binding' do |spec| + spec.license = 'BSD' + spec.author = 'John Doe' + + spec.add_conflict 'mruby-onig-regexp', '> 0.0.0' + spec.add_conflict 'mruby-hs-regexp' + spec.add_conflict 'mruby-pcre-regexp' + spec.add_conflict 'mruby-regexp-pcre' +end +``` In case your GEM has more complex build requirements you can use the following options additionally inside of your GEM specification: @@ -215,12 +224,13 @@ mrbgems expects that you have implemented a C method called `mrb_YOURGEMNAME_gem_init(mrb_state)`. `YOURGEMNAME` will be replaced by the name of your GEM. If you call your GEM *c_extension_example*, your initialisation method could look like this: - - void - mrb_c_extension_example_gem_init(mrb_state* mrb) { - struct RClass *class_cextension = mrb_define_module(mrb, "CExtension"); - mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); - } +```C +void +mrb_c_extension_example_gem_init(mrb_state* mrb) { + struct RClass *class_cextension = mrb_define_module(mrb, "CExtension"); + mrb_define_class_method(mrb, class_cextension, "c_method", mrb_c_method, MRB_ARGS_NONE()); +} +``` ### Finalize @@ -229,10 +239,12 @@ mrbgems expects that you have implemented a C method called by the name of your GEM. If you call your GEM *c_extension_example*, your finalizer method could look like this: - void - mrb_c_extension_example_gem_final(mrb_state* mrb) { - free(someone); - } +```C +void +mrb_c_extension_example_gem_final(mrb_state* mrb) { + free(someone); +} +``` ### Example diff --git a/include/mrbconf.h b/include/mrbconf.h index c84b32cd8..ac33ff0bf 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -59,6 +59,12 @@ /* fixed size GC arena */ //#define MRB_GC_FIXED_ARENA +/* state atexit stack size */ +//#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5 + +/* fixed size state atexit stack */ +//#define MRB_FIXED_STATE_ATEXIT_STACK + /* -DDISABLE_XXXX to drop following features */ //#define DISABLE_STDIO /* use of stdio */ diff --git a/include/mruby.h b/include/mruby.h index dcc01b2dd..7b9f1b428 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -52,6 +52,10 @@ typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud); #define MRB_GC_ARENA_SIZE 100 #endif +#ifndef MRB_FIXED_STATE_ATEXIT_STACK_SIZE +#define MRB_FIXED_STATE_ATEXIT_STACK_SIZE 5 +#endif + typedef struct { mrb_sym mid; struct RProc *proc; @@ -173,7 +177,11 @@ typedef struct mrb_state { void *ud; /* auxiliary data */ +#ifdef MRB_FIXED_STATE_ATEXIT_STACK + mrb_atexit_func atexit_stack[MRB_FIXED_STATE_ATEXIT_STACK_SIZE]; +#else mrb_atexit_func *atexit_stack; +#endif mrb_int atexit_stack_len; } mrb_state; diff --git a/include/mruby/compile.h b/include/mruby/compile.h index 7f896e1fd..188df315d 100644 --- a/include/mruby/compile.h +++ b/include/mruby/compile.h @@ -28,6 +28,7 @@ typedef struct mrbc_context { mrb_bool capture_errors:1; mrb_bool dump_result:1; mrb_bool no_exec:1; + mrb_bool keep_lv:1; } mrbc_context; mrbc_context* mrbc_context_new(mrb_state *mrb); diff --git a/mrbgems/mruby-string-ext/mrblib/string.rb b/mrbgems/mruby-string-ext/mrblib/string.rb index 1cfb7e2f5..b8cb93199 100644 --- a/mrbgems/mruby-string-ext/mrblib/string.rb +++ b/mrbgems/mruby-string-ext/mrblib/string.rb @@ -146,4 +146,74 @@ class String [ "", "", self ] end end + + ## + # call-seq: + # str.slice!(fixnum) -> new_str or nil + # str.slice!(fixnum, fixnum) -> new_str or nil + # str.slice!(range) -> new_str or nil + # str.slice!(other_str) -> new_str or nil + # + # Deletes the specified portion from <i>str</i>, and returns the portion + # deleted. + # + # string = "this is a string" + # string.slice!(2) #=> "i" + # string.slice!(3..6) #=> " is " + # string.slice!("r") #=> "r" + # string #=> "thsa sting" + # + def slice!(arg1, arg2=nil) + raise "wrong number of arguments (for 1..2)" 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 + str = self[idx, arg2] + else + return nil + end + else + validated = false + if arg1.kind_of?(Range) + beg = arg1.begin + ed = arg1.end + beg += self.size if beg < 0 + ed += self.size if ed < 0 + validated = true + elsif arg1.kind_of?(String) + validated = true + else + idx = arg1 + idx += self.size if arg1 < 0 + validated = true if idx >=0 && arg1 < self.size + end + if validated + str = self[arg1] + else + return nil + end + end + unless str == nil || str == "" + if arg1 != nil && arg2 !=nil + idx = arg1 >= 0 ? arg1 : self.size+arg1 + str2 = self[0...idx] + self[idx+arg2..-1] + else + if arg1.kind_of?(Range) + idx = beg >= 0 ? beg : self.size+beg + idx2 = ed>= 0 ? ed : self.size+ed + str2 = self[0...idx] + self[idx2+1..-1] + elsif arg1.kind_of?(String) + idx = self.index(arg1) + 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] + end + end + self.replace(str2) unless str2 == nil + end + str + end end diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index 72c919b35..2a8dd0cca 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -193,3 +193,61 @@ assert('String#clear') do assert_equal("", s) # s is cleared assert_not_equal("", a) # a should not be affected end + +assert('String#slice!') do + a = "AooBar" + b = a.dup + assert_equal "A", a.slice!(0) + assert_equal "AooBar", b + + a = "FooBar" + assert_equal "r", a.slice!(-1) + assert_equal "FooBa", a + + a = "FooBar" + assert_nil a.slice!(6) + assert_nil a.slice!(-7) + assert_equal "FooBar", a + + a = "FooBar" + assert_equal "Foo", a.slice!(0, 3) + assert_equal "Bar", a + + a = "FooBar" + assert_equal "Bar", a.slice!(-3, 3) + assert_equal "Foo", a + + a = "FooBar" + assert_equal "", a.slice!(6, 2) + assert_equal "FooBar", a + + a = "FooBar" + assert_nil a.slice!(-7,10) + assert_equal "FooBar", a + + a = "FooBar" + assert_equal "Foo", a.slice!(0..2) + assert_equal "Bar", a + + a = "FooBar" + assert_equal "Bar", a.slice!(-3..-1) + assert_equal "Foo", a + + a = "FooBar" + assert_equal "", a.slice!(6..2) + assert_equal "FooBar", a + + a = "FooBar" + assert_nil a.slice!(-10..-7) + assert_equal "FooBar", a + + a = "FooBar" + assert_equal "Foo", a.slice!("Foo") + assert_equal "Bar", a + + a = "FooBar" + assert_nil a.slice!("xyzzy") + assert_equal "FooBar", a + + assert_raise(ArgumentError) { "foo".slice! } +end diff --git a/mrbgems/mruby-struct/test/struct.rb b/mrbgems/mruby-struct/test/struct.rb index f4151c493..911e657bd 100644 --- a/mrbgems/mruby-struct/test/struct.rb +++ b/mrbgems/mruby-struct/test/struct.rb @@ -5,10 +5,6 @@ assert('Struct', '15.2.18') do Struct.class == Class end -assert('Struct superclass', '15.2.18.2') do - Struct.superclass == Object -end - assert('Struct.new', '15.2.18.3.1') do c = Struct.new(:m1, :m2) c.superclass == Struct and diff --git a/mrbgems/mruby-time/test/time.rb b/mrbgems/mruby-time/test/time.rb index 450d87b43..ba9b48fab 100644 --- a/mrbgems/mruby-time/test/time.rb +++ b/mrbgems/mruby-time/test/time.rb @@ -9,10 +9,6 @@ assert('Time', '15.2.19') do Time.class == Class end -assert('Time superclass', '15.2.19.2') do - Time.superclass == Object -end - assert('Time.at', '15.2.19.6.1') do Time.at(1300000000.0) end diff --git a/src/parse.y b/src/parse.y index 2c7e788d9..043c86776 100644 --- a/src/parse.y +++ b/src/parse.y @@ -5558,7 +5558,12 @@ load_exec(mrb_state *mrb, parser_state *p, mrbc_context *c) if (c->target_class) { target = c->target_class; } - keep = c->slen + 1; + if (c->keep_lv) { + keep = c->slen + 1; + } + else { + c->keep_lv = TRUE; + } } proc->target_class = target; if (mrb->c->ci) { diff --git a/src/state.c b/src/state.c index c0a9c14c2..3e82a159d 100644 --- a/src/state.c +++ b/src/state.c @@ -226,7 +226,9 @@ mrb_close(mrb_state *mrb) for (i = mrb->atexit_stack_len; i > 0; --i) { mrb->atexit_stack[i - 1](mrb); } +#ifndef MRB_FIXED_STATE_ATEXIT_STACK mrb_free(mrb, mrb->atexit_stack); +#endif } /* free */ @@ -268,6 +270,11 @@ mrb_top_self(mrb_state *mrb) void mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f) { +#ifdef MRB_FIXED_STATE_ATEXIT_STACK + if (mrb->atexit_stack_len + 1 > MRB_FIXED_STATE_ATEXIT_STACK_SIZE) { + mrb_raise(mrb, E_RUNTIME_ERROR, "exceeded fixed state atexit stack limit"); + } +#else size_t stack_size; stack_size = sizeof(mrb_atexit_func) * (mrb->atexit_stack_len + 1); @@ -276,6 +283,7 @@ mrb_state_atexit(mrb_state *mrb, mrb_atexit_func f) } else { mrb->atexit_stack = (mrb_atexit_func*)mrb_realloc(mrb, mrb->atexit_stack, stack_size); } +#endif mrb->atexit_stack[mrb->atexit_stack_len++] = f; } diff --git a/src/string.c b/src/string.c index 9b5707dc0..6570c89fb 100644 --- a/src/string.c +++ b/src/string.c @@ -814,8 +814,6 @@ num_index: * str.slice(fixnum) => fixnum or nil * str.slice(fixnum, fixnum) => new_str or nil * str.slice(range) => new_str or nil - * str.slice(regexp) => new_str or nil - * str.slice(regexp, fixnum) => new_str or nil * str.slice(other_str) => new_str or nil * * Element Reference---If passed a single <code>Fixnum</code>, returns the code @@ -827,10 +825,7 @@ num_index: * <code>nil</code> if the initial offset falls outside the string, the length * is negative, or the beginning of the range is greater than the end. * - * If a <code>Regexp</code> is supplied, the matching portion of <i>str</i> is - * returned. If a numeric parameter follows the regular expression, that - * component of the <code>MatchData</code> is returned instead. If a - * <code>String</code> is given, that string is returned if it occurs in + * If a <code>String</code> is given, that string is returned if it occurs in * <i>str</i>. In both cases, <code>nil</code> is returned if there is no * match. * @@ -842,10 +837,6 @@ num_index: * a[-4..-2] #=> "her" * a[12..-1] #=> nil * a[-2..-4] #=> "" - * a[/[aeiou](.)\1/] #=> "ell" - * a[/[aeiou](.)\1/, 0] #=> "ell" - * a[/[aeiou](.)\1/, 1] #=> "l" - * a[/[aeiou](.)\1/, 2] #=> nil * a["lo"] #=> "lo" * a["bye"] #=> nil */ diff --git a/src/variable.c b/src/variable.c index 5f762dd0b..74bb591cf 100644 --- a/src/variable.c +++ b/src/variable.c @@ -124,10 +124,10 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val) * mrb * t the variable table to be searched. * sym the symbol to be used as the key. - * vp the value pointer. Recieves the value if the specified symbol contains - * in the instance variable table. + * vp the value pointer. Receives the value if the specified symbol is + * contained in the instance variable table. * Returns - * true if the specfiyed symbol contains in the instance variable table. + * true if the specified symbol is contained in the instance variable table. */ static mrb_bool iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) @@ -159,10 +159,10 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) * Parameters * t the variable table to be searched. * sym the symbol to be used as the key. - * vp the value pointer. Recieve the deleted value if the symbol contans - * in the instance varible table. + * vp the value pointer. Receive the deleted value if the symbol is + * contained in the instance variable table. * Returns - * true if the specfied symbol contains in the instance variable table. + * true if the specified symbol is contained in the instance variable table. */ static mrb_bool iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp) diff --git a/test/t/argumenterror.rb b/test/t/argumenterror.rb index c8d277cc5..abb53429b 100644 --- a/test/t/argumenterror.rb +++ b/test/t/argumenterror.rb @@ -14,8 +14,3 @@ assert('ArgumentError', '15.2.24') do assert_equal(Class, ArgumentError.class) assert_equal(ArgumentError, e2.class) end - -assert('ArgumentError superclass', '15.2.24.2') do - assert_equal(StandardError, ArgumentError.superclass) -end - diff --git a/test/t/array.rb b/test/t/array.rb index 56daf0b01..538ea0c3f 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -5,10 +5,6 @@ assert('Array', '15.2.12') do assert_equal(Class, Array.class) end -assert('Array superclass', '15.2.12.2') do - assert_equal(Object, Array.superclass) -end - assert('Array inclueded modules', '15.2.12.3') do assert_true(Array.include?(Enumerable)) end diff --git a/test/t/class.rb b/test/t/class.rb index 821259c5e..f49ccf494 100644 --- a/test/t/class.rb +++ b/test/t/class.rb @@ -5,10 +5,6 @@ assert('Class', '15.2.3') do assert_equal(Class, Class.class) end -assert('Class superclass', '15.2.3.2') do - assert_equal(Module, Class.superclass) -end - assert('Class#initialize', '15.2.3.3.1') do c = Class.new do def test diff --git a/test/t/enumerable.rb b/test/t/enumerable.rb index 5c9b14f00..359c3451b 100644 --- a/test/t/enumerable.rb +++ b/test/t/enumerable.rb @@ -107,15 +107,17 @@ assert('Enumerable#member?', '15.3.2.2.15') do end assert('Enumerable#partition', '15.3.2.2.16') do - [0,1,2,3,4,5,6,7,8,9].partition do |i| + partition = [0,1,2,3,4,5,6,7,8,9].partition do |i| i % 2 == 0 - end == [[0,2,4,6,8], [1,3,5,7,9]] + end + assert_equal [[0,2,4,6,8], [1,3,5,7,9]], partition end assert('Enumerable#reject', '15.3.2.2.17') do - [0,1,2,3,4,5,6,7,8,9].reject do |i| + reject = [0,1,2,3,4,5,6,7,8,9].reject do |i| i % 2 == 0 - end == [1,3,5,7,9] + end + assert_equal [1,3,5,7,9], reject end assert('Enumerable#select', '15.3.2.2.18') do diff --git a/test/t/exception.rb b/test/t/exception.rb index be487162f..d27813028 100644 --- a/test/t/exception.rb +++ b/test/t/exception.rb @@ -5,10 +5,6 @@ assert('Exception', '15.2.22') do assert_equal Class, Exception.class end -assert('Exception superclass', '15.2.22.2') do - assert_equal Object, Exception.superclass -end - assert('Exception.exception', '15.2.22.4.1') do e = Exception.exception('a') diff --git a/test/t/false.rb b/test/t/false.rb index bc684f2e6..3582f697a 100644 --- a/test/t/false.rb +++ b/test/t/false.rb @@ -11,10 +11,6 @@ assert('FalseClass false', '15.2.6.1') do assert_false FalseClass.method_defined? :new end -assert('FalseClass superclass', '15.2.6.2') do - assert_equal Object, FalseClass.superclass -end - assert('FalseClass#&', '15.2.6.3.1') do assert_false false.&(true) assert_false false.&(false) diff --git a/test/t/float.rb b/test/t/float.rb index ded434320..d45709173 100644 --- a/test/t/float.rb +++ b/test/t/float.rb @@ -5,10 +5,6 @@ assert('Float', '15.2.9') do assert_equal Class, Float.class end -assert('Float superclass', '15.2.9.2') do - assert_equal Numeric, Float.superclass -end - assert('Float#+', '15.2.9.3.1') do a = 3.123456788 + 0.000000001 b = 3.123456789 + 1 diff --git a/test/t/hash.rb b/test/t/hash.rb index 0d8d137c4..eee7c7b6a 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -5,10 +5,6 @@ assert('Hash', '15.2.13') do assert_equal Class, Hash.class end -assert('Hash superclass', '15.2.13.2') do - assert_equal Object, Hash.superclass -end - assert('Hash#==', '15.2.13.4.1') do assert_true({ 'abc' => 'abc' } == { 'abc' => 'abc' }) assert_false({ 'abc' => 'abc' } == { 'cba' => 'cba' }) diff --git a/test/t/indexerror.rb b/test/t/indexerror.rb index ea008a227..a8dce23a0 100644 --- a/test/t/indexerror.rb +++ b/test/t/indexerror.rb @@ -4,7 +4,3 @@ assert('IndexError', '15.2.33') do assert_equal Class, IndexError.class end - -assert('IndexError superclass', '15.2.33.2') do - assert_equal StandardError, IndexError.superclass -end diff --git a/test/t/integer.rb b/test/t/integer.rb index 6560dddfe..c50ef112c 100644 --- a/test/t/integer.rb +++ b/test/t/integer.rb @@ -5,10 +5,6 @@ assert('Integer', '15.2.8') do assert_equal Class, Integer.class end -assert('Integer superclass', '15.2.8.2') do - assert_equal Numeric, Integer.superclass -end - assert('Integer#+', '15.2.8.3.1') do a = 1+1 b = 1+1.0 diff --git a/test/t/module.rb b/test/t/module.rb index fcf46fe3a..5ac794330 100644 --- a/test/t/module.rb +++ b/test/t/module.rb @@ -5,10 +5,6 @@ assert('Module', '15.2.2') do assert_equal Class, Module.class end -assert('Module superclass', '15.2.2.2') do - assert_equal Object, Module.superclass -end - # TODO not implemented ATM assert('Module.constants', '15.2.2.3.1') do # TODO not implemented ATM assert('Module.nesting', '15.2.2.3.2') do diff --git a/test/t/nameerror.rb b/test/t/nameerror.rb index 3e3c59264..28682bedc 100644 --- a/test/t/nameerror.rb +++ b/test/t/nameerror.rb @@ -5,10 +5,6 @@ assert('NameError', '15.2.31') do assert_equal Class, NameError.class end -assert('NameError superclass', '15.2.31.2') do - assert_equal StandardError, NameError.superclass -end - assert('NameError#name', '15.2.31.2.1') do # This check is not duplicate with 15.2.31.2.2 check. diff --git a/test/t/nil.rb b/test/t/nil.rb index 971ce2e8e..53b922f9a 100644 --- a/test/t/nil.rb +++ b/test/t/nil.rb @@ -10,10 +10,6 @@ assert('NilClass', '15.2.4.1') do assert_false NilClass.method_defined? :new end -assert('NilClass superclass', '15.2.4.2') do - assert_equal Object, NilClass.superclass -end - assert('NilClass#&', '15.2.4.3.1') do assert_false nil.&(true) assert_false nil.&(nil) diff --git a/test/t/nomethoderror.rb b/test/t/nomethoderror.rb index 709d31165..5fed79689 100644 --- a/test/t/nomethoderror.rb +++ b/test/t/nomethoderror.rb @@ -8,10 +8,6 @@ assert('NoMethodError', '15.2.32') do end end -assert('NoMethodError superclass', '15.2.32.2') do - assert_equal NameError, NoMethodError.superclass -end - assert('NoMethodError#args', '15.2.32.2.1') do a = NoMethodError.new 'test', :test, [1, 2] assert_equal [1, 2], a.args diff --git a/test/t/numeric.rb b/test/t/numeric.rb index ef977da29..2b01611a7 100644 --- a/test/t/numeric.rb +++ b/test/t/numeric.rb @@ -5,10 +5,6 @@ assert('Numeric', '15.2.7') do assert_equal Class, Numeric.class end -assert('Numeric superclass', '15.2.7.2') do - assert_equal Object, Numeric.superclass -end - assert('Numeric#+@', '15.2.7.4.1') do assert_equal(+1, +1) end diff --git a/test/t/proc.rb b/test/t/proc.rb index 9c1b7d4c7..22ccceb68 100644 --- a/test/t/proc.rb +++ b/test/t/proc.rb @@ -5,10 +5,6 @@ assert('Proc', '15.2.17') do assert_equal Class, Proc.class end -assert('Proc superclass', '15.2.17.2') do - assert_equal Object, Proc.superclass -end - assert('Proc.new', '15.2.17.3.1') do assert_raise ArgumentError do Proc.new diff --git a/test/t/range.rb b/test/t/range.rb index b35da40ab..278b26902 100644 --- a/test/t/range.rb +++ b/test/t/range.rb @@ -5,10 +5,6 @@ assert('Range', '15.2.14') do assert_equal Class, Range.class end -assert('Range superclass', '15.2.14.2') do - assert_equal Object, Range.superclass -end - assert('Range#==', '15.2.14.4.1') do assert_true (1..10) == (1..10) assert_false (1..10) == (1..100) diff --git a/test/t/rangeerror.rb b/test/t/rangeerror.rb index 8dc683745..97878096e 100644 --- a/test/t/rangeerror.rb +++ b/test/t/rangeerror.rb @@ -4,7 +4,3 @@ assert('RangeError', '15.2.26') do assert_equal Class, RangeError.class end - -assert('RangeError superclass', '15.2.26.2') do - assert_equal StandardError, RangeError.superclass -end diff --git a/test/t/standarderror.rb b/test/t/standarderror.rb index cab99834e..c349b08cf 100644 --- a/test/t/standarderror.rb +++ b/test/t/standarderror.rb @@ -4,7 +4,3 @@ assert('StandardError', '15.2.23') do assert_equal Class, StandardError.class end - -assert('StandardError superclass', '15.2.23.2') do - assert_equal Exception, StandardError.superclass -end diff --git a/test/t/string.rb b/test/t/string.rb index 00e98f671..c0e545e87 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -5,10 +5,6 @@ assert('String', '15.2.10') do assert_equal Class, String.class end -assert('String superclass', '15.2.10.2') do - assert_equal Object, String.superclass -end - assert('String#<=>', '15.2.10.5.1') do a = '' <=> '' b = '' <=> 'not empty' diff --git a/test/t/superclass.rb b/test/t/superclass.rb new file mode 100644 index 000000000..9fd8830b3 --- /dev/null +++ b/test/t/superclass.rb @@ -0,0 +1,46 @@ +[ + # [:Object, :implementation_defined_value, '15.2.2.1'], + [:Module, :Object, '15.2.2.2'], + [:Class, :Module, '15.2.3.2'], + [:NilClass, :Object, '15.2.4.2'], + [:TrueClass, :Object, '15.2.5.2'], + [:FalseClass, :Object, '15.2.6.2'], + [:Numeric, :Object, '15.2.7.2'], + [:Integer, :Numeric, '15.2.8.2'], + [:Float, :Numeric, '15.2.9.2'], + [:String, :Object, '15.2.10.2'], + [:Symbol, :Object, '15.2.11.2'], + [:Array, :Object, '15.2.12.2'], + [:Hash, :Object, '15.2.13.2'], + [:Range, :Object, '15.2.14.2'], +# [:Regexp, :Object, '15.2.15.2'], #No Regexp in mruby core +# [:MatchData, :Object, '15.2.16.2'], + [:Proc, :Object, '15.2.17.2'], +# [:Struct, :Object, '15.2.18.2'], +# [:Time, :Object, '15.2.19.2'], +# [:IO, :Object, '15.2.20.2'], +# [:File, :IO, '15.2.21.2'], + [:Exception, :Object, '15.2.22.2'], + [:StandardError, :Exception, '15.2.23.2'], + [:ArgumentError, :StandardError, '15.2.24.2'], + [:LocalJumpError, :StandardError, '15.2.25.2'], + [:RangeError, :StandardError, '12.2.26.2'], + [:RegexpError, :StandardError, '12.2.27.2'], + [:RuntimeError, :StandardError, '12.2.28.2'], + [:TypeError, :StandardError, '12.2.29.2'], +# [:ZeroDivisionError, :StandardError, '12.2.30.2'], # No ZeroDivisionError in mruby + [:NameError, :StandardError, '15.2.31.2'], + [:NoMethodError, :NameError, '15.2.32.2'], + [:IndexError, :StandardError, '15.2.33.2'], +# [:IOError, :StandardError, '12.2.34.2'], +# [:EOFError, :IOError, '12.2.35.2'], +# [:SystemCallError, :StandardError, '15.2.36.2'], + [:ScriptError, :Exception, '12.2.37.2'], + [:SyntaxError, :ScriptError, '12.2.38.2'], +# [:LoadError, :ScriptError, '12.2.39,2'], +].each do |cls, super_cls, iso| + assert "Direct superclass of #{cls}", iso do + skip "#{cls} isn't defined" unless Object.const_defined? cls + assert_equal Object.const_get(super_cls), Object.const_get(cls).superclass + end +end diff --git a/test/t/symbol.rb b/test/t/symbol.rb index f852dcd00..b0252849d 100644 --- a/test/t/symbol.rb +++ b/test/t/symbol.rb @@ -5,10 +5,6 @@ assert('Symbol', '15.2.11') do assert_equal Class, Symbol.class end -assert('Symbol superclass', '15.2.11.2') do - assert_equal Object, Symbol.superclass -end - assert('Symbol#===', '15.2.11.3.1') do assert_true :abc == :abc assert_false :abc == :cba diff --git a/test/t/true.rb b/test/t/true.rb index e5da2112c..74f605ef0 100644 --- a/test/t/true.rb +++ b/test/t/true.rb @@ -11,10 +11,6 @@ assert('TrueClass true', '15.2.5.1') do assert_false TrueClass.method_defined? :new end -assert('TrueClass superclass', '15.2.5.2') do - assert_equal Object, TrueClass.superclass -end - assert('TrueClass#&', '15.2.5.3.1') do assert_true true.&(true) assert_false true.&(false) diff --git a/test/t/typeerror.rb b/test/t/typeerror.rb index a91fb1be2..32536a74f 100644 --- a/test/t/typeerror.rb +++ b/test/t/typeerror.rb @@ -4,8 +4,3 @@ assert('TypeError', '15.2.29') do assert_equal Class, TypeError.class end - -assert('TypeError superclass', '15.2.29.2') do - assert_equal StandardError, TypeError.superclass -end - |
