diff --git a/mrbgems/ngx_mruby_mrblib/mrblib/mrb_nginx.rb b/mrbgems/ngx_mruby_mrblib/mrblib/mrb_nginx.rb index c0f8156a..9715e531 100644 --- a/mrbgems/ngx_mruby_mrblib/mrblib/mrb_nginx.rb +++ b/mrbgems/ngx_mruby_mrblib/mrblib/mrb_nginx.rb @@ -127,14 +127,4 @@ module Kernel def get_server_class Nginx end - - def _ngx_mrb_prepare_fiber(nginx_handler) - fiber_handler = Fiber.new { nginx_handler.call } - - lambda do - # BUG?: return nginx_handler directly from fiber, not proc in any case. - result = fiber_handler.resume - [fiber_handler.alive?, result] - end - end end diff --git a/mruby/.github/labeler.yml b/mruby/.github/labeler.yml index b4f73b78..742fc2b3 100644 --- a/mruby/.github/labeler.yml +++ b/mruby/.github/labeler.yml @@ -1,29 +1,50 @@ benchmark: - - benchmark/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - benchmark/**/* build: - - Makefile - - Rakefile - - build_config/**/* - - lib/**/* - - tasks/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - Makefile + - Rakefile + - build_config/**/* + - lib/**/* + - tasks/**/* core: - - include/**/* - - mrblib/**/* - - src/**/* - - test/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - include/**/* + - mrblib/**/* + - src/**/* + - test/**/* doc: - - CONTRIBUTING.md - - LEGAL - - LICENSE - - NEWS - - README.md - - SECURITY.md - - TODO.md - - doc/**/* - - examples/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - CONTRIBUTING.md + - LEGAL + - LICENSE + - NEWS + - README.md + - SECURITY.md + - TODO.md + - doc/**/* + - examples/**/* github: - - .github/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - .github/**/* mrbgems: - - mrbgems/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - mrbgems/**/* oss-fuzz: - - oss-fuzz/**/* + - any: + - changed-files: + - any-glob-to-any-file: + - oss-fuzz/**/* diff --git a/mruby/.github/workflows/labeler.yml b/mruby/.github/workflows/labeler.yml index f85abb12..4d149368 100644 --- a/mruby/.github/workflows/labeler.yml +++ b/mruby/.github/workflows/labeler.yml @@ -9,7 +9,7 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v4 + - uses: actions/labeler@v5 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" sync-labels: true diff --git a/mruby/.github/workflows/super-linter.yml b/mruby/.github/workflows/super-linter.yml index fd577722..8d817ef4 100644 --- a/mruby/.github/workflows/super-linter.yml +++ b/mruby/.github/workflows/super-linter.yml @@ -20,7 +20,7 @@ jobs: # Full git history is needed to get a proper list of changed files within `super-linter` fetch-depth: 0 - name: Lint Code Base - uses: super-linter/super-linter/slim@v5.3.1 + uses: super-linter/super-linter/slim@v5.7.2 env: ERROR_ON_MISSING_EXEC_BIT: true VALIDATE_BASH: true diff --git a/mruby/.pre-commit-config.yaml b/mruby/.pre-commit-config.yaml index 48e353b7..6e0b6024 100644 --- a/mruby/.pre-commit-config.yaml +++ b/mruby/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: identity - id: check-hooks-apply - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -30,7 +30,7 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.1 + rev: v1.5.4 hooks: - id: forbid-tabs exclude: Makefile$|Makefile\..+$|makefile$|\.mk$ @@ -38,7 +38,7 @@ repos: args: [--whitespaces-count, '2'] exclude: Makefile$|Makefile\..+$|makefile$|\.mk$ - repo: https://github.com/codespell-project/codespell - rev: v2.2.5 + rev: v2.2.6 hooks: - id: codespell name: Run codespell @@ -51,7 +51,7 @@ repos: name: Local policy is to exclude extension from all shell files types: [shell] - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.35.0 + rev: v0.37.0 hooks: - id: markdownlint name: Run markdownlint @@ -69,7 +69,7 @@ repos: types: [markdown] files: \.(md|mdown|markdown)$ - repo: https://github.com/adrienverge/yamllint - rev: v1.32.0 + rev: v1.33.0 hooks: - id: yamllint name: Run yamllint diff --git a/mruby/AUTHORS b/mruby/AUTHORS index 6483ddc5..a3016325 100644 --- a/mruby/AUTHORS +++ b/mruby/AUTHORS @@ -1,10 +1,10 @@ # Authors of mruby (mruby developers) -## The List of Contributors sorted by number of commits (as of 2023-08-26 b85b682) +## The List of Contributors sorted by number of commits (as of 2023-11-20 6a3a810) - 9287 Yukihiro "Matz" Matsumoto (@matz)* + 9408 Yukihiro "Matz" Matsumoto (@matz)* 586 KOBAYASHI Shuji (@shuujii) - 494 dearblue (@dearblue)* + 508 dearblue (@dearblue)* 378 Daniel Bovensiepen (@bovi)* 346 Takeshi Watanabe (@take-cheeze)* 334 Masaki Muranaka (@monaka) @@ -12,7 +12,7 @@ 234 Jun Hiroe (@suzukaze) 220 Cremno (@cremno)* 209 Yuki Kurihara (@ksss)+ - 159 John Bampton (@jbampton) + 165 John Bampton (@jbampton) 151 Yasuhiro Matsumoto (@mattn)* 113 Carson McDonald (@carsonmcdonald) 103 Tomasz Dąbrowski (@dabroz)* @@ -115,9 +115,11 @@ 4 Dante Catalfamo (@dantecatalfamo) 4 Goro Kikuchi (@gorogit) 4 Herwin Weststrate (@herwinw) + 4 Horimoto Yasuhiro (@komainu8) 4 Jon Moss (@maclover7) 4 Ken Muramatsu (@ken-mu)+ 4 Kohei Suzuki (@eagletmt) + 4 Lanza (@LanzaSchneider) 4 Li Yazhou (@flaneur2020) 4 Marcus Stollsteimer (@stomar) 4 NARUSE, Yui (@nurse) @@ -132,12 +134,10 @@ 3 David Turnbull (@AE9RB) 3 Franck Verrot (@franckverrot) 3 HASUMI Hitoshi (@hasumikin) - 3 Horimoto Yasuhiro (@komainu8) 3 J. Mutua (@katmutua)+ 3 Jan Berdajs (@mrbrdo) 3 Jonas Minnberg (@sasq64) 3 Joseph McCullough (@joequery) - 3 Lanza (@LanzaSchneider) 3 Mark McCurry (@fundamental) 3 Nobuhiro Iwamatsu (@iwamatsu) 3 Per Lundberg (@perlun)* @@ -283,6 +283,7 @@ 1 Yevhen Viktorov (@yevgenko) 1 Yoji SHIDARA (@darashi) 1 Yoshiori SHOJI (@yoshiori) + 1 Yuji Yokoo (@yujiyokoo) 1 Yukang (@chenyukang) 1 Yurii Nakonechnyi (@inobelar) 1 Yusuke Suzuki (@Constellation)+ diff --git a/mruby/Dockerfile b/mruby/Dockerfile index f6699562..c4419b4f 100644 --- a/mruby/Dockerfile +++ b/mruby/Dockerfile @@ -6,11 +6,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y python3-pip she WORKDIR /app -COPY Gemfile . - -COPY Gemfile.lock . - -COPY .pre-commit-config.yaml . +COPY Gemfile Gemfile.lock .pre-commit-config.yaml ./ RUN bundle install && pip3 install pre-commit && git init . && pre-commit install-hooks diff --git a/mruby/LICENSE b/mruby/LICENSE index 7461282a..b21dbf39 100644 --- a/mruby/LICENSE +++ b/mruby/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2010-2023 mruby developers +Copyright (c) 2010- mruby developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/mruby/build_config/host-shared.rb b/mruby/build_config/host-shared.rb index 38cab814..76e3a071 100644 --- a/mruby/build_config/host-shared.rb +++ b/mruby/build_config/host-shared.rb @@ -1,23 +1,20 @@ +# NOTE: Currently, this configuration file does not support VisualC++! +# Your help is needed! + MRuby::Build.new do |conf| # load specific toolchain settings - - # Gets set by the VS command prompts. - if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] - toolchain :visualcpp - else - toolchain :gcc - end + conf.toolchain # include the GEM box conf.gembox 'default' # C compiler settings - conf.cc do |cc| - cc.flags = '-fPIC' + conf.compilers.each do |cc| + cc.flags << '-fPIC' end conf.archiver do |archiver| - archiver.command = 'gcc' + archiver.command = cc.command archiver.archive_options = '-shared -o %{outfile} %{objs}' end @@ -29,6 +26,9 @@ # file separator # conf.file_separator = '/' + # enable this if better compatibility with C++ is desired + #conf.enable_cxx_exception + # Turn on `enable_debug` for better debugging conf.enable_debug conf.enable_bintest diff --git a/mruby/build_config/nintendo_wii.rb b/mruby/build_config/nintendo_wii.rb new file mode 100644 index 00000000..01ce547b --- /dev/null +++ b/mruby/build_config/nintendo_wii.rb @@ -0,0 +1,96 @@ +# Cross Compiling configuration for the Nintendo Wii +# This configuration requires devkitPPC +# https://devkitpro.org/wiki/Getting_Started +# +# +MRuby::CrossBuild.new("wii") do |conf| + toolchain :gcc + + DEVKITPRO_PATH = "/opt/devkitpro" + BIN_PATH = "#{DEVKITPRO_PATH}/devkitPPC/bin" + + # C compiler + conf.cc do |cc| + cc.command = "#{BIN_PATH}/powerpc-eabi-gcc" + cc.compile_options = %(%{flags} -o "%{outfile}" -c "%{infile}") + end + + # C++ compiler + conf.cxx do |cxx| + cxx.command = "#{BIN_PATH}/powerpc-eabi-g++" + cxx.include_paths = conf.cc.include_paths.dup + cxx.flags = conf.cc.flags.dup + cxx.defines = conf.cc.defines.dup + cxx.compile_options = conf.cc.compile_options.dup + end + + # Linker + conf.linker do |linker| + linker.command = "#{BIN_PATH}/powerpc-eabi-gcc" + end + + # No executables + conf.bins = [] + + # Do not build executable test + conf.build_mrbtest_lib_only + + # Disable C++ exception + conf.disable_cxx_exception + + # All current core gems with ones with build issues commented out + conf.gem 'mrbgems/mruby-array-ext/' + conf.gem 'mrbgems/mruby-bigint/' + conf.gem 'mrbgems/mruby-bin-config/' + conf.gem 'mrbgems/mruby-bin-debugger/' + conf.gem 'mrbgems/mruby-bin-mirb/' + conf.gem 'mrbgems/mruby-bin-mrbc/' + conf.gem 'mrbgems/mruby-bin-mruby/' + conf.gem 'mrbgems/mruby-bin-strip/' + conf.gem 'mrbgems/mruby-binding/' + conf.gem 'mrbgems/mruby-catch/' + conf.gem 'mrbgems/mruby-class-ext/' + conf.gem 'mrbgems/mruby-cmath/' + conf.gem 'mrbgems/mruby-compar-ext/' + conf.gem 'mrbgems/mruby-compiler/' + conf.gem 'mrbgems/mruby-complex/' + conf.gem 'mrbgems/mruby-data/' + #conf.gem 'mrbgems/mruby-dir/' + conf.gem 'mrbgems/mruby-enum-chain/' + conf.gem 'mrbgems/mruby-enum-ext/' + conf.gem 'mrbgems/mruby-enum-lazy/' + conf.gem 'mrbgems/mruby-enumerator/' + conf.gem 'mrbgems/mruby-errno/' + conf.gem 'mrbgems/mruby-error/' + conf.gem 'mrbgems/mruby-eval/' + conf.gem 'mrbgems/mruby-exit/' + conf.gem 'mrbgems/mruby-fiber/' + conf.gem 'mrbgems/mruby-hash-ext/' + #conf.gem 'mrbgems/mruby-io/' + conf.gem 'mrbgems/mruby-kernel-ext/' + conf.gem 'mrbgems/mruby-math/' + conf.gem 'mrbgems/mruby-metaprog/' + conf.gem 'mrbgems/mruby-method/' + conf.gem 'mrbgems/mruby-numeric-ext/' + conf.gem 'mrbgems/mruby-object-ext/' + conf.gem 'mrbgems/mruby-objectspace/' + conf.gem 'mrbgems/mruby-os-memsize/' + conf.gem 'mrbgems/mruby-pack/' + conf.gem 'mrbgems/mruby-print/' + conf.gem 'mrbgems/mruby-proc-binding/' + conf.gem 'mrbgems/mruby-proc-ext/' + conf.gem 'mrbgems/mruby-random/' + conf.gem 'mrbgems/mruby-range-ext/' + conf.gem 'mrbgems/mruby-rational/' + conf.gem 'mrbgems/mruby-set/' + conf.gem 'mrbgems/mruby-sleep/' + #conf.gem 'mrbgems/mruby-socket/' + conf.gem 'mrbgems/mruby-sprintf/' + conf.gem 'mrbgems/mruby-string-ext/' + conf.gem 'mrbgems/mruby-struct/' + conf.gem 'mrbgems/mruby-symbol-ext/' + conf.gem 'mrbgems/mruby-test-inline-struct/' + #conf.gem 'mrbgems/mruby-test/' + conf.gem 'mrbgems/mruby-time/' + conf.gem 'mrbgems/mruby-toplevel-ext/' +end diff --git a/mruby/doc/guides/debugger.md b/mruby/doc/guides/debugger.md index 40afb507..60be1cc8 100644 --- a/mruby/doc/guides/debugger.md +++ b/mruby/doc/guides/debugger.md @@ -61,20 +61,20 @@ $ mrdb sample.rb You can execute the shell commands listed below: -|command|description| -|:-:|:--| -|run|execute programs| -|step|execute stepping| -|continue|execute continuing program| -|break|configure the breaking point| -|delete|deleting the breaking points| -|disable|disabling the breaking points| -|enable|enabling the breaking points| -|info breakpoints|showing list of the breaking points| -|print|evaluating and printing the values of the mruby expressions in the script| -|list|displaying the source cords| -|help|showing help| -|quit|terminating the mruby debugger| +| command | description | +|:----------------:|:--------------------------------------------------------------------------| +| run | execute programs | +| step | execute stepping | +| continue | execute continuing program | +| break | configure the breaking point | +| delete | deleting the breaking points | +| disable | disabling the breaking points | +| enable | enabling the breaking points | +| info breakpoints | showing list of the breaking points | +| print | evaluating and printing the values of the mruby expressions in the script | +| list | displaying the source cords | +| help | showing help | +| quit | terminating the mruby debugger | ### 2.2.2 Debugging mruby Binary Files (mrb file) with mrdb diff --git a/mruby/docker-compose.yml b/mruby/docker-compose.yml index 223e85af..55b61a87 100644 --- a/mruby/docker-compose.yml +++ b/mruby/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3' +version: '3.8' services: test: build: diff --git a/mruby/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md b/mruby/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md index d1877f51..4926afe1 100644 --- a/mruby/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md +++ b/mruby/examples/mrbgems/mruby-YOUR-bigint/TODO-HINT.md @@ -21,9 +21,9 @@ The file structure in this example is as follows: May be depended on by other GEMs. ``` -Implementors of their own bigints should copy below this directory to another directory and do the following: +Implementers of their own bigints should copy below this directory to another directory and do the following: -- Rewrite `spec.author`, `spec.license`, `spec.homepage` and `spec.summary` in `/mrbgem.rake` file to those of your own implementors. +- Rewrite `spec.author`, `spec.license`, `spec.homepage` and `spec.summary` in `/mrbgem.rake` file to those of your own implementers. - Implement the respective functions in `/core/bigint.c`. - Define and use an object structure for `MRB_TT_BIGINT` type-tag. It is recommended to use `mrb_static_assert_object_size()` to ensure that the size of the object structure is within six words. diff --git a/mruby/include/mruby.h b/mruby/include/mruby.h index 5feb8d63..3ed86f8c 100644 --- a/mruby/include/mruby.h +++ b/mruby/include/mruby.h @@ -1,7 +1,7 @@ /* ** mruby - An embeddable Ruby implementation ** -** Copyright (c) mruby developers 2010-2023 +** Copyright (c) mruby developers 2010- ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the @@ -1445,14 +1445,19 @@ MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mr /* obsolete function(s); will be removed */ #define mrb_int(mrb, val) mrb_as_int(mrb, val) +/** + * Create a new Fiber from proc object + * + * Implemented in mruby-fiber + */ +MRB_API mrb_value mrb_fiber_new(mrb_state *mrb, const struct RProc *proc); + /** * Resume a Fiber * * Implemented in mruby-fiber * * Switches to the specified fiber and executes. Like the `Fiber#resume` method. - * - * @note It can only be called before entering the mruby VM (e.g. in the `main()` function). */ MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc, const mrb_value *argv); diff --git a/mruby/include/mruby/compile.h b/mruby/include/mruby/compile.h index 84f09e3e..e3d0d619 100644 --- a/mruby/include/mruby/compile.h +++ b/mruby/include/mruby/compile.h @@ -18,7 +18,7 @@ MRB_BEGIN_DECL struct mrb_parser_state; /* load context */ -typedef struct mrbc_context { +typedef struct mrb_ccontext { mrb_sym *syms; int slen; char *filename; @@ -35,13 +35,21 @@ typedef struct mrbc_context { const struct RProc *upper; size_t parser_nerr; -} mrbc_context; - -MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb); -MRB_API void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt); -MRB_API const char *mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s); -MRB_API void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(struct mrb_parser_state*), void*data); -MRB_API void mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c); +} mrb_ccontext; /* compiler context */ + +MRB_API mrb_ccontext* mrb_ccontext_new(mrb_state *mrb); +MRB_API void mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt); +MRB_API const char *mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s); +MRB_API void mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*partial_hook)(struct mrb_parser_state*), void*data); +MRB_API void mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c); + +/* compatibility macros */ +#define mrbc_context mrb_ccontext +#define mrbc_context_new mrb_ccontext_new +#define mrbc_context_free mrb_ccontext_free +#define mrbc_filename mrb_ccontext_filename +#define mrbc_partial_hook mrb_ccontext_partial_hook +#define mrbc_cleanup_local_variables mrb_ccontext_cleanup_local_variables /* AST node structure */ typedef struct mrb_ast_node { @@ -121,7 +129,7 @@ struct mrb_parser_state { /* If both f and s are non-null, it will be taken preferentially from s until s < send. */ FILE *f; #endif - mrbc_context *cxt; + mrb_ccontext *cxt; mrb_sym filename_sym; uint16_t lineno; int column; @@ -168,19 +176,19 @@ struct mrb_parser_state { MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*); MRB_API void mrb_parser_free(struct mrb_parser_state*); -MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*); +MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrb_ccontext*); MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*); MRB_API mrb_sym mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx); /* utility functions */ #ifndef MRB_NO_STDIO -MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*); +MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrb_ccontext*); #endif -MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*); -MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrbc_context*); +MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrb_ccontext*); +MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrb_ccontext*); MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*); -MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c); +MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrb_ccontext *c); /** program load functions * Please note! Currently due to interactions with the GC calling these functions will @@ -193,13 +201,13 @@ MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc */ #ifndef MRB_NO_STDIO MRB_API mrb_value mrb_load_file(mrb_state*,FILE*); -MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt); -MRB_API mrb_value mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c); +MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrb_ccontext *cxt); +MRB_API mrb_value mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrb_ccontext *c); #endif MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s); MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len); -MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt); -MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *cxt); +MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrb_ccontext *cxt); +MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrb_ccontext *cxt); /** @} */ MRB_END_DECL diff --git a/mruby/include/mruby/dump.h b/mruby/include/mruby/dump.h index 863f2264..c129015d 100644 --- a/mruby/include/mruby/dump.h +++ b/mruby/include/mruby/dump.h @@ -23,7 +23,7 @@ MRB_BEGIN_DECL #ifndef MRB_NO_STDIO MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*); -MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*); +MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrb_ccontext*); mrb_irep *mrb_read_irep_file(mrb_state*, FILE*); int mrb_dump_irep_binary(mrb_state*, const mrb_irep*, uint8_t, FILE*); #endif diff --git a/mruby/include/mruby/error.h b/mruby/include/mruby/error.h index 5f7ec43b..ee6fe8ff 100644 --- a/mruby/include/mruby/error.h +++ b/mruby/include/mruby/error.h @@ -37,19 +37,30 @@ MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value st MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...); #if defined(MRB_64BIT) || defined(MRB_USE_FLOAT32) || defined(MRB_NAN_BOXING) || defined(MRB_WORD_BOXING) +#undef MRB_USE_RBREAK_VALUE_UNION +#else +#define MRB_USE_RBREAK_VALUE_UNION 1 +#endif + +/* + * flags: + * 0..7: enum mrb_vtype (only when defined MRB_USE_RBREAK_VALUE_UNION) + * 8..10: RBREAK_TAGs in src/vm.c (otherwise, set to 0) + */ struct RBreak { MRB_OBJECT_HEADER; - const struct RProc *proc; + uintptr_t ci_break_index; // The top-level ci index to break. One before the return destination. +#ifndef MRB_USE_RBREAK_VALUE_UNION mrb_value val; +#else + union mrb_value_union value; +#endif }; + +#ifndef MRB_USE_RBREAK_VALUE_UNION #define mrb_break_value_get(brk) ((brk)->val) #define mrb_break_value_set(brk, v) ((brk)->val = v) #else -struct RBreak { - MRB_OBJECT_HEADER; - const struct RProc *proc; - union mrb_value_union value; -}; #define RBREAK_VALUE_TT_MASK ((1 << 8) - 1) static inline mrb_value mrb_break_value_get(struct RBreak *brk) @@ -66,9 +77,7 @@ mrb_break_value_set(struct RBreak *brk, mrb_value val) brk->flags &= ~RBREAK_VALUE_TT_MASK; brk->flags |= val.tt; } -#endif /* MRB_64BIT || MRB_USE_FLOAT32 || MRB_NAN_BOXING || MRB_WORD_BOXING */ -#define mrb_break_proc_get(brk) ((brk)->proc) -#define mrb_break_proc_set(brk, p) ((brk)->proc = p) +#endif /* MRB_USE_RBREAK_VALUE_UNION */ /** * Error check diff --git a/mruby/include/mruby/irep.h b/mruby/include/mruby/irep.h index ba390a05..68e89257 100644 --- a/mruby/include/mruby/irep.h +++ b/mruby/include/mruby/irep.h @@ -104,13 +104,13 @@ MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*); MRB_API mrb_value mrb_load_irep_buf(mrb_state*, const void*, size_t); /* @param [const uint8_t*] irep code, expected as a literal */ -MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*); +MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrb_ccontext*); /* * @param [const void*] irep code * @param [size_t] size of irep buffer. */ -MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state*, const void*, size_t, mrbc_context*); +MRB_API mrb_value mrb_load_irep_buf_cxt(mrb_state*, const void*, size_t, mrb_ccontext*); struct mrb_insn_data { uint8_t insn; diff --git a/mruby/include/mruby/proc.h b/mruby/include/mruby/proc.h index def00628..d4c3cdcf 100644 --- a/mruby/include/mruby/proc.h +++ b/mruby/include/mruby/proc.h @@ -44,6 +44,7 @@ struct RProc { union { const mrb_irep *irep; mrb_func_t func; + mrb_sym mid; } body; const struct RProc *upper; union { @@ -86,6 +87,8 @@ struct RProc { #define MRB_PROC_SCOPE_P(p) (((p)->flags & MRB_PROC_SCOPE) != 0) #define MRB_PROC_NOARG 4096 /* for MRB_PROC_CFUNC_FL, it would be something like MRB_ARGS_NONE() or MRB_METHOD_NOARG_FL */ #define MRB_PROC_NOARG_P(p) (((p)->flags & MRB_PROC_NOARG) != 0) +#define MRB_PROC_ALIAS 8192 +#define MRB_PROC_ALIAS_P(p) (((p)->flags & MRB_PROC_ALIAS) != 0) #define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v))) @@ -149,25 +152,25 @@ MRB_API mrb_value mrb_load_proc(mrb_state *mrb, const struct RProc *proc); * main(int argc, char **argv) * { * mrb_state *mrb; - * mrbc_context *cxt; + * mrb_ccontext *cxt; * mrb_value blk, ret; * * mrb = mrb_open(); - * cxt = mrbc_context_new(mrb); + * cxt = mrb_ccontext_new(mrb); * blk = mrb_load_string_cxt(mrb, "x, y, z = 1, 2, 3; proc { [x, y, z] }", cxt); * mrb_vm_ci_env_clear(mrb, mrb->c->cibase); * mrb_load_string_cxt(mrb, "x, y, z = 4, 5, 6", cxt); * ret = mrb_funcall(mrb, blk, "call", 0); * mrb_p(mrb, ret); // => [1, 2, 3] * // => [4, 5, 6] if `mrb_vm_ci_env_clear()` is commented out - * mrbc_context_free(mrb, cxt); + * mrb_ccontext_free(mrb, cxt); * mrb_close(mrb); * * return 0; * } * - * The top-level local variable names stored in `mrbc_context` are retained. - * Use also `mrbc_cleanup_local_variables()` at the same time, if necessary. + * The top-level local variable names stored in `mrb_ccontext` are retained. + * Use also `mrb_ccontext_cleanup_local_variables()` at the same time, if necessary. */ MRB_API void mrb_vm_ci_env_clear(mrb_state *mrb, mrb_callinfo *ci); diff --git a/mruby/include/mruby/version.h b/mruby/include/mruby/version.h index 01492e0c..c2fc83d8 100644 --- a/mruby/include/mruby/version.h +++ b/mruby/include/mruby/version.h @@ -117,7 +117,7 @@ MRB_BEGIN_DECL #define MRUBY_BIRTH_YEAR 2010 /* - * MRuby's authors. + * mruby's authors. */ #define MRUBY_AUTHOR "mruby developers" diff --git a/mruby/lib/mruby/build.rb b/mruby/lib/mruby/build.rb index 9dff12cf..c4bb910b 100644 --- a/mruby/lib/mruby/build.rb +++ b/mruby/lib/mruby/build.rb @@ -397,7 +397,7 @@ def define_installer(src) dst = "#{self.class.install_dir}/#{File.basename(src)}" define_installer_outline(src, dst) do File.unlink(dst) rescue nil - File.symlink(File.expand_path(src), dst) + File.symlink(src.relative_path_from(self.class.install_dir), dst) end end end diff --git a/mruby/lib/mruby/build/load_gems.rb b/mruby/lib/mruby/build/load_gems.rb index 34d35ebd..bc7fd901 100644 --- a/mruby/lib/mruby/build/load_gems.rb +++ b/mruby/lib/mruby/build/load_gems.rb @@ -299,7 +299,7 @@ def fromGit!(url, branch) @build.gem_dir_to_repo_url[repo_dir] = url @build.locks[url] = { 'url' => url, - 'branch' => @build.git.current_branch(repo_dir), + 'branch' => branch || @build.git.current_branch(repo_dir), 'commit' => @build.git.commit_hash(repo_dir), } end diff --git a/mruby/mrbgems/full-core.gembox b/mruby/mrbgems/full-core.gembox index e0d008f0..fdee3268 100644 --- a/mruby/mrbgems/full-core.gembox +++ b/mruby/mrbgems/full-core.gembox @@ -1,6 +1,6 @@ MRuby::GemBox.new do |conf| Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x| - g = File.basename File.dirname x + g = File.basename(File.dirname(x)) conf.gem :core => g unless g =~ /^mruby-(?:bin-debugger|test)$/ end end diff --git a/mruby/mrbgems/mruby-array-ext/mrblib/array.rb b/mruby/mrbgems/mruby-array-ext/mrblib/array.rb index d493a065..7a9a0ac0 100644 --- a/mruby/mrbgems/mruby-array-ext/mrblib/array.rb +++ b/mruby/mrbgems/mruby-array-ext/mrblib/array.rb @@ -820,7 +820,7 @@ def combination(n, &block) return to_enum(:combination, n) unless block size = self.size if n == 0 - yield [] + yield [] elsif n == 1 i = 0 while ino_exec = TRUE; c->capture_errors = TRUE; - mrbc_filename(mrb, c, (const char*)dbg->prvfile); + mrb_ccontext_filename(mrb, c, (const char*)dbg->prvfile); c->lineno = dbg->prvline; /* Load program */ mrb_load_nstring_cxt(mrb, expr, len, c); - mrbc_context_free(mrb, c); + mrb_ccontext_free(mrb, c); } mrb_value diff --git a/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c index e0e3a96f..6516c50a 100644 --- a/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +++ b/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c @@ -706,10 +706,10 @@ main(int argc, char **argv) v = mrb_load_irep_file(mrb, args.rfp); } else { /* .rb */ - mrbc_context *cc = mrbc_context_new(mrb); - mrbc_filename(mrb, cc, args.fname); + mrb_ccontext *cc = mrb_ccontext_new(mrb); + mrb_ccontext_filename(mrb, cc, args.fname); v = mrb_load_file_cxt(mrb, args.rfp, cc); - mrbc_context_free(mrb, cc); + mrb_ccontext_free(mrb, cc); } if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) { const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc)); diff --git a/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h b/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h index 24ccad12..1d379f4c 100644 --- a/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h +++ b/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h @@ -74,10 +74,6 @@ typedef enum { MRB_DEBUG_BPTYPE_METHOD, } mrb_debug_bptype; -struct mrb_irep; -struct mrbc_context; -struct mrb_debug_context; - typedef struct mrb_debug_linepoint { const char *file; uint16_t lineno; diff --git a/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index d4cea8d5..5f32539d 100644 --- a/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -422,7 +422,7 @@ ctrl_c_handler(int signo) #endif #ifndef MRB_NO_MIRB_UNDERSCORE -void decl_lv_underscore(mrb_state *mrb, mrbc_context *cxt) +void decl_lv_underscore(mrb_state *mrb, mrb_ccontext *cxt) { struct RProc *proc; struct mrb_parser_state *parser; @@ -453,7 +453,7 @@ main(int argc, char **argv) char *history_path; char* line; #endif - mrbc_context *cxt; + mrb_ccontext *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; @@ -504,7 +504,7 @@ main(int argc, char **argv) print_hint(); - cxt = mrbc_context_new(mrb); + cxt = mrb_ccontext_new(mrb); /* Load libraries */ for (i = 0; i < args.libc; i++) { @@ -517,7 +517,7 @@ main(int argc, char **argv) mrb_load_file_cxt(mrb, lfp, cxt); fclose(lfp); mrb_vm_ci_env_clear(mrb, mrb->c->cibase); - mrbc_cleanup_local_variables(mrb, cxt); + mrb_ccontext_cleanup_local_variables(mrb, cxt); } #ifndef MRB_NO_MIRB_UNDERSCORE @@ -526,7 +526,7 @@ main(int argc, char **argv) cxt->capture_errors = TRUE; cxt->lineno = 1; - mrbc_filename(mrb, cxt, "(mirb)"); + mrb_ccontext_filename(mrb, cxt, "(mirb)"); if (args.verbose) cxt->dump_result = TRUE; ai = mrb_gc_arena_save(mrb); @@ -707,7 +707,7 @@ main(int argc, char **argv) } mrb_free(mrb, args.libv); } - mrbc_context_free(mrb, cxt); + mrb_ccontext_free(mrb, cxt); mrb_close(mrb); return 0; diff --git a/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c index 88cb51ca..8856beab 100644 --- a/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +++ b/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c @@ -198,7 +198,7 @@ cleanup(mrb_state *mrb, struct mrbc_args *args) static int partial_hook(struct mrb_parser_state *p) { - mrbc_context *c = p->cxt; + mrb_ccontext *c = p->cxt; struct mrbc_args *args = (struct mrbc_args*)c->partial_data; const char *fn; @@ -220,13 +220,13 @@ partial_hook(struct mrb_parser_state *p) static mrb_value load_file(mrb_state *mrb, struct mrbc_args *args) { - mrbc_context *c; + mrb_ccontext *c; mrb_value result; char *input = args->argv[args->idx]; FILE *infile; mrb_bool need_close = FALSE; - c = mrbc_context_new(mrb); + c = mrb_ccontext_new(mrb); if (args->verbose) c->dump_result = TRUE; c->no_exec = TRUE; @@ -242,16 +242,16 @@ load_file(mrb_state *mrb, struct mrbc_args *args) return mrb_nil_value(); } } - mrbc_filename(mrb, c, input); + mrb_ccontext_filename(mrb, c, input); args->idx++; if (args->idx < args->argc) { need_close = FALSE; - mrbc_partial_hook(mrb, c, partial_hook, (void*)args); + mrb_ccontext_partial_hook(mrb, c, partial_hook, (void*)args); } result = mrb_load_file_cxt(mrb, infile, c); if (need_close) fclose(infile); - mrbc_context_free(mrb, c); + mrb_ccontext_free(mrb, c); if (mrb_undef_p(result)) { return mrb_nil_value(); } diff --git a/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c index ad8373b9..10522011 100644 --- a/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +++ b/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c @@ -281,7 +281,7 @@ main(int argc, char **argv) int i; struct _args args; mrb_value ARGV; - mrbc_context *c; + mrb_ccontext *c; mrb_value v; if (mrb == NULL) { @@ -307,7 +307,7 @@ main(int argc, char **argv) mrb_define_global_const(mrb, "ARGV", ARGV); mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug)); - c = mrbc_context_new(mrb); + c = mrb_ccontext_new(mrb); if (args.verbose) c->dump_result = TRUE; if (args.check_syntax) @@ -328,11 +328,11 @@ main(int argc, char **argv) FILE *lfp = fopen(args.libv[i], "rb"); if (lfp == NULL) { fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]); - mrbc_context_free(mrb, c); + mrb_ccontext_free(mrb, c); cleanup(mrb, &args); return EXIT_FAILURE; } - mrbc_filename(mrb, c, args.libv[i]); + mrb_ccontext_filename(mrb, c, args.libv[i]); if (mrb_extension_p(args.libv[i])) { v = mrb_load_irep_file_cxt(mrb, lfp, c); } @@ -341,11 +341,11 @@ main(int argc, char **argv) } fclose(lfp); mrb_vm_ci_env_clear(mrb, mrb->c->cibase); - mrbc_cleanup_local_variables(mrb, c); + mrb_ccontext_cleanup_local_variables(mrb, c); } /* set program file name */ - mrbc_filename(mrb, c, cmdline); + mrb_ccontext_filename(mrb, c, cmdline); /* Load program */ if (args.mrbfile || mrb_extension_p(cmdline)) { @@ -362,7 +362,7 @@ main(int argc, char **argv) } mrb_gc_arena_restore(mrb, ai); - mrbc_context_free(mrb, c); + mrb_ccontext_free(mrb, c); if (mrb->exc) { MRB_EXC_CHECK_EXIT(mrb, mrb->exc); if (!mrb_undef_p(v)) { diff --git a/mruby/mrbgems/mruby-catch/src/catch.c b/mruby/mrbgems/mruby-catch/src/catch.c index 44852c6b..d655ada9 100644 --- a/mruby/mrbgems/mruby-catch/src/catch.c +++ b/mruby/mrbgems/mruby-catch/src/catch.c @@ -6,81 +6,56 @@ #include #include -MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms_3, 1, MRB_SYM(call)) -static const mrb_code catch_iseq_3[18] = { - OP_ENTER, 0x00, 0x00, 0x00, // 000 ENTER 0:0:0:0:0:0:0 (0x0) - OP_GETUPVAR, 0x02, 0x02, 0x01, // 004 GETUPVAR R2 2 1 - OP_GETUPVAR, 0x03, 0x01, 0x01, // 008 GETUPVAR R3 1 1 - OP_SEND, 0x02, 0x00, 0x01, // 012 SEND R2 :call n=1 - OP_RETURN, 0x02, // 016 RETURN R2 -}; -static const mrb_irep catch_irep_3 = { - 2,5,0, - MRB_IREP_STATIC,catch_iseq_3, - NULL,catch_syms_3,NULL, - NULL, - NULL, - 18,0,1,0,0 -}; -static const mrb_irep *catch_reps_2[1] = { - &catch_irep_3, -}; -static const mrb_code catch_iseq_2[13] = { - OP_ENTER, 0x00, 0x00, 0x00, // 000 ENTER 0:0:0:0:0:0:0 (0x0) - OP_LAMBDA, 0x02, 0x00, // 004 LAMBDA R2 I[0] - OP_SEND, 0x02, 0x00, 0x00, // 007 SEND R2 :call n=0 - OP_RETURN, 0x02, // 011 RETURN R2 -}; -static const mrb_irep catch_irep_2 = { - 2,4,0, - MRB_IREP_STATIC,catch_iseq_2, - NULL,catch_syms_3,catch_reps_2, - NULL, - NULL, - 13,0,1,1,0 -}; -static const mrb_irep *catch_reps_1[1] = { - &catch_irep_2, -}; -MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms_1, 3, MRB_SYM(Object), MRB_SYM(new), MRB_SYM(call)) -static const mrb_code catch_iseq_1[29] = { +MRB_PRESYM_DEFINE_VAR_AND_INITER(catch_syms, 3, MRB_SYM(Object), MRB_SYM(new), MRB_SYM(call)) +/* + * def catch(r1 = Object.new, &r2) + * r2.call(r1) + * end + */ +static const mrb_code catch_iseq[] = { OP_ENTER, 0x00, 0x20, 0x01, // 000 ENTER 0:1:0:0:0:0:1 (0x2001) - OP_JMP, 0x00, 0x03, // 004 JMP 010 - OP_JMP, 0x00, 0x0a, // 007 JMP 020 - OP_GETCONST, 0x03, 0x00, // 010 GETCONST R3 Object - OP_SEND, 0x03, 0x01, 0x00, // 013 SEND R3 :new n=0 - OP_MOVE, 0x01, 0x03, // 017 MOVE R1 R3 - OP_LAMBDA, 0x03, 0x00, // 020 LAMBDA R3 I[0] - OP_SEND, 0x03, 0x02, 0x00, // 023 SEND R3 :call n=0 - OP_RETURN, 0x03, // 027 RETURN R3 + OP_JMP, 0x00, 0x06, // 004 JMP 013 + + // copy for block parameter "tag" when method argument are given + OP_MOVE, 0x03, 0x01, // 007 MOVE R3 R1 + OP_JMP, 0x00, 0x0a, // 010 JMP 023 + + // create a tag for default parameter + OP_GETCONST, 0x03, 0x00, // 013 GETCONST R3 Object + OP_SEND, 0x03, 0x01, 0x00, // 016 SEND R3 :new n=0 + OP_MOVE, 0x01, 0x03, // 020 MOVE R1 R3 + + // to save on the stack, block variables are used as is + OP_SEND, 0x02, 0x02, 0x01, // 023 SEND R2 :call n=1 + OP_RETURN, 0x02, // 027 RETURN R2 }; static const mrb_irep catch_irep = { 3,5,0, - MRB_IREP_STATIC,catch_iseq_1, - NULL,catch_syms_1,catch_reps_1, + MRB_IREP_STATIC,catch_iseq, + NULL,catch_syms,NULL, NULL, NULL, - 29,0,3,1,0 + sizeof(catch_iseq),0,3,0,0 }; static const struct RProc catch_proc = { NULL, NULL, MRB_TT_PROC, MRB_GC_RED, MRB_FL_OBJ_IS_FROZEN | MRB_PROC_SCOPE | MRB_PROC_STRICT, { &catch_irep }, NULL, { NULL } }; -static const mrb_callinfo * +static uintptr_t find_catcher(mrb_state *mrb, mrb_value tag) { - const mrb_callinfo *ci = mrb->c->ci; - size_t n = ci - mrb->c->cibase; - ci--; + const mrb_callinfo *ci = mrb->c->ci - 1; // skip ownself throw + ptrdiff_t n = ci - mrb->c->cibase; + for (; n > 0; n--, ci--) { const mrb_value *arg1 = ci->stack + 1; if (ci->proc == &catch_proc && mrb_obj_eq(mrb, *arg1, tag)) { - return ci; + return (uintptr_t)n; } } - return NULL; + return 0; } static mrb_value @@ -91,11 +66,11 @@ throw_m(mrb_state *mrb, mrb_value self) obj = mrb_nil_value(); } - const mrb_callinfo *ci = find_catcher(mrb, tag); - if (ci) { + uintptr_t ci_index = find_catcher(mrb, tag); + if (ci_index > 0) { struct RBreak *b = MRB_OBJ_ALLOC(mrb, MRB_TT_BREAK, NULL); mrb_break_value_set(b, obj); - mrb_break_proc_set(b, ci[2].proc); /* Back to the closure in `catch` method */ + b->ci_break_index = ci_index; /* Back to the caller directly */ mrb_exc_raise(mrb, mrb_obj_value(b)); } else { @@ -111,8 +86,7 @@ mrb_mruby_catch_gem_init(mrb_state *mrb) { mrb_method_t m; - MRB_PRESYM_INIT_SYMBOLS(mrb, catch_syms_3); - MRB_PRESYM_INIT_SYMBOLS(mrb, catch_syms_1); + MRB_PRESYM_INIT_SYMBOLS(mrb, catch_syms); MRB_METHOD_FROM_PROC(m, &catch_proc); mrb_define_method_raw(mrb, mrb->kernel_module, MRB_SYM(catch), m); diff --git a/mruby/mrbgems/mruby-compiler/core/parse.y b/mruby/mrbgems/mruby-compiler/core/parse.y index d8760550..4522296c 100644 --- a/mruby/mrbgems/mruby-compiler/core/parse.y +++ b/mruby/mrbgems/mruby-compiler/core/parse.y @@ -6588,7 +6588,7 @@ yylex(void *lval, parser_state *p) } static void -parser_init_cxt(parser_state *p, mrbc_context *cxt) +parser_init_cxt(parser_state *p, mrb_ccontext *cxt) { if (!cxt) return; if (cxt->filename) mrb_parser_set_filename(p, cxt->filename); @@ -6611,7 +6611,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt) } static void -parser_update_cxt(parser_state *p, mrbc_context *cxt) +parser_update_cxt(parser_state *p, mrb_ccontext *cxt) { node *n, *n0; int i = 0; @@ -6634,7 +6634,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt) void mrb_parser_dump(mrb_state *mrb, node *tree, int offset); MRB_API void -mrb_parser_parse(parser_state *p, mrbc_context *c) +mrb_parser_parse(parser_state *p, mrb_ccontext *c) { struct mrb_jmpbuf buf1; struct mrb_jmpbuf *prev = p->mrb->jmp; @@ -6722,14 +6722,14 @@ mrb_parser_free(parser_state *p) { mrb_pool_close(p->pool); } -MRB_API mrbc_context* -mrbc_context_new(mrb_state *mrb) +MRB_API mrb_ccontext* +mrb_ccontext_new(mrb_state *mrb) { - return (mrbc_context*)mrb_calloc(mrb, 1, sizeof(mrbc_context)); + return (mrb_ccontext*)mrb_calloc(mrb, 1, sizeof(mrb_ccontext)); } MRB_API void -mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) +mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt) { mrb_free(mrb, cxt->filename); mrb_free(mrb, cxt->syms); @@ -6737,7 +6737,7 @@ mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) } MRB_API const char* -mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) +mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s) { if (s) { size_t len = strlen(s); @@ -6754,14 +6754,14 @@ mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) } MRB_API void -mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser_state*), void *data) +mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*func)(struct mrb_parser_state*), void *data) { c->partial_hook = func; c->partial_data = data; } MRB_API void -mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c) +mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c) { if (c->syms) { mrb_free(mrb, c->syms); @@ -6813,7 +6813,7 @@ mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) { #ifndef MRB_NO_STDIO static struct mrb_parser_state * -mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t prebufsize, mrbc_context *c) +mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t prebufsize, mrb_ccontext *c) { parser_state *p; @@ -6833,14 +6833,14 @@ mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t preb } MRB_API parser_state* -mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) +mrb_parse_file(mrb_state *mrb, FILE *f, mrb_ccontext *c) { return mrb_parse_file_continue(mrb, f, NULL, 0, c); } #endif MRB_API parser_state* -mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c) +mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrb_ccontext *c) { parser_state *p; @@ -6854,13 +6854,13 @@ mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c) } MRB_API parser_state* -mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) +mrb_parse_string(mrb_state *mrb, const char *s, mrb_ccontext *c) { return mrb_parse_nstring(mrb, s, strlen(s), c); } MRB_API mrb_value -mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) +mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrb_ccontext *c) { struct RClass *target = mrb->object_class; struct RProc *proc; @@ -6923,7 +6923,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) #ifndef MRB_NO_STDIO MRB_API mrb_value -mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) +mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrb_ccontext *c) { return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c); } @@ -6943,7 +6943,7 @@ mrb_load_file(mrb_state *mrb, FILE *f) * - `NUL` is included in the first 64 bytes of the file */ MRB_API mrb_value -mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c) +mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrb_ccontext *c) { union { char b[DETECT_SIZE]; @@ -6986,7 +6986,7 @@ mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c) #endif MRB_API mrb_value -mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *c) +mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrb_ccontext *c) { return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); } @@ -6998,7 +6998,7 @@ mrb_load_nstring(mrb_state *mrb, const char *s, size_t len) } MRB_API mrb_value -mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c) +mrb_load_string_cxt(mrb_state *mrb, const char *s, mrb_ccontext *c) { return mrb_load_nstring_cxt(mrb, s, strlen(s), c); } diff --git a/mruby/mrbgems/mruby-compiler/core/y.tab.c b/mruby/mrbgems/mruby-compiler/core/y.tab.c index 2ab6fbc5..7706d58f 100644 --- a/mruby/mrbgems/mruby-compiler/core/y.tab.c +++ b/mruby/mrbgems/mruby-compiler/core/y.tab.c @@ -13163,7 +13163,7 @@ yylex(void *lval, parser_state *p) } static void -parser_init_cxt(parser_state *p, mrbc_context *cxt) +parser_init_cxt(parser_state *p, mrb_ccontext *cxt) { if (!cxt) return; if (cxt->filename) mrb_parser_set_filename(p, cxt->filename); @@ -13186,7 +13186,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt) } static void -parser_update_cxt(parser_state *p, mrbc_context *cxt) +parser_update_cxt(parser_state *p, mrb_ccontext *cxt) { node *n, *n0; int i = 0; @@ -13209,7 +13209,7 @@ parser_update_cxt(parser_state *p, mrbc_context *cxt) void mrb_parser_dump(mrb_state *mrb, node *tree, int offset); MRB_API void -mrb_parser_parse(parser_state *p, mrbc_context *c) +mrb_parser_parse(parser_state *p, mrb_ccontext *c) { struct mrb_jmpbuf buf1; struct mrb_jmpbuf *prev = p->mrb->jmp; @@ -13297,14 +13297,14 @@ mrb_parser_free(parser_state *p) { mrb_pool_close(p->pool); } -MRB_API mrbc_context* -mrbc_context_new(mrb_state *mrb) +MRB_API mrb_ccontext* +mrb_ccontext_new(mrb_state *mrb) { - return (mrbc_context*)mrb_calloc(mrb, 1, sizeof(mrbc_context)); + return (mrb_ccontext*)mrb_calloc(mrb, 1, sizeof(mrb_ccontext)); } MRB_API void -mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) +mrb_ccontext_free(mrb_state *mrb, mrb_ccontext *cxt) { mrb_free(mrb, cxt->filename); mrb_free(mrb, cxt->syms); @@ -13312,7 +13312,7 @@ mrbc_context_free(mrb_state *mrb, mrbc_context *cxt) } MRB_API const char* -mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) +mrb_ccontext_filename(mrb_state *mrb, mrb_ccontext *c, const char *s) { if (s) { size_t len = strlen(s); @@ -13329,14 +13329,14 @@ mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s) } MRB_API void -mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser_state*), void *data) +mrb_ccontext_partial_hook(mrb_state *mrb, mrb_ccontext *c, int (*func)(struct mrb_parser_state*), void *data) { c->partial_hook = func; c->partial_data = data; } MRB_API void -mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c) +mrb_ccontext_cleanup_local_variables(mrb_state *mrb, mrb_ccontext *c) { if (c->syms) { mrb_free(mrb, c->syms); @@ -13388,7 +13388,7 @@ mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) { #ifndef MRB_NO_STDIO static struct mrb_parser_state * -mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t prebufsize, mrbc_context *c) +mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t prebufsize, mrb_ccontext *c) { parser_state *p; @@ -13408,14 +13408,14 @@ mrb_parse_file_continue(mrb_state *mrb, FILE *f, const void *prebuf, size_t preb } MRB_API parser_state* -mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) +mrb_parse_file(mrb_state *mrb, FILE *f, mrb_ccontext *c) { return mrb_parse_file_continue(mrb, f, NULL, 0, c); } #endif MRB_API parser_state* -mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c) +mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrb_ccontext *c) { parser_state *p; @@ -13429,13 +13429,13 @@ mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c) } MRB_API parser_state* -mrb_parse_string(mrb_state *mrb, const char *s, mrbc_context *c) +mrb_parse_string(mrb_state *mrb, const char *s, mrb_ccontext *c) { return mrb_parse_nstring(mrb, s, strlen(s), c); } MRB_API mrb_value -mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) +mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrb_ccontext *c) { struct RClass *target = mrb->object_class; struct RProc *proc; @@ -13498,7 +13498,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c) #ifndef MRB_NO_STDIO MRB_API mrb_value -mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrbc_context *c) +mrb_load_file_cxt(mrb_state *mrb, FILE *f, mrb_ccontext *c) { return mrb_load_exec(mrb, mrb_parse_file(mrb, f, c), c); } @@ -13518,7 +13518,7 @@ mrb_load_file(mrb_state *mrb, FILE *f) * - `NUL` is included in the first 64 bytes of the file */ MRB_API mrb_value -mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c) +mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrb_ccontext *c) { union { char b[DETECT_SIZE]; @@ -13561,7 +13561,7 @@ mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c) #endif MRB_API mrb_value -mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *c) +mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrb_ccontext *c) { return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c); } @@ -13573,7 +13573,7 @@ mrb_load_nstring(mrb_state *mrb, const char *s, size_t len) } MRB_API mrb_value -mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *c) +mrb_load_string_cxt(mrb_state *mrb, const char *s, mrb_ccontext *c) { return mrb_load_nstring_cxt(mrb, s, strlen(s), c); } diff --git a/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb b/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb index e4f116a9..2b50ff31 100644 --- a/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +++ b/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb @@ -47,9 +47,12 @@ def to_enum(meth=:each, *args, &block) raise ArgumentError, "undefined method #{meth}" end lz = Lazy.new(self, &block) - lz.obj = self - lz.meth = meth - lz.args = args + obj = self + lz.instance_eval { + @obj = obj + @meth = meth + @args = args + } lz end alias enum_for to_enum diff --git a/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb index 4cc18efd..faaabf18 100644 --- a/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -132,16 +132,20 @@ def initialize(obj=NONE, meth=:each, *args, **kwd, &block) @stop_exc = false end - attr_accessor :obj, :meth, :args, :kwd - attr_reader :fib - def initialize_copy(obj) raise TypeError, "can't copy type #{obj.class}" unless obj.kind_of? Enumerator - raise TypeError, "can't copy execution context" if obj.fib - @obj = obj.obj - @meth = obj.meth - @args = obj.args - @kwd = obj.kwd + raise TypeError, "can't copy execution context" if obj.instance_eval{@fib} + meth = args = kwd = fib = nil + obj.instance_eval { + obj = @obj + meth = @meth + args = @args + kwd = @kwd + } + @obj = obj + @meth = meth + @args = args + @kwd = kwd @fib = nil @lookahead = nil @feedvalue = nil @@ -169,7 +173,7 @@ def with_index(offset=0, &block) end n = offset - 1 - enumerator_block_call do |*i| + __enumerator_block_call do |*i| n += 1 block.call i.__svalue, n end @@ -219,7 +223,7 @@ def each_with_index(&block) def with_object(object, &block) return to_enum(:with_object, object) unless block - enumerator_block_call do |i| + __enumerator_block_call do |i| block.call [i,object] end object @@ -234,6 +238,14 @@ def inspect end end + def size + if @size + @size + elsif @obj.respond_to?(:size) + @obj.size + end + end + ## # call-seq: # enum.each { |elm| block } -> obj @@ -274,23 +286,23 @@ def each(*argv, &block) obj = self if 0 < argv.length obj = self.dup - args = obj.args + args = obj.instance_eval{@args} if !args.empty? args = args.dup args.concat argv else args = argv.dup end - obj.args = args + obj.instance_eval{@args = args} end return obj unless block - enumerator_block_call(&block) + __enumerator_block_call(&block) end - def enumerator_block_call(&block) + def __enumerator_block_call(&block) @obj.__send__ @meth, *@args, **@kwd, &block end - private :enumerator_block_call + private :__enumerator_block_call ## # call-seq: diff --git a/mruby/mrbgems/mruby-eval/src/eval.c b/mruby/mrbgems/mruby-eval/src/eval.c index 5b843216..fe164582 100644 --- a/mruby/mrbgems/mruby-eval/src/eval.c +++ b/mruby/mrbgems/mruby-eval/src/eval.c @@ -22,7 +22,7 @@ void mrb_parser_foreach_top_variable(mrb_state *mrb, struct mrb_parser_state *p, static struct RProc* create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line) { - mrbc_context *cxt; + mrb_ccontext *cxt; struct mrb_parser_state *p; struct RProc *proc; const struct RProc *scope; @@ -60,10 +60,10 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi file = "(eval)"; } - cxt = mrbc_context_new(mrb); + cxt = mrb_ccontext_new(mrb); cxt->lineno = (uint16_t)line; - mrbc_filename(mrb, cxt, file); + mrb_ccontext_filename(mrb, cxt, file); cxt->capture_errors = TRUE; cxt->no_optimize = TRUE; cxt->upper = scope && MRB_PROC_CFUNC_P(scope) ? NULL : scope; @@ -72,7 +72,7 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi /* only occur when memory ran out */ if (!p) { - mrbc_context_free(mrb, cxt); + mrb_ccontext_free(mrb, cxt); mrb_raise(mrb, E_RUNTIME_ERROR, "Failed to create parser state (out of memory)"); } @@ -80,7 +80,7 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi /* parse error */ mrb_value str; - mrbc_context_free(mrb, cxt); + mrb_ccontext_free(mrb, cxt); if (!p->error_buffer[0].message) { mrb_parser_free(p); mrb_raise(mrb, E_SYNTAX_ERROR, "compile error"); @@ -104,7 +104,7 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi if (proc == NULL) { /* codegen error */ mrb_parser_free(p); - mrbc_context_free(mrb, cxt); + mrb_ccontext_free(mrb, cxt); mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error"); } if (c->ci > c->cibase) { @@ -134,7 +134,7 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi /* mrb_codedump_all(mrb, proc); */ mrb_parser_free(p); - mrbc_context_free(mrb, cxt); + mrb_ccontext_free(mrb, cxt); return proc; } @@ -207,7 +207,7 @@ expand_lvspace(mrb_state *mrb, mrb_sym sym, void *user) struct binding_eval_prepare_body { mrb_value binding; const char *file; - mrbc_context *mrbc; + mrb_ccontext *cxt; struct mrb_parser_state *pstate; }; @@ -218,7 +218,7 @@ binding_eval_prepare_body(mrb_state *mrb, void *opaque) const struct RProc *proc = mrb_binding_extract_proc(mrb, p->binding); mrb_assert(!MRB_PROC_CFUNC_P(proc)); - p->mrbc->upper = proc; + p->cxt->upper = proc; binding_eval_error_check(mrb, p->pstate, p->file); struct expand_lvspace args = { @@ -240,15 +240,15 @@ binding_eval_prepare(mrb_state *mrb, mrb_value binding, const char *expr, mrb_in { struct binding_eval_prepare_body d = { binding }; - d.mrbc = mrbc_context_new(mrb); - d.file = mrbc_filename(mrb, d.mrbc, file ? file : "(eval)"); - d.mrbc->capture_errors = TRUE; - d.pstate = mrb_parse_nstring(mrb, expr, exprlen, d.mrbc); + d.cxt = mrb_ccontext_new(mrb); + d.file = mrb_ccontext_filename(mrb, d.cxt, file ? file : "(eval)"); + d.cxt->capture_errors = TRUE; + d.pstate = mrb_parse_nstring(mrb, expr, exprlen, d.cxt); mrb_bool error; mrb_value ret = mrb_protect_error(mrb, binding_eval_prepare_body, &d, &error); if (d.pstate) mrb_parser_free(d.pstate); - if (d.mrbc) mrbc_context_free(mrb, d.mrbc); + if (d.cxt) mrb_ccontext_free(mrb, d.cxt); if (error) mrb_exc_raise(mrb, ret); } diff --git a/mruby/mrbgems/mruby-eval/test/binding.rb b/mruby/mrbgems/mruby-eval/test/binding.rb index 1266690e..1a470329 100644 --- a/mruby/mrbgems/mruby-eval/test/binding.rb +++ b/mruby/mrbgems/mruby-eval/test/binding.rb @@ -62,3 +62,20 @@ bx.eval("a = 2") assert_equal 2, block.call end + +assert "Binding#eval on another target class" do + obj = Object.new + Module.new do + self::BINDING = obj.instance_eval { binding } + + def self.eval(code) + self::BINDING.eval code + end + + self.eval "def self.m1; :m1; end" + self.eval "def m2; :m2; end" + end + + assert_equal :m1, obj.m1 + assert_equal :m2, obj.m2 +end diff --git a/mruby/mrbgems/mruby-fiber/src/fiber.c b/mruby/mrbgems/mruby-fiber/src/fiber.c index 05baac96..baddf65c 100644 --- a/mruby/mrbgems/mruby-fiber/src/fiber.c +++ b/mruby/mrbgems/mruby-fiber/src/fiber.c @@ -1,8 +1,12 @@ #include #include #include +#include #include +#include #include +#include +#include #define fiber_ptr(o) ((struct RFiber*)mrb_ptr(o)) @@ -11,6 +15,66 @@ /* copied from vm.c */ #define CINFO_RESUMED 3 +static mrb_value +fiber_init_fiber(mrb_state *mrb, struct RFiber *f, const struct RProc *p) +{ + static const struct mrb_context mrb_context_zero = { 0 }; + struct mrb_context *c; + mrb_callinfo *ci; + size_t slen; + + if (f->cxt) { + mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice"); + } + if (MRB_PROC_CFUNC_P(p)) { + mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method"); + } + + c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); + *c = mrb_context_zero; + f->cxt = c; + + /* initialize VM stack */ + slen = FIBER_STACK_INIT_SIZE; + if (p->body.irep->nregs > slen) { + slen += p->body.irep->nregs; + } + c->stbase = (mrb_value*)mrb_malloc(mrb, slen*sizeof(mrb_value)); + c->stend = c->stbase + slen; + + { + mrb_value *p = c->stbase; + mrb_value *pend = c->stend; + + while (p < pend) { + SET_NIL_VALUE(*p); + p++; + } + } + + /* copy receiver from a block */ + c->stbase[0] = mrb->c->ci->stack[0]; + + /* initialize callinfo stack */ + c->cibase = (mrb_callinfo*)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo)); + c->ciend = c->cibase + FIBER_CI_INIT_SIZE; + c->ci = c->cibase; + + /* adjust return callinfo */ + ci = c->ci; + mrb_vm_ci_target_class_set(ci, MRB_PROC_TARGET_CLASS(p)); + mrb_vm_ci_proc_set(ci, p); + mrb_field_write_barrier(mrb, (struct RBasic*)f, (struct RBasic*)p); + ci->stack = c->stbase; + ci[1] = ci[0]; + c->ci++; /* push dummy callinfo */ + + c->fib = f; + c->status = MRB_FIBER_CREATED; + + return mrb_obj_value(f); +} + /* * call-seq: * Fiber.new{...} -> obj @@ -66,67 +130,9 @@ static mrb_value fiber_init(mrb_state *mrb, mrb_value self) { - static const struct mrb_context mrb_context_zero = { 0 }; - struct RFiber *f = fiber_ptr(self); - struct mrb_context *c; - struct RProc *p; - mrb_callinfo *ci; mrb_value blk; - size_t slen; - mrb_get_args(mrb, "&!", &blk); - - if (f->cxt) { - mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice"); - } - p = mrb_proc_ptr(blk); - if (MRB_PROC_CFUNC_P(p)) { - mrb_raise(mrb, E_FIBER_ERROR, "tried to create Fiber from C defined method"); - } - - c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); - *c = mrb_context_zero; - f->cxt = c; - - /* initialize VM stack */ - slen = FIBER_STACK_INIT_SIZE; - if (p->body.irep->nregs > slen) { - slen += p->body.irep->nregs; - } - c->stbase = (mrb_value*)mrb_malloc(mrb, slen*sizeof(mrb_value)); - c->stend = c->stbase + slen; - - { - mrb_value *p = c->stbase; - mrb_value *pend = c->stend; - - while (p < pend) { - SET_NIL_VALUE(*p); - p++; - } - } - - /* copy receiver from a block */ - c->stbase[0] = mrb->c->ci->stack[0]; - - /* initialize callinfo stack */ - c->cibase = (mrb_callinfo*)mrb_calloc(mrb, FIBER_CI_INIT_SIZE, sizeof(mrb_callinfo)); - c->ciend = c->cibase + FIBER_CI_INIT_SIZE; - c->ci = c->cibase; - - /* adjust return callinfo */ - ci = c->ci; - mrb_vm_ci_target_class_set(ci, MRB_PROC_TARGET_CLASS(p)); - mrb_vm_ci_proc_set(ci, p); - mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p); - ci->stack = c->stbase; - ci[1] = ci[0]; - c->ci++; /* push dummy callinfo */ - - c->fib = f; - c->status = MRB_FIBER_CREATED; - - return self; + return fiber_init_fiber(mrb, fiber_ptr(self), mrb_proc_ptr(blk)); } static struct mrb_context* @@ -164,6 +170,17 @@ fiber_check_cfunc(mrb_state *mrb, struct mrb_context *c) } } +static void +fiber_check_cfunc_recursive(mrb_state *mrb, struct mrb_context *c) +{ + for (;; c = c->prev) { + fiber_check_cfunc(mrb, c); + if (c == mrb->root_c || !c->prev) { + break; + } + } +} + static void fiber_switch_context(mrb_state *mrb, struct mrb_context *c) { @@ -269,14 +286,17 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr else { value = fiber_result(mrb, a, len); if (vmexec) { + if (c->ci > c->cibase) c->ci--; /* pop dummy callinfo */ c->ci[1].stack[0] = value; } } if (vmexec) { + int cci = old_c->ci->cci; c->vmexec = TRUE; value = mrb_vm_exec(mrb, c->ci->proc, c->ci->pc); mrb->c = old_c; + old_c->ci->cci = cci; /* restore values as they may have changed in Fiber.yield */ } else { MARK_CONTEXT_MODIFY(c); @@ -298,18 +318,19 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr * to the next Fiber.yield statement inside the fiber's block * or to the block value if it runs to completion without any * Fiber.yield - * - * This method cannot be called from C using mrb_funcall(). - * Use mrb_fiber_resume() function instead. */ static mrb_value fiber_resume(mrb_state *mrb, mrb_value self) { const mrb_value *a; mrb_int len; + mrb_bool vmexec = FALSE; mrb_get_args(mrb, "*!", &a, &len); - return fiber_switch(mrb, self, len, a, TRUE, FALSE); + if (mrb->c->ci->cci > 0) { + vmexec = TRUE; + } + return fiber_switch(mrb, self, len, a, TRUE, vmexec); } MRB_API mrb_value @@ -344,6 +365,62 @@ fiber_eq(mrb_state *mrb, mrb_value self) return mrb_bool_value(fiber_ptr(self) == fiber_ptr(other)); } +/* + * call-seq: + * fiber.to_s -> string + * fiber.inspect -> string + * + * Returns fiber object information as a string. + * + * If the file information cannot be obtained, it is replaced with `(unknown):0`. + * Also, if the fiber is terminated, it will be replaced in the same way (mruby limitation). + */ +static mrb_value +fiber_to_s(mrb_state *mrb, mrb_value self) +{ + fiber_check(mrb, self); + const struct RFiber *f = fiber_ptr(self); + + mrb_value s = mrb_str_new_lit(mrb, "#<"); + mrb_value cname = mrb_class_path(mrb, mrb_class_real(mrb_class(mrb, self))); + if (mrb_nil_p(cname)) { + mrb_str_cat_lit(mrb, s, "Fiber:"); + } + else { + mrb_str_cat_str(mrb, s, cname); + mrb_str_cat_lit(mrb, s, ":"); + } + mrb_str_cat_str(mrb, s, mrb_ptr_to_str(mrb, mrb_ptr(self))); + + const char *file; + int32_t line; + const struct RProc *p = f->cxt->cibase->proc; + if (f->cxt->status != MRB_FIBER_TERMINATED && !MRB_PROC_CFUNC_P(p) && !MRB_PROC_ALIAS_P(p) && + mrb_debug_get_position(mrb, p->body.irep, 0, &line, &file)) { + mrb_str_cat_lit(mrb, s, " "); + mrb_str_cat_cstr(mrb, s, file); + mrb_str_cat_lit(mrb, s, ":"); + char buf[16]; + mrb_str_cat_cstr(mrb, s, mrb_int_to_cstr(buf, sizeof(buf), line, 10)); + } + + const char *st; + switch (fiber_ptr(self)->cxt->status) { + case MRB_FIBER_CREATED: st = "created"; break; + case MRB_FIBER_RUNNING: st = "resumed"; break; + case MRB_FIBER_RESUMED: st = "suspended by resuming"; break; + case MRB_FIBER_SUSPENDED: st = "suspended"; break; + case MRB_FIBER_TRANSFERRED: st = "suspended"; break; + case MRB_FIBER_TERMINATED: st = "terminated"; break; + default: st = "UNKNOWN STATUS (BUG)"; break; + } + mrb_str_cat_lit(mrb, s, " ("); + mrb_str_cat_cstr(mrb, s, st); + mrb_str_cat_lit(mrb, s, ")>"); + + return s; +} + /* * call-seq: * fiber.transfer(args, ...) -> obj @@ -363,7 +440,7 @@ fiber_transfer(mrb_state *mrb, mrb_value self) const mrb_value* a; mrb_int len; - fiber_check_cfunc(mrb, mrb->c); + fiber_check_cfunc_recursive(mrb, mrb->c); mrb_get_args(mrb, "*!", &a, &len); if (c->status == MRB_FIBER_RESUMED) { @@ -406,7 +483,6 @@ mrb_fiber_yield(mrb_state *mrb, mrb_int len, const mrb_value *a) if (c->vmexec) { c->vmexec = FALSE; mrb->c->ci->cci = CINFO_RESUMED; - c->ci--; /* pop callinfo for yield */ } MARK_CONTEXT_MODIFY(mrb->c); return fiber_result(mrb, a, len); @@ -456,6 +532,18 @@ fiber_current(mrb_state *mrb, mrb_value self) return mrb_obj_value(mrb->c->fib); } +MRB_API mrb_value +mrb_fiber_new(mrb_state *mrb, const struct RProc *p) +{ + struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Fiber)); + if (MRB_INSTANCE_TT(c) != MRB_TT_FIBER) { + mrb_raise(mrb, E_TYPE_ERROR, "wrong Fiber class"); + } + + struct RFiber *f = MRB_OBJ_ALLOC(mrb, MRB_TT_FIBER, c); + return fiber_init_fiber(mrb, f, p); +} + void mrb_mruby_fiber_gem_init(mrb_state* mrb) { @@ -469,6 +557,8 @@ mrb_mruby_fiber_gem_init(mrb_state* mrb) mrb_define_method(mrb, c, "transfer", fiber_transfer, MRB_ARGS_ANY()); mrb_define_method(mrb, c, "alive?", fiber_alive_p, MRB_ARGS_NONE()); mrb_define_method(mrb, c, "==", fiber_eq, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, c, "to_s", fiber_to_s, MRB_ARGS_NONE()); + mrb_define_alias(mrb, c, "inspect", "to_s"); mrb_define_class_method(mrb, c, "yield", fiber_yield, MRB_ARGS_ANY()); mrb_define_class_method(mrb, c, "current", fiber_current, MRB_ARGS_NONE()); diff --git a/mruby/mrbgems/mruby-fiber/test/fiber.rb b/mruby/mrbgems/mruby-fiber/test/fiber.rb index 64b9d817..ea541acf 100644 --- a/mruby/mrbgems/mruby-fiber/test/fiber.rb +++ b/mruby/mrbgems/mruby-fiber/test/fiber.rb @@ -1,204 +1,210 @@ -assert('Fiber.new') do - f = Fiber.new{} - assert_kind_of Fiber, f -end +begin + $fiber_test_activity = __FILE__ -assert('Fiber#resume') do - f = Fiber.new{|x| x } - assert_equal 2, f.resume(2) -end + assert('Fiber.new') do + f = Fiber.new{} + assert_kind_of Fiber, f + end -assert('Fiber#transfer') do - ary = [] - f2 = nil - f1 = Fiber.new{ - ary << f2.transfer(:foo) - :ok - } - f2 = Fiber.new{ - ary << f1.transfer(:baz) - :ng - } - assert_equal(:ok, f1.transfer) - assert_equal([:baz], ary) - assert_false f1.alive? -end + assert('Fiber#resume') do + f = Fiber.new{|x| x } + assert_equal 2, f.resume(2) + end -assert('Fiber#alive?') do - f = Fiber.new{ Fiber.yield } - f.resume - assert_true f.alive? - f.resume - assert_false f.alive? -end + assert('Fiber#transfer') do + ary = [] + f2 = nil + f1 = Fiber.new{ + ary << f2.transfer(:foo) + :ok + } + f2 = Fiber.new{ + ary << f1.transfer(:baz) + :ng + } + assert_equal(:ok, f1.transfer) + assert_equal([:baz], ary) + assert_false f1.alive? + end -assert('Fiber#==') do - root = Fiber.current - assert_equal root, root - assert_equal root, Fiber.current - assert_false root != Fiber.current - f = Fiber.new { - assert_false root == Fiber.current - } - f.resume - assert_false f == root - assert_true f != root -end + assert('Fiber#alive?') do + f = Fiber.new{ Fiber.yield } + f.resume + assert_true f.alive? + f.resume + assert_false f.alive? + end -assert('Fiber.yield') do - f = Fiber.new{|x| Fiber.yield x } - assert_equal 3, f.resume(3) - assert_true f.alive? -end + assert('Fiber#==') do + root = Fiber.current + assert_equal root, root + assert_equal root, Fiber.current + assert_false root != Fiber.current + f = Fiber.new { + assert_false root == Fiber.current + } + f.resume + assert_false f == root + assert_true f != root + end -assert('FiberError') do - assert_equal StandardError, FiberError.superclass -end + assert('Fiber.yield') do + f = Fiber.new{|x| Fiber.yield x } + assert_equal 3, f.resume(3) + assert_true f.alive? + end -assert('Fiber iteration') do - f1 = Fiber.new{ - [1,2,3].each{|x| Fiber.yield(x)} - } - f2 = Fiber.new{ - [9,8,7].each{|x| Fiber.yield(x)} - } - a = [] - 3.times { - a << f1.resume - a << f2.resume - } - assert_equal [1,9,2,8,3,7], a -end + assert('FiberError') do + assert_equal StandardError, FiberError.superclass + end -assert('Fiber with splat in the block argument list') { - assert_equal([1], Fiber.new{|*x|x}.resume(1)) -} + assert('Fiber iteration') do + f1 = Fiber.new{ + [1,2,3].each{|x| Fiber.yield(x)} + } + f2 = Fiber.new{ + [9,8,7].each{|x| Fiber.yield(x)} + } + a = [] + 3.times { + a << f1.resume + a << f2.resume + } + assert_equal [1,9,2,8,3,7], a + end -assert('Fiber raises on resume when dead') do - assert_raise(FiberError) do - f = Fiber.new{} - f.resume - assert_false f.alive? - f.resume + assert('Fiber with splat in the block argument list') { + assert_equal([1], Fiber.new{|*x|x}.resume(1)) + } + + assert('Fiber raises on resume when dead') do + assert_raise(FiberError) do + f = Fiber.new{} + f.resume + assert_false f.alive? + f.resume + end end -end -assert('Yield raises when called on root fiber') do - assert_raise(FiberError) { Fiber.yield } -end + assert('Yield raises when called on root fiber') do + assert_raise(FiberError) { Fiber.yield } + end -assert('Double resume of Fiber') do - f1 = Fiber.new {} - f2 = Fiber.new { - f1.resume - assert_raise(FiberError) { f2.resume } - Fiber.yield 0 - } - assert_equal 0, f2.resume - f2.resume - assert_false f1.alive? - assert_false f2.alive? -end + assert('Double resume of Fiber') do + f1 = Fiber.new {} + f2 = Fiber.new { + f1.resume + assert_raise(FiberError) { f2.resume } + Fiber.yield 0 + } + assert_equal 0, f2.resume + f2.resume + assert_false f1.alive? + assert_false f2.alive? + end -assert('Recursive resume of Fiber') do - f1, f2 = nil, nil - f1 = Fiber.new { assert_raise(FiberError) { f2.resume } } - f2 = Fiber.new { - f1.resume - Fiber.yield 0 - } - f3 = Fiber.new { + assert('Recursive resume of Fiber') do + f1, f2 = nil, nil + f1 = Fiber.new { assert_raise(FiberError) { f2.resume } } + f2 = Fiber.new { + f1.resume + Fiber.yield 0 + } + f3 = Fiber.new { + f2.resume + } + assert_equal 0, f3.resume f2.resume - } - assert_equal 0, f3.resume - f2.resume - assert_false f1.alive? - assert_false f2.alive? - assert_false f3.alive? -end + assert_false f1.alive? + assert_false f2.alive? + assert_false f3.alive? + end -assert('Root fiber resume') do - root = Fiber.current - assert_raise(FiberError) { root.resume } - f = Fiber.new { + assert('Root fiber resume') do + root = Fiber.current assert_raise(FiberError) { root.resume } - } - f.resume - assert_false f.alive? -end - -assert('Fiber without block') do - assert_raise(ArgumentError) { Fiber.new } -end + f = Fiber.new { + assert_raise(FiberError) { root.resume } + } + f.resume + assert_false f.alive? + end + assert('Fiber without block') do + assert_raise(ArgumentError) { Fiber.new } + end -assert('Transfer to self.') do - result = [] - f = Fiber.new { result << :start; f.transfer; result << :end } - f.transfer - assert_equal [:start, :end], result - result = [] - f = Fiber.new { result << :start; f.transfer; result << :end } - f.resume - assert_equal [:start, :end], result -end + assert('Transfer to self.') do + result = [] + f = Fiber.new { result << :start; f.transfer; result << :end } + f.transfer + assert_equal [:start, :end], result -assert('Resume transferred fiber') do - f = Fiber.new { - assert_raise(FiberError) { f.resume } - } - f.transfer -end + result = [] + f = Fiber.new { result << :start; f.transfer; result << :end } + f.resume + assert_equal [:start, :end], result + end -assert('Root fiber transfer.') do - result = nil - root = Fiber.current - f = Fiber.new { - result = :ok - root.transfer - } - f.transfer - assert_true f.alive? - assert_equal :ok, result -end + assert('Resume transferred fiber') do + f = Fiber.new { + assert_raise(FiberError) { f.resume } + } + f.transfer + end -assert('Break nested fiber with root fiber transfer') do - root = Fiber.current + assert('Root fiber transfer.') do + result = nil + root = Fiber.current + f = Fiber.new { + result = :ok + root.transfer + } + f.transfer + assert_true f.alive? + assert_equal :ok, result + end - result = nil - f2 = nil - f1 = Fiber.new { - root.transfer(f2.transfer) - result = :f1 - } - f2 = Fiber.new { - result = :to_root - root.transfer :from_f2 - result = :f2 - } - assert_equal :from_f2, f1.transfer - assert_equal :to_root, result - assert_equal :f2, f2.transfer - assert_equal :f2, result - assert_false f2.alive? - assert_equal nil, f1.transfer - assert_equal :f1, f1.transfer - assert_equal :f1, result - assert_false f1.alive? -end + assert('Break nested fiber with root fiber transfer') do + root = Fiber.current + + result = nil + f2 = nil + f1 = Fiber.new { + root.transfer(f2.transfer) + result = :f1 + } + f2 = Fiber.new { + result = :to_root + root.transfer :from_f2 + result = :f2 + } + assert_equal :from_f2, f1.transfer + assert_equal :to_root, result + assert_equal :f2, f2.transfer + assert_equal :f2, result + assert_false f2.alive? + assert_equal nil, f1.transfer + assert_equal :f1, f1.transfer + assert_equal :f1, result + assert_false f1.alive? + end -assert('CRuby Fiber#transfer test.') do - ary = [] - f2 = nil - f1 = Fiber.new{ - ary << f2.transfer(:foo) - :ok - } - f2 = Fiber.new{ - ary << f1.transfer(:baz) - :ng - } - assert_equal :ok, f1.transfer - assert_equal [:baz], ary + assert('CRuby Fiber#transfer test.') do + ary = [] + f2 = nil + f1 = Fiber.new{ + ary << f2.transfer(:foo) + :ok + } + f2 = Fiber.new{ + ary << f1.transfer(:baz) + :ng + } + assert_equal :ok, f1.transfer + assert_equal [:baz], ary + end +ensure + $fiber_test_activity = nil end diff --git a/mruby/mrbgems/mruby-fiber/test/fiber2.rb b/mruby/mrbgems/mruby-fiber/test/fiber2.rb new file mode 100644 index 00000000..a6ff8a79 --- /dev/null +++ b/mruby/mrbgems/mruby-fiber/test/fiber2.rb @@ -0,0 +1,155 @@ +# This file tests fiber switching crossing C functions + +unless RUBY_ENGINE == "mruby" + class Fiber + alias resume_by_c_func resume + alias resume_by_c_method resume + + class << self + alias yield_by_c_func yield + + def yield_by_c_method(*args) + raise FiberError, "ycan't cross C function boundary" + end + end + end + + def Proc.c_tunnel + yield + end +end + +begin + $fiber_test_activity = __FILE__ + + assert('Call Fiber#resume nested with C') do + assert_equal "ok1", Fiber.new { Fiber.new { "ok1" }.resume_by_c_func }.resume_by_c_func + assert_equal "ok2", Fiber.new { Fiber.new { "ok2" }.resume_by_c_method }.resume_by_c_func + assert_equal "ok3", Fiber.new { Fiber.new { "ok3" }.resume_by_c_func }.resume_by_c_method + assert_equal "ok4", Fiber.new { Fiber.new { "ok4" }.resume_by_c_method }.resume_by_c_method + assert_equal "ok5", Fiber.new { Proc.c_tunnel { Fiber.new { "ok5" }.resume_by_c_func } }.resume_by_c_func + assert_equal "ok6", Fiber.new { Proc.c_tunnel { Fiber.new { "ok6" }.resume_by_c_method } }.resume_by_c_func + assert_equal "ok7", Fiber.new { Proc.c_tunnel { Fiber.new { "ok7" }.resume_by_c_func } }.resume_by_c_method + assert_equal "ok8", Fiber.new { Proc.c_tunnel { Fiber.new { "ok8" }.resume_by_c_method } }.resume_by_c_method + assert_equal "ok9", Fiber.new { Proc.c_tunnel { Fiber.new { "ok9" }.resume } }.resume_by_c_func + assert_equal "ok10", Fiber.new { Proc.c_tunnel { Fiber.new { "ok10" }.resume } }.resume_by_c_method + end + + assert('Call Fiber#resume and Fiber.yield mixed with C.') do + assert_equal 1, Fiber.new { Fiber.yield 1 }.resume_by_c_func + assert_equal 2, Fiber.new { Fiber.yield 2 }.resume_by_c_method + assert_equal 3, Fiber.new { Fiber.yield_by_c_func 3 }.resume + assert_equal 4, Fiber.new { Fiber.yield_by_c_func 4 }.resume_by_c_func + assert_equal 5, Fiber.new { Fiber.yield_by_c_func 5 }.resume_by_c_method + assert_raise(FiberError) { Fiber.new { Fiber.yield_by_c_method "bad" }.resume } + assert_raise(FiberError) { Fiber.new { Fiber.yield_by_c_method "bad" }.resume_by_c_func } + assert_raise(FiberError) { Fiber.new { Fiber.yield_by_c_method "bad" }.resume_by_c_method } + + result = [] + f1 = Fiber.new { result << Fiber.new { Fiber.yield 1; "bad" }.resume_by_c_func; 2 } + f2 = Fiber.new { result << f1.resume; 3 } + result << f2.resume + assert_equal [1, 2, 3], result + + f1 = Fiber.new { + -> { + Fiber.yield 1 + Fiber.yield_by_c_func 2 + f2 = Fiber.new { + -> { + Fiber.yield_by_c_func 3 + Fiber.yield 4 + Fiber.yield_by_c_func 5 + Fiber.yield 6 + }.call + 7 + } + Fiber.yield f2.resume_by_c_func + Fiber.yield f2.resume + Fiber.yield f2.resume_by_c_method + Fiber.yield f2.resume + Fiber.yield f2.resume_by_c_func + Fiber.yield 8 + }.call + Fiber.yield 9 + 10 + } + result = [] + 10.times { result << f1.resume } + assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], result + end + + assert('Call Fiber#resume and Fiber.yield mixed with C and raising exceptions') do + f = Fiber.new do + raise ZeroDivisionError + rescue + Fiber.yield "rescue" + "pass1" + ensure + Fiber.yield "ensure" + end + assert_equal "rescue", f.resume_by_c_method + assert_equal "ensure", f.resume_by_c_method + assert_equal "pass1", f.resume_by_c_method + assert_raise(FiberError) { f.resume_by_c_method } + + f = Fiber.new do + raise ZeroDivisionError + rescue + Fiber.yield "rescue" + "pass2" + ensure + Fiber.yield "ensure" + end + assert_equal "rescue", f.resume_by_c_func + assert_equal "ensure", f.resume_by_c_func + assert_equal "pass2", f.resume_by_c_func + assert_raise(FiberError) { f.resume_by_c_func } + + f2 = Fiber.new do + -> do + Fiber.yield 1 + raise "3" + ensure + Fiber.yield 2 + end.call + "NOT REACH 1" + end + f1 = Fiber.new do + Fiber.yield f2.resume_by_c_func + begin + Fiber.yield f2.resume + Fiber.yield f2.resume_by_c_method + Fiber.yield "NOT REACH 2" + rescue => e + Fiber.yield e.message + Fiber.yield 4 + ensure + Fiber.yield 5 + end + Fiber.yield 6 + 7 + end + result = [] + 7.times { result << f1.resume } + assert_equal [1, 2, "3", 4, 5, 6, 7], result + end + + assert('Call Fiber#transfer with C') do + assert_equal "ok1", Fiber.new { Fiber.new { "ok1" }.resume_by_c_method }.transfer + assert_equal "ok2", Fiber.new { Fiber.new { "ok2" }.resume_by_c_func }.transfer + assert_raise(FiberError) { Proc.c_tunnel { Fiber.new { "BAD!" }.transfer } } + + b = Fiber.current + a = Fiber.new { + Proc.c_tunnel { + Fiber.new { + b.transfer + }.resume + } + } + assert_raise(FiberError) { a.transfer } + end +ensure + $fiber_test_activity = nil +end diff --git a/mruby/mrbgems/mruby-fiber/test/fibertest.c b/mruby/mrbgems/mruby-fiber/test/fibertest.c new file mode 100644 index 00000000..69680aec --- /dev/null +++ b/mruby/mrbgems/mruby-fiber/test/fibertest.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include + +static mrb_value +fiber_s_yield_by_c_func(mrb_state *mrb, mrb_value self) +{ + mrb_value a = mrb_get_arg1(mrb); + return mrb_fiber_yield(mrb, 1, &a); +} + +static mrb_value +fiber_s_yield_by_c_method(mrb_state *mrb, mrb_value self) +{ + mrb_value a = mrb_get_arg1(mrb); + return mrb_funcall_argv(mrb, self, mrb_intern_lit(mrb, "yield"), 1, &a); +} + +static mrb_value +fiber_resume_by_c_func(mrb_state *mrb, mrb_value self) +{ + int ci_index = mrb->c->ci - mrb->c->cibase; + mrb_value ret = mrb_fiber_resume(mrb, self, 0, NULL); + if (ci_index != mrb->c->ci - mrb->c->cibase) { + mrb_raisef(mrb, E_EXCEPTION, + "[BUG] INVALID CI POSITION (expected %d, but actual %d) [BUG]", + (int)ci_index, (int)(mrb->c->ci - mrb->c->cibase)); + } + return ret; +} + +static mrb_value +fiber_resume_by_c_method(mrb_state *mrb, mrb_value self) +{ + int ci_index = mrb->c->ci - mrb->c->cibase; + mrb_value ret = mrb_funcall_argv(mrb, self, mrb_intern_lit(mrb, "resume"), 0, NULL); + if (ci_index != mrb->c->ci - mrb->c->cibase) { + mrb_raisef(mrb, E_EXCEPTION, + "[BUG] INVALID CI POSITION (expected %d, but actual %d) [BUG]", + (int)ci_index, (int)(mrb->c->ci - mrb->c->cibase)); + } + return ret; +} + +static mrb_value +fiber_transfer_by_c(mrb_state *mrb, mrb_value self) +{ + return mrb_funcall_argv(mrb, self, mrb_intern_lit(mrb, "transfer"), 0, NULL); +} + +static mrb_value +proc_s_c_tunnel(mrb_state *mrb, mrb_value self) +{ + mrb_value b; + mrb_get_args(mrb, "&!", &b); + return mrb_yield_argv(mrb, b, 0, NULL); +} + +static void +check_activity(mrb_state *mrb) +{ + mrb_value act = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$fiber_test_activity")); + if (mrb_test(act)) { + act = mrb_obj_as_string(mrb, act); + fprintf(stderr, "\n\t<<<%s%.*s>>>\n", + "mruby VM has an unexpected outage in ", (int)RSTRING_LEN(act), RSTRING_PTR(act)); + abort(); + } +} + +void +mrb_mruby_fiber_gem_test(mrb_state *mrb) +{ + struct RClass *fiber_class = mrb_class_get(mrb, "Fiber"); + mrb_define_class_method(mrb, fiber_class, "yield_by_c_func", fiber_s_yield_by_c_func, MRB_ARGS_ANY()); + mrb_define_class_method(mrb, fiber_class, "yield_by_c_method", fiber_s_yield_by_c_method, MRB_ARGS_ANY()); + mrb_define_method(mrb, fiber_class, "resume_by_c_func", fiber_resume_by_c_func, MRB_ARGS_NONE()); + mrb_define_method(mrb, fiber_class, "resume_by_c_method", fiber_resume_by_c_method, MRB_ARGS_NONE()); + mrb_define_method(mrb, fiber_class, "transfer_by_c", fiber_transfer_by_c, MRB_ARGS_NONE()); + + mrb_define_class_method(mrb, mrb->proc_class, "c_tunnel", proc_s_c_tunnel, MRB_ARGS_NONE() | MRB_ARGS_BLOCK()); + + mrb_gv_set(mrb, mrb_intern_lit(mrb, "$fiber_test_activity"), mrb_nil_value()); + mrb_state_atexit(mrb, check_activity); +} diff --git a/mruby/mrbgems/mruby-io/src/io.c b/mruby/mrbgems/mruby-io/src/io.c index 560acde6..f796cf66 100644 --- a/mruby/mrbgems/mruby-io/src/io.c +++ b/mruby/mrbgems/mruby-io/src/io.c @@ -139,8 +139,7 @@ io_modestr_to_flags(mrb_state *mrb, const char *mode) flags = O_WRONLY | O_CREAT | O_APPEND; break; default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode); - flags = 0; /* not reached */ + goto modeerr; } while (*m) { @@ -150,17 +149,25 @@ io_modestr_to_flags(mrb_state *mrb, const char *mode) flags |= O_BINARY; #endif break; + case 'x': + if (mode[0] != 'w') goto modeerr; + flags |= O_EXCL; + break; case '+': flags = (flags & ~OPEN_ACCESS_MODE_FLAGS) | O_RDWR; break; case ':': /* XXX: PASSTHROUGH*/ default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode); + goto modeerr; } } return flags; + + modeerr: + mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode); + return 0; /* not reached */ } static int @@ -1037,13 +1044,13 @@ io_seek(mrb_state *mrb, mrb_value io) static mrb_value io_write_common(mrb_state *mrb, fssize_t (*writefunc)(int, const void*, fsize_t, off_t), - struct mrb_io *fptr, const void *buf, fsize_t blen, off_t offset) + struct mrb_io *fptr, const void *buf, mrb_ssize blen, off_t offset) { int fd; fssize_t length; fd = io_get_write_fd(fptr); - length = writefunc(fd, buf, blen, offset); + length = writefunc(fd, buf, (fsize_t)blen, offset); if (length == -1) { mrb_sys_fail(mrb, "syswrite"); } @@ -1571,6 +1578,9 @@ io_ungetc(mrb_state *mrb, mrb_value io) mrb_get_args(mrb, "S", &str); len = RSTRING_LEN(str); + if (len > SHRT_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "string too long to ungetc"); + } if (len > MRB_IO_BUF_SIZE - buf->len) { fptr->buf = (struct mrb_io_buf*)mrb_realloc(mrb, buf, sizeof(struct mrb_io_buf)+buf->len+len-MRB_IO_BUF_SIZE); buf = fptr->buf; @@ -1578,7 +1588,7 @@ io_ungetc(mrb_state *mrb, mrb_value io) memmove(buf->mem+len, buf->mem+buf->start, buf->len); memcpy(buf->mem, RSTRING_PTR(str), len); buf->start = 0; - buf->len += len; + buf->len += (short)len; return mrb_nil_value(); } @@ -1596,8 +1606,9 @@ io_buf_shift(struct mrb_io *fptr, mrb_int n) { struct mrb_io_buf *buf = fptr->buf; - buf->start += n; - buf->len -= n; + mrb_assert(n <= SHRT_MAX); + buf->start += (short)n; + buf->len -= (short)n; } #ifdef MRB_UTF8_STRING diff --git a/mruby/mrbgems/mruby-io/test/file.rb b/mruby/mrbgems/mruby-io/test/file.rb index 419b40e2..5746986a 100644 --- a/mruby/mrbgems/mruby-io/test/file.rb +++ b/mruby/mrbgems/mruby-io/test/file.rb @@ -260,4 +260,30 @@ end end +assert('File.open with "x" mode') do + File.unlink $mrbtest_io_wfname rescue nil + assert_nothing_raised do + File.open($mrbtest_io_wfname, "wx") {} + end + assert_raise(RuntimeError) do + File.open($mrbtest_io_wfname, "wx") {} + end + + File.unlink $mrbtest_io_wfname rescue nil + assert_nothing_raised do + File.open($mrbtest_io_wfname, "w+x") {} + end + assert_raise(RuntimeError) do + File.open($mrbtest_io_wfname, "w+x") {} + end + + assert_raise(ArgumentError) do + File.open($mrbtest_io_wfname, "rx") {} + end + + assert_raise(ArgumentError) do + File.open($mrbtest_io_wfname, "ax") {} + end +end + MRubyIOTestUtil.io_test_cleanup diff --git a/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb b/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb index e5876f97..0bec08f7 100644 --- a/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb +++ b/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb @@ -50,17 +50,19 @@ def m1; __method__ end assert_equal(:m2, c.new.m4) end +# CRuby __callee__ always gives the calling method name +# mruby __callee__ gives the original method name for aliases assert('Kernel#__callee__') do c = Class.new do def m1; __callee__ end define_method(:m2) {__callee__} - alias m3 m1 - alias_method :m4, :m2 +# alias m3 m1 +# alias_method :m4, :m2 end assert_equal(:m1, c.new.m1) assert_equal(:m2, c.new.m2) - assert_equal(:m3, c.new.m3) - assert_equal(:m4, c.new.m4) +# assert_equal(:m3, c.new.m3) +# assert_equal(:m4, c.new.m4) end assert('Kernel#Integer') do diff --git a/mruby/mrbgems/mruby-method/src/method.c b/mruby/mrbgems/mruby-method/src/method.c index 78fc6326..deb37b4a 100644 --- a/mruby/mrbgems/mruby-method/src/method.c +++ b/mruby/mrbgems/mruby-method/src/method.c @@ -9,7 +9,7 @@ // Defined by mruby-proc-ext on which mruby-method depends mrb_value mrb_proc_parameters(mrb_state *mrb, mrb_value proc); -mrb_value mrb_proc_source_location(mrb_state *mrb, struct RProc *p); +mrb_value mrb_proc_source_location(mrb_state *mrb, const struct RProc *p); static mrb_value args_shift(mrb_state *mrb) @@ -267,13 +267,12 @@ method_bcall(mrb_state *mrb, mrb_value self) static mrb_value method_unbind(mrb_state *mrb, mrb_value self) { - struct RObject *ume; mrb_value owner = mrb_iv_get(mrb, self, MRB_SYM(_owner)); mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name)); mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc)); mrb_value klass = mrb_iv_get(mrb, self, MRB_SYM(_klass)); - ume = method_object_alloc(mrb, mrb_class_get_id(mrb, MRB_SYM(UnboundMethod))); + struct RObject *ume = method_object_alloc(mrb, mrb_class_get_id(mrb, MRB_SYM(UnboundMethod))); mrb_obj_iv_set(mrb, ume, MRB_SYM(_owner), owner); mrb_obj_iv_set(mrb, ume, MRB_SYM(_recv), mrb_nil_value()); mrb_obj_iv_set(mrb, ume, MRB_SYM(_name), name); @@ -307,8 +306,6 @@ method_super_method(mrb_state *mrb, mrb_value self) mrb_value owner = mrb_iv_get(mrb, self, MRB_SYM(_owner)); mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name)); struct RClass *super, *rklass; - struct RProc *proc; - struct RObject *me; if (mrb_type(owner) == MRB_TT_MODULE) { struct RClass *m = mrb_class_ptr(owner); @@ -323,19 +320,18 @@ method_super_method(mrb_state *mrb, mrb_value self) super = mrb_class_ptr(owner)->super; } - proc = method_search_vm(mrb, &super, mrb_symbol(name)); + struct RProc *proc = method_search_vm(mrb, &super, mrb_symbol(name)); if (!proc) return mrb_nil_value(); - rklass = super; - super = mrb_class_real(super); if (!super) return mrb_nil_value(); + super = mrb_class_real(super); - me = method_object_alloc(mrb, mrb_obj_class(mrb, self)); + struct RObject *me = method_object_alloc(mrb, mrb_obj_class(mrb, self)); mrb_obj_iv_set(mrb, me, MRB_SYM(_owner), mrb_obj_value(super)); mrb_obj_iv_set(mrb, me, MRB_SYM(_recv), recv); mrb_obj_iv_set(mrb, me, MRB_SYM(_name), name); mrb_obj_iv_set(mrb, me, MRB_SYM(_proc), mrb_obj_value(proc)); - mrb_obj_iv_set(mrb, me, MRB_SYM(_klass), mrb_obj_value(rklass)); + mrb_obj_iv_set(mrb, me, MRB_SYM(_klass), mrb_obj_value(super)); return mrb_obj_value(me); } @@ -380,7 +376,7 @@ method_to_s(mrb_state *mrb, mrb_value self) mrb_value klass = mrb_iv_get(mrb, self, MRB_SYM(_klass)); mrb_value name = mrb_iv_get(mrb, self, MRB_SYM(_name)); mrb_value str = mrb_str_new_lit(mrb, "#<"); - struct RClass *rklass; + mrb_value proc = mrb_iv_get(mrb, self, MRB_SYM(_proc)); mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self)); mrb_str_cat_lit(mrb, str, ": "); @@ -393,22 +389,37 @@ method_to_s(mrb_state *mrb, mrb_value self) goto finish; } } - - rklass = mrb_class_ptr(klass); - if (mrb_class_ptr(owner) == rklass) { - mrb_str_concat(mrb, str, owner); - mrb_str_cat_lit(mrb, str, "#"); - mrb_str_concat(mrb, str, name); - } - else { - rklass = mrb_class_real(rklass); /* skip internal class */ - mrb_str_concat(mrb, str, mrb_obj_value(rklass)); - mrb_str_cat_lit(mrb, str, "("); - mrb_str_concat(mrb, str, owner); - mrb_str_cat_lit(mrb, str, ")#"); - mrb_str_concat(mrb, str, name); + { + struct RClass *ok = mrb_class_ptr(owner); + struct RClass *rk = mrb_class_ptr(klass); + struct RClass *rklass = mrb_class_real(rk); /* skip internal class */ + if (ok == rk || ok == rklass) { + mrb_str_concat(mrb, str, owner); + mrb_str_cat_lit(mrb, str, "#"); + mrb_str_concat(mrb, str, name); + } + else { + mrb_str_concat(mrb, str, mrb_obj_value(rklass)); + mrb_str_cat_lit(mrb, str, "("); + mrb_str_concat(mrb, str, owner); + mrb_str_cat_lit(mrb, str, ")#"); + mrb_str_concat(mrb, str, name); + } } finish:; + if (!mrb_nil_p(proc)) { + const struct RProc *p = mrb_proc_ptr(proc); + if (MRB_PROC_ALIAS_P(p)) { + mrb_sym mid; + while (MRB_PROC_ALIAS_P(p)) { + mid = p->body.mid; + p = p->upper; + } + mrb_str_cat_lit(mrb, str, "("); + mrb_str_concat(mrb, str, mrb_symbol_value(mid)); + mrb_str_cat_lit(mrb, str, ")"); + } + } mrb_value loc = method_source_location(mrb, self); if (mrb_array_p(loc) && RARRAY_LEN(loc) == 2) { mrb_str_cat_lit(mrb, str, " "); @@ -423,8 +434,6 @@ method_to_s(mrb_state *mrb, mrb_value self) static mrb_bool search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound) { - mrb_value ret; - *owner = c; *proc = method_search_vm(mrb, owner, name); if (!*proc) { @@ -434,7 +443,7 @@ search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym nam if (!mrb_respond_to(mrb, obj, MRB_SYM_Q(respond_to_missing))) { return FALSE; } - ret = mrb_funcall_id(mrb, obj, MRB_SYM_Q(respond_to_missing), 2, mrb_symbol_value(name), mrb_true_value()); + mrb_value ret = mrb_funcall_id(mrb, obj, MRB_SYM_Q(respond_to_missing), 2, mrb_symbol_value(name), mrb_true_value()); if (!mrb_test(ret)) { return FALSE; } @@ -458,7 +467,6 @@ method_alloc(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, mrb_ { struct RClass *owner; struct RProc *proc; - struct RObject *me; if (!search_method_owner(mrb, c, obj, name, &owner, &proc, unbound)) { if (singleton) { @@ -471,7 +479,8 @@ method_alloc(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, mrb_ if (singleton && owner != c) { singleton_method_error(mrb, name, obj); } - me = method_object_alloc(mrb, mrb_class_get_id(mrb, unbound ? MRB_SYM(UnboundMethod) : MRB_SYM(Method))); + + struct RObject *me = method_object_alloc(mrb, mrb_class_get_id(mrb, unbound ? MRB_SYM(UnboundMethod) : MRB_SYM(Method))); mrb_obj_iv_set(mrb, me, MRB_SYM(_owner), mrb_obj_value(owner)); mrb_obj_iv_set(mrb, me, MRB_SYM(_recv), unbound ? mrb_nil_value() : obj); mrb_obj_iv_set(mrb, me, MRB_SYM(_name), mrb_symbol_value(name)); @@ -493,12 +502,11 @@ mrb_kernel_method(mrb_state *mrb, mrb_value self) static mrb_value mrb_kernel_singleton_method(mrb_state *mrb, mrb_value self) { - struct RClass *c; mrb_sym name; mrb_get_args(mrb, "n", &name); - c = mrb_class(mrb, self); + struct RClass *c = mrb_class(mrb, self); if (c->tt != MRB_TT_SCLASS) { singleton_method_error(mrb, name, self); } diff --git a/mruby/mrbgems/mruby-pack/src/pack.c b/mruby/mrbgems/mruby-pack/src/pack.c index 26c2890b..08db9091 100644 --- a/mruby/mrbgems/mruby-pack/src/pack.c +++ b/mruby/mrbgems/mruby-pack/src/pack.c @@ -921,7 +921,7 @@ unpack_bstr(mrb_state *mrb, const void *src, int slen, mrb_value ary, int count, const char *sptr0 = (const char*)src; const char *sptr = sptr0; - if (count == -1) + if (count == -1 || count > slen * 8) count = slen * 8; mrb_value dst = mrb_str_new(mrb, NULL, count); diff --git a/mruby/mrbgems/mruby-proc-binding/src/proc-binding.c b/mruby/mrbgems/mruby-proc-binding/src/proc-binding.c index f513dafd..fd494efc 100644 --- a/mruby/mrbgems/mruby-proc-binding/src/proc-binding.c +++ b/mruby/mrbgems/mruby-proc-binding/src/proc-binding.c @@ -4,7 +4,7 @@ #include /* provided by mruby-proc-ext */ -mrb_value mrb_proc_source_location(mrb_state *mrb, struct RProc *p); +mrb_value mrb_proc_source_location(mrb_state *mrb, const struct RProc *p); /* provided by mruby-binding */ mrb_value mrb_binding_new(mrb_state *mrb, const struct RProc *proc, mrb_value recv, struct REnv *env); diff --git a/mruby/mrbgems/mruby-proc-ext/src/proc.c b/mruby/mrbgems/mruby-proc-ext/src/proc.c index 8713e8bb..b022d5d2 100644 --- a/mruby/mrbgems/mruby-proc-ext/src/proc.c +++ b/mruby/mrbgems/mruby-proc-ext/src/proc.c @@ -14,21 +14,25 @@ proc_lambda_p(mrb_state *mrb, mrb_value self) } mrb_value -mrb_proc_source_location(mrb_state *mrb, struct RProc *p) +mrb_proc_source_location(mrb_state *mrb, const struct RProc *p) { if (MRB_PROC_CFUNC_P(p)) { return mrb_nil_value(); } - else { - const mrb_irep *irep = p->body.irep; - int32_t line; - const char *filename; - if (!mrb_debug_get_position(mrb, irep, 0, &line, &filename)) { - return mrb_nil_value(); - } - return mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, filename), mrb_fixnum_value(line)); + /* handle alias */ + if (MRB_PROC_ALIAS_P(p)) { + p = p->upper; + } + + const mrb_irep *irep = p->body.irep; + int32_t line; + const char *filename; + + if (!mrb_debug_get_position(mrb, irep, 0, &line, &filename)) { + return mrb_nil_value(); } + return mrb_assoc_new(mrb, mrb_str_new_cstr(mrb, filename), mrb_fixnum_value(line)); } static mrb_value diff --git a/mruby/mrbgems/mruby-range-ext/mrblib/range.rb b/mruby/mrbgems/mruby-range-ext/mrblib/range.rb index e229c918..7fc05c19 100644 --- a/mruby/mrbgems/mruby-range-ext/mrblib/range.rb +++ b/mruby/mrbgems/mruby-range-ext/mrblib/range.rb @@ -102,6 +102,23 @@ def min(&block) # (1..5).overlap?(7..9) # => false def overlap?(other) raise TypeError, "argument must be a range" unless other.kind_of?(Range) - other.begin == self.begin || self.cover?(other.begin) || other.cover?(self.begin) + + self_begin = self.begin + other_end = other.end + other_excl = other.exclude_end? + + return false if __empty_range?(self_begin, other_end, other_excl) + + other_begin = other.begin + self_end = self.end + self_excl = self.exclude_end? + + return false if __empty_range?(other_begin, self_end, self_excl) + return true if self_begin == other_begin + + return false if __empty_range?(self_begin, self_end, self_excl) + return false if __empty_range?(other_begin, other_end, other_excl) + + true end end diff --git a/mruby/mrbgems/mruby-range-ext/src/range.c b/mruby/mrbgems/mruby-range-ext/src/range.c index 9aaeac81..d1d33106 100644 --- a/mruby/mrbgems/mruby-range-ext/src/range.c +++ b/mruby/mrbgems/mruby-range-ext/src/range.c @@ -189,6 +189,20 @@ range_size(mrb_state *mrb, mrb_value range) } #endif /* MRB_NO_FLOAT */ +static mrb_value +range_empty_p(mrb_state *mrb, mrb_value range) +{ + mrb_value b, e; + mrb_bool excl; + + mrb_get_args(mrb, "oob", &b, &e, &excl); + if (mrb_nil_p(b) || mrb_nil_p(e)) + return mrb_false_value(); + + mrb_int comp = mrb_cmp(mrb, b, e); + return mrb_bool_value(comp == -2 || comp > 0 || (comp == 0 && excl)); +} + void mrb_mruby_range_ext_gem_init(mrb_state* mrb) { @@ -196,6 +210,7 @@ mrb_mruby_range_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "cover?", range_cover, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "size", range_size, MRB_ARGS_NONE()); + mrb_define_method(mrb, s, "__empty_range?", range_empty_p, MRB_ARGS_REQ(3)); } void diff --git a/mruby/mrbgems/mruby-set/mrblib/set.rb b/mruby/mrbgems/mruby-set/mrblib/set.rb index 467290c7..b0594663 100644 --- a/mruby/mrbgems/mruby-set/mrblib/set.rb +++ b/mruby/mrbgems/mruby-set/mrblib/set.rb @@ -140,9 +140,9 @@ def intersect?(set) end end - def disjoint?(set) - !intersect?(set) - end + def disjoint?(set) + !intersect?(set) + end def each(&block) return to_enum :each unless block_given? @@ -190,10 +190,10 @@ def keep_if end def collect! - return to_enum :collect! unless block_given? - set = self.class.new - each { |o| set << yield(o) } - replace(set) + return to_enum :collect! unless block_given? + set = self.class.new + each { |o| set << yield(o) } + replace(set) end alias map! collect! diff --git a/mruby/mrbgems/mruby-socket/mrblib/socket.rb b/mruby/mrbgems/mruby-socket/mrblib/socket.rb index 6736df3d..43b57952 100644 --- a/mruby/mrbgems/mruby-socket/mrblib/socket.rb +++ b/mruby/mrbgems/mruby-socket/mrblib/socket.rb @@ -251,7 +251,7 @@ def initialize(host, service, local_host=nil, local_service=nil) end end - def self.new_with_prelude pre, *args + def self._new_with_prelude(*args, &pre) o = self._allocate o.instance_eval(&pre) o.initialize(*args) @@ -277,7 +277,9 @@ def initialize(host=nil, service) def accept fd = self.sysaccept begin - TCPSocket.new_with_prelude(proc { @init_with_fd = true }, fd, "r+") + TCPSocket._new_with_prelude(fd, "r+") { + @init_with_fd = true + } rescue IO._sysclose(fd) rescue nil raise diff --git a/mruby/mrbgems/mruby-string-ext/src/string.c b/mruby/mrbgems/mruby-string-ext/src/string.c index 4e2be81f..79b4743a 100644 --- a/mruby/mrbgems/mruby-string-ext/src/string.c +++ b/mruby/mrbgems/mruby-string-ext/src/string.c @@ -1002,8 +1002,8 @@ str_succ(mrb_state *mrb, mrb_value self) #ifdef MRB_UTF8_STRING extern const char mrb_utf8len_table[]; -static mrb_int -utf8code(unsigned char* p, mrb_int limit) +MRB_INLINE mrb_int +utf8code(mrb_state* mrb, const unsigned char* p, const unsigned char *e) { mrb_int len; @@ -1011,7 +1011,7 @@ utf8code(unsigned char* p, mrb_int limit) return p[0]; len = mrb_utf8len_table[p[0]>>3]; - if (len <= limit && len > 1 && (p[1] & 0xc0) == 0x80) { + if (p+len <= e && len > 1 && (p[1] & 0xc0) == 0x80) { if (len == 2) return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f); if ((p[2] & 0xc0) == 0x80) { @@ -1025,6 +1025,8 @@ utf8code(unsigned char* p, mrb_int limit) } } } + mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid UTF-8 byte sequence"); + /* not reached */ return -1; } @@ -1033,27 +1035,26 @@ str_ord(mrb_state* mrb, mrb_value str) { if (RSTRING_LEN(str) == 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "empty string"); - mrb_int c = utf8code((unsigned char*)RSTRING_PTR(str), RSTRING_LEN(str)); - if (c < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid UTF-8 byte sequence"); + const unsigned char *p = (unsigned char*)RSTRING_PTR(str); + const unsigned char *e = p + RSTRING_LEN(str); + + mrb_int c = utf8code(mrb, p, e); return mrb_fixnum_value(c); } static mrb_value -str_codepoints(mrb_state *mrb, mrb_value self) +str_codepoints(mrb_state *mrb, mrb_value str) { mrb_value result; - char *p = RSTRING_PTR(self); - mrb_int len = RSTRING_LEN(self); - char *e = p + len; + const unsigned char *p = (unsigned char*)RSTRING_PTR(str); + const unsigned char *e = p + RSTRING_LEN(str); mrb->c->ci->mid = 0; result = mrb_ary_new(mrb); while (p < e) { - mrb_int c = utf8code((unsigned char*)p, len); + mrb_int c = utf8code(mrb, p, e); mrb_ary_push(mrb, result, mrb_int_value(mrb, c)); - mrb_int ulen = mrb_utf8len(p, e); - len -= ulen; - p += ulen; + p += mrb_utf8len_table[p[0]>>3]; } return result; } @@ -1317,6 +1318,48 @@ str_uminus(mrb_state *mrb, mrb_value str) return mrb_obj_freeze(mrb, mrb_str_dup(mrb, str)); } +/* + * call-seq: + * string.valid_encoding? -> true or false + * + * Returns true for a string which is encoded correctly. + * + */ +static mrb_value +str_valid_enc_p(mrb_state *mrb, mrb_value str) +{ +#ifdef MRB_UTF8_STRING +#define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80) + + struct RString *s = mrb_str_ptr(str); + if (RSTR_ASCII_P(s)) return mrb_true_value(); + + mrb_int byte_len = RSTR_LEN(s); + mrb_int utf8_len = 0; + const char *p = RSTR_PTR(s); + const char *e = p + byte_len; + while (p < e) { + mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3]; + if (len == 0 || len > e - p) + return mrb_false_value(); + switch (len) { + case 4: + if (utf8_islead(p[3])) return mrb_false_value(); + case 3: + if (utf8_islead(p[2])) return mrb_false_value(); + case 2: + if (utf8_islead(p[1])) return mrb_false_value(); + default: + break; + } + p += len; + utf8_len++; + } + if (byte_len == utf8_len) RSTR_SET_ASCII_FLAG(s); +#endif + return mrb_true_value(); +} + void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -1354,6 +1397,7 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "casecmp?", str_casecmp_p, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "+@", str_uplus, MRB_ARGS_REQ(1)); mrb_define_method(mrb, s, "-@", str_uminus, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "valid_encoding?", str_valid_enc_p, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "__lines", str_lines, MRB_ARGS_NONE()); mrb_define_method(mrb, s, "__codepoints", str_codepoints, MRB_ARGS_NONE()); diff --git a/mruby/mrbgems/mruby-string-ext/test/string.rb b/mruby/mrbgems/mruby-string-ext/test/string.rb index 0400a8da..f36eeea6 100644 --- a/mruby/mrbgems/mruby-string-ext/test/string.rb +++ b/mruby/mrbgems/mruby-string-ext/test/string.rb @@ -726,3 +726,14 @@ def assert_upto(exp, receiver, *args) a = -(a.freeze) assert_true(a.frozen?) end + +assert('String#valid_encoding?') do + assert_true "hello".valid_encoding? + if UTF8STRING + assert_true "あ".valid_encoding? + assert_false "\xfe".valid_encoding? + assert_false "あ\xfe".valid_encoding? + else + assert_true "\xfe".valid_encoding? + end +end diff --git a/mruby/mrbgems/mruby-struct/src/struct.c b/mruby/mrbgems/mruby-struct/src/struct.c index 757e4daf..4f6dadcf 100644 --- a/mruby/mrbgems/mruby-struct/src/struct.c +++ b/mruby/mrbgems/mruby-struct/src/struct.c @@ -617,7 +617,7 @@ mrb_struct_to_h(mrb_state *mrb, mrb_value self) ret = mrb_hash_new_capa(mrb, RARRAY_LEN(members)); for (i = 0; i < RARRAY_LEN(members); i++) { - mrb_hash_set(mrb, ret, RARRAY_PTR(members)[i], RARRAY_PTR(self)[i]); + mrb_hash_set(mrb, ret, RARRAY_PTR(members)[i], mrb_ary_ref(mrb, self, i)); } return ret; @@ -669,7 +669,7 @@ mrb_struct_to_s(mrb_state *mrb, mrb_value self) if (i>0) mrb_str_cat_lit(mrb, ret, ", "); mrb_str_cat(mrb, ret, name, len); mrb_str_cat_lit(mrb, ret, "="); - mrb_str_cat_str(mrb, ret, mrb_inspect(mrb, RARRAY_PTR(self)[i])); + mrb_str_cat_str(mrb, ret, mrb_inspect(mrb, mrb_ary_ref(mrb, self, i))); mrb_gc_arena_restore(mrb, ai); } mrb_str_cat_lit(mrb, ret, ">"); diff --git a/mruby/src/array.c b/mruby/src/array.c index 67b12ca3..01ccd85a 100644 --- a/mruby/src/array.c +++ b/mruby/src/array.c @@ -1110,14 +1110,13 @@ static mrb_value mrb_ary_last(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); - mrb_int n, size, alen; + mrb_int alen = ARY_LEN(a); - n = mrb_get_args(mrb, "|i", &size); - alen = ARY_LEN(a); - if (n == 0) { + if (mrb_get_argc(mrb) == 0) { return (alen > 0) ? ARY_PTR(a)[alen - 1]: mrb_nil_value(); } + mrb_int size = mrb_integer(mrb_get_arg1(mrb)); if (size < 0) { mrb_raise(mrb, E_ARGUMENT_ERROR, "negative array size"); } @@ -1403,41 +1402,41 @@ mrb_init_array(mrb_state *mrb) { struct RClass *a; - mrb->array_class = a = mrb_define_class(mrb, "Array", mrb->object_class); /* 15.2.12 */ + mrb->array_class = a = mrb_define_class_id(mrb, MRB_SYM(Array), mrb->object_class); /* 15.2.12 */ MRB_SET_INSTANCE_TT(a, MRB_TT_ARRAY); - mrb_define_class_method(mrb, a, "[]", mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */ - - mrb_define_method(mrb, a, "+", mrb_ary_plus, MRB_ARGS_REQ(1)); /* 15.2.12.5.1 */ - mrb_define_method(mrb, a, "*", mrb_ary_times, MRB_ARGS_REQ(1)); /* 15.2.12.5.2 */ - mrb_define_method(mrb, a, "<<", mrb_ary_push_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.3 */ - mrb_define_method(mrb, a, "[]", mrb_ary_aget, MRB_ARGS_ARG(1,1)); /* 15.2.12.5.4 */ - mrb_define_method(mrb, a, "[]=", mrb_ary_aset, MRB_ARGS_ARG(2,1)); /* 15.2.12.5.5 */ - mrb_define_method(mrb, a, "clear", mrb_ary_clear_m, MRB_ARGS_NONE()); /* 15.2.12.5.6 */ - mrb_define_method(mrb, a, "concat", mrb_ary_concat_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.8 */ - mrb_define_method(mrb, a, "delete_at", mrb_ary_delete_at, MRB_ARGS_REQ(1)); /* 15.2.12.5.9 */ - mrb_define_method(mrb, a, "empty?", mrb_ary_empty_p, MRB_ARGS_NONE()); /* 15.2.12.5.12 */ - mrb_define_method(mrb, a, "first", mrb_ary_first, MRB_ARGS_OPT(1)); /* 15.2.12.5.13 */ - mrb_define_method(mrb, a, "index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.14 */ - mrb_define_method(mrb, a, "initialize_copy", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.16 */ - mrb_define_method(mrb, a, "join", mrb_ary_join_m, MRB_ARGS_OPT(1)); /* 15.2.12.5.17 */ - mrb_define_method(mrb, a, "last", mrb_ary_last, MRB_ARGS_OPT(1)); /* 15.2.12.5.18 */ - mrb_define_method(mrb, a, "length", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.19 */ - mrb_define_method(mrb, a, "pop", mrb_ary_pop, MRB_ARGS_NONE()); /* 15.2.12.5.21 */ - mrb_define_method(mrb, a, "push", mrb_ary_push_m, MRB_ARGS_ANY()); /* 15.2.12.5.22 */ - mrb_define_method(mrb, a, "replace", mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */ - mrb_define_method(mrb, a, "reverse", mrb_ary_reverse, MRB_ARGS_NONE()); /* 15.2.12.5.24 */ - mrb_define_method(mrb, a, "reverse!", mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */ - mrb_define_method(mrb, a, "rindex", mrb_ary_rindex_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.26 */ - mrb_define_method(mrb, a, "shift", mrb_ary_shift_m, MRB_ARGS_OPT(1)); /* 15.2.12.5.27 */ - mrb_define_method(mrb, a, "size", mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.28 */ - mrb_define_method(mrb, a, "slice", mrb_ary_aget, MRB_ARGS_ARG(1,1)); /* 15.2.12.5.29 */ - mrb_define_method(mrb, a, "unshift", mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */ - mrb_define_method(mrb, a, "to_s", mrb_ary_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, a, "inspect", mrb_ary_to_s, MRB_ARGS_NONE()); - - mrb_define_method(mrb, a, "__ary_eq", mrb_ary_eq, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "__ary_cmp", mrb_ary_cmp, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, a, "__ary_index", mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */ - mrb_define_method(mrb, a, "__svalue", mrb_ary_svalue, MRB_ARGS_NONE()); + mrb_define_class_method_id(mrb, a, MRB_OPSYM(aref), mrb_ary_s_create, MRB_ARGS_ANY()); /* 15.2.12.4.1 */ + + mrb_define_method_id(mrb, a, MRB_OPSYM(add), mrb_ary_plus, MRB_ARGS_REQ(1)); /* 15.2.12.5.1 */ + mrb_define_method_id(mrb, a, MRB_OPSYM(mul), mrb_ary_times, MRB_ARGS_REQ(1)); /* 15.2.12.5.2 */ + mrb_define_method_id(mrb, a, MRB_OPSYM(lshift), mrb_ary_push_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.3 */ + mrb_define_method_id(mrb, a, MRB_OPSYM(aref), mrb_ary_aget, MRB_ARGS_ARG(1,1)); /* 15.2.12.5.4 */ + mrb_define_method_id(mrb, a, MRB_OPSYM(aset), mrb_ary_aset, MRB_ARGS_ARG(2,1)); /* 15.2.12.5.5 */ + mrb_define_method_id(mrb, a, MRB_SYM(clear), mrb_ary_clear_m, MRB_ARGS_NONE()); /* 15.2.12.5.6 */ + mrb_define_method_id(mrb, a, MRB_SYM(concat), mrb_ary_concat_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.8 */ + mrb_define_method_id(mrb, a, MRB_SYM(delete_at), mrb_ary_delete_at, MRB_ARGS_REQ(1)); /* 15.2.12.5.9 */ + mrb_define_method_id(mrb, a, MRB_SYM_Q(empty), mrb_ary_empty_p, MRB_ARGS_NONE()); /* 15.2.12.5.12 */ + mrb_define_method_id(mrb, a, MRB_SYM(first), mrb_ary_first, MRB_ARGS_OPT(1)); /* 15.2.12.5.13 */ + mrb_define_method_id(mrb, a, MRB_SYM(index), mrb_ary_index_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.14 */ + mrb_define_method_id(mrb, a, MRB_SYM(initialize_copy), mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.16 */ + mrb_define_method_id(mrb, a, MRB_SYM(join), mrb_ary_join_m, MRB_ARGS_OPT(1)); /* 15.2.12.5.17 */ + mrb_define_method_id(mrb, a, MRB_SYM(last), mrb_ary_last, MRB_ARGS_OPT(1)); /* 15.2.12.5.18 */ + mrb_define_method_id(mrb, a, MRB_SYM(length), mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.19 */ + mrb_define_method_id(mrb, a, MRB_SYM(pop), mrb_ary_pop, MRB_ARGS_NONE()); /* 15.2.12.5.21 */ + mrb_define_method_id(mrb, a, MRB_SYM(push), mrb_ary_push_m, MRB_ARGS_ANY()); /* 15.2.12.5.22 */ + mrb_define_method_id(mrb, a, MRB_SYM(replace), mrb_ary_replace_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.23 */ + mrb_define_method_id(mrb, a, MRB_SYM(reverse), mrb_ary_reverse, MRB_ARGS_NONE()); /* 15.2.12.5.24 */ + mrb_define_method_id(mrb, a, MRB_SYM_B(reverse), mrb_ary_reverse_bang, MRB_ARGS_NONE()); /* 15.2.12.5.25 */ + mrb_define_method_id(mrb, a, MRB_SYM(rindex), mrb_ary_rindex_m, MRB_ARGS_REQ(1)); /* 15.2.12.5.26 */ + mrb_define_method_id(mrb, a, MRB_SYM(shift), mrb_ary_shift_m, MRB_ARGS_OPT(1)); /* 15.2.12.5.27 */ + mrb_define_method_id(mrb, a, MRB_SYM(size), mrb_ary_size, MRB_ARGS_NONE()); /* 15.2.12.5.28 */ + mrb_define_method_id(mrb, a, MRB_SYM(slice), mrb_ary_aget, MRB_ARGS_ARG(1,1)); /* 15.2.12.5.29 */ + mrb_define_method_id(mrb, a, MRB_SYM(unshift), mrb_ary_unshift_m, MRB_ARGS_ANY()); /* 15.2.12.5.30 */ + mrb_define_method_id(mrb, a, MRB_SYM(to_s), mrb_ary_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, a, MRB_SYM(inspect), mrb_ary_to_s, MRB_ARGS_NONE()); + + mrb_define_method_id(mrb, a, MRB_SYM(__ary_eq), mrb_ary_eq, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, a, MRB_SYM(__ary_cmp), mrb_ary_cmp, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, a, MRB_SYM(__ary_index), mrb_ary_index_m, MRB_ARGS_REQ(1)); /* kept for mruby-array-ext */ + mrb_define_method_id(mrb, a, MRB_SYM(__svalue), mrb_ary_svalue, MRB_ARGS_NONE()); } diff --git a/mruby/src/class.c b/mruby/src/class.c index 6d0385e3..8f33cd73 100644 --- a/mruby/src/class.c +++ b/mruby/src/class.c @@ -1268,7 +1268,7 @@ get_args_v(mrb_state *mrb, mrb_args_format format, void** ptr, va_list *ap) const mrb_sym *kname = kwargs->table; mrb_value *values = kwargs->values; mrb_int j; - const uint32_t keyword_max = 40; + const mrb_int keyword_max = 40; mrb_assert(kwnum >= 0); mrb_assert(required >= 0); @@ -1343,7 +1343,7 @@ get_args_v(mrb_state *mrb, mrb_args_format format, void** ptr, va_list *ap) s: String [const char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil z: String [const char*] NUL terminated string; z! gives NULL for nil a: Array [const mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil - c: Class/Module [strcut RClass*] c! gives NULL for nil + c: Class/Module [struct RClass*] c! gives NULL for nil f: Integer/Float [mrb_float] i: Integer/Float [mrb_int] b: boolean [mrb_bool] @@ -2252,22 +2252,14 @@ mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b) if (!MRB_METHOD_CFUNC_P(m)) { struct RProc *p = MRB_METHOD_PROC(m); - - if (MRB_PROC_ENV_P(p)) { - MRB_PROC_ENV(p)->mid = b; - } - else if (p->color != MRB_GC_RED) { - struct RClass *tc = MRB_PROC_TARGET_CLASS(p); - struct REnv *e = MRB_OBJ_ALLOC(mrb, MRB_TT_ENV, NULL); - - e->mid = b; - if (tc) { - e->c = tc; - mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc); - } - p->e.env = e; - p->flags |= MRB_PROC_ENVSET; - mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e); + if (!MRB_PROC_CFUNC_P(p) && !MRB_PROC_ALIAS_P(p)) { + struct RProc *pnew = MRB_OBJ_ALLOC(mrb, MRB_TT_PROC, mrb->proc_class); + + pnew->body.mid = b; + pnew->upper = p; + pnew->e.env = NULL; + pnew->flags |= MRB_PROC_ALIAS; + MRB_METHOD_FROM_PROC(m, pnew); } } mrb_define_method_raw(mrb, c, a, m); @@ -3018,68 +3010,65 @@ mrb_init_class(mrb_state *mrb) mrb_class_name_class(mrb, NULL, mod, MRB_SYM(Module)); /* 15.2.2 */ mrb_class_name_class(mrb, NULL, cls, MRB_SYM(Class)); /* 15.2.3 */ - mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); /* 15.2.17 */ - MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC); - MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS); - mrb_define_method(mrb, bob, "initialize", mrb_do_nothing, MRB_ARGS_NONE()); - mrb_define_method(mrb, bob, "!", mrb_bob_not, MRB_ARGS_NONE()); - mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ - mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.4 */ - mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.5 */ - mrb_define_method(mrb, bob, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ - mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.3.1.3.18 */ - mrb_define_method(mrb, bob, "singleton_method_added", mrb_do_nothing, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, bob, "method_missing", mrb_obj_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ - - mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); - mrb_define_method(mrb, cls, "allocate", mrb_instance_alloc, MRB_ARGS_NONE()); - mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ - mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */ - mrb_define_method(mrb, cls, "inherited", mrb_do_nothing, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, bob, MRB_SYM(initialize), mrb_do_nothing, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, bob, MRB_OPSYM(not), mrb_bob_not, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, bob, MRB_OPSYM(eq), mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */ + mrb_define_method_id(mrb, bob, MRB_SYM(__id__), mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.4 */ + mrb_define_method_id(mrb, bob, MRB_SYM(__send__), mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.5 */ + mrb_define_method_id(mrb, bob, MRB_SYM_Q(equal), mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ + mrb_define_method_id(mrb, bob, MRB_SYM(instance_eval), mrb_obj_instance_eval, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.3.1.3.18 */ + mrb_define_method_id(mrb, bob, MRB_SYM(singleton_method_added), mrb_do_nothing, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, bob, MRB_SYM(method_missing), mrb_obj_missing, MRB_ARGS_ANY()); /* 15.3.1.3.30 */ + + mrb_define_class_method_id(mrb, cls, MRB_SYM(new), mrb_class_new_class, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); + mrb_define_method_id(mrb, cls, MRB_SYM(allocate), mrb_instance_alloc, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, cls, MRB_SYM(superclass), mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */ + mrb_define_method_id(mrb, cls, MRB_SYM(initialize), mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */ + mrb_define_method_id(mrb, cls, MRB_SYM(inherited), mrb_do_nothing, MRB_ARGS_REQ(1)); init_class_new(mrb, cls); MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE); - 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_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */ - mrb_define_method(mrb, mod, "prepended", mrb_do_nothing, 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_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 */ - mrb_define_method(mrb, mod, "class_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */ - mrb_define_method(mrb, mod, "included", mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */ - mrb_define_method(mrb, mod, "initialize", mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */ - mrb_define_method(mrb, mod, "module_eval", mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */ - mrb_define_method(mrb, mod, "module_function", mrb_mod_module_function, MRB_ARGS_ANY()); - mrb_define_method(mrb, mod, "private", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */ - mrb_define_method(mrb, mod, "protected", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */ - mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ - 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()); - mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */ - mrb_define_method(mrb, mod, "ancestors", mrb_mod_ancestors, MRB_ARGS_NONE()); /* 15.2.2.4.9 */ - mrb_define_method(mrb, mod, "undef_method", mrb_mod_undef, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ - mrb_define_method(mrb, mod, "const_defined?", mrb_mod_const_defined, MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */ - mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */ - mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */ - mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ - mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ - mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,1)); - mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); /* 15.2.2.4.7 */ - mrb_define_method(mrb, mod, "dup", mrb_mod_dup, MRB_ARGS_NONE()); - mrb_define_method(mrb, mod, "method_added", mrb_do_nothing, MRB_ARGS_REQ(1)); - - mrb_undef_method(mrb, cls, "append_features"); - mrb_undef_method(mrb, cls, "prepend_features"); - mrb_undef_method(mrb, cls, "extend_object"); - mrb_undef_method(mrb, cls, "module_function"); + mrb_define_method_id(mrb, mod, MRB_SYM(extend_object), mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */ + mrb_define_method_id(mrb, mod, MRB_SYM(extended), mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */ + mrb_define_method_id(mrb, mod, MRB_SYM(prepended), mrb_do_nothing, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, mod, MRB_SYM(prepend_features), mrb_mod_prepend_features, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, mod, MRB_SYM_Q(include), mrb_mod_include_p, MRB_ARGS_REQ(1)); /* 15.2.2.4.28 */ + mrb_define_method_id(mrb, mod, MRB_SYM(append_features), mrb_mod_append_features, MRB_ARGS_REQ(1)); /* 15.2.2.4.10 */ + mrb_define_method_id(mrb, mod, MRB_SYM(class_eval), mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.15 */ + mrb_define_method_id(mrb, mod, MRB_SYM(included), mrb_do_nothing, MRB_ARGS_REQ(1)); /* 15.2.2.4.29 */ + mrb_define_method_id(mrb, mod, MRB_SYM(initialize), mrb_mod_initialize, MRB_ARGS_NONE()); /* 15.2.2.4.31 */ + mrb_define_method_id(mrb, mod, MRB_SYM(module_eval), mrb_mod_module_eval, MRB_ARGS_ANY()); /* 15.2.2.4.35 */ + mrb_define_method_id(mrb, mod, MRB_SYM(module_function), mrb_mod_module_function, MRB_ARGS_ANY()); + mrb_define_method_id(mrb, mod, MRB_SYM(private), mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.36 */ + mrb_define_method_id(mrb, mod, MRB_SYM(protected), mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.37 */ + mrb_define_method_id(mrb, mod, MRB_SYM(public), mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */ + mrb_define_method_id(mrb, mod, MRB_SYM(attr_reader), mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */ + mrb_define_method_id(mrb, mod, MRB_SYM(attr_writer), mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */ + mrb_define_method_id(mrb, mod, MRB_SYM(to_s), mrb_mod_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, mod, MRB_SYM(inspect), mrb_mod_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, mod, MRB_SYM(alias_method), mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */ + mrb_define_method_id(mrb, mod, MRB_SYM(ancestors), mrb_mod_ancestors, MRB_ARGS_NONE()); /* 15.2.2.4.9 */ + mrb_define_method_id(mrb, mod, MRB_SYM(undef_method), mrb_mod_undef, MRB_ARGS_ANY()); /* 15.2.2.4.41 */ + mrb_define_method_id(mrb, mod, MRB_SYM_Q(const_defined), mrb_mod_const_defined, MRB_ARGS_ARG(1,1)); /* 15.2.2.4.20 */ + mrb_define_method_id(mrb, mod, MRB_SYM(const_get), mrb_mod_const_get, MRB_ARGS_REQ(1)); /* 15.2.2.4.21 */ + mrb_define_method_id(mrb, mod, MRB_SYM(const_set), mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */ + mrb_define_method_id(mrb, mod, MRB_SYM(remove_const), mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */ + mrb_define_method_id(mrb, mod, MRB_SYM(const_missing), mrb_mod_const_missing, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, mod, MRB_SYM_Q(method_defined), mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */ + mrb_define_method_id(mrb, mod, MRB_SYM(define_method), mod_define_method, MRB_ARGS_ARG(1,1)); + mrb_define_method_id(mrb, mod, MRB_OPSYM(eqq), mrb_mod_eqq, MRB_ARGS_REQ(1)); /* 15.2.2.4.7 */ + mrb_define_method_id(mrb, mod, MRB_SYM(dup), mrb_mod_dup, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, mod, MRB_SYM(method_added), mrb_do_nothing, MRB_ARGS_REQ(1)); + + mrb_undef_method_id(mrb, cls, MRB_SYM(append_features)); + mrb_undef_method_id(mrb, cls, MRB_SYM(prepend_features)); + mrb_undef_method_id(mrb, cls, MRB_SYM(extend_object)); + mrb_undef_method_id(mrb, cls, MRB_SYM(module_function)); mrb->top_self = MRB_OBJ_ALLOC(mrb, MRB_TT_OBJECT, mrb->object_class); - mrb_define_singleton_method(mrb, mrb->top_self, "inspect", inspect_main, MRB_ARGS_NONE()); - mrb_define_singleton_method(mrb, mrb->top_self, "to_s", inspect_main, MRB_ARGS_NONE()); - mrb_define_singleton_method(mrb, mrb->top_self, "define_method", top_define_method, MRB_ARGS_ARG(1,1)); + mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(inspect), inspect_main, MRB_ARGS_NONE()); + mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(to_s), inspect_main, MRB_ARGS_NONE()); + mrb_define_singleton_method_id(mrb, mrb->top_self, MRB_SYM(define_method), top_define_method, MRB_ARGS_ARG(1,1)); } diff --git a/mruby/src/compar.c b/mruby/src/compar.c deleted file mode 100644 index 0032fc85..00000000 --- a/mruby/src/compar.c +++ /dev/null @@ -1,13 +0,0 @@ -/* -** compar.c - Comparable module -** -** See Copyright Notice in mruby.h -*/ - -#include - -void -mrb_init_comparable(mrb_state *mrb) -{ - mrb_define_module(mrb, "Comparable"); /* 15.3.3 */ -} diff --git a/mruby/src/enum.c b/mruby/src/enum.c index b9595671..08b90d05 100644 --- a/mruby/src/enum.c +++ b/mruby/src/enum.c @@ -6,6 +6,7 @@ #include #include +#include /* internal method `__update_hash(oldhash, index, itemhash)` */ static mrb_value @@ -25,6 +26,6 @@ void mrb_init_enumerable(mrb_state *mrb) { struct RClass *enumerable; - enumerable = mrb_define_module(mrb, "Enumerable"); /* 15.3.2 */ - mrb_define_module_function(mrb, enumerable, "__update_hash", enum_update_hash, MRB_ARGS_REQ(3)); + enumerable = mrb_define_module_id(mrb, MRB_SYM(Enumerable)); /* 15.3.2 */ + mrb_define_module_function_id(mrb, enumerable, MRB_SYM(__update_hash), enum_update_hash, MRB_ARGS_REQ(3)); } diff --git a/mruby/src/error.c b/mruby/src/error.c index 7f6d07a6..c9172528 100644 --- a/mruby/src/error.c +++ b/mruby/src/error.c @@ -665,24 +665,24 @@ mrb_init_exception(mrb_state *mrb) { struct RClass *exception, *script_error, *stack_error, *nomem_error; - mrb->eException_class = exception = mrb_define_class(mrb, "Exception", mrb->object_class); /* 15.2.22 */ + mrb->eException_class = exception = mrb_define_class_id(mrb, MRB_SYM(Exception), mrb->object_class); /* 15.2.22 */ MRB_SET_INSTANCE_TT(exception, MRB_TT_EXCEPTION); - mrb_define_class_method(mrb, exception, "exception", mrb_instance_new, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, exception, "exception", exc_exception, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, exception, "initialize", exc_initialize, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, exception, "to_s", exc_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "inspect", mrb_exc_inspect, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); - mrb_define_method(mrb, exception, "set_backtrace", exc_set_backtrace, MRB_ARGS_REQ(1)); - - mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ - mrb_define_class(mrb, "RuntimeError", E_STANDARD_ERROR); /* 15.2.28 */ - script_error = mrb_define_class(mrb, "ScriptError", exception); /* 15.2.37 */ - mrb_define_class(mrb, "SyntaxError", script_error); /* 15.2.38 */ - stack_error = mrb_define_class(mrb, "SystemStackError", exception); + mrb_define_class_method_id(mrb, exception, MRB_SYM(exception), mrb_instance_new, MRB_ARGS_OPT(1)); + mrb_define_method_id(mrb, exception, MRB_SYM(exception), exc_exception, MRB_ARGS_OPT(1)); + mrb_define_method_id(mrb, exception, MRB_SYM(initialize), exc_initialize, MRB_ARGS_OPT(1)); + mrb_define_method_id(mrb, exception, MRB_SYM(to_s), exc_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, exception, MRB_SYM(inspect), mrb_exc_inspect, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, exception, MRB_SYM(backtrace), mrb_exc_backtrace, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, exception, MRB_SYM(set_backtrace), exc_set_backtrace, MRB_ARGS_REQ(1)); + + mrb->eStandardError_class = mrb_define_class_id(mrb, MRB_SYM(StandardError), mrb->eException_class); /* 15.2.23 */ + mrb_define_class_id(mrb, MRB_SYM(RuntimeError), E_STANDARD_ERROR); /* 15.2.28 */ + script_error = mrb_define_class_id(mrb, MRB_SYM(ScriptError), exception); /* 15.2.37 */ + mrb_define_class_id(mrb, MRB_SYM(SyntaxError), script_error); /* 15.2.38 */ + stack_error = mrb_define_class_id(mrb, MRB_SYM(SystemStackError), exception); mrb->stack_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, stack_error, "stack level too deep")); - nomem_error = mrb_define_class(mrb, "NoMemoryError", exception); + nomem_error = mrb_define_class_id(mrb, MRB_SYM(NoMemoryError), exception); mrb->nomem_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, nomem_error, "Out of memory")); #ifdef MRB_GC_FIXED_ARENA mrb->arena_err = mrb_obj_ptr(mrb_exc_new_lit(mrb, nomem_error, "arena overflow error")); diff --git a/mruby/src/gc.c b/mruby/src/gc.c index 3543bb76..9eb84311 100644 --- a/mruby/src/gc.c +++ b/mruby/src/gc.c @@ -677,7 +677,6 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) case MRB_TT_BREAK: { struct RBreak *brk = (struct RBreak*)obj; - mrb_gc_mark(mrb, (struct RBasic*)mrb_break_proc_get(brk)); mrb_gc_mark_value(mrb, mrb_break_value_get(brk)); } break; @@ -777,7 +776,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) { struct RProc *p = (struct RProc*)obj; - if (!MRB_PROC_CFUNC_P(p) && p->body.irep) { + if (!MRB_PROC_CFUNC_P(p) && !MRB_PROC_ALIAS_P(p) && p->body.irep) { mrb_irep *irep = (mrb_irep*)p->body.irep; if (end) { mrb_irep_cutref(mrb, irep); @@ -1576,15 +1575,15 @@ mrb_init_gc(mrb_state *mrb) mrb_static_assert_object_size(RVALUE); - gc = mrb_define_module(mrb, "GC"); - - mrb_define_class_method(mrb, gc, "start", gc_start, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "enable", gc_enable, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "disable", gc_disable, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "interval_ratio", gc_interval_ratio_get, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "interval_ratio=", gc_interval_ratio_set, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, gc, "step_ratio", gc_step_ratio_get, MRB_ARGS_NONE()); - mrb_define_class_method(mrb, gc, "step_ratio=", gc_step_ratio_set, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, gc, "generational_mode=", gc_generational_mode_set, MRB_ARGS_REQ(1)); - mrb_define_class_method(mrb, gc, "generational_mode", gc_generational_mode_get, MRB_ARGS_NONE()); + gc = mrb_define_module_id(mrb, MRB_SYM(GC)); + + mrb_define_class_method_id(mrb, gc, MRB_SYM(start), gc_start, MRB_ARGS_NONE()); + mrb_define_class_method_id(mrb, gc, MRB_SYM(enable), gc_enable, MRB_ARGS_NONE()); + mrb_define_class_method_id(mrb, gc, MRB_SYM(disable), gc_disable, MRB_ARGS_NONE()); + mrb_define_class_method_id(mrb, gc, MRB_SYM(interval_ratio), gc_interval_ratio_get, MRB_ARGS_NONE()); + mrb_define_class_method_id(mrb, gc, MRB_SYM_E(interval_ratio), gc_interval_ratio_set, MRB_ARGS_REQ(1)); + mrb_define_class_method_id(mrb, gc, MRB_SYM(step_ratio), gc_step_ratio_get, MRB_ARGS_NONE()); + mrb_define_class_method_id(mrb, gc, MRB_SYM_E(step_ratio), gc_step_ratio_set, MRB_ARGS_REQ(1)); + mrb_define_class_method_id(mrb, gc, MRB_SYM_E(generational_mode), gc_generational_mode_set, MRB_ARGS_REQ(1)); + mrb_define_class_method_id(mrb, gc, MRB_SYM(generational_mode), gc_generational_mode_get, MRB_ARGS_NONE()); } diff --git a/mruby/src/hash.c b/mruby/src/hash.c index ad92f541..1aa12f6e 100644 --- a/mruby/src/hash.c +++ b/mruby/src/hash.c @@ -1865,36 +1865,36 @@ mrb_init_hash(mrb_state *mrb) { struct RClass *h; - mrb->hash_class = h = mrb_define_class(mrb, "Hash", mrb->object_class); /* 15.2.13 */ + mrb->hash_class = h = mrb_define_class_id(mrb, MRB_SYM(Hash), mrb->object_class); /* 15.2.13 */ MRB_SET_INSTANCE_TT(h, MRB_TT_HASH); - mrb_define_method(mrb, h, "[]", mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */ - mrb_define_method(mrb, h, "[]=", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */ - mrb_define_method(mrb, h, "clear", mrb_hash_clear, MRB_ARGS_NONE()); /* 15.2.13.4.4 */ - mrb_define_method(mrb, h, "default", mrb_hash_default, MRB_ARGS_OPT(1)); /* 15.2.13.4.5 */ - mrb_define_method(mrb, h, "default=", mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6 */ - mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */ - mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */ - mrb_define_method(mrb, h, "__delete", mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */ - mrb_define_method(mrb, h, "empty?", mrb_hash_empty_m, MRB_ARGS_NONE()); /* 15.2.13.4.12 */ - mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */ - mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */ - mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */ - mrb_define_method(mrb, h, "initialize", mrb_hash_init, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.2.13.4.16 */ - mrb_define_method(mrb, h, "initialize_copy", mrb_hash_init_copy, MRB_ARGS_REQ(1)); /* 15.2.13.4.17 */ - mrb_define_method(mrb, h, "key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */ - mrb_define_method(mrb, h, "keys", mrb_hash_keys, MRB_ARGS_NONE()); /* 15.2.13.4.19 */ - mrb_define_method(mrb, h, "length", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.20 */ - mrb_define_method(mrb, h, "member?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */ - mrb_define_method(mrb, h, "replace", mrb_hash_init_copy, MRB_ARGS_REQ(1)); /* 15.2.13.4.23 */ - mrb_define_method(mrb, h, "shift", mrb_hash_shift, MRB_ARGS_NONE()); /* 15.2.13.4.24 */ - mrb_define_method(mrb, h, "size", mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.25 */ - mrb_define_method(mrb, h, "store", mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */ - mrb_define_method(mrb, h, "value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */ - mrb_define_method(mrb, h, "values", mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */ - mrb_define_method(mrb, h, "to_s", mrb_hash_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, h, "inspect", mrb_hash_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, h, "rehash", mrb_hash_rehash, MRB_ARGS_NONE()); - mrb_define_method(mrb, h, "__merge", mrb_hash_merge_m, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, h, "__compact", mrb_hash_compact, MRB_ARGS_NONE()); /* implementation of Hash#compact! */ + mrb_define_method_id(mrb, h, MRB_OPSYM(aref), mrb_hash_aget, MRB_ARGS_REQ(1)); /* 15.2.13.4.2 */ + mrb_define_method_id(mrb, h, MRB_OPSYM(aset), mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.3 */ + mrb_define_method_id(mrb, h, MRB_SYM(clear), mrb_hash_clear, MRB_ARGS_NONE()); /* 15.2.13.4.4 */ + mrb_define_method_id(mrb, h, MRB_SYM(default), mrb_hash_default, MRB_ARGS_OPT(1)); /* 15.2.13.4.5 */ + mrb_define_method_id(mrb, h, MRB_SYM_E(default), mrb_hash_set_default, MRB_ARGS_REQ(1)); /* 15.2.13.4.6 */ + mrb_define_method_id(mrb, h, MRB_SYM(default_proc), mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */ + mrb_define_method_id(mrb, h, MRB_SYM_E(default_proc), mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */ + mrb_define_method_id(mrb, h, MRB_SYM(__delete), mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(empty), mrb_hash_empty_m, MRB_ARGS_NONE()); /* 15.2.13.4.12 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(has_key), mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(has_value), mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(include), mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */ + mrb_define_method_id(mrb, h, MRB_SYM(initialize), mrb_hash_init, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.2.13.4.16 */ + mrb_define_method_id(mrb, h, MRB_SYM(initialize_copy), mrb_hash_init_copy, MRB_ARGS_REQ(1)); /* 15.2.13.4.17 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(key), mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.18 */ + mrb_define_method_id(mrb, h, MRB_SYM(keys), mrb_hash_keys, MRB_ARGS_NONE()); /* 15.2.13.4.19 */ + mrb_define_method_id(mrb, h, MRB_SYM(length), mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.20 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(member), mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.21 */ + mrb_define_method_id(mrb, h, MRB_SYM(replace), mrb_hash_init_copy, MRB_ARGS_REQ(1)); /* 15.2.13.4.23 */ + mrb_define_method_id(mrb, h, MRB_SYM(shift), mrb_hash_shift, MRB_ARGS_NONE()); /* 15.2.13.4.24 */ + mrb_define_method_id(mrb, h, MRB_SYM(size), mrb_hash_size_m, MRB_ARGS_NONE()); /* 15.2.13.4.25 */ + mrb_define_method_id(mrb, h, MRB_SYM(store), mrb_hash_aset, MRB_ARGS_REQ(2)); /* 15.2.13.4.26 */ + mrb_define_method_id(mrb, h, MRB_SYM_Q(value), mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.27 */ + mrb_define_method_id(mrb, h, MRB_SYM(values), mrb_hash_values, MRB_ARGS_NONE()); /* 15.2.13.4.28 */ + mrb_define_method_id(mrb, h, MRB_SYM(to_s), mrb_hash_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, h, MRB_SYM(inspect), mrb_hash_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, h, MRB_SYM(rehash), mrb_hash_rehash, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, h, MRB_SYM(__merge), mrb_hash_merge_m, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, h, MRB_SYM(__compact), mrb_hash_compact, MRB_ARGS_NONE()); /* implementation of Hash#compact! */ } diff --git a/mruby/src/init.c b/mruby/src/init.c index afd69975..0e9875d6 100644 --- a/mruby/src/init.c +++ b/mruby/src/init.c @@ -10,7 +10,6 @@ void mrb_init_symtbl(mrb_state*); void mrb_init_class(mrb_state*); void mrb_init_object(mrb_state*); void mrb_init_kernel(mrb_state*); -void mrb_init_comparable(mrb_state*); void mrb_init_enumerable(mrb_state*); void mrb_init_symbol(mrb_state*); void mrb_init_string(mrb_state*); @@ -34,7 +33,6 @@ mrb_init_core(mrb_state *mrb) mrb_init_class(mrb); DONE; mrb_init_object(mrb); DONE; mrb_init_kernel(mrb); DONE; - mrb_init_comparable(mrb); DONE; mrb_init_enumerable(mrb); DONE; mrb_init_symbol(mrb); DONE; diff --git a/mruby/src/kernel.c b/mruby/src/kernel.c index 59474be8..bc161b59 100644 --- a/mruby/src/kernel.c +++ b/mruby/src/kernel.c @@ -411,7 +411,7 @@ mrb_false(mrb_state *mrb, mrb_value self) * raise "Failed to create socket" * raise ArgumentError, "No parameters", caller */ -MRB_API mrb_value +mrb_value mrb_f_raise(mrb_state *mrb, mrb_value self) { mrb_value exc, mesg; @@ -547,55 +547,43 @@ mrb_obj_ceqq(mrb_state *mrb, mrb_value self) return mrb_false_value(); } -static mrb_value -mrb_encoding(mrb_state *mrb, mrb_value self) -{ - mrb_get_args(mrb, ""); -#ifdef MRB_UTF8_STRING - return mrb_str_new_lit(mrb, "UTF-8"); -#else - return mrb_str_new_lit(mrb, "ASCII-8BIT"); -#endif -} - void mrb_init_kernel(mrb_state *mrb) { struct RClass *krn; - mrb->kernel_module = krn = mrb_define_module(mrb, "Kernel"); /* 15.3.1 */ - mrb_define_class_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */ - mrb_define_class_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */ - mrb_define_class_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */ - - mrb_define_method(mrb, krn, "===", mrb_eqq_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ - mrb_define_method(mrb, krn, "<=>", mrb_cmp_m, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ - mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ - mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ - mrb_define_method(mrb, krn, "dup", mrb_obj_dup, MRB_ARGS_NONE()); /* 15.3.1.3.9 */ - mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */ - mrb_define_method(mrb, krn, "freeze", mrb_obj_freeze, MRB_ARGS_NONE()); - mrb_define_method(mrb, krn, "frozen?", mrb_obj_frozen, MRB_ARGS_NONE()); - mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ - mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ - mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */ - mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */ - - mrb_define_method(mrb, krn, "is_a?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */ - mrb_define_method(mrb, krn, "iterator?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */ - mrb_define_method(mrb, krn, "kind_of?", mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */ - mrb_define_method(mrb, krn, "nil?", mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */ - mrb_define_method(mrb, krn, "object_id", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */ - mrb_define_method(mrb, krn, "raise", mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */ - mrb_define_method(mrb, krn, "remove_instance_variable", mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */ - mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ARG(1,1)); /* 15.3.1.3.43 */ - mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ - mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ - mrb_define_method(mrb, krn, "__to_int", mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */ - mrb_define_method(mrb, krn, "__ENCODING__", mrb_encoding, MRB_ARGS_NONE()); - mrb_define_method(mrb, krn, "respond_to_missing?", mrb_false, MRB_ARGS_ARG(1,1)); - mrb_define_method(mrb, krn, "__inspect_recursive?", mrb_obj_inspect_recursive_p, MRB_ARGS_NONE()); + mrb->kernel_module = krn = mrb_define_module_id(mrb, MRB_SYM(Kernel)); /* 15.3.1 */ + mrb_define_class_method_id(mrb, krn, MRB_SYM_Q(block_given), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.2 */ + mrb_define_class_method_id(mrb, krn, MRB_SYM_Q(iterator), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.2.5 */ + mrb_define_class_method_id(mrb, krn, MRB_SYM(raise), mrb_f_raise, MRB_ARGS_OPT(2)); /* 15.3.1.2.12 */ + + mrb_define_method_id(mrb, krn, MRB_OPSYM(eqq), mrb_eqq_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */ + mrb_define_method_id(mrb, krn, MRB_OPSYM(cmp), mrb_cmp_m, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, krn, MRB_SYM_Q(block_given), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */ + mrb_define_method_id(mrb, krn, MRB_SYM(class), mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */ + mrb_define_method_id(mrb, krn, MRB_SYM(clone), mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */ + mrb_define_method_id(mrb, krn, MRB_SYM(dup), mrb_obj_dup, MRB_ARGS_NONE()); /* 15.3.1.3.9 */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(eql), mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */ + mrb_define_method_id(mrb, krn, MRB_SYM(freeze), mrb_obj_freeze, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, krn, MRB_SYM_Q(frozen), mrb_obj_frozen, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, krn, MRB_SYM(hash), mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ + mrb_define_method_id(mrb, krn, MRB_SYM(initialize_copy), mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ + mrb_define_method_id(mrb, krn, MRB_SYM(inspect), mrb_obj_inspect, MRB_ARGS_NONE()); /* 15.3.1.3.17 */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(instance_of), obj_is_instance_of, MRB_ARGS_REQ(1)); /* 15.3.1.3.19 */ + + mrb_define_method_id(mrb, krn, MRB_SYM_Q(is_a), mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.24 */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(iterator), mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.25 */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(kind_of), mrb_obj_is_kind_of_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.26 */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(nil), mrb_false, MRB_ARGS_NONE()); /* 15.3.1.3.32 */ + mrb_define_method_id(mrb, krn, MRB_SYM(object_id), mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.33 */ + mrb_define_method_id(mrb, krn, MRB_SYM(raise), mrb_f_raise, MRB_ARGS_ANY()); /* 15.3.1.3.40 */ + mrb_define_method_id(mrb, krn, MRB_SYM(remove_instance_variable), mrb_obj_remove_instance_variable,MRB_ARGS_REQ(1)); /* 15.3.1.3.41 */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(respond_to), obj_respond_to, MRB_ARGS_ARG(1,1)); /* 15.3.1.3.43 */ + mrb_define_method_id(mrb, krn, MRB_SYM(to_s), mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ + mrb_define_method_id(mrb, krn, MRB_SYM(__case_eqq), mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ + mrb_define_method_id(mrb, krn, MRB_SYM(__to_int), mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */ + mrb_define_method_id(mrb, krn, MRB_SYM_Q(respond_to_missing), mrb_false, MRB_ARGS_ARG(1,1)); + mrb_define_method_id(mrb, krn, MRB_SYM_Q(__inspect_recursive), mrb_obj_inspect_recursive_p, MRB_ARGS_NONE()); mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); } diff --git a/mruby/src/load.c b/mruby/src/load.c index 3287da2e..3008a4cd 100644 --- a/mruby/src/load.c +++ b/mruby/src/load.c @@ -670,7 +670,7 @@ irep_error(mrb_state *mrb) } static mrb_value -load_irep(mrb_state *mrb, struct RProc *proc, mrbc_context *c) +load_irep(mrb_state *mrb, struct RProc *proc, mrb_ccontext *c) { if (!proc || !proc->body.irep) { irep_error(mrb); @@ -683,7 +683,7 @@ load_irep(mrb_state *mrb, struct RProc *proc, mrbc_context *c) } MRB_API mrb_value -mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c) +mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrb_ccontext *c) { struct RProc *proc = mrb_proc_read_irep(mrb, bin); if (!proc) return mrb_undef_value(); @@ -691,7 +691,7 @@ mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c) } MRB_API mrb_value -mrb_load_irep_buf_cxt(mrb_state *mrb, const void *buf, size_t bufsize, mrbc_context *c) +mrb_load_irep_buf_cxt(mrb_state *mrb, const void *buf, size_t bufsize, mrb_ccontext *c) { return load_irep(mrb, mrb_proc_read_irep_buf(mrb, buf, bufsize), c); } @@ -755,7 +755,7 @@ DEFINE_READ_IREP_FUNC( mrb_proc_read_irep_file(mrb, fp)) MRB_API mrb_value -mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrbc_context *c) +mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrb_ccontext *c) { return load_irep(mrb, mrb_proc_read_irep_file(mrb, fp), c); } diff --git a/mruby/src/numeric.c b/mruby/src/numeric.c index ecc7aa59..5b098c8b 100644 --- a/mruby/src/numeric.c +++ b/mruby/src/numeric.c @@ -2012,9 +2012,14 @@ mrb_integer_to_str(mrb_state *mrb, mrb_value x, mrb_int base) static mrb_value int_to_s(mrb_state *mrb, mrb_value self) { - mrb_int base = 10; + mrb_int base; - mrb_get_args(mrb, "|i", &base); + if (mrb_get_argc(mrb) > 0) { + base = mrb_integer(mrb_get_arg1(mrb)); + } + else { + base = 10; + } return mrb_integer_to_str(mrb, self, base); } @@ -2215,95 +2220,95 @@ mrb_init_numeric(mrb_state *mrb) #endif /* Numeric Class */ - numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ - mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE()); - mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE()); - mrb_define_method(mrb, numeric, "eql?", num_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ + numeric = mrb_define_class_id(mrb, MRB_SYM(Numeric), mrb->object_class); /* 15.2.7 */ + mrb_define_method_id(mrb, numeric, MRB_SYM_Q(finite), num_finite_p, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, numeric, MRB_SYM_Q(infinite),num_infinite_p, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, numeric, MRB_SYM_Q(eql), num_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ /* Integer Class */ - mrb->integer_class = integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ + mrb->integer_class = integer = mrb_define_class_id(mrb, MRB_SYM(Integer), numeric); /* 15.2.8 */ MRB_SET_INSTANCE_TT(integer, MRB_TT_UNDEF); - mrb_undef_class_method(mrb, integer, "new"); - mrb_define_method(mrb, integer, "**", int_pow, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integer, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ - mrb_define_method(mrb, integer, "<", num_lt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integer, "<=", num_le, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integer, ">", num_gt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integer, ">=", num_ge, MRB_ARGS_REQ(1)); - - mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ - mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); - - mrb_define_method(mrb, integer, "+", int_add, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ - mrb_define_method(mrb, integer, "-", int_sub, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ - mrb_define_method(mrb, integer, "*", int_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ - mrb_define_method(mrb, integer, "%", int_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */ - mrb_define_method(mrb, integer, "/", int_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.6 */ - mrb_define_method(mrb, integer, "quo", int_quo, MRB_ARGS_REQ(1)); /* 15.2.7.4.5(x) */ - mrb_define_method(mrb, integer, "div", int_idiv, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integer, "==", int_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */ - mrb_define_method(mrb, integer, "~", int_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */ - mrb_define_method(mrb, integer, "&", int_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */ - mrb_define_method(mrb, integer, "|", int_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */ - mrb_define_method(mrb, integer, "^", int_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */ - mrb_define_method(mrb, integer, "<<", int_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */ - mrb_define_method(mrb, integer, ">>", int_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */ - mrb_define_method(mrb, integer, "ceil", int_ceil, MRB_ARGS_OPT(1)); /* 15.2.8.3.14 */ - mrb_define_method(mrb, integer, "floor", int_floor, MRB_ARGS_OPT(1)); /* 15.2.8.3.17 */ - mrb_define_method(mrb, integer, "round", int_round, MRB_ARGS_OPT(1)); /* 15.2.8.3.20 */ - mrb_define_method(mrb, integer, "truncate", int_truncate, MRB_ARGS_OPT(1)); /* 15.2.8.3.26 */ - mrb_define_method(mrb, integer, "hash", int_hash, MRB_ARGS_NONE()); /* 15.2.8.3.18 */ + mrb_undef_class_method_id(mrb, integer, MRB_SYM(new)); + mrb_define_method_id(mrb, integer, MRB_OPSYM(pow), int_pow, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, integer, MRB_OPSYM(cmp), num_cmp, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(lt), num_lt, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, integer, MRB_OPSYM(le), num_le, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, integer, MRB_OPSYM(gt), num_gt, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, integer, MRB_OPSYM(ge), num_ge, MRB_ARGS_REQ(1)); + + mrb_define_method_id(mrb, integer, MRB_SYM(to_i), int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ + mrb_define_method_id(mrb, integer, MRB_SYM(to_int), int_to_i, MRB_ARGS_NONE()); + + mrb_define_method_id(mrb, integer, MRB_OPSYM(add), int_add, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(sub), int_sub, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(mul), int_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(mod), int_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(div), int_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.6 */ + mrb_define_method_id(mrb, integer, MRB_SYM(quo), int_quo, MRB_ARGS_REQ(1)); /* 15.2.7.4.5(x) */ + mrb_define_method_id(mrb, integer, MRB_SYM(div), int_idiv, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, integer, MRB_OPSYM(eq), int_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(neg), int_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(and), int_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(or), int_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(xor), int_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(lshift), int_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */ + mrb_define_method_id(mrb, integer, MRB_OPSYM(rshift), int_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */ + mrb_define_method_id(mrb, integer, MRB_SYM(ceil), int_ceil, MRB_ARGS_OPT(1)); /* 15.2.8.3.14 */ + mrb_define_method_id(mrb, integer, MRB_SYM(floor), int_floor, MRB_ARGS_OPT(1)); /* 15.2.8.3.17 */ + mrb_define_method_id(mrb, integer, MRB_SYM(round), int_round, MRB_ARGS_OPT(1)); /* 15.2.8.3.20 */ + mrb_define_method_id(mrb, integer, MRB_SYM(truncate), int_truncate, MRB_ARGS_OPT(1)); /* 15.2.8.3.26 */ + mrb_define_method_id(mrb, integer, MRB_SYM(hash), int_hash, MRB_ARGS_NONE()); /* 15.2.8.3.18 */ #ifndef MRB_NO_FLOAT - mrb_define_method(mrb, integer, "to_f", int_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */ + mrb_define_method_id(mrb, integer, MRB_SYM(to_f), int_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */ #endif - mrb_define_method(mrb, integer, "to_s", int_to_s, MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */ - mrb_define_method(mrb, integer, "inspect", int_to_s, MRB_ARGS_OPT(1)); - mrb_define_method(mrb, integer, "divmod", int_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30(x) */ - mrb_define_method(mrb, integer, "__coerce_step_counter", coerce_step_counter, MRB_ARGS_REQ(2)); + mrb_define_method_id(mrb, integer, MRB_SYM(to_s), int_to_s, MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */ + mrb_define_method_id(mrb, integer, MRB_SYM(inspect), int_to_s, MRB_ARGS_OPT(1)); + mrb_define_method_id(mrb, integer, MRB_SYM(divmod), int_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30(x) */ + mrb_define_method_id(mrb, integer, MRB_SYM(__coerce_step_counter), coerce_step_counter, MRB_ARGS_REQ(2)); /* Fixnum Class for compatibility */ - mrb_define_const(mrb, mrb->object_class, "Fixnum", mrb_obj_value(integer)); + mrb_define_const_id(mrb, mrb->object_class, MRB_SYM(Fixnum), mrb_obj_value(integer)); #ifndef MRB_NO_FLOAT /* Float Class */ - mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */ + mrb->float_class = fl = mrb_define_class_id(mrb, MRB_SYM(Float), numeric); /* 15.2.9 */ MRB_SET_INSTANCE_TT(fl, MRB_TT_UNDEF); mrb_undef_class_method(mrb, fl, "new"); - mrb_define_method(mrb, fl, "**", flo_pow, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "/", flo_div, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ - mrb_define_method(mrb, fl, "quo", flo_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5(x) */ - mrb_define_method(mrb, fl, "div", flo_idiv, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "+", flo_add, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ - mrb_define_method(mrb, fl, "-", flo_sub, MRB_ARGS_REQ(1)); /* 15.2.9.3.4 */ - mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ - mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ - mrb_define_method(mrb, fl, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ - mrb_define_method(mrb, fl, "<", num_lt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "<=", num_le, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, ">", num_gt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, ">=", num_ge, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ - mrb_define_method(mrb, fl, "~", flo_rev, MRB_ARGS_NONE()); - mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, ">>", flo_rshift, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "<<", flo_lshift, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_OPT(1)); /* 15.2.9.3.8 */ - mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ - mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_OPT(1)); /* 15.2.9.3.10 */ - mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */ - mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ - mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ - mrb_define_method(mrb, fl, "to_i", flo_to_i, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ - mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_OPT(1)); /* 15.2.9.3.15 */ - mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1)); - - mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ - mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE()); - mrb_define_method(mrb, fl, "abs", flo_abs, MRB_ARGS_NONE()); /* 15.2.7.4.3 */ - mrb_define_method(mrb, fl, "hash", flo_hash, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, fl, MRB_OPSYM(pow), flo_pow, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(div), flo_div, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ + mrb_define_method_id(mrb, fl, MRB_SYM(quo), flo_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5(x) */ + mrb_define_method_id(mrb, fl, MRB_SYM(div), flo_idiv, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(add), flo_add, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */ + mrb_define_method_id(mrb, fl, MRB_OPSYM(sub), flo_sub, MRB_ARGS_REQ(1)); /* 15.2.9.3.4 */ + mrb_define_method_id(mrb, fl, MRB_OPSYM(mul), flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */ + mrb_define_method_id(mrb, fl, MRB_OPSYM(mod), flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */ + mrb_define_method_id(mrb, fl, MRB_OPSYM(cmp), num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */ + mrb_define_method_id(mrb, fl, MRB_OPSYM(lt), num_lt, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(le), num_le, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(gt), num_gt, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(ge), num_ge, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(eq), flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */ + mrb_define_method_id(mrb, fl, MRB_OPSYM(neg), flo_rev, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, fl, MRB_OPSYM(and), flo_and, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(or), flo_or, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(xor), flo_xor, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(rshift), flo_rshift, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_OPSYM(lshift), flo_lshift, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, fl, MRB_SYM(ceil), flo_ceil, MRB_ARGS_OPT(1)); /* 15.2.9.3.8 */ + mrb_define_method_id(mrb, fl, MRB_SYM_Q(finite), flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ + mrb_define_method_id(mrb, fl, MRB_SYM(floor), flo_floor, MRB_ARGS_OPT(1)); /* 15.2.9.3.10 */ + mrb_define_method_id(mrb, fl, MRB_SYM_Q(infinite),flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */ + mrb_define_method_id(mrb, fl, MRB_SYM(round), flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ + mrb_define_method_id(mrb, fl, MRB_SYM(to_f), flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ + mrb_define_method_id(mrb, fl, MRB_SYM(to_i), flo_to_i, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ + mrb_define_method_id(mrb, fl, MRB_SYM(truncate), flo_truncate, MRB_ARGS_OPT(1)); /* 15.2.9.3.15 */ + mrb_define_method_id(mrb, fl, MRB_SYM(divmod), flo_divmod, MRB_ARGS_REQ(1)); + + mrb_define_method_id(mrb, fl, MRB_SYM(to_s), flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */ + mrb_define_method_id(mrb, fl, MRB_SYM(inspect), flo_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, fl, MRB_SYM_Q(nan), flo_nan_p, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, fl, MRB_SYM(abs), flo_abs, MRB_ARGS_NONE()); /* 15.2.7.4.3 */ + mrb_define_method_id(mrb, fl, MRB_SYM(hash), flo_hash, MRB_ARGS_NONE()); #ifdef INFINITY mrb_define_const_id(mrb, fl, MRB_SYM(INFINITY), mrb_float_value(mrb, INFINITY)); diff --git a/mruby/src/object.c b/mruby/src/object.c index 91e4a881..f8e9c0b7 100644 --- a/mruby/src/object.c +++ b/mruby/src/object.c @@ -302,33 +302,33 @@ mrb_init_object(mrb_state *mrb) struct RClass *t; struct RClass *f; - mrb->nil_class = n = mrb_define_class(mrb, "NilClass", mrb->object_class); + mrb->nil_class = n = mrb_define_class_id(mrb, MRB_SYM(NilClass), mrb->object_class); MRB_SET_INSTANCE_TT(n, MRB_TT_FALSE); - mrb_undef_class_method(mrb, n, "new"); - mrb_define_method(mrb, n, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ - mrb_define_method(mrb, n, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ - mrb_define_method(mrb, n, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.4.3.3 */ - mrb_define_method(mrb, n, "nil?", mrb_true, MRB_ARGS_NONE()); /* 15.2.4.3.4 */ - mrb_define_method(mrb, n, "to_s", nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */ - mrb_define_method(mrb, n, "inspect", nil_inspect, MRB_ARGS_NONE()); - - mrb->true_class = t = mrb_define_class(mrb, "TrueClass", mrb->object_class); + mrb_undef_class_method_id(mrb, n, MRB_SYM(new)); + mrb_define_method_id(mrb, n, MRB_OPSYM(and), false_and, MRB_ARGS_REQ(1)); /* 15.2.4.3.1 */ + mrb_define_method_id(mrb, n, MRB_OPSYM(or), false_or, MRB_ARGS_REQ(1)); /* 15.2.4.3.2 */ + mrb_define_method_id(mrb, n, MRB_OPSYM(xor), false_xor, MRB_ARGS_REQ(1)); /* 15.2.4.3.3 */ + mrb_define_method_id(mrb, n, MRB_SYM_Q(nil), mrb_true, MRB_ARGS_NONE()); /* 15.2.4.3.4 */ + mrb_define_method_id(mrb, n, MRB_SYM(to_s), nil_to_s, MRB_ARGS_NONE()); /* 15.2.4.3.5 */ + mrb_define_method_id(mrb, n, MRB_SYM(inspect), nil_inspect, MRB_ARGS_NONE()); + + mrb->true_class = t = mrb_define_class_id(mrb, MRB_SYM(TrueClass), mrb->object_class); MRB_SET_INSTANCE_TT(t, MRB_TT_TRUE); - mrb_undef_class_method(mrb, t, "new"); - mrb_define_method(mrb, t, "&", true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ - mrb_define_method(mrb, t, "^", true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ - mrb_define_method(mrb, t, "to_s", true_to_s, MRB_ARGS_NONE()); /* 15.2.5.3.3 */ - mrb_define_method(mrb, t, "|", true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.4 */ - mrb_define_method(mrb, t, "inspect", true_to_s, MRB_ARGS_NONE()); - - mrb->false_class = f = mrb_define_class(mrb, "FalseClass", mrb->object_class); + mrb_undef_class_method_id(mrb, t, MRB_SYM(new)); + mrb_define_method_id(mrb, t, MRB_OPSYM(and), true_and, MRB_ARGS_REQ(1)); /* 15.2.5.3.1 */ + mrb_define_method_id(mrb, t, MRB_OPSYM(or), true_or, MRB_ARGS_REQ(1)); /* 15.2.5.3.2 */ + mrb_define_method_id(mrb, t, MRB_OPSYM(xor), true_xor, MRB_ARGS_REQ(1)); /* 15.2.5.3.3 */ + mrb_define_method_id(mrb, t, MRB_SYM(to_s), true_to_s, MRB_ARGS_NONE()); /* 15.2.5.3.4 */ + mrb_define_method_id(mrb, t, MRB_SYM(inspect), true_to_s, MRB_ARGS_NONE()); + + mrb->false_class = f = mrb_define_class_id(mrb, MRB_SYM(FalseClass), mrb->object_class); MRB_SET_INSTANCE_TT(f, MRB_TT_FALSE); - mrb_undef_class_method(mrb, f, "new"); - mrb_define_method(mrb, f, "&", false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ - mrb_define_method(mrb, f, "^", false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ - mrb_define_method(mrb, f, "to_s", false_to_s, MRB_ARGS_NONE()); /* 15.2.6.3.3 */ - mrb_define_method(mrb, f, "|", false_or, MRB_ARGS_REQ(1)); /* 15.2.6.3.4 */ - mrb_define_method(mrb, f, "inspect", false_to_s, MRB_ARGS_NONE()); + mrb_undef_class_method_id(mrb, f, MRB_SYM(new)); + mrb_define_method_id(mrb, f, MRB_OPSYM(and), false_and, MRB_ARGS_REQ(1)); /* 15.2.6.3.1 */ + mrb_define_method_id(mrb, f, MRB_OPSYM(or), false_or, MRB_ARGS_REQ(1)); /* 15.2.6.3.2 */ + mrb_define_method_id(mrb, f, MRB_OPSYM(xor), false_xor, MRB_ARGS_REQ(1)); /* 15.2.6.3.3 */ + mrb_define_method_id(mrb, f, MRB_SYM(to_s), false_to_s, MRB_ARGS_NONE()); /* 15.2.6.3.4 */ + mrb_define_method_id(mrb, f, MRB_SYM(inspect), false_to_s, MRB_ARGS_NONE()); } static const char* @@ -646,5 +646,6 @@ MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2) { if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE; + if (mrb_class(mrb, obj1) != mrb_class(mrb, obj2)) return FALSE; return mrb_test(mrb_funcall_argv(mrb, obj1, MRB_SYM_Q(eql), 1, &obj2)); } diff --git a/mruby/src/pool.c b/mruby/src/pool.c index 26088186..dbf13367 100644 --- a/mruby/src/pool.c +++ b/mruby/src/pool.c @@ -69,7 +69,6 @@ mrb_pool_open(mrb_state *mrb) pool->mrb = mrb; pool->pages = NULL; } - return pool; } @@ -108,19 +107,16 @@ MRB_API void* mrb_pool_alloc(mrb_pool *pool, size_t len) { struct mrb_pool_page *page; - size_t n; if (!pool) return NULL; len += ALIGN_PADDING(len); - page = pool->pages; - while (page) { + for (page = pool->pages; page; page = page->next) { if (page->offset + len <= page->len) { - n = page->offset; + size_t n = page->offset; page->offset += len; - page->last = (char*)page->page+n; + page->last = (void*)(page->page+n); return page->last; } - page = page->next; } page = page_alloc(pool, len); if (!page) return NULL; @@ -132,53 +128,31 @@ mrb_pool_alloc(mrb_pool *pool, size_t len) return page->last; } -MRB_API mrb_bool -mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len) -{ - struct mrb_pool_page *page; - - if (!pool) return FALSE; - len += ALIGN_PADDING(len); - page = pool->pages; - while (page) { - if (page->last == p) { - size_t beg; - - beg = (char*)p - page->page; - if (beg + len > page->len) return FALSE; - return TRUE; - } - page = page->next; - } - return FALSE; -} - MRB_API void* mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen) { - struct mrb_pool_page *page; - void *np; - if (!pool) return NULL; + if (newlen < oldlen) return p; oldlen += ALIGN_PADDING(oldlen); newlen += ALIGN_PADDING(newlen); - page = pool->pages; - while (page) { + for (struct mrb_pool_page *page = pool->pages; page; page = page->next) { if (page->last == p) { - size_t beg; - - beg = (char*)p - page->page; + /* if p is a last allocation from the page */ + size_t beg = (char*)p - page->page; + /* check beg + oldlen points bottom */ + /* assert(beg + oldlen == page->offset) */ if (beg + oldlen != page->offset) break; if (beg + newlen > page->len) { + /* new allocation need more space */ + /* abandon this space */ page->offset = beg; break; } page->offset = beg + newlen; return p; } - page = page->next; } - np = mrb_pool_alloc(pool, newlen); + void *np = mrb_pool_alloc(pool, newlen); if (np == NULL) { return NULL; } @@ -197,7 +171,7 @@ main(void) pool = mrb_pool_open(NULL); p = mrb_pool_alloc(pool, len); for (i=1; i<20; i++) { - printf("%p (len=%d) %ud\n", p, len, mrb_pool_can_realloc(pool, p, len*2)); + printf("%p (len=%d)\n", p, len); p = mrb_pool_realloc(pool, p, len, len*2); len *= 2; } diff --git a/mruby/src/proc.c b/mruby/src/proc.c index ac601a4b..978813f7 100644 --- a/mruby/src/proc.c +++ b/mruby/src/proc.c @@ -102,6 +102,9 @@ closure_setup(mrb_state *mrb, struct RProc *p) else if (up) { struct RClass *tc = ci->u.target_class; + if (MRB_PROC_ALIAS_P(up)) { /* alias */ + up = up->upper; + } e = mrb_env_new(mrb, mrb->c, ci, up->body.irep->nlocals, ci->stack, tc); ci->u.env = e; if (MRB_PROC_ENV_P(up) && MRB_PROC_ENV(up)->cxt == NULL) { @@ -418,18 +421,13 @@ mrb_proc_get_caller(mrb_state *mrb, struct REnv **envp) if (envp) *envp = NULL; } else { - struct RClass *tc = MRB_PROC_TARGET_CLASS(proc); struct REnv *e = mrb_vm_ci_env(ci); if (e == NULL) { int nstacks = proc->body.irep->nlocals; - e = mrb_env_new(mrb, c, ci, nstacks, ci->stack, tc); + e = mrb_env_new(mrb, c, ci, nstacks, ci->stack, mrb_vm_ci_target_class(ci)); ci->u.env = e; } - else if (tc) { - e->c = tc; - mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc); - } if (envp) *envp = e; } @@ -490,17 +488,21 @@ void mrb_init_proc(mrb_state *mrb) { mrb_method_t m; + struct RClass *pc = mrb->proc_class = mrb_define_class_id(mrb, MRB_SYM(Proc), mrb->object_class); /* 15.2.17 */ + + MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC); - mrb_define_class_method(mrb, mrb->proc_class, "new", mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); - mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE()); /* 15.2.17.4.2 */ - mrb_define_method(mrb, mrb->proc_class, "==", proc_eql, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mrb->proc_class, "eql?", proc_eql, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, mrb->proc_class, "hash", proc_hash, MRB_ARGS_NONE()); /* 15.2.17.4.2 */ + MRB_SET_INSTANCE_TT(pc, MRB_TT_UNDEF); + mrb_define_class_method_id(mrb, pc, MRB_SYM(new), mrb_proc_s_new, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); + mrb_define_method_id(mrb, pc, MRB_SYM(initialize_copy), mrb_proc_init_copy, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, pc, MRB_SYM(arity), proc_arity, MRB_ARGS_NONE()); /* 15.2.17.4.2 */ + mrb_define_method_id(mrb, pc, MRB_OPSYM(eq), proc_eql, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, pc, MRB_SYM_Q(eql), proc_eql, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, pc, MRB_SYM(hash), proc_hash, MRB_ARGS_NONE()); /* 15.2.17.4.2 */ MRB_METHOD_FROM_PROC(m, &call_proc); - mrb_define_method_raw(mrb, mrb->proc_class, MRB_SYM(call), m); /* 15.2.17.4.3 */ - mrb_define_method_raw(mrb, mrb->proc_class, MRB_OPSYM(aref), m); /* 15.2.17.4.1 */ + mrb_define_method_raw(mrb, pc, MRB_SYM(call), m); /* 15.2.17.4.3 */ + mrb_define_method_raw(mrb, pc, MRB_OPSYM(aref), m); /* 15.2.17.4.1 */ mrb_define_method(mrb, mrb->kernel_module, "lambda", proc_lambda, MRB_ARGS_NONE()|MRB_ARGS_BLOCK()); /* 15.3.1.3.27 */ } diff --git a/mruby/src/range.c b/mruby/src/range.c index 7741e90a..367e4c99 100644 --- a/mruby/src/range.c +++ b/mruby/src/range.c @@ -504,23 +504,23 @@ mrb_init_range(mrb_state *mrb) { struct RClass *r; - r = mrb_define_class(mrb, "Range", mrb->object_class); /* 15.2.14 */ + r = mrb_define_class_id(mrb, MRB_SYM(Range), mrb->object_class); /* 15.2.14 */ mrb->range_class = r; MRB_SET_INSTANCE_TT(r, MRB_TT_RANGE); - mrb_define_method(mrb, r, "begin", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */ - mrb_define_method(mrb, r, "end", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */ - mrb_define_method(mrb, r, "==", range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */ - mrb_define_method(mrb, r, "===", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */ - mrb_define_method(mrb, r, "exclude_end?", range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */ - mrb_define_method(mrb, r, "first", range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */ - mrb_define_method(mrb, r, "include?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */ - mrb_define_method(mrb, r, "initialize", range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */ - mrb_define_method(mrb, r, "last", range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */ - mrb_define_method(mrb, r, "member?", range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */ - mrb_define_method(mrb, r, "to_s", range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */ - mrb_define_method(mrb, r, "inspect", range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */ - mrb_define_method(mrb, r, "eql?", range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */ - mrb_define_method(mrb, r, "initialize_copy", range_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.14.4.15(x) */ - mrb_define_method(mrb, r, "__num_to_a", range_num_to_a, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, r, MRB_SYM(begin), range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.3 */ + mrb_define_method_id(mrb, r, MRB_SYM(end), range_end, MRB_ARGS_NONE()); /* 15.2.14.4.5 */ + mrb_define_method_id(mrb, r, MRB_OPSYM(eq), range_eq, MRB_ARGS_REQ(1)); /* 15.2.14.4.1 */ + mrb_define_method_id(mrb, r, MRB_OPSYM(eqq), range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.2 */ + mrb_define_method_id(mrb, r, MRB_SYM_Q(exclude_end), range_excl, MRB_ARGS_NONE()); /* 15.2.14.4.6 */ + mrb_define_method_id(mrb, r, MRB_SYM(first), range_beg, MRB_ARGS_NONE()); /* 15.2.14.4.7 */ + mrb_define_method_id(mrb, r, MRB_SYM_Q(include), range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.8 */ + mrb_define_method_id(mrb, r, MRB_SYM(initialize), range_initialize, MRB_ARGS_ANY()); /* 15.2.14.4.9 */ + mrb_define_method_id(mrb, r, MRB_SYM(last), range_end, MRB_ARGS_NONE()); /* 15.2.14.4.10 */ + mrb_define_method_id(mrb, r, MRB_SYM_Q(member), range_include, MRB_ARGS_REQ(1)); /* 15.2.14.4.11 */ + mrb_define_method_id(mrb, r, MRB_SYM(to_s), range_to_s, MRB_ARGS_NONE()); /* 15.2.14.4.12(x) */ + mrb_define_method_id(mrb, r, MRB_SYM(inspect), range_inspect, MRB_ARGS_NONE()); /* 15.2.14.4.13(x) */ + mrb_define_method_id(mrb, r, MRB_SYM_Q(eql), range_eql, MRB_ARGS_REQ(1)); /* 15.2.14.4.14(x) */ + mrb_define_method_id(mrb, r, MRB_SYM(initialize_copy), range_initialize_copy, MRB_ARGS_REQ(1)); /* 15.2.14.4.15(x) */ + mrb_define_method_id(mrb, r, MRB_SYM(__num_to_a), range_num_to_a, MRB_ARGS_NONE()); } diff --git a/mruby/src/string.c b/mruby/src/string.c index d3c3b2e1..b7e3a650 100644 --- a/mruby/src/string.c +++ b/mruby/src/string.c @@ -29,8 +29,12 @@ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz"; #define mrb_obj_alloc_string(mrb) MRB_OBJ_ALLOC((mrb), MRB_TT_STRING, (mrb)->string_class) #ifndef MRB_STR_LENGTH_MAX +#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) +#define MRB_STR_LENGTH_MAX 0 +#else #define MRB_STR_LENGTH_MAX 1048576 #endif +#endif static void str_check_length(mrb_state *mrb, mrb_int len) @@ -242,7 +246,8 @@ str_modify_keep_ascii(mrb_state *mrb, struct RString *s) static void check_null_byte(mrb_state *mrb, struct RString *str) { - if (memchr(RSTR_PTR(str), '\0', RSTR_LEN(str))) { + const char *p = RSTR_PTR(str); + if (p && memchr(p, '\0', RSTR_LEN(str))) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte"); } } @@ -2418,7 +2423,7 @@ mrb_str_len_to_integer(mrb_state *mrb, const char *str, size_t len, mrb_int base return mrb_fixnum_value(0); } -/* obslete: use RSTRING_CSTR() or mrb_string_cstr() */ +/* obsolete: use RSTRING_CSTR() or mrb_string_cstr() */ MRB_API const char* mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) { @@ -2431,6 +2436,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) check_null_byte(mrb, ps); p = RSTR_PTR(ps); len = RSTR_LEN(ps); + if (p == NULL) return ""; if (p[len] == '\0') { return p; } @@ -3031,6 +3037,17 @@ mrb_str_bytesplice(mrb_state *mrb, mrb_value str) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arumgnts"); } +static mrb_value +mrb_encoding(mrb_state *mrb, mrb_value self) +{ + mrb_get_args(mrb, ""); +#ifdef MRB_UTF8_STRING + return mrb_str_new_lit(mrb, "UTF-8"); +#else + return mrb_str_new_lit(mrb, "ASCII-8BIT"); +#endif +} + /* ---------------------------*/ void mrb_init_string(mrb_state *mrb) @@ -3040,61 +3057,63 @@ mrb_init_string(mrb_state *mrb) mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << MRB_STR_EMBED_LEN_BIT), "pointer size too big for embedded string"); - mrb->string_class = s = mrb_define_class(mrb, "String", mrb->object_class); /* 15.2.10 */ + mrb->string_class = s = mrb_define_class_id(mrb, MRB_SYM(String), mrb->object_class); /* 15.2.10 */ MRB_SET_INSTANCE_TT(s, MRB_TT_STRING); - mrb_define_method(mrb, s, "bytesize", mrb_str_bytesize, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "<=>", mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */ - mrb_define_method(mrb, s, "==", mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.2 */ - mrb_define_method(mrb, s, "+", mrb_str_plus_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.4 */ - mrb_define_method(mrb, s, "*", mrb_str_times, MRB_ARGS_REQ(1)); /* 15.2.10.5.5 */ - mrb_define_method(mrb, s, "[]", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.6 */ - mrb_define_method(mrb, s, "[]=", mrb_str_aset_m, MRB_ARGS_ANY()); - mrb_define_method(mrb, s, "capitalize", mrb_str_capitalize, MRB_ARGS_NONE()); /* 15.2.10.5.7 */ - mrb_define_method(mrb, s, "capitalize!", mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8 */ - mrb_define_method(mrb, s, "chomp", mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */ - mrb_define_method(mrb, s, "chomp!", mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */ - mrb_define_method(mrb, s, "chop", mrb_str_chop, MRB_ARGS_NONE()); /* 15.2.10.5.11 */ - mrb_define_method(mrb, s, "chop!", mrb_str_chop_bang, MRB_ARGS_NONE()); /* 15.2.10.5.12 */ - mrb_define_method(mrb, s, "downcase", mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */ - mrb_define_method(mrb, s, "downcase!", mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */ - mrb_define_method(mrb, s, "empty?", mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */ - mrb_define_method(mrb, s, "eql?", mrb_str_eql, MRB_ARGS_REQ(1)); /* 15.2.10.5.17 */ - - mrb_define_method(mrb, s, "hash", mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */ - mrb_define_method(mrb, s, "include?", mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */ - mrb_define_method(mrb, s, "index", mrb_str_index_m, MRB_ARGS_ARG(1,1)); /* 15.2.10.5.22 */ - mrb_define_method(mrb, s, "initialize", mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */ - mrb_define_method(mrb, s, "initialize_copy", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */ - mrb_define_method(mrb, s, "intern", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */ - mrb_define_method(mrb, s, "length", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.26 */ - mrb_define_method(mrb, s, "replace", mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */ - mrb_define_method(mrb, s, "reverse", mrb_str_reverse, MRB_ARGS_NONE()); /* 15.2.10.5.29 */ - mrb_define_method(mrb, s, "reverse!", mrb_str_reverse_bang, MRB_ARGS_NONE()); /* 15.2.10.5.30 */ - mrb_define_method(mrb, s, "rindex", mrb_str_rindex_m, MRB_ARGS_ANY()); /* 15.2.10.5.31 */ - mrb_define_method(mrb, s, "size", mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.33 */ - mrb_define_method(mrb, s, "slice", mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */ - mrb_define_method(mrb, s, "split", mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */ + mrb_define_method_id(mrb, s, MRB_SYM(bytesize), mrb_str_bytesize, MRB_ARGS_NONE()); + + mrb_define_method_id(mrb, s, MRB_OPSYM(cmp), mrb_str_cmp_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.1 */ + mrb_define_method_id(mrb, s, MRB_OPSYM(eq), mrb_str_equal_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.2 */ + mrb_define_method_id(mrb, s, MRB_OPSYM(add), mrb_str_plus_m, MRB_ARGS_REQ(1)); /* 15.2.10.5.4 */ + mrb_define_method_id(mrb, s, MRB_OPSYM(mul), mrb_str_times, MRB_ARGS_REQ(1)); /* 15.2.10.5.5 */ + mrb_define_method_id(mrb, s, MRB_OPSYM(aref), mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.6 */ + mrb_define_method_id(mrb, s, MRB_OPSYM(aset), mrb_str_aset_m, MRB_ARGS_ANY()); + mrb_define_method_id(mrb, s, MRB_SYM(capitalize), mrb_str_capitalize, MRB_ARGS_NONE()); /* 15.2.10.5.7 */ + mrb_define_method_id(mrb, s, MRB_SYM_B(capitalize), mrb_str_capitalize_bang, MRB_ARGS_NONE()); /* 15.2.10.5.8 */ + mrb_define_method_id(mrb, s, MRB_SYM(chomp), mrb_str_chomp, MRB_ARGS_ANY()); /* 15.2.10.5.9 */ + mrb_define_method_id(mrb, s, MRB_SYM_B(chomp), mrb_str_chomp_bang, MRB_ARGS_ANY()); /* 15.2.10.5.10 */ + mrb_define_method_id(mrb, s, MRB_SYM(chop), mrb_str_chop, MRB_ARGS_NONE()); /* 15.2.10.5.11 */ + mrb_define_method_id(mrb, s, MRB_SYM_B(chop), mrb_str_chop_bang, MRB_ARGS_NONE()); /* 15.2.10.5.12 */ + mrb_define_method_id(mrb, s, MRB_SYM(downcase), mrb_str_downcase, MRB_ARGS_NONE()); /* 15.2.10.5.13 */ + mrb_define_method_id(mrb, s, MRB_SYM_B(downcase), mrb_str_downcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.14 */ + mrb_define_method_id(mrb, s, MRB_SYM_Q(empty), mrb_str_empty_p, MRB_ARGS_NONE()); /* 15.2.10.5.16 */ + mrb_define_method_id(mrb, s, MRB_SYM_Q(eql), mrb_str_eql, MRB_ARGS_REQ(1)); /* 15.2.10.5.17 */ + + mrb_define_method_id(mrb, s, MRB_SYM(hash), mrb_str_hash_m, MRB_ARGS_NONE()); /* 15.2.10.5.20 */ + mrb_define_method_id(mrb, s, MRB_SYM_Q(include), mrb_str_include, MRB_ARGS_REQ(1)); /* 15.2.10.5.21 */ + mrb_define_method_id(mrb, s, MRB_SYM(index), mrb_str_index_m, MRB_ARGS_ARG(1,1)); /* 15.2.10.5.22 */ + mrb_define_method_id(mrb, s, MRB_SYM(initialize), mrb_str_init, MRB_ARGS_REQ(1)); /* 15.2.10.5.23 */ + mrb_define_method_id(mrb, s, MRB_SYM(initialize_copy), mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.24 */ + mrb_define_method_id(mrb, s, MRB_SYM(intern), mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.25 */ + mrb_define_method_id(mrb, s, MRB_SYM(length), mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.26 */ + mrb_define_method_id(mrb, s, MRB_SYM(replace), mrb_str_replace, MRB_ARGS_REQ(1)); /* 15.2.10.5.28 */ + mrb_define_method_id(mrb, s, MRB_SYM(reverse), mrb_str_reverse, MRB_ARGS_NONE()); /* 15.2.10.5.29 */ + mrb_define_method_id(mrb, s, MRB_SYM_B(reverse), mrb_str_reverse_bang, MRB_ARGS_NONE()); /* 15.2.10.5.30 */ + mrb_define_method_id(mrb, s, MRB_SYM(rindex), mrb_str_rindex_m, MRB_ARGS_ANY()); /* 15.2.10.5.31 */ + mrb_define_method_id(mrb, s, MRB_SYM(size), mrb_str_size, MRB_ARGS_NONE()); /* 15.2.10.5.33 */ + mrb_define_method_id(mrb, s, MRB_SYM(slice), mrb_str_aref_m, MRB_ARGS_ANY()); /* 15.2.10.5.34 */ + mrb_define_method_id(mrb, s, MRB_SYM(split), mrb_str_split_m, MRB_ARGS_ANY()); /* 15.2.10.5.35 */ #ifndef MRB_NO_FLOAT - mrb_define_method(mrb, s, "to_f", mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.38 */ + mrb_define_method_id(mrb, s, MRB_SYM(to_f), mrb_str_to_f, MRB_ARGS_NONE()); /* 15.2.10.5.38 */ #endif - mrb_define_method(mrb, s, "to_i", mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */ - mrb_define_method(mrb, s, "to_s", mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */ - mrb_define_method(mrb, s, "to_str", mrb_str_to_s, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "to_sym", mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */ - mrb_define_method(mrb, s, "upcase", mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */ - mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ - mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ - mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "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, "byteindex", mrb_str_byteindex_m, MRB_ARGS_ARG(1,1)); - mrb_define_method(mrb, s, "byterindex", mrb_str_byterindex_m, MRB_ARGS_ARG(1,1)); - mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_ARG(1,1)); - mrb_define_method(mrb, s, "bytesplice", mrb_str_bytesplice, MRB_ARGS_ANY()); - - mrb_define_method(mrb, s, "__sub_replace", sub_replace, MRB_ARGS_REQ(3)); /* internal */ + mrb_define_method_id(mrb, s, MRB_SYM(to_i), mrb_str_to_i, MRB_ARGS_ANY()); /* 15.2.10.5.39 */ + mrb_define_method_id(mrb, s, MRB_SYM(to_s), mrb_str_to_s, MRB_ARGS_NONE()); /* 15.2.10.5.40 */ + mrb_define_method_id(mrb, s, MRB_SYM(to_str), mrb_str_to_s, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, s, MRB_SYM(to_sym), mrb_str_intern, MRB_ARGS_NONE()); /* 15.2.10.5.41 */ + mrb_define_method_id(mrb, s, MRB_SYM(upcase), mrb_str_upcase, MRB_ARGS_NONE()); /* 15.2.10.5.42 */ + mrb_define_method_id(mrb, s, MRB_SYM_B(upcase), mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ + mrb_define_method_id(mrb, s, MRB_SYM(inspect), mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ + mrb_define_method_id(mrb, s, MRB_SYM(bytes), mrb_str_bytes, MRB_ARGS_NONE()); + + mrb_define_method_id(mrb, s, MRB_SYM(getbyte), mrb_str_getbyte, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, s, MRB_SYM(setbyte), mrb_str_setbyte, MRB_ARGS_REQ(2)); + mrb_define_method_id(mrb, s, MRB_SYM(byteindex), mrb_str_byteindex_m, MRB_ARGS_ARG(1,1)); + mrb_define_method_id(mrb, s, MRB_SYM(byterindex), mrb_str_byterindex_m, MRB_ARGS_ARG(1,1)); + mrb_define_method_id(mrb, s, MRB_SYM(byteslice), mrb_str_byteslice, MRB_ARGS_ARG(1,1)); + mrb_define_method_id(mrb, s, MRB_SYM(bytesplice), mrb_str_bytesplice, MRB_ARGS_ANY()); + + mrb_define_method_id(mrb, s, MRB_SYM(__sub_replace), sub_replace, MRB_ARGS_REQ(3)); /* internal */ + + mrb_define_method_id(mrb, mrb->kernel_module, MRB_SYM(__ENCODING__), mrb_encoding, MRB_ARGS_NONE()); } diff --git a/mruby/src/symbol.c b/mruby/src/symbol.c index ffac3437..3f0ddb53 100644 --- a/mruby/src/symbol.c +++ b/mruby/src/symbol.c @@ -690,13 +690,13 @@ mrb_init_symbol(mrb_state *mrb) { struct RClass *sym; - mrb->symbol_class = sym = mrb_define_class(mrb, "Symbol", mrb->object_class); /* 15.2.11 */ + mrb->symbol_class = sym = mrb_define_class_id(mrb, MRB_SYM(Symbol), mrb->object_class); /* 15.2.11 */ MRB_SET_INSTANCE_TT(sym, MRB_TT_SYMBOL); - mrb_undef_class_method(mrb, sym, "new"); + mrb_undef_class_method_id(mrb, sym, MRB_SYM(new)); - mrb_define_method(mrb, sym, "to_s", sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */ - mrb_define_method(mrb, sym, "name", sym_name, MRB_ARGS_NONE()); - mrb_define_method(mrb, sym, "to_sym", sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ - mrb_define_method(mrb, sym, "inspect", sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ - mrb_define_method(mrb, sym, "<=>", sym_cmp, MRB_ARGS_REQ(1)); + mrb_define_method_id(mrb, sym, MRB_SYM(to_s), sym_to_s, MRB_ARGS_NONE()); /* 15.2.11.3.3 */ + mrb_define_method_id(mrb, sym, MRB_SYM(name), sym_name, MRB_ARGS_NONE()); + mrb_define_method_id(mrb, sym, MRB_SYM(to_sym), sym_to_sym, MRB_ARGS_NONE()); /* 15.2.11.3.4 */ + mrb_define_method_id(mrb, sym, MRB_SYM(inspect), sym_inspect, MRB_ARGS_NONE()); /* 15.2.11.3.5(x) */ + mrb_define_method_id(mrb, sym, MRB_OPSYM(cmp), sym_cmp, MRB_ARGS_REQ(1)); } diff --git a/mruby/src/vm.c b/mruby/src/vm.c index 47457b12..35e1650f 100644 --- a/mruby/src/vm.c +++ b/mruby/src/vm.c @@ -41,9 +41,19 @@ void abort(void); #endif /* Maximum recursive depth. Should be set lower on memory constrained systems. */ +#ifdef __clang__ +#if __has_feature(address_sanitizer) && !defined(__SANITIZE_ADDRESS__) +#define __SANITIZE_ADDRESS__ +#endif +#endif + #ifndef MRB_CALL_LEVEL_MAX +#if defined(__SANITIZE_ADDRESS__) +#define MRB_CALL_LEVEL_MAX 128 +#else #define MRB_CALL_LEVEL_MAX 512 #endif +#endif /* Maximum stack depth. Should be set lower on memory constrained systems. The value below allows about 60000 recursive calls in the simplest case. */ @@ -255,7 +265,7 @@ top_proc(mrb_state *mrb, const struct RProc *proc) #define CI_PROC_SET(ci, p) do {\ ci->proc = p;\ - ci->pc = (p && !MRB_PROC_CFUNC_P(p) && p->body.irep) ? p->body.irep->iseq : NULL;\ + ci->pc = (p && !MRB_PROC_CFUNC_P(p) && !MRB_PROC_ALIAS_P(p) && p->body.irep) ? p->body.irep->iseq : NULL; \ } while (0) void @@ -698,6 +708,11 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc cipop(mrb); } else { + /* handle alias */ + if (MRB_PROC_ALIAS_P(ci->proc)) { + ci->mid = ci->proc->body.mid; + ci->proc = ci->proc->upper; + } ci->cci = CINFO_SKIP; val = mrb_run(mrb, ci->proc, self); } @@ -729,15 +744,20 @@ check_method_noarg(mrb_state *mrb, const mrb_callinfo *ci) } static mrb_value -exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) +exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; mrb_int keep, nregs; ci->stack[0] = self; + /* handle alias */ + if (MRB_PROC_ALIAS_P(p)) { + ci->mid = p->body.mid; + p = p->upper; + } CI_PROC_SET(ci, p); if (MRB_PROC_CFUNC_P(p)) { - if (MRB_PROC_NOARG_P(p)) { + if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) { check_method_noarg(mrb, ci); } return MRB_PROC_CFUNC(p)(mrb, self); @@ -767,7 +787,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) else { mrb_value ret; if (MRB_PROC_CFUNC_P(p)) { - if (MRB_PROC_NOARG_P(p)) { + if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) { check_method_noarg(mrb, ci); } cipush(mrb, 0, CINFO_DIRECT, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4)); @@ -859,18 +879,23 @@ mrb_f_send(mrb_state *mrb, mrb_value self) ci->n--; } + const struct RProc *p; + if (MRB_METHOD_PROC_P(m)) { + p = MRB_METHOD_PROC(m); + /* handle alias */ + if (MRB_PROC_ALIAS_P(p)) { + ci->mid = p->body.mid; + p = p->upper; + } + CI_PROC_SET(ci, p); + } if (MRB_METHOD_CFUNC_P(m)) { - if (MRB_METHOD_NOARG_P(m)) { + if (MRB_METHOD_NOARG_P(m) && (ci->n > 0 || ci->nk > 0)) { check_method_noarg(mrb, ci); } - - if (MRB_METHOD_PROC_P(m)) { - const struct RProc *p = MRB_METHOD_PROC(m); - CI_PROC_SET(ci, p); - } return MRB_METHOD_CFUNC(m)(mrb, self); } - return exec_irep(mrb, self, MRB_METHOD_PROC(m)); + return exec_irep(mrb, self, p); } static void @@ -898,6 +923,8 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) } ci->u.target_class = c; p = mrb_proc_ptr(blk); + /* just in case irep is NULL; #6065 */ + if (p->body.irep == NULL) return mrb_nil_value(); CI_PROC_SET(ci, p); ci->n = 1; ci->nk = 0; @@ -1050,13 +1077,8 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const #define RBREAK_TAG_FOREACH(f) \ f(RBREAK_TAG_BREAK, 0) \ - f(RBREAK_TAG_BREAK_UPPER, 1) \ - f(RBREAK_TAG_BREAK_INTARGET, 2) \ - f(RBREAK_TAG_RETURN_BLOCK, 3) \ - f(RBREAK_TAG_RETURN, 4) \ - f(RBREAK_TAG_RETURN_TOPLEVEL, 5) \ - f(RBREAK_TAG_JUMP, 6) \ - f(RBREAK_TAG_STOP, 7) + f(RBREAK_TAG_JUMP, 1) \ + f(RBREAK_TAG_STOP, 2) #define RBREAK_TAG_DEFINE(tag, i) tag = i, enum { @@ -1082,12 +1104,12 @@ mrb_break_tag_set(struct RBreak *brk, uint32_t tag) } static struct RBreak* -break_new(mrb_state *mrb, uint32_t tag, const struct RProc *p, mrb_value val) +break_new(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci, mrb_value val) { - struct RBreak *brk; + mrb_assert((size_t)(return_ci - mrb->c->cibase) <= (size_t)(mrb->c->ci - mrb->c->cibase)); - brk = MRB_OBJ_ALLOC(mrb, MRB_TT_BREAK, NULL); - mrb_break_proc_set(brk, p); + struct RBreak *brk = MRB_OBJ_ALLOC(mrb, MRB_TT_BREAK, NULL); + brk->ci_break_index = return_ci - mrb->c->cibase; mrb_break_value_set(brk, val); mrb_break_tag_set(brk, tag); @@ -1191,27 +1213,27 @@ break_tag_p(struct RBreak *brk, uint32_t tag) } static void -prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb_value val) +prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci, mrb_value val) { if (break_tag_p((struct RBreak*)mrb->exc, tag)) { mrb_break_tag_set((struct RBreak*)mrb->exc, tag); } else { - mrb->exc = (struct RObject*)break_new(mrb, tag, proc, val); + mrb->exc = (struct RObject*)break_new(mrb, tag, return_ci, val); } } -#define THROW_TAGGED_BREAK(mrb, tag, proc, val) \ +#define THROW_TAGGED_BREAK(mrb, tag, return_ci, val) \ do { \ - prepare_tagged_break(mrb, tag, proc, val); \ + prepare_tagged_break(mrb, tag, return_ci, val); \ goto L_CATCH_TAGGED_BREAK; \ } while (0) -#define UNWIND_ENSURE(mrb, ci, pc, tag, proc, val) \ +#define UNWIND_ENSURE(mrb, ci, pc, tag, return_ci, val) \ do { \ ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ENSURE); \ if (ch) { \ - THROW_TAGGED_BREAK(mrb, tag, proc, val); \ + THROW_TAGGED_BREAK(mrb, tag, return_ci, val); \ } \ } while (0) @@ -1674,7 +1696,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) if (ch) { /* avoiding a jump from a catch handler into the same handler */ if (a < mrb_irep_catch_handler_unpack(ch->begin) || a >= mrb_irep_catch_handler_unpack(ch->end)) { - THROW_TAGGED_BREAK(mrb, RBREAK_TAG_JUMP, proc, mrb_fixnum_value(a)); + THROW_TAGGED_BREAK(mrb, RBREAK_TAG_JUMP, mrb->c->ci, mrb_fixnum_value(a)); } } } @@ -1812,11 +1834,12 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) recv = p->body.func(mrb, recv); } else { - if (MRB_METHOD_NOARG_P(m)) { + if (MRB_METHOD_NOARG_P(m) && (ci->n > 0 || ci->nk > 0)) { check_method_noarg(mrb, ci); } recv = MRB_METHOD_FUNC(m)(mrb, recv); } + mrb_assert(mrb->c->ci > mrb->c->cibase); mrb_gc_arena_shrink(mrb, ai); if (mrb->exc) goto L_RAISE; ci = mrb->c->ci; @@ -1841,6 +1864,11 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) else { /* setup environment for calling method */ proc = MRB_METHOD_PROC(m); + /* handle alias */ + if (MRB_PROC_ALIAS_P(proc)) { + ci->mid = proc->body.mid; + proc = proc->upper; + } CI_PROC_SET(ci, proc); irep = proc->body.irep; pool = irep->pool; @@ -1854,18 +1882,23 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) CASE(OP_CALL, Z) { mrb_callinfo *ci = mrb->c->ci; mrb_value recv = ci->stack[0]; - struct RProc *m = mrb_proc_ptr(recv); + const struct RProc *p = mrb_proc_ptr(recv); - /* replace callinfo */ - ci->u.target_class = MRB_PROC_TARGET_CLASS(m); - CI_PROC_SET(ci, m); - if (MRB_PROC_ENV_P(m)) { - ci->mid = MRB_PROC_ENV(m)->mid; + /* handle alias */ + if (MRB_PROC_ALIAS_P(p)) { + ci->mid = p->body.mid; + p = p->upper; + } + else if (MRB_PROC_ENV_P(p)) { + ci->mid = MRB_PROC_ENV(p)->mid; } + /* replace callinfo */ + ci->u.target_class = MRB_PROC_TARGET_CLASS(p); + CI_PROC_SET(ci, p); /* prepare stack */ - if (MRB_PROC_CFUNC_P(m)) { - recv = MRB_PROC_CFUNC(m)(mrb, recv); + if (MRB_PROC_CFUNC_P(p)) { + recv = MRB_PROC_CFUNC(p)(mrb, recv); mrb_gc_arena_shrink(mrb, ai); if (mrb->exc) goto L_RAISE; /* pop stackpos */ @@ -1876,8 +1909,8 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) } else { /* setup environment for calling method */ - proc = m; - irep = m->body.irep; + proc = p; + irep = p->body.irep; if (!irep) { mrb->c->ci->stack[0] = mrb_nil_value(); a = 0; @@ -1889,8 +1922,8 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) stack_extend(mrb, irep->nregs); stack_clear(regs+nargs, irep->nregs-nargs); } - if (MRB_PROC_ENV_P(m)) { - regs[0] = MRB_PROC_ENV(m)->stack[0]; + if (MRB_PROC_ENV_P(p)) { + regs[0] = MRB_PROC_ENV(p)->stack[0]; } pc = irep->iseq; } @@ -1902,14 +1935,9 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) CASE(OP_SUPER, BB) { mrb_callinfo *ci = mrb->c->ci; mrb_value recv; - const struct RProc *p = ci->proc; struct RClass* target_class = CI_TARGET_CLASS(ci); mid = ci->mid; - if (MRB_PROC_ENV_P(p) && p->e.env->mid && p->e.env->mid != mid) { /* alias support */ - mid = p->e.env->mid; /* restore old mid */ - } - if (mid == 0 || !target_class) { RAISE_LIT(mrb, E_NOMETHOD_ERROR, "super called outside of method"); } @@ -2198,14 +2226,14 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) if (mrb->exc) { L_RAISE: ci = mrb->c->ci; - while ((ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ALL)) == NULL) { + while ((ch = catch_handler_find(mrb, ci, ci->pc, MRB_CATCH_FILTER_ALL)) == NULL) { if (ci != mrb->c->cibase) { ci = cipop(mrb); - if (ci[1].cci == CINFO_SKIP && prev_jmp) { + if (ci[1].cci == CINFO_SKIP) { + mrb_assert(prev_jmp != NULL); mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } - pc = ci[0].pc; } else if (mrb->c == mrb->root_c) { mrb->c->ci->stack = mrb->c->stbase; @@ -2218,7 +2246,10 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) mrb->c = c->prev; if (!mrb->c) mrb->c = mrb->root_c; else c->prev = NULL; - goto L_RAISE; + if (!c->vmexec) goto L_RAISE; + mrb->jmp = prev_jmp; + if (!prev_jmp) return mrb_obj_value(mrb->exc); + MRB_THROW(prev_jmp); } } @@ -2269,21 +2300,6 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; } - ci = mrb->c->ci; - while (cibase <= ci && ci->proc != dst) { - CHECKPOINT_RESTORE(RBREAK_TAG_RETURN_BLOCK) { - cibase = mrb->c->cibase; - dst = top_proc(mrb, proc); - } - CHECKPOINT_MAIN(RBREAK_TAG_RETURN_BLOCK) { - UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN_BLOCK, proc, v); - } - CHECKPOINT_END(RBREAK_TAG_RETURN_BLOCK); - ci = cipop(mrb); - pc = ci->pc; - } - proc = ci->proc; - mrb->exc = NULL; /* clear break object */ break; } /* fallthrough */ @@ -2306,34 +2322,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) else if (!c->vmexec && c->prev->ci == c->prev->cibase) { RAISE_LIT(mrb, E_FIBER_ERROR, "double resume"); } - CHECKPOINT_RESTORE(RBREAK_TAG_RETURN_TOPLEVEL) { - c = mrb->c; - } - CHECKPOINT_MAIN(RBREAK_TAG_RETURN_TOPLEVEL) { - UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN_TOPLEVEL, proc, v); - } - CHECKPOINT_END(RBREAK_TAG_RETURN_TOPLEVEL); - /* automatic yield at the end */ - c->status = MRB_FIBER_TERMINATED; - mrb->c = c->prev; - mrb->c->status = MRB_FIBER_RUNNING; - c->prev = NULL; - if (c->vmexec) { - mrb_gc_arena_restore(mrb, ai); - c->vmexec = FALSE; - mrb->jmp = prev_jmp; - return v; - } - ci = mrb->c->ci; - } - CHECKPOINT_RESTORE(RBREAK_TAG_RETURN) { - /* do nothing */ - } - CHECKPOINT_MAIN(RBREAK_TAG_RETURN) { - UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_RETURN, proc, v); } - CHECKPOINT_END(RBREAK_TAG_RETURN); - mrb->exc = NULL; /* clear break object */ break; case OP_R_BREAK: if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN; @@ -2348,37 +2337,22 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) goto L_BREAK_ERROR; } } - CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) { - /* do nothing */ - } - CHECKPOINT_MAIN(RBREAK_TAG_BREAK) { - UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK, proc, v); - } - CHECKPOINT_END(RBREAK_TAG_BREAK); - /* break from fiber block */ - if (ci == mrb->c->cibase && ci->pc) { - struct mrb_context *c = mrb->c; - - mrb->c = c->prev; - c->prev = NULL; - ci = mrb->c->ci; + proc = proc->upper; + while (mrb->c->cibase < ci && ci[-1].proc != proc) { + ci--; } - if (ci->cci > CINFO_NONE) { - ci = cipop(mrb); - mrb->exc = (struct RObject*)break_new(mrb, RBREAK_TAG_BREAK, proc, v); - mrb_gc_arena_restore(mrb, ai); - mrb->c->vmexec = FALSE; - mrb->jmp = prev_jmp; - MRB_THROW(prev_jmp); + if (ci == mrb->c->cibase) { + goto L_BREAK_ERROR; } if (FALSE) { struct RBreak *brk; L_BREAK: brk = (struct RBreak*)mrb->exc; - proc = mrb_break_proc_get(brk); + ci = &mrb->c->cibase[brk->ci_break_index]; + proc = ci->proc; v = mrb_break_value_get(brk); - ci = mrb->c->ci; + pc = ci->pc; switch (mrb_break_tag_get(brk)) { #define DISPATCH_CHECKPOINTS(n, i) case n: goto CHECKPOINT_LABEL_MAKE(n); @@ -2388,38 +2362,54 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) mrb_assert(!"wrong break tag"); } } - while (mrb->c->cibase < ci && ci[-1].proc != proc->upper) { - if (ci[-1].cci == CINFO_SKIP) { - goto L_BREAK_ERROR; - } - CHECKPOINT_RESTORE(RBREAK_TAG_BREAK_UPPER) { - /* do nothing */ - } - CHECKPOINT_MAIN(RBREAK_TAG_BREAK_UPPER) { - UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK_UPPER, proc, v); - } - CHECKPOINT_END(RBREAK_TAG_BREAK_UPPER); - ci = cipop(mrb); - pc = ci->pc; - } - CHECKPOINT_RESTORE(RBREAK_TAG_BREAK_INTARGET) { - /* do nothing */ - } - CHECKPOINT_MAIN(RBREAK_TAG_BREAK_INTARGET) { - UNWIND_ENSURE(mrb, ci, pc, RBREAK_TAG_BREAK_INTARGET, proc, v); - } - CHECKPOINT_END(RBREAK_TAG_BREAK_INTARGET); - if (ci == mrb->c->cibase) { - goto L_BREAK_ERROR; - } - mrb->exc = NULL; /* clear break object */ break; default: /* cannot happen */ break; } - mrb_assert(ci == mrb->c->ci); - mrb_assert(mrb->exc == NULL); + + for (;;) { + CHECKPOINT_RESTORE(RBREAK_TAG_BREAK) { + struct RBreak *brk = (struct RBreak*)mrb->exc; + ci = &mrb->c->cibase[brk->ci_break_index]; + v = mrb_break_value_get(brk); + mrb_gc_protect(mrb, v); + } + CHECKPOINT_MAIN(RBREAK_TAG_BREAK) { + UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_BREAK, ci, v); + } + CHECKPOINT_END(RBREAK_TAG_BREAK); + + if (mrb->c->ci == ci) { + break; + } + cipop(mrb); + if (mrb->c->ci[1].cci != CINFO_NONE) { + mrb_assert(prev_jmp != NULL); + mrb->exc = (struct RObject*)break_new(mrb, RBREAK_TAG_BREAK, ci, v); + mrb_gc_arena_restore(mrb, ai); + mrb->c->vmexec = FALSE; + mrb->jmp = prev_jmp; + MRB_THROW(prev_jmp); + } + } + mrb->exc = NULL; /* clear break object */ + + if (ci == mrb->c->cibase) { + struct mrb_context *c = mrb->c; + /* automatic yield at the end */ + c->status = MRB_FIBER_TERMINATED; + mrb->c = c->prev; + mrb->c->status = MRB_FIBER_RUNNING; + c->prev = NULL; + if (c->vmexec) { + mrb_gc_arena_restore(mrb, ai); + c->vmexec = FALSE; + mrb->jmp = prev_jmp; + return v; + } + ci = mrb->c->ci; + } if (mrb->c->vmexec && !CI_TARGET_CLASS(ci)) { mrb_gc_arena_restore(mrb, ai); @@ -3091,7 +3081,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) /* do nothing */ } CHECKPOINT_MAIN(RBREAK_TAG_STOP) { - UNWIND_ENSURE(mrb, mrb->c->ci, pc, RBREAK_TAG_STOP, proc, mrb_nil_value()); + UNWIND_ENSURE(mrb, mrb->c->ci, mrb->c->ci->pc, RBREAK_TAG_STOP, mrb->c->ci, mrb_nil_value()); } CHECKPOINT_END(RBREAK_TAG_STOP); L_STOP: diff --git a/mruby/tasks/libmruby.rake b/mruby/tasks/libmruby.rake index 38878b1e..eafac3d2 100644 --- a/mruby/tasks/libmruby.rake +++ b/mruby/tasks/libmruby.rake @@ -7,36 +7,32 @@ MRuby.each_target do next unless libmruby_enabled? - copy_headers_task = "expose_header_files:#{name}" + copy_headers_task = "expose_header_files:#{self.name}" file libmruby_static => libmruby_objs.flatten do |t| Rake::Task[copy_headers_task].invoke archiver.run t.name, t.prerequisites end - task copy_headers_task do |_t| + task copy_headers_task do |t| # Since header files may be generated dynamically and it is hard to know all of them, # the task is executed depending on when libmruby.a is generated. - gemsbasedir = File.join(build_dir, 'include/mruby/gems') + gemsbasedir = File.join(build_dir, "include/mruby/gems") dirmap = { MRUBY_ROOT => build_dir } - gems.each do |g| + gems.each { |g| dirmap[g.dir] = File.join(gemsbasedir, g.name) dirmap[g.build_dir] = File.join(gemsbasedir, g.name) - end + } dirs = each_header_files.to_a dirs.uniq! dirs.replace_prefix_by(dirmap).zip(dirs).each do |dest, src| - next unless File.mtime(src).to_i > begin - File.mtime(dest).to_i - rescue StandardError - 0 + if File.mtime(src).to_i > (File.mtime(dest).to_i rescue 0) + mkpath File.dirname(dest) + cp src, dest end - - mkpath File.dirname(dest) - cp src, dest end end @@ -50,15 +46,15 @@ MRuby.each_target do FLAGS_MAKE [ - [cc, 'MRUBY_CC', 'MRUBY_CFLAGS'], - [cxx, 'MRUBY_CXX', 'MRUBY_CXXFLAGS'], - [asm, 'MRUBY_AS', 'MRUBY_ASFLAGS'], - [objc, 'MRUBY_OBJC', 'MRUBY_OBJCFLAGS'] + [cc, "MRUBY_CC", "MRUBY_CFLAGS"], + [cxx, "MRUBY_CXX", "MRUBY_CXXFLAGS"], + [asm, "MRUBY_AS", "MRUBY_ASFLAGS"], + [objc, "MRUBY_OBJC", "MRUBY_OBJCFLAGS"] ].each do |cc, cmd, flags| incpaths = cc.include_paths.dup dirmaps = { - MRUBY_ROOT => '$(MRUBY_PACKAGE_DIR)', - build_dir => '$(MRUBY_PACKAGE_DIR)' + MRUBY_ROOT => "$(MRUBY_PACKAGE_DIR)", + build_dir => "$(MRUBY_PACKAGE_DIR)" } gems.each do |g| incpaths.concat g.export_include_paths @@ -74,19 +70,19 @@ MRuby.each_target do f.puts "MRUBY_LD = #{linker.command}" - libgems = gems.reject { |g| g.bin? } - gem_flags = libgems.map { |g| g.linker.flags } - gem_library_paths = libgems.map { |g| g.linker.library_paths } - f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % '$(MRUBY_PACKAGE_DIR)/lib'}" + libgems = gems.reject{|g| g.bin?} + gem_flags = libgems.map {|g| g.linker.flags } + gem_library_paths = libgems.map {|g| g.linker.library_paths } + f.puts "MRUBY_LDFLAGS = #{linker.all_flags(gem_library_paths, gem_flags)} #{linker.option_library_path % "$(MRUBY_PACKAGE_DIR)/lib"}" - gem_flags_before_libraries = libgems.map { |g| g.linker.flags_before_libraries } + gem_flags_before_libraries = libgems.map {|g| g.linker.flags_before_libraries } f.puts "MRUBY_LDFLAGS_BEFORE_LIBS = #{[linker.flags_before_libraries, gem_flags_before_libraries].flatten.join(' ')}" - gem_libraries = libgems.map { |g| g.linker.libraries } - libmruby = toolchains.find { |e| e == 'visualcpp' } ? 'libmruby' : 'mruby' + gem_libraries = libgems.map {|g| g.linker.libraries } + libmruby = (toolchains.find { |e| e == "visualcpp" }) ? "libmruby" : "mruby" f.puts "MRUBY_LIBS = #{linker.option_library % libmruby} #{linker.library_flags(gem_libraries)}" - f.puts "MRUBY_LIBMRUBY_PATH = #{libmruby_static.replace_prefix_by(build_dir => '$(MRUBY_PACKAGE_DIR)')}" + f.puts "MRUBY_LIBMRUBY_PATH = #{libmruby_static.replace_prefix_by(build_dir => "$(MRUBY_PACKAGE_DIR)")}" end end diff --git a/src/http/ngx_http_mruby_async.c b/src/http/ngx_http_mruby_async.c index 175481b3..aca111ef 100644 --- a/src/http/ngx_http_mruby_async.c +++ b/src/http/ngx_http_mruby_async.c @@ -45,10 +45,11 @@ mrb_value ngx_mrb_start_fiber(ngx_http_request_t *r, mrb_state *mrb, struct RPro ctx = ngx_mrb_http_get_module_ctx(mrb, r); ctx->async_handler_result = result; - handler_proc = mrb_closure_new(mrb, rproc->body.irep); + handler_proc = rproc; + handler_proc->upper = NULL; + handler_proc->e.target_class = mrb->object_class; fiber_proc = (mrb_value *)ngx_palloc(r->pool, sizeof(mrb_value)); - *fiber_proc = - mrb_funcall(mrb, mrb_obj_value(mrb->kernel_module), "_ngx_mrb_prepare_fiber", 1, mrb_obj_value(handler_proc)); + *fiber_proc = mrb_fiber_new(mrb, rproc); if (mrb->exc) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "%s NOTICE %s:%d: preparing fiber got the raise, leave the fiber", MODULE_NAME, __func__, __LINE__); @@ -60,7 +61,6 @@ mrb_value ngx_mrb_start_fiber(ngx_http_request_t *r, mrb_state *mrb, struct RPro mrb_value ngx_mrb_run_fiber(mrb_state *mrb, mrb_value *fiber_proc, mrb_value *result) { - mrb_value resume_result = mrb_nil_value(); ngx_http_request_t *r = ngx_mrb_get_request(); mrb_value aliving = mrb_false_value(); mrb_value handler_result = mrb_nil_value(); @@ -69,21 +69,14 @@ mrb_value ngx_mrb_run_fiber(mrb_state *mrb, mrb_value *fiber_proc, mrb_value *re ctx = ngx_mrb_http_get_module_ctx(mrb, r); ctx->fiber_proc = fiber_proc; - resume_result = mrb_funcall(mrb, *fiber_proc, "call", 0, NULL); + handler_result = mrb_fiber_resume(mrb, *fiber_proc, 0, NULL); if (mrb->exc) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "%s NOTICE %s:%d: fiber got the raise, leave the fiber", MODULE_NAME, __func__, __LINE__); return mrb_false_value(); } - if (!mrb_array_p(resume_result)) { - mrb->exc = mrb_obj_ptr(mrb_exc_new_lit( - mrb, E_RUNTIME_ERROR, - "_ngx_mrb_prepare_fiber proc must return array included handler_return and fiber alive status")); - return mrb_false_value(); - } - aliving = mrb_ary_entry(resume_result, 0); - handler_result = mrb_ary_entry(resume_result, 1); + aliving = mrb_fiber_alive_p(mrb, *fiber_proc); if (!mrb_test(aliving) && result != NULL) { *result = handler_result; diff --git a/src/http/ngx_http_mruby_module.c b/src/http/ngx_http_mruby_module.c index 77bafddb..17b2ae31 100644 --- a/src/http/ngx_http_mruby_module.c +++ b/src/http/ngx_http_mruby_module.c @@ -11,6 +11,7 @@ #include "ngx_http_mruby_init.h" #include "ngx_http_mruby_request.h" +#include #include #define ON 1 @@ -910,7 +911,7 @@ ngx_int_t ngx_mrb_run(ngx_http_request_t *r, ngx_mrb_state_t *state, ngx_mrb_cod static ngx_int_t ngx_http_mruby_state_reinit_from_file(ngx_mrb_state_t *state, ngx_mrb_code_t *code) { FILE *mrb_file; - struct mrb_parser_state *p; + mrb_value proc; if ((mrb_file = fopen((char *)code->code.file, "r")) == NULL) { return NGX_ERROR; @@ -919,18 +920,15 @@ static ngx_int_t ngx_http_mruby_state_reinit_from_file(ngx_mrb_state_t *state, n NGX_MRUBY_CODE_MRBC_CONTEXT_FREE(state->mrb, code); code->ctx = mrbc_context_new(state->mrb); mrbc_filename(state->mrb, code->ctx, (char *)code->code.file); - p = mrb_parse_file(state->mrb, mrb_file, code->ctx); + code->ctx->no_exec = TRUE; + proc = mrb_load_file_cxt(state->mrb, mrb_file, code->ctx); fclose(mrb_file); - if (p == NULL || (0 < p->nerr)) { + if (!mrb_proc_p(proc)) { return NGX_ERROR; } - code->proc = mrb_generate_code(state->mrb, p); - mrb_pool_close(p->pool); - if (code->proc == NULL) { - return NGX_ERROR; - } + code->proc = mrb_proc_ptr(proc); return NGX_OK; } @@ -994,10 +992,11 @@ static ngx_int_t ngx_http_mruby_shared_state_init(ngx_mrb_state_t *state) static ngx_int_t ngx_http_mruby_shared_state_compile(ngx_conf_t *cf, ngx_mrb_state_t *state, ngx_mrb_code_t *code) { FILE *mrb_file; - struct mrb_parser_state *p; + mrb_value proc; NGX_MRUBY_CODE_MRBC_CONTEXT_FREE(state->mrb, code); code->ctx = mrbc_context_new(state->mrb); + code->ctx->no_exec = TRUE; #ifdef NGX_MRUBY_IREP_DEBUG code->ctx->dump_result = TRUE; #endif @@ -1007,23 +1006,18 @@ static ngx_int_t ngx_http_mruby_shared_state_compile(ngx_conf_t *cf, ngx_mrb_sta return NGX_ERROR; } mrbc_filename(state->mrb, code->ctx, (char *)code->code.file); - p = mrb_parse_file(state->mrb, mrb_file, code->ctx); + proc = mrb_load_file_cxt(state->mrb, mrb_file, code->ctx); fclose(mrb_file); } else { mrbc_filename(state->mrb, code->ctx, "INLINE CODE"); - p = mrb_parse_string(state->mrb, (char *)code->code.string, code->ctx); - } - - if (p == NULL || (0 < p->nerr)) { - return NGX_ERROR; + proc = mrb_load_string_cxt(state->mrb, (char *)code->code.string, code->ctx); } - code->proc = mrb_generate_code(state->mrb, p); - mrb_pool_close(p->pool); - if (code->proc == NULL) { + if (!mrb_proc_p(proc)) { return NGX_ERROR; } + code->proc = mrb_proc_ptr(proc); #ifdef NGX_MRUBY_IREP_DEBUG /* mrb_codedump_all() is not declared in mruby headers. So just follows the mruby way. See mruby/src/load.c. */ void mrb_codedump_all(mrb_state *, struct RProc *); diff --git a/src/stream/ngx_stream_mruby_async.c b/src/stream/ngx_stream_mruby_async.c index 14289eb3..cec7b2f2 100644 --- a/src/stream/ngx_stream_mruby_async.c +++ b/src/stream/ngx_stream_mruby_async.c @@ -23,7 +23,6 @@ typedef struct { static mrb_value ngx_stream_mrb_run_fiber(mrb_state *mrb, mrb_value *fiber_proc, mrb_value *result) { - mrb_value resume_result = mrb_nil_value(); mrb_value aliving = mrb_false_value(); mrb_value handler_result = mrb_nil_value(); ngx_stream_mruby_ctx_t *ctx; @@ -33,21 +32,14 @@ static mrb_value ngx_stream_mrb_run_fiber(mrb_state *mrb, mrb_value *fiber_proc, ctx = ngx_stream_mrb_get_module_ctx(mrb, ictx->s); ctx->fiber_proc = fiber_proc; - resume_result = mrb_funcall(mrb, *fiber_proc, "call", 0, NULL); + handler_result = mrb_fiber_resume(mrb, *fiber_proc, 0, NULL); if (mrb->exc) { ngx_log_error(NGX_LOG_NOTICE, ictx->s->connection->log, 0, "%s NOTICE %s:%d: fiber got the raise, leave the fiber", MODULE_NAME, __func__, __LINE__); return mrb_false_value(); } - if (!mrb_array_p(resume_result)) { - mrb->exc = mrb_obj_ptr(mrb_exc_new_lit( - mrb, E_RUNTIME_ERROR, - "_ngx_mrb_prepare_fiber proc must return array included handler_return and fiber alive status")); - return mrb_false_value(); - } - aliving = mrb_ary_entry(resume_result, 0); - handler_result = mrb_ary_entry(resume_result, 1); + aliving = mrb_fiber_alive_p(mrb, *fiber_proc); if (!mrb_test(aliving) && result != NULL) { *result = handler_result; @@ -65,10 +57,11 @@ mrb_value ngx_stream_mrb_start_fiber(ngx_stream_session_t *s, mrb_state *mrb, st ctx = ngx_stream_mrb_get_module_ctx(mrb, s); ctx->async_handler_result = result; - handler_proc = mrb_closure_new(mrb, rproc->body.irep); + handler_proc = rproc; + handler_proc->upper = NULL; + handler_proc->e.target_class = mrb->object_class; fiber_proc = (mrb_value *)ngx_palloc(s->connection->pool, sizeof(mrb_value)); - *fiber_proc = - mrb_funcall(mrb, mrb_obj_value(mrb->kernel_module), "_ngx_mrb_prepare_fiber", 1, mrb_obj_value(handler_proc)); + *fiber_proc = mrb_fiber_new(mrb, rproc); if (mrb->exc) { ngx_log_error(NGX_LOG_NOTICE, s->connection->log, 0, "%s NOTICE %s:%d: preparing fiber got the raise, leave the fiber", MODULE_NAME, __func__, __LINE__); diff --git a/src/stream/ngx_stream_mruby_module.c b/src/stream/ngx_stream_mruby_module.c index 4ea28350..3a64e009 100644 --- a/src/stream/ngx_stream_mruby_module.c +++ b/src/stream/ngx_stream_mruby_module.c @@ -10,6 +10,7 @@ #include "ngx_stream_mruby_init.h" +#include #include "mruby/string.h" #define NGX_MRUBY_CODE_MRBC_CONTEXT_FREE(mrb, code) \ @@ -361,7 +362,7 @@ static ngx_mrb_code_t *ngx_stream_mruby_mrb_code_from_string(ngx_pool_t *pool, n static ngx_int_t ngx_stream_mruby_shared_state_compile(ngx_conf_t *cf, mrb_state *mrb, ngx_mrb_code_t *code) { FILE *mrb_file; - struct mrb_parser_state *p; + mrb_value proc; if (code->code_type == NGX_MRB_CODE_TYPE_FILE) { if ((mrb_file = fopen((char *)code->code.file, "r")) == NULL) { @@ -370,24 +371,22 @@ static ngx_int_t ngx_stream_mruby_shared_state_compile(ngx_conf_t *cf, mrb_state NGX_MRUBY_CODE_MRBC_CONTEXT_FREE(mrb, code); code->ctx = mrbc_context_new(mrb); mrbc_filename(mrb, code->ctx, (char *)code->code.file); - p = mrb_parse_file(mrb, mrb_file, code->ctx); + code->ctx->no_exec = TRUE; + proc = mrb_load_file_cxt(mrb, mrb_file, code->ctx); fclose(mrb_file); } else { NGX_MRUBY_CODE_MRBC_CONTEXT_FREE(mrb, code); code->ctx = mrbc_context_new(mrb); mrbc_filename(mrb, code->ctx, "INLINE CODE"); - p = mrb_parse_string(mrb, (char *)code->code.string, code->ctx); + code->ctx->no_exec = TRUE; + proc = mrb_load_string_cxt(mrb, (char *)code->code.string, code->ctx); } - if (p == NULL || (0 < p->nerr)) { + if (!mrb_proc_p(proc)) { return NGX_ERROR; } - code->proc = mrb_generate_code(mrb, p); - mrb_pool_close(p->pool); - if (code->proc == NULL) { - return NGX_ERROR; - } + code->proc = mrb_proc_ptr(proc); if (code->code_type == NGX_MRB_CODE_TYPE_FILE) { ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0, "%s NOTICE %s:%d: compile info: code->code.file=(%s)", MODULE_NAME,