Compare commits

..

185 Commits

Author SHA1 Message Date
KOBAYASHI Shuji 112120969d Use type tag for hash code in ht_hash_func()
The function corresponding to `ht_hash_func()` was as follows in the days of
khash implementation (before d78acc7a).

  ```c
  mrb_hash_ht_hash_func(mrb_state *mrb, mrb_value key)
  {
    enum mrb_vtype t = mrb_type(key);
    ...
    switch (t) {
    ...
    default:
      hv = mrb_funcall(mrb, key, "hash", 0);
      h = (khint_t)t ^ (khint_t)mrb_fixnum(hv);
      break;
    }
    ...
  }
  ```

When switched to the segmented list implementation (d78acc7a), this function
was changed as follows.

  ```c
  sg_hash_func(mrb_state *mrb, seglist *t, mrb_value key)
  {
    enum mrb_vtype tt = mrb_type(key);
    ...
    switch (tt) {
    ...
    default:
      hv = mrb_funcall(mrb, key, "hash", 0);
      h = (size_t)t ^ (size_t)mrb_fixnum(hv);
      break;
    }
    ...
  }
  ```

Since the argument `t` was added, the variable for type tag was changed from
`t` to `tt`, but the variable used in the expression of `h` remained `t`.

Probably this is an omission of change, so fixed it.
2020-07-29 09:17:32 +09:00
Yukihiro "Matz" Matsumoto 63956036e1 Fix the VM stack handling bug in 'mrb_yield_with_class()`; fix #5042 2020-07-29 09:09:37 +09:00
dearblue cdf45438f0 Fixed shift width for MRB_ENV_SET_BIDX()
ref c07f24cd1 and close #5035
2020-07-29 09:05:29 +09:00
Hiroshi Mimaki b6b9c57f24 Update version to 2.1.2. (mruby 2.1.2 RC) 2020-07-01 16:49:21 +09:00
Hiroshi Mimaki aa578c346d Revert "Free the original pointer if realloc failed."
This reverts commit 9cdf439db5.
2020-06-30 18:33:47 +09:00
Yukihiro "Matz" Matsumoto ac8360003e Fix the bug that mrbc generates a.rb.mrb instead of a.mrb.
The bug was introduced by 9dfe50f1d.
2020-06-29 07:25:03 +09:00
Yukihiro "Matz" Matsumoto 233cb49903 Remove unnecessary stack adjustment in OP_CALL. 2020-06-25 06:57:43 +09:00
Yukihiro "Matz" Matsumoto 9cdf439db5 Free the original pointer if realloc failed.
The POSIX `realloc` keep the original pointer untouched, so it can
easily leads to memory leakage. `mrb_realloc()` should handle those
bookkeeping, while `mrb_realloc_simple()` keeps the original `realloc`
behavior.
2020-06-25 06:57:43 +09:00
Yukihiro "Matz" Matsumoto 95360a17f2 Remove unnecessary break from numeric.c. 2020-06-25 06:57:42 +09:00
Yukihiro "Matz" Matsumoto 9dfe50f1d9 Use snprintf instead of memcpy in mrbc.c. 2020-06-25 06:57:42 +09:00
Yukihiro "Matz" Matsumoto c07f24cd18 Change flag names in preparation of REnv refactoring. 2020-06-25 06:57:41 +09:00
Yukihiro "Matz" Matsumoto 03c2b8656b Use mrb_get_argc() to improve performance. 2020-06-25 06:57:41 +09:00
Yukihiro "Matz" Matsumoto ea6e1b003c Create codeql-analysis.yml 2020-06-23 12:36:20 +09:00
Yukihiro "Matz" Matsumoto c2b37e76b3 Skip mrb_get_args() in mrb_ary_{aget,aset} unless necessary.
Use simpler `mrb_get_argc()` and `mrb_get_arg1()` instead.
2020-06-22 21:47:23 +09:00
Yukihiro "Matz" Matsumoto d40b922c98 Fix potential buffer overflow in sprintf.c. 2020-06-20 18:56:33 +09:00
Yukihiro "Matz" Matsumoto 28e793496a Support integer and float combination in mrb_equal(). 2020-06-20 18:56:05 +09:00
Yukihiro "Matz" Matsumoto 33c8d6af1e Move definition of BasicObject#!= to mrblib.
C implementation used `mrb_funcall()` that bypassed many optimization.
2020-06-20 14:09:23 +09:00
Yukihiro "Matz" Matsumoto 49ae2a69f2 Add mrb_get_arg1() that retrieves single (and only) argument.
`mrb_get_arg1()` raises `ArgumentError` if the method does not receive one
argument.

And replaces all `mrb_get_args(mrb, "o", &arg)` by the new function.
2020-06-20 12:49:46 +09:00
Yukihiro "Matz" Matsumoto 2ffb77586a Symbolify saved alias name to improve performance. 2020-06-20 12:07:49 +09:00
Yukihiro "Matz" Matsumoto dad99afae8 Remove unnecessary comments from MRB_TT_* definitions. 2020-06-15 09:54:55 +09:00
Yukihiro "Matz" Matsumoto f93dffb5ee Remove unused MRB_TT_FILE. 2020-06-15 07:47:22 +09:00
Yukihiro "Matz" Matsumoto 742117e7a3 Reorganize gray mark functions in GC. 2020-06-11 16:18:52 +09:00
Yukihiro "Matz" Matsumoto 15ceb35e05 Remove GC test code from ancient. 2020-06-11 16:18:51 +09:00
Yukihiro "Matz" Matsumoto f0bad600e0 Remove endian configuration methods.
Since we made our opcode byte based, we need no endian option (`-e`
and `-E`) to `mrbc`.
2020-06-11 16:18:50 +09:00
Yukihiro "Matz" Matsumoto a8aeba89ef Merge pull request #5023 from dearblue/nesting
Remove `mrb_assert()` in `Module.nesting`
2020-06-11 12:21:26 +09:00
Yukihiro "Matz" Matsumoto 7f593893e8 Update OP_HASH generation to support big hash creation. 2020-06-09 22:42:38 +09:00
Yukihiro "Matz" Matsumoto 5d5b1d1f3c Merge pull request #5022 from dearblue/test-dir
Need `build/XXX/mrbgems/mruby-test` directory
2020-06-09 22:42:29 +09:00
Yukihiro "Matz" Matsumoto bb6846468a Merge pull request #5021 from dearblue/kernel-test
Update `test/t/kernel.rb`
2020-06-09 22:41:44 +09:00
dearblue 960c82e396 Remove mrb_assert() in Module.nesting
The following code was causing SIGSEGV:

```ruby
Module.method(:nesting).call
```
2020-06-09 21:54:13 +09:00
dearblue 5be33b82c7 Need build/XXX/mrbgems/mruby-test directory
An error may occur when performing `rake clean all` or `rake clean test`.

The directory is needed before writing to `mrbgems/mruby-test/assert.c`.
2020-06-09 21:24:53 +09:00
dearblue 4cd858f93d Update test/t/kernel.rb
- Remove unnecessoury assert
- Fix typo
2020-06-09 20:33:56 +09:00
Yukihiro "Matz" Matsumoto 2098acee7d Merge pull request #5020 from jethrodaniel/master
only use GEMNAME if defined in assert.rb
2020-06-08 15:51:03 +09:00
Mark Delk 3157efa57c only use GEMNAME if defined in assert.rb
Check if the constant GEMNAME is defined before use in `assert.rb`.

This is added to prevent an undefined constant error when using
`assert.rb` in other environments - for example, testing CRuby.
2020-06-08 00:30:46 -05:00
Yukihiro "Matz" Matsumoto 613e0bee5e Merge pull request #5013 from shuujii/print-exception-backtrace-if-possible-without--v-in-test
Print exception backtrace if possible without `-v` in test
2020-06-08 09:59:43 +09:00
Yukihiro "Matz" Matsumoto 78c9c71bdf Add proper cast. 2020-06-05 17:52:22 +09:00
Yukihiro "Matz" Matsumoto aa30b13b36 Change arena index from mrb_int to int. 2020-06-05 17:26:40 +09:00
Yukihiro "Matz" Matsumoto 6ba542cd53 Revert part of #5019 (mruby_io_test.c) to honor #4987
The issue was reported by @shuujii.
2020-06-05 17:20:41 +09:00
Yukihiro "Matz" Matsumoto 106f4c4e9d Add proper casts to silence VC warnings. 2020-06-05 16:04:30 +09:00
Yukihiro "Matz" Matsumoto f1523d2404 Squashed commit of the following:
commit 2d7d545c4c4bfce7fdcbcbe9baaeb437915742f0
Merge: 625a1249 b178914b
Author: Yukihiro "Matz" Matsumoto <matz@ruby.or.jp>
Date:   Fri Jun 5 14:35:13 2020 +0900

    Merge branch 'fix-mrb_open-with-nomem' of https://github.com/dearblue/mruby into dearblue-fix-mrb_open-with-nomem

commit b178914b11
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 22:22:44 2019 +0900

    Fix invalid pointer free inside other heap's block

     1. `e = mrb_obj_alloc(...)`
     2. `e->stack = mrb->c->stack` (`mrb->c->stack` is anywhere in the range `stbase...stend`)
     3. And raised exception by `mrb_malloc()`!
     4. `mrb_free(e->stack)` by GC part (wrong free)

commit 52e3d5d858
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 21:55:36 2019 +0900

    Fix memory leak for temporary symbols when out of memory

commit 4c5499b88e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 11:42:07 2019 +0900

    Fix uninitialized pointer dereference for debug section

commit 8e993167de
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 11:41:09 2019 +0900

    Fix memory leak for temporary filenames when out of memory

commit 8b422577e6
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 10:57:51 2019 +0900

    Fix memory leak for irep when out of memory

commit 6b35ebf49a
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 10:55:50 2019 +0900

    Fix uninitialized pointer dereference when do not finished initializing irep

commit 2531f2631e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 10:48:15 2019 +0900

    Fix NULL pointer dereference when do not finished initializing irep

commit e2d6896eba
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 12:54:19 2019 +0900

    Fix memory leak for irep when out of memory by `mrb_proc_new()`

commit b6214ff8a0
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 12:53:07 2019 +0900

    Fix memory leak for `khash_t` in `kh_init_size()` when out of memory by `kh_alloc()`

commit 19162dd6c1
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 02:15:07 2019 +0900

    Fix memory leak for symbol string when out of memory in `kh_put()`

commit 15e67297ff
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 02:12:24 2019 +0900

    Fix keep wrong symbol index when out of memory

commit 3f8e2b3752
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 02:08:13 2019 +0900

    Fix keep wrong symbol capacity when out of memory

commit a3cfe755ab
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 10:11:37 2019 +0900

    Fix NULL pointer dereference `mrb->c` by `mark_context()`

commit d9c7b6be6e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 15:25:09 2019 +0900

    Fix protect exception for print error message

commit 100642750e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 11:59:02 2019 +0900

    Protect exception for mruby core initialization

commit 7a0418304e
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Fri Jan 18 20:38:27 2019 +0900

    Fix memory leak for string object when out of memory

    The `mrb_str_pool()` function has a path to call `malloc()` twice.

    If occurs `NoMemoryError` exception in second `malloc()`,
    first `malloc()` pointer is not freed.

commit fef1c152ce
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sat Jan 19 13:05:09 2019 +0900

    Fix stack overflow when out of memory

    As a result of this change, no backtrace information is set
    for NoMemoryError (`mrb->nomem_err`).

    Detailes:

    When generating a backtrace, called `mrb_intern_lit()`,
    `mrb_str_new_cstr()` and `mrb_obj_iv_set()` function with
    `exc_debug_info()` function in `src/error.c`.

    If a `NoMemoryError` exception occurs at this time,
    the `exc_debug_info()` function will be called again,
    and in the same way `NoMemoryError` exception raised will result
    in an infinite loop to occurs stack overflow (and SIGSEGV).

commit da7d7f881b
Author: dearblue <dearblue@users.noreply.github.com>
Date:   Sun Jan 20 12:00:38 2019 +0900

    Fix NULL pointer dereference `mrb->nomem_err` when not initialized

    Add internal functions (not `static`):

      * `mrb_raise_nomemory()`
      * `mrb_core_init_abort()`
2020-06-05 14:40:07 +09:00
Yukihiro "Matz" Matsumoto 00f6271e3b Change arena index from mrb_int to int. 2020-06-05 14:40:07 +09:00
Yukihiro "Matz" Matsumoto b0e49ef79e Merge pull request #5019 from mruby/stable
Merge mruby 2.1.1
2020-06-05 13:04:36 +09:00
Hiroshi Mimaki 81d340e042 Merge master. 2020-06-05 12:42:56 +09:00
Yukihiro "Matz" Matsumoto 4e40169ed6 Remove rake -v option from GitHub Actions. 2020-06-04 18:24:58 +09:00
Yukihiro "Matz" Matsumoto 49f1c0e94d Ignore files for clangd.
- `compile_flags.txt'
- `compile_commands.json`
2020-06-04 18:09:03 +09:00
Yukihiro "Matz" Matsumoto dcfebc6eed Remove bison installation from GitHub Actions. 2020-06-04 18:08:08 +09:00
Hiroshi Mimaki f9d113f764 Update release date. 2020-06-04 17:20:46 +09:00
Yukihiro "Matz" Matsumoto 3d2d9f8a9b Add explicit cast to DROP_PRECISION macro in rtional.c. 2020-06-04 11:01:31 +09:00
Yukihiro "Matz" Matsumoto 07129c76d9 Add mruby-complex and mruby-rational to default.gembox. 2020-06-04 11:01:30 +09:00
Yukihiro "Matz" Matsumoto 6fe03f3b39 Add explicit cast to silence warnings on AppVeyor. 2020-06-04 11:01:30 +09:00
Yukihiro "Matz" Matsumoto 41f3456a28 Merge pull request #4865 from take-cheeze/istruct_align
Align RIStruct data for rational/complex
2020-06-04 11:01:04 +09:00
Yukihiro "Matz" Matsumoto 7a420d4bba Add .ccls* to .gitignore. 2020-06-04 10:05:42 +09:00
Yukihiro "Matz" Matsumoto d2b9c90f28 Merge branch 'dearblue-hide-func'; merge #4937 2020-06-03 14:16:11 +09:00
dearblue ce12ef7e5c Hiding method implementation C functions in mruby-io 2020-06-03 14:12:51 +09:00
Yukihiro "Matz" Matsumoto 8bca11a64e Merge pull request #4800 from shuujii/set-MRB_STR_ASCII-flag-to-some-stringize-methods
Set `MRB_STR_ASCII` flag to some stringize methods
2020-06-03 14:01:52 +09:00
Yukihiro "Matz" Matsumoto 14e325e45d Merge branch 'dearblue-eval-patchfree'; close #5016 2020-06-02 14:49:49 +09:00
dearblue f85906b679 Remove patch_irep() in mruby-eval
- It can now deal with operands in the range of `OP_EXT*`.
- It can now call the same method as the variable name without arguments.

  ```ruby
  def a
    "Safe!"
  end

  a = "Auto!"

  eval "a()" # call method `a`
  ```
2020-06-02 14:49:27 +09:00
Yukihiro "Matz" Matsumoto 1fc9345b45 Add mruby-eval to default.gembox. 2020-06-01 23:00:37 +09:00
Yukihiro "Matz" Matsumoto 0a5983dd5e Merge pull request #5014 from dearblue/local_variables
Get local variable names from orphan block; ref #3710
2020-06-01 22:58:17 +09:00
Yukihiro "Matz" Matsumoto aec40d10b8 Merge pull request #5017 from RoryO/master
Fix float constant redefinition warnings
2020-06-01 21:26:57 +09:00
Rory OConnell 89ceb3e7ba Fix float constant redefinition warnings 2020-05-31 20:11:38 -07:00
dearblue fc80e4b651 Get local variable names from orphan block; ref #3710 2020-05-31 15:56:04 +09:00
KOBAYASHI Shuji 52ab095ccf Print exception backtrace if possible without -v in test
Backtrace is useful for debugging.
2020-05-29 13:46:16 +09:00
Yukihiro "Matz" Matsumoto d5cca2bdb2 Check c->eidx before decrement in ecall(); close #4977 2020-05-28 18:53:27 +09:00
Yukihiro "Matz" Matsumoto ebbb4fd7fb Merge pull request #5011 from shuujii/respect-CFLAGS-CXXFLAGS-and-LDFLAGS-env-vars-in-appveyor_config.rb
Respect CFLAGS, CXXFLAGS, and LDFLAGS env vars in appveyor_config.rb
2020-05-27 22:15:44 +09:00
KOBAYASHI Shuji b717cc7830 Respect CFLAGS, CXXFLAGS, and LDFLAGS env vars in appveyor_config.rb
[skip travis]
2020-05-27 16:50:44 +09:00
Yukihiro "Matz" Matsumoto a476c83caf Move fmt_setup until absolutely necessary. 2020-05-27 14:09:36 +09:00
Yukihiro "Matz" Matsumoto 15c63688e3 Integer format can be bigger than 32 on 64bit platforms.
We made it `64` which should be big enough:
- Format modifier: 4 characters max
- Maximum width: 19 digits max
- Period between width and precision: 1 character
- Maximum precision: 19 digits max
- Format specifier: 1 character
- NUL terminator: 1 byte
- Total: 45 < 64
2020-05-26 23:53:16 +09:00
Yukihiro "Matz" Matsumoto 69c62415c0 Merge pull request #5010 from udzura/patch-1
Detect newly added mrbgems when re-creating gem_init.c
2020-05-26 23:37:22 +09:00
Kondo Uchio 690b2aa761 Detect newly added mrbgems when re-creating gem_init.c 2020-05-26 23:15:00 +09:00
Yukihiro "Matz" Matsumoto 69311fa4c9 Merge pull request #5009 from shuujii/removed-Bison-related-settings-from-.travis.yml-and-appveyor.yml
Removed Bison related settings from `.travis.yml` and `appveyor.yml`
2020-05-26 20:17:49 +09:00
Yukihiro "Matz" Matsumoto ab9be1b48a Merge pull request #5008 from shuujii/revert-part-of-Start-GitHub-Actions
Revert part of "Start GitHub Actions" (4ce3997c)
2020-05-26 12:43:38 +09:00
KOBAYASHI Shuji 5a682bfc7b Removed Bison related settings from .travis.yml and appveyor.yml 2020-05-26 11:56:35 +09:00
KOBAYASHI Shuji 53ea8abea6 Revert part of "Start GitHub Actions" (4ce3997c)
Because some changes have been overridden.
2020-05-26 11:48:42 +09:00
Yukihiro "Matz" Matsumoto 6445e4683f Specify the latest bison on macOS; ref #4903 2020-05-26 08:17:39 +09:00
Yukihiro "Matz" Matsumoto 6d49ec25a9 Merge pull request #5007 from shuujii/add-y.tab.c-to-remove-Bison-from-build-dependencies
Add `y.tab.c` to remove Bison from build dependencies; ref 4ce3997c
2020-05-26 08:17:23 +09:00
KOBAYASHI Shuji a3ec6ede76 Add y.tab.c to remove Bison from build dependencies; ref 4ce3997c
I sometimes see Bison related problems in setting up build environments.
Therefore to remove Bison from build time dependencies, add `y.tab.c`
generated by Bison to the repository.

The reduction of dependency at build time also reduces the labor and time
for setup and installation in CI.

In addition, a path in `#line` directive is converted to a relative path so
that its path is constant regardless of development environments.
2020-05-25 23:26:30 +09:00
Yukihiro "Matz" Matsumoto 6803ddb8e2 Use the newer bison on GitHub actions macOS; ref #4903
`Windows-MinGW` and `Windows-VC` also requires updates.
2020-05-24 23:12:27 +09:00
Takeshi Watanabe 4ce3997ca4 Start GitHub Actions; close #4903 2020-05-24 22:34:28 +09:00
Yukihiro "Matz" Matsumoto 93e78fcde1 Merge pull request #5006 from mame/fix-send-with-splat-args
Do not destruct rest arguments for __send__
2020-05-24 08:31:06 +09:00
Yusuke Endoh 6f4c585bd7 Do not destruct rest arguments for __send__
Formerly, `__send__(*args)` modified `args` with `Array#shift`.
This bug affects optcarrot.

This changeset avoids the array destruction by using
`args = args[1, len-1]`.
2020-05-24 01:25:03 +09:00
Yukihiro "Matz" Matsumoto 47ea60814b Merge pull request #5003 from shuujii/retry-rake--m-on-AppVeyor
Retry `rake -m` on AppVeyor [skip travis]
2020-05-20 13:49:10 +09:00
KOBAYASHI Shuji 86223b6eca Retry rake -m on AppVeyor [skip travis]
The following error occurs when using `rake -m` on AppVeyor:

  ```
  fatal error C1041: cannot open program database 'C:\projects\mruby\vc140.pdb'; if multiple CL.EXE write to the same .PDB file, please use /FS
  ```

Therefore, the issue is solved by not creating the PDB file. It is expected
to be somewhat faster by not generating debugging information (I don't think
debugging information is necessary for normal CI).
2020-05-20 13:32:23 +09:00
Yukihiro "Matz" Matsumoto d79147fe5d Revert "Use rake -m (multi-task) to appveyor.yml."
This reverts commit ac68c90800.
`rake -m` does not work for VisualC.
2020-05-19 22:42:19 +09:00
Yukihiro "Matz" Matsumoto ac68c90800 Use rake -m (multi-task) to appveyor.yml. 2020-05-19 17:37:17 +09:00
Yukihiro "Matz" Matsumoto 82194c01ca Merge pull request #5002 from RoryO/master
Adding warnings for mrb_load functions leaking RProc objects
2020-05-19 17:34:56 +09:00
Rory OConnell 69bc477b43 Adding warnings for mrb_load functions leaking RProc objects 2020-05-19 01:07:49 -07:00
Yukihiro "Matz" Matsumoto 3655d4e0f4 Merge pull request #5000 from shuujii/unify-eql-receiver-in-Hash-according-to-Ruby
Unify `eql?` receiver in `Hash` according to Ruby
2020-05-15 23:42:19 +09:00
KOBAYASHI Shuji bc929656fb Unify eql? receiver in Hash according to Ruby
### Example

  ```ruby
  # example.rb
  class A
    def eql?(o)
      p self.class
      super
    end
    def hash
      1
    end
  end

  class B < A; end

  h = {A.new => 1}
  h[B.new]
  ```

#### Before this patch:

  ```console
  $ bin/mruby example.rb
  A
  ```

#### After this patch (same as Ruby)

  ```console
  $ bin/mruby example.rb
  B
  ```
2020-05-15 21:17:24 +09:00
Yukihiro "Matz" Matsumoto 4aba93c969 Rename C function mrb_proc_lambda. 2020-05-15 15:55:35 +09:00
Yukihiro "Matz" Matsumoto 49d97d6051 Add pread/pwrite support on __MACH__ (MacOS) in addition to __unix__. 2020-05-15 12:31:18 +09:00
Yukihiro "Matz" Matsumoto 484577670f Remove YYERROR_VERBOSE which no longer supported since bison 3.6.
Instead we added `%define parse.error verbose`.
2020-05-15 12:30:13 +09:00
Yukihiro "Matz" Matsumoto d64c4d64e6 Make off_t handling simpler; #4872 #4939
The newer `clang` warns implicit float conversions.
2020-05-11 10:14:25 +09:00
Yukihiro "Matz" Matsumoto 846af371c0 Merge pull request #4998 from dearblue/special-vars
Get an irep symbol if it's `OP_GETSV` or `OP_SETSV`
2020-05-11 09:59:23 +09:00
Yukihiro "Matz" Matsumoto 38b4483f9d Merge pull request #4999 from dearblue/opcode-doc
Update `doc/opcode.md` [ci skip]
2020-05-11 09:58:11 +09:00
dearblue bb2512641f Update doc/opcode.md [ci skip]
The difference of `include/mruby/ops.h` is applied.

- OP_NOP - update semantics
- OP_GETSV - update semantics
- OP_SETSV - update semantics
- OP_GETUPVAR - update prefix
- OP_SETUPVAR - update prefix
- OP_JMPIF - update operands and semantics
- OP_JMPNOT - update operands and semantics
- OP_JMPNIL - add entry
- OP_ONERR - update semantics
- OP_POPERR - update prefix
- OP_EPOP - update prefix
- OP_SENDB - update semantics
- OP_ADD - update prefix and operands
- OP_ADDI - update operands and semantics
- OP_SUB - update prefix and operands
- OP_SUBI - update semantics
- OP_MUL - update prefix and operands
- OP_DIV - update prefix and operands
- OP_EQ - update prefix and operands
- OP_LT - update prefix and operands
- OP_LE - update prefix and operands
- OP_GT - update prefix and operands
- OP_GE - update prefix and operands
- OP_ARYDUP - add entry
- OP_INTERN - add entry
- OP_HASHCAT - add entry
- OP_ERR - update semantics
2020-05-10 20:34:10 +09:00
dearblue bd60ad98eb Get an irep symbol if it's OP_GETSV or OP_SETSV 2020-05-10 20:15:55 +09:00
Yukihiro "Matz" Matsumoto 7826af38ac Merge pull request #4997 from dearblue/byteorder
Remove byteorder constants; ref 87576b8
2020-05-09 23:01:02 +09:00
Yukihiro "Matz" Matsumoto 84d842ea5c Merge pull request #4996 from dearblue/loadi16
Fix boundary check for `OP_LOADI16`; ref fa8668c
2020-05-09 22:41:23 +09:00
dearblue f6c2662632 Remove byteorder constants; ref 87576b8
The `FLAG_BYTEORDER_NATIVE` and `FLAG_BYTEORDER_NONATIVE` are no longer
needed.
2020-05-09 22:30:05 +09:00
dearblue e2aecacaeb Fix boundary check for OP_LOADI16; ref fa8668c
It was making a negative integer if the highest-order bit of a 16-bit
integer was 1.

no patched:

```ruby
p 0x7fff  # => 32767
p 0x8000  # => -32768
p 0xffff  # => -1
p 0x10000 # => 65536
```
2020-05-09 21:12:31 +09:00
Yukihiro "Matz" Matsumoto 8cdf6a87ed Merge pull request #4995 from shuujii/fix-some-Hash-methods-are-inconsistent-with-values
Fix some `Hash` methods are inconsistent with `values`
2020-05-09 18:59:22 +09:00
KOBAYASHI Shuji 181f7b97d6 Fix some Hash methods are inconsistent with values
Inconsistent when hash has duplicate key.

### Example

  ```ruby
  # example.rb
  keys = (1..3).map{[_1]}
  h = keys.to_h{[_1, _1[0]]}
  keys[0][0] = 2
  p h.values
  p h.each_value.to_a
  p h
  ```

#### Before this patch:

  ```console
  $ bin/mruby example.rb
  [1, 2, 3]
  [1, 1, 3]
  {[2]=>1, [2]=>1, [3]=>3}
  ```

#### After this patch (same as Ruby)

  ```console
  $ bin/mruby example.rb
  [1, 2, 3]
  [1, 2, 3]
  {[2]=>1, [2]=>2, [3]=>3}
  ```
2020-05-09 15:27:42 +09:00
Yukihiro "Matz" Matsumoto 3491372a1d Update doc/opcode.md for operand signs. [ci skip] 2020-05-07 18:41:43 +09:00
Yukihiro "Matz" Matsumoto 03b0741994 Remove unnecessary sprintf test that fails since 91368c1. 2020-05-07 10:31:49 +09:00
Yukihiro "Matz" Matsumoto a87f0b158d Update README.md to address old bison problem on macOS. 2020-05-07 10:17:38 +09:00
Yukihiro "Matz" Matsumoto e82b8b7bf8 Update cmpnum document.
`cmpnum` function may return `nil` on error.
2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 91368c117c Avoid mrb_funcall if MRB_UFT8_STRING is not set. 2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 87576b819e Remove endian information/flags from compiled binary format.
Since `mruby 2.0`, compiled bytecode no longer depends on the
endian of the machine.
2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 48c473a0c4 Remove -e/-E options from mrbc.
You don't have to specify endian since `mruby 2.0`.
2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 87d77c13f5 Update compiled binary format version for OP_LOADI16. 2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 4188219620 Update doc/opcode.md to reflect the latest bytecode.
- Add `OP_LOADI16`
- Update keyword argument related ops (e.g. OP_KEY_P, etc.)
- Fix some wrong descriptions
2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto fa8668c77d Add a new instruction OP_LOADI16.
Which loads 16bit integer to the register. The instruction number should
be reorder on massive instruction refactoring. The instruction is added
for `mruby/c` which had performance issue with `OP_EXT`. With this
instruction, `mruby/c` VM can just raise errors on `OP_EXT` extension
instructions.
2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 47f5f887e8 Fix wrong line number before comment line; fix #4993 2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto c143d87e7c Remove mrb_run from MRB_API; #4488
`mrb_run` requires to push callinfo stack before calling, which is very
hard from outside of `vm.c`. So there should be virtually no correct
usage of the function, hence the cause of #4488. We removed it.

You can use `mrb_top_run(mrb, proc, self, 0)` instead of
`mrb_run(mrb, proc self)`.
2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 2fcdd3f8eb Add assertion as originally intended; ref #4986 2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 8c0dc55af8 Update doc/guides/compile.md to note the bison failure on Mac. 2020-05-07 08:38:46 +09:00
Yukihiro "Matz" Matsumoto 8c04379a4c Merge pull request #4990 from komainu8/enable-method-t-struct-on-32bit-linux
Enable MRB_METHOD_T_STRUCT by default on 32bit GUN/Linux
2020-05-05 22:57:40 +09:00
Horimoto Yasuhiro a5bfe548d7 Enable MRB_METHOD_T_STRUCT by default on 32bit GUN/Linux
Because we can't use the highest 2 bits of function pointers.
2020-05-04 15:34:16 +09:00
Yukihiro "Matz" Matsumoto 84aad39940 Merge pull request #4987 from shuujii/avoid-changing-directory-in-mruby-io-test
Avoid changing directory in `mruby-io` test
2020-04-30 17:13:11 +09:00
Yukihiro "Matz" Matsumoto c89ca5ebb8 Merge pull request #4988 from shuujii/refine-.travis.yml
Refine `.travis.yml`
2020-04-30 17:12:36 +09:00
KOBAYASHI Shuji 1a4b86233f Refine .travis.yml
* Disable automatic update and clean up on `brew install` (install time
  160 sec -> 5 sec).
* Avoid using deprecated keys.
2020-04-30 13:42:24 +09:00
Yukihiro "Matz" Matsumoto 69a487c407 Merge pull request #4984 from dearblue/break-to_s
Sorting the list of gems at build time by name
2020-04-30 08:38:33 +09:00
Yukihiro "Matz" Matsumoto f32c73ad1f Merge pull request #4986 from dearblue/assert-io
Avoid comparing pointers and integers
2020-04-29 18:34:40 +09:00
Yukihiro "Matz" Matsumoto a343439973 Merge pull request #4985 from dearblue/print-gems
Makes `mrb_any_to_s()` accept an object whose class is `NULL`
2020-04-29 18:34:03 +09:00
KOBAYASHI Shuji aeb86d953e Avoid changing directory in mruby-io test 2020-04-29 17:48:01 +09:00
dearblue 49bba6c997 Avoid comparing pointers and integers 2020-04-29 17:18:09 +09:00
dearblue 49b2e8c3a9 Makes mrb_any_to_s() accept an object whose class is NULL
When using `mrb_any_to_s()` for debugging purposes, giving an object
whose class is `NULL` no longer causes a SIGSEGV and no crash.
This is achieved by making `mrb_class_name()` and `mrb_str_cat_cstr()`
null safe.
2020-04-29 16:59:16 +09:00
dearblue 9c1220e14d Sorting the list of gems at build time by name
Printing them in sorted order makes it easier to find the desired gem.
But it has come to completely ignore the dependency.
2020-04-29 16:55:18 +09:00
Yukihiro "Matz" Matsumoto e2ac2a82a5 Should not use assert with expressions with side-effect; ref #4981
`assert()` can be completely removed when `NDEBUG` is set.
2020-04-28 22:37:14 +09:00
Yukihiro "Matz" Matsumoto bb6290a5d5 Fixed wrong condition in #4981. 2020-04-28 22:34:33 +09:00
Yukihiro "Matz" Matsumoto 312411dea0 Add #include <string.h> on all platforms for strncpy; #4981 2020-04-28 22:34:33 +09:00
Yukihiro "Matz" Matsumoto 7277682cfb Remove unused local variable if MRB_UTF8_STRING is not set.
Ref #4982 #4983
2020-04-28 22:34:01 +09:00
Yukihiro "Matz" Matsumoto 0f229bfbbf Avoid snprintf in mruby-io test; ref #4981 2020-04-28 18:30:50 +09:00
Yukihiro "Matz" Matsumoto 28b23b44ec Remove the temporary file from the AF_UNIX socket test; #4981 2020-04-28 18:13:43 +09:00
Yukihiro "Matz" Matsumoto 8627157298 Fix IO#readchar to return broken UTF-8 rather than EOF error.
The behavior is different from CRuby, but we believe this is a right
behavior for mruby, which only supports either ASCII or UTF-8
exclusively; fix #4983, ref #4982

```
$ printf '\xe3\x81' | ruby -e 'p STDIN.readchar'
"\xE3\x81"
```

```
$ printf '\xe3\x81' | mruby -e 'p STDIN.readchar'
"\xE3"
```
2020-04-28 18:07:17 +09:00
Yukihiro "Matz" Matsumoto b87268f130 Fix IO#readchar to support UTF-8 char reading; fix #4712
This fix only effective when `MRB_UTF8_STRING` is set.
2020-04-28 13:57:46 +09:00
Yukihiro "Matz" Matsumoto a395f8e2c8 Rename (and expose) UTF-8 related functions; ref #4712
- mrb_utf8len() - returns the size of a UTF-8 char (in bytes)
- mrb_utf8_strlen() - returns the length of a UTF-8 string (in char)
2020-04-28 13:57:46 +09:00
Yukihiro "Matz" Matsumoto 3ce459f23a Fix _read_buf to be more efficient; fix #4982
The bug was introduced by #4712. The `getc' problem resurrected.
It should be addressed soon.
2020-04-28 13:57:46 +09:00
Yukihiro "Matz" Matsumoto e51923778f Fix IO#sysread to update buffer string on EOF; ref #4982 2020-04-28 13:57:46 +09:00
Yukihiro "Matz" Matsumoto 468578113a Update IO#ungetc to keep @buf string; ref #4982 2020-04-28 13:57:46 +09:00
Yukihiro "Matz" Matsumoto 2c32154115 Fix UTF-8 boundary check; ref #4982 2020-04-28 13:57:46 +09:00
Yukihiro "Matz" Matsumoto 47d99457d9 Merge pull request #4981 from udzura/fix-test-mruby-io-on-vboxsf
Test mruby-io in tmpdir when AF_UNIX cannot be created on cwd
2020-04-28 09:46:56 +09:00
Uchio Kondo 88b756b39f Fix typo and include location 2020-04-28 01:52:56 +09:00
Uchio Kondo 462ff4cc84 Skip socket check on windows 2020-04-28 01:49:39 +09:00
Uchio Kondo 18274e717a Follow C90 style 2020-04-28 01:45:46 +09:00
Uchio Kondo 7870f74c21 Test mruby-io in tmpdir when AF_UNIX cannot be created on cwd 2020-04-28 01:33:50 +09:00
Yukihiro "Matz" Matsumoto 8dee2e3984 Updating parse.y for recent bison` (retry). 2020-04-27 18:52:43 +09:00
Yukihiro "Matz" Matsumoto 8e86e64d78 Revert "Change obsolete %pure-parser to %define api.pure."
This reverts commit 682a31f92b.
Unfortunately, I couldn't run newer `bison` on TravisCI. Maybe next
time.
2020-04-27 12:27:56 +09:00
Yukihiro "Matz" Matsumoto e79e972255 Update .travis.yml to support newer bison on MacOS.
If it doesn't work, I will revert the last update to `parse.y`.
2020-04-27 12:21:35 +09:00
Yukihiro "Matz" Matsumoto 682a31f92b Change obsolete %pure-parser to %define api.pure.
Recent `bison` warns for `%pure-parser`. We kept it since MacOS only
provide ancient `bison`, but the warning is noisy and there's no hope
that Apple will upgrade `bison`. MacOS users must install the newer
version of `bison`, by typing `brew install bison` for example.

Note that `brew` does not overwrite the `bison` execution path
automatically, so you need to update your `.bash_profile` as instructed
by `brew`.
2020-04-27 09:00:22 +09:00
Yukihiro "Matz" Matsumoto 17974aa285 Merge pull request #4978 from dearblue/test-ensure
Integrate class `EnsureYieldBreak` under test
2020-04-27 09:00:13 +09:00
Yukihiro "Matz" Matsumoto 0a7fd86d59 Merge pull request #4980 from dearblue/context
Reduce `struct mrb_context`
2020-04-27 08:59:19 +09:00
Yukihiro "Matz" Matsumoto d95d46dee6 Merge pull request #4979 from dearblue/mruby-bin
Remove unused `mruby-error` in `mruby-bin-mruby`
2020-04-27 08:56:50 +09:00
dearblue 81c8352179 Integrate class EnsureYieldBreak under test 2020-04-26 21:16:44 +09:00
dearblue 6d80c9505d Remove unused mruby-error in mruby-bin-mruby 2020-04-26 21:16:22 +09:00
dearblue 1b0cf6a91b Reduce struct mrb_context 2020-04-26 21:15:24 +09:00
Yukihiro "Matz" Matsumoto 954ce5379c Implemented argument forwarding by ... 2020-04-25 00:00:22 +09:00
Yukihiro "Matz" Matsumoto 8b5c19218d Merge pull request #4976 from dearblue/splice-undef
Support `undef` for `mrb_ary_splice()` instead of `[]`
2020-04-24 23:36:12 +09:00
Yukihiro "Matz" Matsumoto f6408c7b11 Merge pull request #4975 from dearblue/io-comment
Removed comments mentioning `MRB_WITHOUT_FLOAT`; ref 2e661e8
2020-04-24 23:35:10 +09:00
dearblue 095aae5e2c Removed comments mentioning MRB_WITHOUT_FLOAT; ref 2e661e8
The comment is for messages when `MRB_INT16` and `MRB_WITHOUT_FLOAT` are
specified at the same time.
The comment itself is no longer needed now that `MRB_INT16` is gone.
2020-04-24 21:47:20 +09:00
dearblue 26eb29547b Support undef for mrb_ary_splice() instead of []
When removing elements from an array, it is possible to avoid creating
an empty array.

Before this patch:

```c
mrb_ary_splice(mrb, ary, head, len, mrb_ary_new(mrb));
```

After this patch:

```c
mrb_ary_splice(mrb, ary, head, len, mrb_undef_value());
```
2020-04-24 21:32:35 +09:00
Yukihiro "Matz" Matsumoto d3a02a297f Fix instance_exec and class_exec to avoid crash on indirect calls.
Thank you @shuujii to additional report on #4973
2020-04-22 16:48:33 +09:00
Yukihiro "Matz" Matsumoto ab508e1e7f Make mrb_obj_instance_eval to use mrb_singleton_class_ptr; #4973 2020-04-22 16:47:26 +09:00
Yukihiro "Matz" Matsumoto 87d1bbe947 Add new function mrb_singleton_class_ptr(); ref #4973
The difference between `mrb_singleton_class` and `mrb_singleton_class_ptr`:

- `mrb_singleton_class_ptr` returns `struct RClass*`.
- `mrb_singleton_class_ptr` returns `NULL` on immediate values where
  `mrb_singleton_class` raises exceptions.
2020-04-22 16:44:39 +09:00
Yukihiro "Matz" Matsumoto 2e661e82d1 Removed comments mentioning MRB_INT16. 2020-04-21 20:47:22 +09:00
Yukihiro "Matz" Matsumoto 61c6832b48 Fix the bug by #instance_eval called via a method object; fix #4973
The tranpoline code in 6a0b68f8b was wrong; reverted.
2020-04-21 15:44:21 +09:00
Yukihiro "Matz" Matsumoto ed0038fdf2 Simplified mrb_obj_instance_eval; ref #4973 2020-04-21 15:43:35 +09:00
Yukihiro "Matz" Matsumoto c181d89c9d Kernel#clone and Kernel#dup no longer raise TypeError; fix #4974
In ISO, those methods should raise `TypeError`, but the spec has been
changed.  The change was discussed in [Feature#12979].
2020-04-21 13:21:12 +09:00
Yukihiro "Matz" Matsumoto c91c9e2429 Merge pull request #4968 from dearblue/check-fd
Check the file descriptor with `IO#initialize`; resolve #4966
2020-04-15 09:58:20 +09:00
Yukihiro "Matz" Matsumoto 7add524041 Selecting fd should be less than FD_SETSIZE; close #4966 2020-04-14 14:51:22 +09:00
Yukihiro "Matz" Matsumoto 72928f201c Merge pull request #4972 from dearblue/boxnan-cptr
Fix `MRB_TT_CPTR` object with `MRB_NAN_BOXING`
2020-04-14 14:51:00 +09:00
Yukihiro "Matz" Matsumoto 81a9210091 Merge pull request #4969 from dearblue/nostdio-pack
Support `MRB_DISABLE_STDIO` for mruby-pack; ref #4954
2020-04-14 14:46:25 +09:00
Yukihiro "Matz" Matsumoto e9877bc72a Merge pull request #4970 from dearblue/nostdio-sprintf
Support `MRB_DISABLE_STDIO` for mruby-sprintf; ref #4954
2020-04-14 14:45:26 +09:00
Yukihiro "Matz" Matsumoto ea632ab8a4 Merge pull request #4971 from dearblue/mruby-config
Fixed a build error in mruby-config
2020-04-14 09:29:00 +09:00
dearblue d0501c69b0 Fix MRB_TT_CPTR object with MRB_NAN_BOXING
Previously, if `MRB_NAN_BOXING` is defined, for example,
`mrb_cptr_value()` could not keep an odd address.

If it is `MRB_32BIT`, it can be embedded in `NaN` as it is.

If it is `MRB_64BIT`, some operations are shared with `MRB_WORD_BOXING`.
In this case, the MRB_API function `mrb_nan_boxing_cptr_value()` is
defined.
2020-04-13 23:12:09 +09:00
dearblue 3c03385e2e Check the file descriptor with IO#initialize; resolve #4966 2020-04-12 14:18:36 +09:00
dearblue 191ccbf660 Support MRB_DISABLE_STDIO for mruby-sprintf; ref #4954 2020-04-11 22:11:24 +09:00
dearblue d983269908 Add mrb_float_to_cstr() MRB_API function
In order to share the same operation with `mrb_float_to_str()`,
the internal structure is modified.
2020-04-11 22:11:24 +09:00
dearblue 2ceab2d270 Supports some specifier flags with mrb_float_to_str()
Changed to understand `#`, `0`, `-`, ` ` and `+`.

Based on src/stdio/vfprintf.c in git://git.musl-libc.org/musl
2020-04-11 22:11:10 +09:00
dearblue 8ce3664305 Supports width specifier with mrb_float_to_str()
Based on src/stdio/vfprintf.c in git://git.musl-libc.org/musl
2020-04-11 22:10:57 +09:00
dearblue ccd8485111 Add missing MRB_API 2020-04-11 21:59:30 +09:00
dearblue 70caf4ed6d Fixed a build error in mruby-config
The build error occurred when the "build/XXX/bin" directory did not exist.
2020-04-11 15:43:24 +09:00
dearblue b7c8bf7781 Support MRB_DISABLE_STDIO for mruby-pack; ref #4954 2020-04-11 15:29:07 +09:00
take-cheeze 6af555b394 Align RIStruct data for rational 2019-12-13 04:41:43 +09:00
KOBAYASHI Shuji ad6c58972c Set MRB_STR_ASCII flag to some stringize methods
- `Fixnum#to_s`, `Fixnum#inspect`
- `Float#to_s`, `Float#inspect`
- `NilClass#to_s`, `NilClass#inspect`
- `FalseClass#to_s`, `FalseClass#inspect`
- `TrueClass#to_s`, `TrueClass#inspect`
- `Time#to_s`, `Time#inspect`
2019-10-31 22:04:56 +09:00
99 changed files with 14886 additions and 1656 deletions
+106
View File
@@ -0,0 +1,106 @@
name: Build & Test
on: [push, pull_request]
jobs:
Ubuntu-1604:
runs-on: ubuntu-16.04
steps:
- uses: actions/checkout@v1
- name: apt
run: sudo apt install ruby gperf
- name: build and test
run: rake -m -j4 all test
env:
MRUBY_CONFIG: travis_config.rb
Ubuntu-1804-gcc:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1
- name: apt
run: sudo apt install ruby gperf gcc g++
- name: build and test
run: rake -m -j4 all test
env:
MRUBY_CONFIG: travis_config.rb
CC: gcc
CXX: g++
Ubuntu-1804-clang:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1
- name: apt
run: sudo apt install ruby gperf
- name: build and test
run: rake -m -j4 all test
env:
MRUBY_CONFIG: travis_config.rb
CC: clang
CXX: clang++
macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- name: brew
run: brew install ruby gperf
- name: build and test
run: rake -m -j4 all test
env:
MRUBY_CONFIG: travis_config.rb
Windows-MinGW:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: chocolatey
run: choco install -y ruby gperf
- name: build and test
run: rake -E '$stdout.sync=true' -j4 test
env:
MRUBY_CONFIG: travis_config.rb
CFLAGS: -g -O1 -Wall -Wundef
Windows-Cygwin:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
with:
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
key: ${{ runner.os }}-cygwin-chocolatey-${{ matrix.os }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-cygwin-chocolatey-${{ matrix.os }}-
${{ runner.os }}-cygwin-chocolatey-
- name: chocolatey
run: choco install -y cygwin
- name: Install cygwin packages
shell: cmd
run: C:\tools\cygwin\cygwinsetup.exe -qgnNdO -R C:/tools/cygwin -l C:/tools/cygwin/package -s http://mirrors.kernel.org/sourceware/cygwin/ -P gcc-core,gcc-g++,make,gperf,ruby
- name: Set ENV
run: |
echo '::set-env name=PATH::C:\tools\cygwin\bin;C:\tools\cygwin\usr\bin'
- name: build and test
shell: cmd
run: C:\tools\cygwin\bin\ruby.exe /usr/bin/rake -m -j4 -E 'STDOUT.sync=true' test
env:
MRUBY_CONFIG: travis_config.rb
Windows-VC:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: chocolatey
run: choco install -y ruby gperf
- name: build and test
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
rake -E "STDOUT.sync=true" -m -j4 test
env:
MRUBY_CONFIG: appveyor_config.rb
# TODO(take-cheeze): Re-enable /O2
CFLAGS: "/c /nologo /W3 /we4013 /Zi /MD /D_CRT_SECURE_NO_WARNINGS"
CXXFLAGS: "/c /nologo /W3 /Zi /MD /EHs /D_CRT_SECURE_NO_WARNINGS"
+51
View File
@@ -0,0 +1,51 @@
name: "Code scanning - action"
on:
push:
pull_request:
schedule:
- cron: '0 19 * * 4'
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+3
View File
@@ -17,6 +17,9 @@
.svn
.vscode
.yardoc
.ccls*
compile_flags.txt
compile_commands.json
cscope.files
cscope.out
tags
+6 -9
View File
@@ -1,14 +1,11 @@
language: c
sudo: false
matrix:
include:
- os: linux
sudo: false
- os: osx
osx_image: xcode7.1
jobs:
- os: linux
- os: osx
env:
- MRUBY_CONFIG=travis_config.rb
script: "rake -m && rake test"
script:
- rake -m && rake test
+1 -1
View File
@@ -6,7 +6,7 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "mruby"
PROJECT_NUMBER = 2.1.1
PROJECT_NUMBER = 2.1.2
PROJECT_BRIEF = "mruby is the lightweight implementation of the Ruby language"
+5 -1
View File
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
The stable version 2.1.1 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.1.zip](https://github.com/mruby/mruby/archive/2.1.1.zip)
The stable version 2.1.2 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.1.2.zip](https://github.com/mruby/mruby/archive/2.1.2.zip)
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
@@ -46,6 +46,10 @@ To run the tests, execute the following from the project's root directory.
$ rake test
Note: `bison` bundled with MacOS is too old to compile `mruby`.
Try `brew install bison` and follow the instuction shown to update
the `$PATH` to compile `mruby`.
## Building documentation
There are two sets of documentation in mruby: the mruby API (generated by yard) and C API (Doxygen)
+1 -12
View File
@@ -4,11 +4,6 @@ os: Visual Studio 2017
shallow_clone: true
cache:
- win_flex_bison
environment:
matrix:
# Visual Studio 2017 64bit
@@ -38,13 +33,7 @@ init:
- ruby --version
install:
- if not exist win_flex_bison (
appveyor DownloadFile "https://github.com/lexxmark/winflexbison/releases/download/v.2.5.10/win_flex_bison-2.5.10.zip" &
7z x -y -owin_flex_bison win_flex_bison-2.5.10.zip
)
build_script:
- set YACC=.\win_flex_bison\win_bison.exe
- set MRUBY_CONFIG=appveyor_config.rb
- rake -m
- rake -E $stdout.sync=true test
+9
View File
@@ -1,3 +1,9 @@
def setup_option(conf)
conf.cc.flags[0].delete("/Zi") unless ENV['CFLAGS']
conf.cxx.flags[0].delete("/Zi") unless ENV['CFLAGS'] || ENV['CXXFLAGS']
conf.linker.flags << "/DEBUG:NONE" unless ENV['LDFLAGS']
end
MRuby::Build.new('full-debug') do |conf|
toolchain :visualcpp
enable_debug
@@ -5,6 +11,7 @@ MRuby::Build.new('full-debug') do |conf|
# include all core GEMs
conf.gembox 'full-core'
conf.cc.defines += %w(MRB_GC_STRESS MRB_METHOD_CACHE MRB_ENABLE_DEBUG_HOOK)
setup_option(conf)
conf.enable_test
end
@@ -17,6 +24,7 @@ MRuby::Build.new do |conf|
conf.compilers.each do |c|
c.defines += %w(MRB_GC_FIXED_ARENA)
end
setup_option(conf)
conf.enable_bintest
conf.enable_test
end
@@ -28,6 +36,7 @@ MRuby::Build.new('cxx_abi') do |conf|
conf.compilers.each do |c|
c.defines += %w(MRB_GC_FIXED_ARENA)
end
setup_option(conf)
conf.enable_bintest
conf.enable_test
+6 -2
View File
@@ -6,12 +6,16 @@ binaries.
## Prerequisites
To compile mruby out of the source code you need the following tools:
* C Compiler (e.g. `gcc`)
* Linker (e.g. `gcc`)
* C Compiler (e.g. `gcc` or `clang`)
* Linker (e.g. `gcc` or `clang`)
* Archive utility (e.g. `ar`)
* Parser generator (e.g. `bison`)
* Ruby 2.0 or later (e.g. `ruby` or `jruby`)
Note that `bison` bundled with MacOS is too old to compile `mruby`.
Try `brew install bison` and follow the instuction shown to update
the `$PATH` to compile `mruby`.
Optional:
* GIT (to update mruby source and integrate mrbgems easier)
* C++ compiler (to use GEMs which include \*.cpp, \*.cxx, \*.cc)
+1 -1
View File
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
mruby 2.1.1 (2020-04-20)
mruby 2.1.2 (2020-07-10)
```
## 2.2 Basic Operation
+10 -10
View File
@@ -38,7 +38,7 @@ puts [1,2,3]
3
```
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
```
[1, 2, 3]
@@ -61,7 +61,7 @@ end
`ZeroDivisionError` is raised.
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
No exception is raised.
@@ -89,7 +89,7 @@ p Liste.new "foobar"
` [] `
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
`ArgumentError` is raised.
@@ -119,7 +119,7 @@ false
true
```
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
```
true
@@ -156,7 +156,7 @@ p 'ok'
ok
```
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
```
test.rb:8: undefined method 'test_func' (NoMethodError)
@@ -178,7 +178,7 @@ defined?(Foo)
nil
```
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
`NameError` is raised.
@@ -195,7 +195,7 @@ alias $a $__a__
` nil `
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
Syntax error
@@ -217,7 +217,7 @@ end
`ArgumentError` is raised.
The re-defined `+` operator does not accept any arguments.
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
` 'ab' `
Behavior of the operator wasn't changed.
@@ -233,7 +233,7 @@ $ ruby -e 'puts Proc.new {}.binding'
#<Binding:0x00000e9deabb9950>
```
#### mruby [2.1.1 (2020-04-20)]
#### mruby [2.1.2 (2020-07-10)]
```
$ ./bin/mruby -e 'puts Proc.new {}.binding'
@@ -255,7 +255,7 @@ $ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
[[{"a"=>1}], {:b=>2}]
```
#### mruby [mruby 2.1.1]
#### mruby [mruby 2.1.2]
```
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
+108 -95
View File
@@ -16,7 +16,6 @@ In the table.1 below, the second field describes the size (and
sign) of operands.
* B: 8bit
* sB: signed 8bit
* S: 16bit
* sS: signed 16bit
* W: 24bit
@@ -31,97 +30,111 @@ with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
## table.1 Instruction Table
| Instruction Name | Operand type | Semantics |
|:-----------------|--------------|---------------------|
| OP_NOP | - | |
| OP_MOVE" | BB | R(a) = R(b)
| OP_LOADL" | BB | R(a) = Pool(b)
| OP_LOADI" | BsB | R(a) = mrb_int(b)
| OP_LOADI_0' | B | R(a) = 0
| OP_LOADI_1' | B | R(a) = 1
| OP_LOADI_2' | B | R(a) = 2
| OP_LOADI_3' | B | R(a) = 3
| OP_LOADSYM" | BB | R(a) = Syms(b)
| OP_LOADNIL' | B | R(a) = nil
| OP_LOADSELF' | B | R(a) = self
| OP_LOADT' | B | R(a) = true
| OP_LOADF' | B | R(a) = false
| OP_GETGV" | BB | R(a) = getglobal(Syms(b))
| OP_SETGV" | BB | setglobal(Syms(b), R(a))
| OP_GETSV" | BB | R(a) = Special[b]
| OP_SETSV" | BB | Special[b] = R(a)
| OP_GETIV" | BB | R(a) = ivget(Syms(b))
| OP_SETIV" | BB | ivset(Syms(b),R(a))
| OP_GETCV" | BB | R(a) = cvget(Syms(b))
| OP_SETCV" | BB | cvset(Syms(b),R(a))
| OP_GETCONST" | BB | R(a) = constget(Syms(b))
| OP_SETCONST" | BB | constset(Syms(b),R(a))
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b)
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a)
| OP_GETUPVAR' | BBB | R(a) = uvget(b,c)
| OP_SETUPVAR' | BBB | uvset(b,c,R(a))
| OP_JMP | S | pc+=a
| OP_JMPIF' | SB | if R(b) pc+=a
| OP_JMPNOT' | SB | if !R(b) pc+=a
| OP_ONERR | sS | rescue_push(pc+a)
| OP_EXCEPT' | B | R(a) = exc
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b))
| OP_POPERR | B | a.times{rescue_pop()}
| OP_RAISE' | B | raise(R(a))
| OP_EPUSH' | B | ensure_push(SEQ[a])
| OP_EPOP | B | A.times{ensure_pop().call}
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1))
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
| OP_CALL' | B | R(a) = self.call(frame.argc, frame.argv)
| OP_SUPER' | BB | R(a) = super(R(a+1),... ,R(a+b+1))
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4)
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1)
| OP_KARG" | BB | R(a) = kdict[Syms(Bx)] # todo
| OP_KARG2" | BB | R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
| OP_RETURN' | B | return R(a) (normal)
| OP_RETURN_BLK' | B | return R(a) (in-block return)
| OP_BREAK' | B | break R(a)
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4)
| OP_ADD" | BB | R(a) = R(a)+R(a+1)
| OP_ADDI" | BBB | R(a) = R(a)+mrb_int(c)
| OP_SUB" | BB | R(a) = R(a)-R(a+1)
| OP_SUBI" | BB | R(a) = R(a)-C
| OP_MUL" | BB | R(a) = R(a)*R(a+1)
| OP_DIV" | BB | R(a) = R(a)/R(a+1)
| OP_EQ" | BB | R(a) = R(a)==R(a+1)
| OP_LT" | BB | R(a) = R(a)<R(a+1)
| OP_LE" | BB | R(a) = R(a)<=R(a+1)
| OP_GT" | BB | R(a) = R(a)>R(a+1)
| OP_GE" | BB | R(a) = R(a)>=R(a+1)
| OP_ARRAY' | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b))
| OP_ARRAY2" | BB | R(a) = ary_new(R(b),R(b+1)..R(b+c))
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1))
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1))
| OP_AREF' | BB | R(a) = R(a)[b]
| OP_ASET' | BB | R(a)[b] = R(a+1)
| OP_APOST' | BB | *R(a),R(A+1)..R(A+C) = R(a)[B..]
| OP_STRING" | BB | R(a) = str_dup(Lit(b))
| OP_STRCAT' | B | str_cat(R(a),R(a+1))
| OP_HASH' | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b))
| OP_HASHADD' | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b))
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA)
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK)
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD)
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE)
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE)
| OP_OCLASS' | B | R(a) = ::Object
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1))
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b))
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b])
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1))
| OP_ALIAS' | B | alias_method(R(a),R(a+1),R(a+2))
| OP_UNDEF" | BB | undef_method(R(a),Syms(b))
| OP_SCLASS' | B | R(a) = R(a).singleton_class
| OP_TCLASS' | B | R(a) = target_class
| OP_ERR' | B | raise(RuntimeError, Lit(Bx))
| OP_EXT1 | - | make 1st operand 16bit
| OP_EXT2 | - | make 2nd operand 16bit
| OP_EXT3 | - | make 1st and 2nd operands 16bit
| OP_STOP | - | stop VM
| Instruction Name | Operand type | Semantics |
|------------------|--------------|--------------------------------------------------------|
| OP_NOP | - | no operation |
| OP_MOVE" | BB | R(a) = R(b) |
| OP_LOADL" | BB | R(a) = Pool(b) |
| OP_LOADI" | BB | R(a) = mrb_int(b) |
| OP_LOADINEG" | BB | R(a) = mrb_int(-b) |
| OP_LOADI__1' | B | R(a) = mrb_int(-1) |
| OP_LOADI_0' | B | R(a) = mrb_int(0) |
| OP_LOADI_1' | B | R(a) = mrb_int(1) |
| OP_LOADI_2' | B | R(a) = mrb_int(2) |
| OP_LOADI_3' | B | R(a) = mrb_int(3) |
| OP_LOADI_4' | B | R(a) = mrb_int(4) |
| OP_LOADI_5' | B | R(a) = mrb_int(5) |
| OP_LOADI_6' | B | R(a) = mrb_int(6) |
| OP_LOADI_7' | B | R(a) = mrb_int(7) |
| OP_LOADI16' | BsS | R(a) = mrb_int(b) |
| OP_LOADSYM" | BB | R(a) = Syms(b) |
| OP_LOADNIL' | B | R(a) = nil |
| OP_LOADSELF' | B | R(a) = self |
| OP_LOADT' | B | R(a) = true |
| OP_LOADF' | B | R(a) = false |
| OP_GETGV" | BB | R(a) = getglobal(Syms(b)) |
| OP_SETGV" | BB | setglobal(Syms(b), R(a)) |
| OP_GETSV" | BB | R(a) = Special[Syms(b)] |
| OP_SETSV" | BB | Special[Syms(b)] = R(a) |
| OP_GETIV" | BB | R(a) = ivget(Syms(b)) |
| OP_SETIV" | BB | ivset(Syms(b),R(a)) |
| OP_GETCV" | BB | R(a) = cvget(Syms(b)) |
| OP_SETCV" | BB | cvset(Syms(b),R(a)) |
| OP_GETCONST" | BB | R(a) = constget(Syms(b)) |
| OP_SETCONST" | BB | constset(Syms(b),R(a)) |
| OP_GETMCNST" | BB | R(a) = R(a)::Syms(b) |
| OP_SETMCNST" | BB | R(a+1)::Syms(b) = R(a) |
| OP_GETUPVAR" | BBB | R(a) = uvget(b,c) |
| OP_SETUPVAR" | BBB | uvset(b,c,R(a)) |
| OP_JMP | S | pc=a |
| OP_JMPIF' | BS | if R(a) pc=b |
| OP_JMPNOT' | BS | if !R(a) pc=b |
| OP_JMPNIL' | BS | if R(a)==nil pc=b |
| OP_ONERR | S | rescue_push(a) |
| OP_EXCEPT' | B | R(a) = exc |
| OP_RESCUE" | BB | R(b) = R(a).isa?(R(b)) |
| OP_POPERR' | B | a.times{rescue_pop()} |
| OP_RAISE' | B | raise(R(a)) |
| OP_EPUSH' | B | ensure_push(SEQ[a]) |
| OP_EPOP' | B | A.times{ensure_pop().call} |
| OP_SENDV" | BB | R(a) = call(R(a),Syms(b),*R(a+1)) |
| OP_SENDVB" | BB | R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) |
| OP_SEND" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) |
| OP_SENDB" | BBB | R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c),&R(a+c+1)) |
| OP_CALL | - | R(0) = self.call(frame.argc, frame.argv) |
| OP_SUPER" | BB | R(a) = super(R(a+1),... ,R(a+b+1)) |
| OP_ARGARY' | BS | R(a) = argument array (16=5:1:5:1:4) |
| OP_ENTER | W | arg setup according to flags (23=5:5:1:5:5:1:1) |
| OP_KEY_P" | BB | R(a) = kdict.key?(Syms(b)) |
| OP_KEYEND | - | raise unless kdict.empty? |
| OP_KARG" | BB | R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) |
| OP_RETURN' | B | return R(a) (normal) |
| OP_RETURN_BLK' | B | return R(a) (in-block return) |
| OP_BREAK' | B | break R(a) |
| OP_BLKPUSH' | BS | R(a) = block (16=5:1:5:1:4) |
| OP_ADD' | B | R(a) = R(a)+R(a+1) |
| OP_ADDI" | BB | R(a) = R(a)+mrb_int(b) |
| OP_SUB' | B | R(a) = R(a)-R(a+1) |
| OP_SUBI" | BB | R(a) = R(a)-mrb_int(b) |
| OP_MUL' | B | R(a) = R(a)*R(a+1) |
| OP_DIV' | B | R(a) = R(a)/R(a+1) |
| OP_EQ' | B | R(a) = R(a)==R(a+1) |
| OP_LT' | B | R(a) = R(a)<R(a+1) |
| OP_LE' | B | R(a) = R(a)<=R(a+1) |
| OP_GT' | B | R(a) = R(a)>R(a+1) |
| OP_GE' | B | R(a) = R(a)>=R(a+1) |
| OP_ARRAY" | BB | R(a) = ary_new(R(a),R(a+1)..R(a+b)) |
| OP_ARRAY2" | BBB | R(a) = ary_new(R(b),R(b+1)..R(b+c)) |
| OP_ARYCAT' | B | ary_cat(R(a),R(a+1)) |
| OP_ARYPUSH' | B | ary_push(R(a),R(a+1)) |
| OP_ARYDUP' | B | R(a) = ary_dup(R(a)) |
| OP_AREF" | BBB | R(a) = R(b)[c] |
| OP_ASET" | BBB | R(a)[c] = R(b) |
| OP_APOST" | BBB | *R(a),R(a+1)..R(a+c) = R(a)[b..] |
| OP_INTERN' | B | R(a) = intern(R(a)) |
| OP_STRING" | BB | R(a) = str_dup(Lit(b)) |
| OP_STRCAT' | B | str_cat(R(a),R(a+1)) |
| OP_HASH" | BB | R(a) = hash_new(R(a),R(a+1)..R(a+b)) |
| OP_HASHADD" | BB | R(a) = hash_push(R(a),R(a+1)..R(a+b)) |
| OP_HASHCAT' | B | R(a) = hash_cat(R(a),R(a+1)) |
| OP_LAMBDA" | BB | R(a) = lambda(SEQ[b],OP_L_LAMBDA) |
| OP_BLOCK" | BB | R(a) = lambda(SEQ[b],OP_L_BLOCK) |
| OP_METHOD" | BB | R(a) = lambda(SEQ[b],OP_L_METHOD) |
| OP_RANGE_INC' | B | R(a) = range_new(R(a),R(a+1),FALSE) |
| OP_RANGE_EXC' | B | R(a) = range_new(R(a),R(a+1),TRUE) |
| OP_OCLASS' | B | R(a) = ::Object |
| OP_CLASS" | BB | R(a) = newclass(R(a),Syms(b),R(a+1)) |
| OP_MODULE" | BB | R(a) = newmodule(R(a),Syms(b)) |
| OP_EXEC" | BB | R(a) = blockexec(R(a),SEQ[b]) |
| OP_DEF" | BB | R(a).newmethod(Syms(b),R(a+1)) |
| OP_ALIAS" | BB | alias_method(target_class,Syms(a),Syms(b)) |
| OP_UNDEF' | B | undef_method(target_class,Syms(a)) |
| OP_SCLASS' | B | R(a) = R(a).singleton_class |
| OP_TCLASS' | B | R(a) = target_class |
| OP_DEBUG" | BBB | print a,b,c |
| OP_ERR' | B | raise(LocalJumpError, Lit(a)) |
| OP_EXT1 | - | make 1st operand 16bit |
| OP_EXT2 | - | make 2nd operand 16bit |
| OP_EXT3 | - | make 1st and 2nd operands 16bit |
| OP_STOP | - | stop VM |
|------------------|--------------|--------------------------------------------------------|
+3 -2
View File
@@ -39,8 +39,9 @@
/* add -DMRB_METHOD_T_STRUCT on machines that use higher bits of pointers */
/* no MRB_METHOD_T_STRUCT requires highest 2 bits of function pointers to be zero */
#ifndef MRB_METHOD_T_STRUCT
// can't use highest 2 bits of function pointers on 32bit Windows.
# if defined(_WIN32) && !defined(_WIN64)
// can't use highest 2 bits of function pointers at least on 32bit
// Windows and 32bit Linux.
# ifdef MRB_32BIT
# define MRB_METHOD_T_STRUCT
# endif
#endif
+18 -3
View File
@@ -76,6 +76,7 @@
#include <mruby/version.h>
#ifndef MRB_WITHOUT_FLOAT
#include <float.h>
#ifndef FLT_EPSILON
#define FLT_EPSILON (1.19209290e-07f)
#endif
@@ -164,8 +165,8 @@ struct mrb_context {
struct RProc **ensure; /* ensure handler stack */
uint16_t esize, eidx;
enum mrb_fiber_state status;
mrb_bool vmexec;
enum mrb_fiber_state status : 4;
mrb_bool vmexec : 1;
struct RFiber *fib;
};
@@ -317,7 +318,9 @@ MRB_API struct RClass *mrb_define_class(mrb_state *mrb, const char *name, struct
* @return [struct RClass *] Reference to the newly defined module.
*/
MRB_API struct RClass *mrb_define_module(mrb_state *mrb, const char *name);
MRB_API mrb_value mrb_singleton_class(mrb_state *mrb, mrb_value val);
MRB_API struct RClass *mrb_singleton_class_ptr(mrb_state *mrb, mrb_value val);
/**
* Include a module in another class or module.
@@ -956,8 +959,21 @@ mrb_get_mid(mrb_state *mrb) /* get method symbol */
*/
MRB_API mrb_int mrb_get_argc(mrb_state *mrb);
/**
* Retrieve an array of arguments from mrb_state.
*
* Correctly handles *splat arguments.
*/
MRB_API mrb_value* mrb_get_argv(mrb_state *mrb);
/**
* Retrieve the first and only argument from mrb_state.
* Raises ArgumentError unless the number of arguments is exactly one.
*
* Correctly handles *splat arguments.
*/
MRB_API mrb_value mrb_get_arg1(mrb_state *mrb);
/* `strlen` for character string literals (use with caution or `strlen` instead)
Adjacent string literals are concatenated in C/C++ in translation phase 6.
If `lit` is not one, the compiler will report a syntax error:
@@ -1148,7 +1164,6 @@ MRB_API void mrb_close(mrb_state *mrb);
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
MRB_API mrb_value mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *iseq);
+4
View File
@@ -239,6 +239,7 @@ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
* @param head Beginning position of a replacement subsequence.
* @param len Length of a replacement subsequence.
* @param rpl The array of replacement elements.
* It is possible to pass `mrb_undef_value()` instead of an empty array.
* @return The receiver array.
*/
MRB_API mrb_value mrb_ary_splice(mrb_state *mrb, mrb_value self, mrb_int head, mrb_int len, mrb_value rpl);
@@ -291,6 +292,9 @@ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
*/
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
/* helper functions */
mrb_value mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len);
MRB_END_DECL
#endif /* MRUBY_ARRAY_H */
+11 -2
View File
@@ -44,6 +44,9 @@ typedef struct mrb_value {
};
)
};
#ifdef MRB_64BIT
struct RCptr *vp;
#endif
} value;
};
} mrb_value;
@@ -54,13 +57,15 @@ typedef struct mrb_value {
#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < (o).value.ttt ? mrb_tt(o) : MRB_TT_FLOAT)
#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)((o).value.p)))<<2))
#define mrb_float(o) (o).f
#define mrb_cptr(o) mrb_ptr(o)
#define mrb_fixnum(o) (o).value.i
#define mrb_symbol(o) (o).value.sym
#ifdef MRB_64BIT
MRB_API mrb_value mrb_nan_boxing_cptr_value(struct mrb_state*, void*);
#define mrb_cptr(o) (((struct RCptr*)mrb_ptr(o))->p)
#define BOXNAN_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff)
#else
#define mrb_cptr(o) ((o).value.p)
#define BOXNAN_SHIFT_LONG_POINTER(v) 0
#endif
@@ -90,7 +95,11 @@ typedef struct mrb_value {
#define SET_INT_VALUE(r,n) BOXNAN_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
#define SET_SYM_VALUE(r,v) BOXNAN_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
#define SET_OBJ_VALUE(r,v) BOXNAN_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v))
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_OBJ_VALUE(r, MRB_TT_CPTR, v)
#ifdef MRB_64BIT
#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_nan_boxing_cptr_value(mrb, v))
#else
#define SET_CPTR_VALUE(mrb,r,v) BOXNAN_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
#endif
#define SET_UNDEF_VALUE(r) BOXNAN_SET_VALUE(r, MRB_TT_UNDEF, value.i, 0)
#endif /* MRUBY_BOXING_NAN_H */
-6
View File
@@ -18,11 +18,6 @@ struct RFloat {
};
#endif
struct RCptr {
MRB_OBJECT_HEADER;
void *p;
};
enum mrb_special_consts {
MRB_Qnil = 0,
MRB_Qfalse = 4,
@@ -142,7 +137,6 @@ MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
#define mrb_sclass_p(o) BOXWORD_OBJ_TYPE_P(o, SCLASS)
#define mrb_proc_p(o) BOXWORD_OBJ_TYPE_P(o, PROC)
#define mrb_range_p(o) BOXWORD_OBJ_TYPE_P(o, RANGE)
#define mrb_file_p(o) BOXWORD_OBJ_TYPE_P(o, FILE)
#define mrb_env_p(o) BOXWORD_OBJ_TYPE_P(o, ENV)
#define mrb_data_p(o) BOXWORD_OBJ_TYPE_P(o, DATA)
#define mrb_fiber_p(o) BOXWORD_OBJ_TYPE_P(o, FIBER)
+11 -3
View File
@@ -33,7 +33,7 @@ typedef struct mrbc_context {
mrb_bool no_exec:1;
mrb_bool keep_lv:1;
mrb_bool no_optimize:1;
mrb_bool on_eval:1;
struct RProc *upper;
size_t parser_nerr;
} mrbc_context;
@@ -151,8 +151,8 @@ struct mrb_parser_state {
mrb_ast_node *tree;
mrb_bool no_optimize:1;
mrb_bool on_eval:1;
mrb_bool capture_errors:1;
struct RProc *upper;
struct mrb_parser_message error_buffer[10];
struct mrb_parser_message warn_buffer[10];
@@ -180,7 +180,15 @@ MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t
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);
/* program load functions */
/** program load functions
* Please note! Currently due to interactions with the GC calling these functions will
* leak one RProc object per function call.
* To prevent this save the current memory arena before calling and restore the arena
* right after, like so
* int ai = mrb_gc_arena_save(mrb);
* mrb_value status = mrb_load_string(mrb, buffer);
* mrb_gc_arena_restore(mrb, ai);
*/
#ifndef MRB_DISABLE_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);
+1 -17
View File
@@ -17,10 +17,6 @@
MRB_BEGIN_DECL
#define DUMP_DEBUG_INFO 1
#define DUMP_ENDIAN_BIG 2
#define DUMP_ENDIAN_LIL 4
#define DUMP_ENDIAN_NAT 6
#define DUMP_ENDIAN_MASK 6
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
#ifndef MRB_DISABLE_STDIO
@@ -52,8 +48,7 @@ MRB_API mrb_irep *mrb_read_irep_buf(mrb_state*, const void*, size_t);
/* Rite Binary File header */
#define RITE_BINARY_IDENT "RITE"
#define RITE_BINARY_IDENT_LIL "ETIR"
#define RITE_BINARY_FORMAT_VER "0006"
#define RITE_BINARY_FORMAT_VER "0007"
#define RITE_COMPILER_NAME "MATZ"
#define RITE_COMPILER_VERSION "0000"
@@ -106,17 +101,6 @@ struct rite_binary_footer {
RITE_SECTION_HEADER;
};
static inline int
bigendian_p()
{
int i;
char *p;
i = 1;
p = (char*)&i;
return p[0]?0:1;
}
static inline size_t
uint8_to_bin(uint8_t s, uint8_t *bin)
{
+10
View File
@@ -49,6 +49,16 @@ typedef struct mrb_irep {
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
/** load mruby bytecode functions
* Please note! Currently due to interactions with the GC calling these functions will
* leak one RProc object per function call.
* To prevent this save the current memory arena before calling and restore the arena
* right after, like so
* int ai = mrb_gc_arena_save(mrb);
* mrb_value status = mrb_load_irep(mrb, buffer);
* mrb_gc_arena_restore(mrb, ai);
*/
/* @param [const uint8_t*] irep code, expected as a literal */
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
+4 -1
View File
@@ -21,7 +21,10 @@ MRB_BEGIN_DECL
struct RIStruct {
MRB_OBJECT_HEADER;
char inline_data[ISTRUCT_DATA_SIZE];
union {
intptr_t inline_alignment[3];
char inline_data[ISTRUCT_DATA_SIZE];
};
};
#define RISTRUCT(obj) ((struct RIStruct*)(mrb_ptr(obj)))
+23 -5
View File
@@ -73,6 +73,7 @@ static const uint8_t __m_either[] = {0x03, 0x0c, 0x30, 0xc0};
void kh_clear_##name(mrb_state *mrb, kh_##name##_t *h); \
khint_t kh_get_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key); \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret); \
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h); \
void kh_resize_##name(mrb_state *mrb, kh_##name##_t *h, khint_t new_n_buckets); \
void kh_del_##name(mrb_state *mrb, kh_##name##_t *h, khint_t x); \
kh_##name##_t *kh_copy_##name(mrb_state *mrb, kh_##name##_t *h);
@@ -95,16 +96,25 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
__hash_equal: hash comparation function
*/
#define KHASH_DEFINE(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb); \
int kh_alloc_simple_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
khint_t sz = h->n_buckets; \
size_t len = sizeof(khkey_t) + (kh_is_map ? sizeof(khval_t) : 0); \
uint8_t *p = (uint8_t*)mrb_malloc(mrb, sizeof(uint8_t)*sz/4+len*sz); \
uint8_t *p = (uint8_t*)mrb_malloc_simple(mrb, sizeof(uint8_t)*sz/4+len*sz); \
if (!p) { return 1; } \
h->size = h->n_occupied = 0; \
h->keys = (khkey_t *)p; \
h->vals = kh_is_map ? (khval_t *)(p+sizeof(khkey_t)*sz) : NULL; \
h->ed_flags = p+len*sz; \
kh_fill_flags(h->ed_flags, 0xaa, sz/4); \
return 0; \
} \
void kh_alloc_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
if (kh_alloc_simple_##name(mrb, h)) { \
mrb_raise_nomemory(mrb); \
} \
} \
kh_##name##_t *kh_init_##name##_size(mrb_state *mrb, khint_t size) { \
kh_##name##_t *h = (kh_##name##_t*)mrb_calloc(mrb, 1, sizeof(kh_##name##_t)); \
@@ -112,7 +122,10 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
size = KHASH_MIN_SIZE; \
khash_power2(size); \
h->n_buckets = size; \
kh_alloc_##name(mrb, h); \
if (kh_alloc_simple_##name(mrb, h)) { \
mrb_free(mrb, h); \
mrb_raise_nomemory(mrb); \
} \
return h; \
} \
kh_##name##_t *kh_init_##name(mrb_state *mrb) { \
@@ -171,12 +184,16 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
mrb_free(mrb, old_keys); \
} \
} \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
void kh_put_prepare_##name(mrb_state *mrb, kh_##name##_t *h) \
{ \
khint_t k, del_k, step = 0; \
if (h->n_occupied >= khash_upper_bound(h)) { \
kh_resize_##name(mrb, h, h->n_buckets*2); \
} \
} \
khint_t kh_put_##name(mrb_state *mrb, kh_##name##_t *h, khkey_t key, int *ret) \
{ \
khint_t k, del_k, step = 0; \
kh_put_prepare_##name(mrb, h); \
k = __hash_func(mrb,key) & khash_mask(h); \
del_k = kh_end(h); \
while (!__ac_isempty(h->ed_flags, k)) { \
@@ -239,6 +256,7 @@ kh_fill_flags(uint8_t *p, uint8_t c, size_t len)
#define kh_destroy(name, mrb, h) kh_destroy_##name(mrb, h)
#define kh_clear(name, mrb, h) kh_clear_##name(mrb, h)
#define kh_resize(name, mrb, h, s) kh_resize_##name(mrb, h, s)
#define kh_put_prepare(name, mrb, h) kh_put_prepare_##name(mrb, h)
#define kh_put(name, mrb, h, k) kh_put_##name(mrb, h, k, NULL)
#define kh_put2(name, mrb, h, k, r) kh_put_##name(mrb, h, k, r)
#define kh_get(name, mrb, h, k) kh_get_##name(mrb, h, k)
+1
View File
@@ -37,6 +37,7 @@ MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
MRB_API int mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float f);
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f);
#endif
+3 -2
View File
@@ -92,8 +92,8 @@ OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+c) = R(a)[b..] */
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b*2-1)) */
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b*2)) */
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
@@ -115,3 +115,4 @@ OPCODE(EXT1, Z) /* make 1st operand 16bit */
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
OPCODE(STOP, Z) /* stop VM */
OPCODE(LOADI16, BS) /* R(a) = mrb_int(b) */
+13 -8
View File
@@ -22,14 +22,19 @@ struct REnv {
mrb_sym mid;
};
/* flags (21bits): 1(shared flag):10(cioff/bidx):10(stack_len) */
#define MRB_ENV_SET_STACK_LEN(e,len) ((e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff)))
#define MRB_ENV_STACK_LEN(e) ((mrb_int)((e)->flags & 0x3ff))
#define MRB_ENV_STACK_UNSHARED (1<<20)
#define MRB_ENV_UNSHARE_STACK(e) ((e)->flags |= MRB_ENV_STACK_UNSHARED)
#define MRB_ENV_STACK_SHARED_P(e) (((e)->flags & MRB_ENV_STACK_UNSHARED) == 0)
#define MRB_ENV_BIDX(e) (((e)->flags >> 10) & 0x3ff)
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10))
/* flags (21bits): 1(close):1(touched):1(heap):8(cioff/bidx):8(stack_len) */
#define MRB_ENV_SET_LEN(e,len) ((e)->flags = (((e)->flags & ~0xff)|((unsigned int)(len) & 0xff)))
#define MRB_ENV_LEN(e) ((mrb_int)((e)->flags & 0xff))
#define MRB_ENV_CLOSED (1<<20)
#define MRB_ENV_TOUCHED (1<<19)
#define MRB_ENV_HEAPED (1<<18)
#define MRB_ENV_CLOSE(e) ((e)->flags |= MRB_ENV_CLOSED)
#define MRB_ENV_TOUCH(e) ((e)->flags |= MRB_ENV_TOUCHED)
#define MRB_ENV_HEAP(e) ((e)->flags |= MRB_ENV_HEAPED)
#define MRB_ENV_HEAP_P(e) ((e)->flags & MRB_ENV_HEAPED)
#define MRB_ENV_ONSTACK_P(e) (((e)->flags & MRB_ENV_CLOSED) == 0)
#define MRB_ENV_BIDX(e) (((e)->flags >> 8) & 0xff)
#define MRB_ENV_SET_BIDX(e,idx) ((e)->flags = (((e)->flags & ~(0xff<<8))|((unsigned int)(idx) & 0xff)<<8))
void mrb_env_unshare(mrb_state*, struct REnv*);
+32 -29
View File
@@ -103,32 +103,31 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
#endif
enum mrb_vtype {
MRB_TT_FALSE = 0, /* 0 */
MRB_TT_TRUE, /* 1 */
MRB_TT_FLOAT, /* 2 */
MRB_TT_FIXNUM, /* 3 */
MRB_TT_SYMBOL, /* 4 */
MRB_TT_UNDEF, /* 5 */
MRB_TT_CPTR, /* 6 */
MRB_TT_FREE, /* 7 */
MRB_TT_OBJECT, /* 8 */
MRB_TT_CLASS, /* 9 */
MRB_TT_MODULE, /* 10 */
MRB_TT_ICLASS, /* 11 */
MRB_TT_SCLASS, /* 12 */
MRB_TT_PROC, /* 13 */
MRB_TT_ARRAY, /* 14 */
MRB_TT_HASH, /* 15 */
MRB_TT_STRING, /* 16 */
MRB_TT_RANGE, /* 17 */
MRB_TT_EXCEPTION, /* 18 */
MRB_TT_FILE, /* 19 */
MRB_TT_ENV, /* 20 */
MRB_TT_DATA, /* 21 */
MRB_TT_FIBER, /* 22 */
MRB_TT_ISTRUCT, /* 23 */
MRB_TT_BREAK, /* 24 */
MRB_TT_MAXDEFINE /* 25 */
MRB_TT_FALSE = 0,
MRB_TT_TRUE,
MRB_TT_FLOAT,
MRB_TT_FIXNUM,
MRB_TT_SYMBOL,
MRB_TT_UNDEF,
MRB_TT_CPTR,
MRB_TT_FREE,
MRB_TT_OBJECT,
MRB_TT_CLASS,
MRB_TT_MODULE,
MRB_TT_ICLASS,
MRB_TT_SCLASS,
MRB_TT_PROC,
MRB_TT_ARRAY,
MRB_TT_HASH,
MRB_TT_STRING,
MRB_TT_RANGE,
MRB_TT_EXCEPTION,
MRB_TT_ENV,
MRB_TT_DATA,
MRB_TT_FIBER,
MRB_TT_ISTRUCT,
MRB_TT_BREAK,
MRB_TT_MAXDEFINE
};
#include <mruby/object.h>
@@ -149,6 +148,13 @@ typedef void mrb_value;
#endif
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
struct RCptr {
MRB_OBJECT_HEADER;
void *p;
};
#endif
#if defined(MRB_NAN_BOXING)
#include "boxing_nan.h"
#elif defined(MRB_WORD_BOXING)
@@ -233,9 +239,6 @@ typedef void mrb_value;
#ifndef mrb_range_p
#define mrb_range_p(o) (mrb_type(o) == MRB_TT_RANGE)
#endif
#ifndef mrb_file_p
#define mrb_file_p(o) (mrb_type(o) == MRB_TT_FILE)
#endif
#ifndef mrb_env_p
#define mrb_env_p(o) (mrb_type(o) == MRB_TT_ENV)
#endif
+3 -3
View File
@@ -47,7 +47,7 @@ MRB_BEGIN_DECL
/*
* Tiny release version number.
*/
#define MRUBY_RELEASE_TEENY 1
#define MRUBY_RELEASE_TEENY 2
/*
* The mruby version.
@@ -67,12 +67,12 @@ MRB_BEGIN_DECL
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 4
#define MRUBY_RELEASE_MONTH 7
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 20
#define MRUBY_RELEASE_DAY 10
/*
* Release date as a string.
+2 -22
View File
@@ -336,7 +336,8 @@ EOS
puts " Binaries: #{@bins.join(', ')}" unless @bins.empty?
unless @gems.empty?
puts " Included Gems:"
@gems.map do |gem|
gems = @gems.sort_by { |gem| gem.name }
gems.each do |gem|
gem_version = " - #{gem.version}" if gem.version != '0.0.0'
gem_summary = " - #{gem.summary}" if gem.summary
puts " #{gem.name}#{gem_version}#{gem_summary}"
@@ -387,26 +388,5 @@ EOS
@test_runner.run(mrbtest)
end
end
def big_endian
if @endian
puts "Endian has already specified as #{@endian}."
return
end
@endian = :big
@mrbc.compile_options += ' -E'
compilers.each do |c|
c.defines += %w(MRB_ENDIAN_BIG)
end
end
def little_endian
if @endian
puts "Endian has already specified as #{@endian}."
return
end
@endian = :little
@mrbc.compile_options += ' -e'
end
end # CrossBuild
end # MRuby
+3 -1
View File
@@ -6,7 +6,9 @@ module MRuby
ROOT = Pathname.new(File.expand_path('../../../',__FILE__))
# Reads a constant defined at version.h
MRUBY_READ_VERSION_CONSTANT = Proc.new { |name| ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?$/)[1] }
MRUBY_READ_VERSION_CONSTANT = Proc.new do |name|
ROOT.join('include','mruby','version.h').read.match(/^#define #{name} +"?([\w\. ]+)"?\r?$/)[1]
end
MRUBY_RUBY_VERSION = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_VERSION']
MRUBY_RUBY_ENGINE = MRUBY_READ_VERSION_CONSTANT['MRUBY_RUBY_ENGINE']
+7
View File
@@ -71,6 +71,10 @@ MRuby::GemBox.new do |conf|
# Use toplevel object (main) methods extension
conf.gem :core => "mruby-toplevel-ext"
# Use Rational/Complex numbers
conf.gem :core => "mruby-rational"
conf.gem :core => "mruby-complex"
# Generate mirb command
conf.gem :core => "mruby-bin-mirb"
@@ -89,6 +93,9 @@ MRuby::GemBox.new do |conf|
# Use Method/UnboundMethod class
conf.gem :core => "mruby-method"
# Use eval()
conf.gem :core => "mruby-eval"
# Use mruby-compiler to build other mrbgems
conf.gem :core => "mruby-compiler"
end
+5 -8
View File
@@ -28,9 +28,8 @@ static mrb_value
mrb_ary_assoc(mrb_state *mrb, mrb_value ary)
{
mrb_int i;
mrb_value v, k;
mrb_get_args(mrb, "o", &k);
mrb_value v;
mrb_value k = mrb_get_arg1(mrb);
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
@@ -59,9 +58,8 @@ static mrb_value
mrb_ary_rassoc(mrb_state *mrb, mrb_value ary)
{
mrb_int i;
mrb_value v, value;
mrb_get_args(mrb, "o", &value);
mrb_value v;
mrb_value value = mrb_get_arg1(mrb);
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = RARRAY_PTR(ary)[i];
@@ -140,9 +138,8 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
mrb_ary_modify(mrb, a);
if (mrb_get_argc(mrb) == 1) {
mrb_value index;
mrb_value index = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o|i", &index, &len);
switch (mrb_type(index)) {
case MRB_TT_RANGE:
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
+5 -2
View File
@@ -5,13 +5,16 @@ unless MRuby::Build.current.kind_of?(MRuby::CrossBuild)
spec.author = 'mruby developers'
spec.summary = "#{name} command"
mruby_config_dir = "#{build.build_dir}/bin"
mruby_config = name + (ENV['OS'] == 'Windows_NT' ? '.bat' : '')
mruby_config_path = "#{build.build_dir}/bin/#{mruby_config}"
mruby_config_path = "#{mruby_config_dir}/#{mruby_config}"
make_cfg = "#{build.build_dir}/lib/libmruby.flags.mak"
tmplt_path = "#{__dir__}/#{mruby_config}"
build.bins << mruby_config
file mruby_config_path => [make_cfg, tmplt_path] do |t|
directory mruby_config_dir
file mruby_config_path => [mruby_config_dir, make_cfg, tmplt_path] do |t|
config = Hash[File.readlines(make_cfg).map!(&:chomp).map! {|l|
l.gsub('\\"', '"').split(' = ', 2).map! {|s| s.sub(/^(?=.)/, 'echo ')}
}]
+2 -2
View File
@@ -649,8 +649,8 @@ main(int argc, char **argv)
/* adjust stack length of toplevel environment */
if (mrb->c->cibase->env) {
struct REnv *e = mrb->c->cibase->env;
if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) {
MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals);
if (e && MRB_ENV_LEN(e) < proc->body.irep->nlocals) {
MRB_ENV_SET_LEN(e, proc->body.irep->nlocals);
}
}
/* pass a proc for evaluation */
+18 -19
View File
@@ -36,8 +36,6 @@ usage(const char *name)
"-v print version number, then turn on verbose mode",
"-g produce debugging information",
"-B<symbol> binary <symbol> output in C language format",
"-e generate little endian iseq data",
"-E generate big endian iseq data",
"--remove-lv remove local variables",
"--verbose run at verbose mode",
"--version print the version",
@@ -54,19 +52,26 @@ usage(const char *name)
static char *
get_outfilename(mrb_state *mrb, char *infile, const char *ext)
{
size_t infilelen;
size_t extlen;
size_t ilen, flen, elen;
char *outfile;
char *p;
char *p = NULL;
infilelen = strlen(infile);
extlen = strlen(ext);
outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
memcpy(outfile, infile, infilelen + 1);
ilen = strlen(infile);
flen = ilen;
if (*ext) {
if ((p = strrchr(outfile, '.')) == NULL)
p = outfile + infilelen;
memcpy(p, ext, extlen + 1);
elen = strlen(ext);
if ((p = strrchr(infile, '.'))) {
ilen = p - infile;
}
flen += elen;
}
else {
flen = ilen;
}
outfile = (char*)mrb_malloc(mrb, flen+1);
strncpy(outfile, infile, ilen+1);
if (p) {
strncpy(outfile+ilen, ext, elen+1);
}
return outfile;
@@ -124,10 +129,8 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
args->flags |= DUMP_DEBUG_INFO;
break;
case 'E':
args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
break;
case 'e':
args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
fprintf(stderr, "%s: -e/-E option no longer needed.\n", args->prog);
break;
case 'h':
return -1;
@@ -160,10 +163,6 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
break;
}
}
if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
args->prog, bigendian_p() ? "big" : "little");
}
return i;
}
-1
View File
@@ -4,7 +4,6 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
spec.summary = 'mruby command'
spec.bins = %w(mruby)
spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
spec.add_dependency('mruby-error', :core => 'mruby-error')
spec.add_test_dependency('mruby-print', :core => 'mruby-print')
if build.cxx_exception_enabled?
+6 -1
View File
@@ -43,10 +43,15 @@ mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
const mrb_value *argv;
mrb_int argc;
mrb_value blk;
struct RClass *c;
mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
mrb->c->ci->target_class = mrb_class_ptr(self);
c = mrb_class_ptr(self);
if (mrb->c->ci->acc < 0) {
return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
}
mrb->c->ci->target_class = c;
return mrb_yield_cont(mrb, blk, self, argc, argv);
}
+76 -48
View File
@@ -281,15 +281,6 @@ no_optimize(codegen_scope *s)
return FALSE;
}
static
mrb_bool
on_eval(codegen_scope *s)
{
if (s && s->parser && s->parser->on_eval)
return TRUE;
return FALSE;
}
struct mrb_insn_data
mrb_decode_insn(const mrb_code *pc)
{
@@ -407,9 +398,6 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
if (no_peephole(s)) {
normal:
genop_2(s, OP_MOVE, dst, src);
if (on_eval(s)) {
genop_0(s, OP_NOP);
}
return;
}
else {
@@ -674,6 +662,43 @@ lv_idx(codegen_scope *s, mrb_sym id)
return 0;
}
static int
search_upvar(codegen_scope *s, mrb_sym id, int *idx)
{
struct RProc *u;
int lv = 0;
codegen_scope *up = s->prev;
while (up) {
*idx = lv_idx(up, id);
if (*idx > 0) {
return lv;
}
lv ++;
up = up->prev;
}
if (lv < 1) lv = 1;
u = s->parser->upper;
while (u && !MRB_PROC_CFUNC_P(u)) {
struct mrb_irep *ir = u->body.irep;
uint_fast16_t n = ir->nlocals;
const struct mrb_locals *v = ir->lv;
for (; n > 1; n --, v ++) {
if (v->name == id) {
*idx = v->r;
return lv - 1;
}
}
if (MRB_PROC_SCOPE_P(u)) break;
u = u->upper;
lv ++;
}
codegen_error(s, "Can't found local variables");
return -1; /* not reached */
}
static void
for_body(codegen_scope *s, node *tree)
{
@@ -786,12 +811,19 @@ lambda_body(codegen_scope *s, node *tree, int blk)
i = 0;
while (opt) {
int idx;
mrb_sym id = nsym(opt->car->car);
dispatch(s, pos+i*3+1);
codegen(s, opt->car->cdr, VAL);
pop();
idx = lv_idx(s, nsym(opt->car->car));
gen_move(s, idx, cursp(), 0);
idx = lv_idx(s, id);
if (idx > 0) {
gen_move(s, idx, cursp(), 0);
}
else {
int lv = search_upvar(s, id, &idx);
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
}
i++;
opt = opt->cdr;
}
@@ -818,11 +850,19 @@ lambda_body(codegen_scope *s, node *tree, int blk)
mrb_assert(nint(kwd->car) == NODE_KW_ARG);
if (def_arg) {
int idx;
genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
codegen(s, def_arg, VAL);
pop();
gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
idx = lv_idx(s, kwd_sym);
if (idx > 0) {
gen_move(s, idx, cursp(), 0);
}
else {
int lv = search_upvar(s, kwd_sym, &idx);
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
}
jmp_def_set = genjmp(s, OP_JMP, 0);
dispatch(s, jmpif_key_p);
}
@@ -1103,23 +1143,12 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
if (idx > 0) {
if (idx != sp) {
gen_move(s, idx, sp, val);
if (val && on_eval(s)) genop_0(s, OP_NOP);
}
break;
}
else { /* upvar */
int lv = 0;
codegen_scope *up = s->prev;
while (up) {
idx = lv_idx(up, nsym(tree));
if (idx > 0) {
genop_3(s, OP_SETUPVAR, sp, idx, lv);
break;
}
lv++;
up = up->prev;
}
int lv = search_upvar(s, nsym(tree), &idx);
genop_3(s, OP_SETUPVAR, sp, idx, lv);
}
break;
case NODE_NVAR:
@@ -1860,7 +1889,7 @@ codegen(codegen_scope *s, node *tree, int val)
len++;
}
tree = tree->cdr;
if (val && len == 255) {
if (val && cursp() > 127) {
pop_n(len*2);
if (!update) {
genop_2(s, OP_HASH, cursp(), len);
@@ -2324,21 +2353,10 @@ codegen(codegen_scope *s, node *tree, int val)
if (idx > 0) {
gen_move(s, cursp(), idx, val);
if (val && on_eval(s)) genop_0(s, OP_NOP);
}
else {
int lv = 0;
codegen_scope *up = s->prev;
while (up) {
idx = lv_idx(up, nsym(tree));
if (idx > 0) {
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
break;
}
lv++;
up = up->prev;
}
int lv = search_upvar(s, nsym(tree), &idx);
genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
}
push();
}
@@ -2349,7 +2367,6 @@ codegen(codegen_scope *s, node *tree, int val)
int idx = nint(tree);
gen_move(s, cursp(), idx, val);
if (val && on_eval(s)) genop_0(s, OP_NOP);
push();
}
@@ -2440,12 +2457,20 @@ codegen(codegen_scope *s, node *tree, int val)
else
#endif
{
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
if (i < 0) {
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
else if (i >= -0xff) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
else if (i >= -0x8000) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
else goto lit_int;
}
else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
else if (i <= 0xff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
else if (i <= 0x7fff) genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
else {
int off = new_lit(s, mrb_fixnum_value(i));
int off;
lit_int:
off = new_lit(s, mrb_fixnum_value(i));
genop_2(s, OP_LOADL, cursp(), off);
}
}
@@ -2501,9 +2526,12 @@ codegen(codegen_scope *s, node *tree, int val)
else {
#endif
if (i == -1) genop_1(s, OP_LOADI__1, cursp());
else if (i >= -0xffff) {
else if (i >= -0xff) {
genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
}
else if (i >= -0x8000) {
genop_2S(s, OP_LOADI16, cursp(), (uint16_t)i);
}
else {
int off = new_lit(s, mrb_fixnum_value(i));
genop_2(s, OP_LOADL, cursp(), off);
+80 -15
View File
@@ -9,7 +9,6 @@
#ifdef PARSER_DEBUG
# define YYDEBUG 1
#endif
#define YYERROR_VERBOSE 1
#define YYSTACK_USE_ALLOCA 1
#include <ctype.h>
@@ -266,6 +265,7 @@ local_unnest(parser_state *p)
static mrb_bool
local_var_p(parser_state *p, mrb_sym sym)
{
struct RProc *u;
node *l = p->locals;
while (l) {
@@ -276,6 +276,18 @@ local_var_p(parser_state *p, mrb_sym sym)
}
l = l->cdr;
}
u = p->upper;
while (u && !MRB_PROC_CFUNC_P(u)) {
struct mrb_irep *ir = u->body.irep;
uint_fast16_t n = ir->nlocals;
const struct mrb_locals *v = ir->lv;
for (; n > 1; n --, v ++) {
if (v->name == sym) return TRUE;
}
if (MRB_PROC_SCOPE_P(u)) break;
u = u->upper;
}
return FALSE;
}
@@ -827,6 +839,13 @@ new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
}
/* (:kw_rest_args . a) */
static node*
new_kw_rest_args(parser_state *p, node *a)
{
return cons((node*)NODE_KW_REST_ARGS, a);
}
/* (:block_arg . a) */
static node*
new_block_arg(parser_state *p, node *a)
@@ -1323,7 +1342,8 @@ heredoc_end(parser_state *p)
%}
%pure-parser
%define parse.error verbose
%define api.pure
%parse-param {parser_state *p}
%lex-param {parser_state *p}
@@ -2265,6 +2285,30 @@ paren_args : '(' opt_call_args ')'
{
$$ = $2;
}
| '(' tDOT3 rparen
{
#if 1
mrb_sym r = mrb_intern_lit(p->mrb, "*");
mrb_sym b = mrb_intern_lit(p->mrb, "&");
if (local_var_p(p, r) && local_var_p(p, b)) {
$$ = cons(list1(new_splat(p, new_lvar(p, r))),
new_block_arg(p, new_lvar(p, b)));
}
#else
mrb_sym r = mrb_intern_lit(p->mrb, "*");
mrb_sym k = mrb_intern_lit(p->mrb, "**");
mrb_sym b = mrb_intern_lit(p->mrb, "&");
if (local_var_p(p, r) && local_var_p(p, k) && local_var_p(p, b)) {
$$ = cons(list2(new_splat(p, new_lvar(p, r)),
new_kw_hash(p, list1(cons(new_kw_rest_args(p, 0), new_lvar(p, k))))),
new_block_arg(p, new_lvar(p, b)));
}
#endif
else {
yyerror(p, "unexpected argument forwarding ...");
$$ = 0;
}
}
;
opt_paren_args : none
@@ -3361,6 +3405,24 @@ f_arglist : '(' f_args rparen
p->lstate = EXPR_BEG;
p->cmd_start = TRUE;
}
| '(' tDOT3 rparen
{
#if 1
/* til real keyword args implemented */
mrb_sym r = mrb_intern_lit(p->mrb, "*");
mrb_sym b = mrb_intern_lit(p->mrb, "&");
local_add_f(p, r);
$$ = new_args(p, 0, 0, r, 0,
new_args_tail(p, 0, 0, b));
#else
mrb_sym r = mrb_intern_lit(p->mrb, "*");
mrb_sym k = mrb_intern_lit(p->mrb, "**");
mrb_sym b = mrb_intern_lit(p->mrb, "&");
local_add_f(p, r); local_add_f(p, k);
$$ = new_args(p, 0, 0, r, 0,
new_args_tail(p, 0, new_kw_rest_args(p, nsym(k)), b));
#endif
}
| f_args term
{
$$ = $1;
@@ -3424,11 +3486,11 @@ kwrest_mark : tPOW
f_kwrest : kwrest_mark tIDENTIFIER
{
$$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
$$ = new_kw_rest_args(p, nsym($2));
}
| kwrest_mark
{
$$ = cons((node*)NODE_KW_REST_ARGS, 0);
$$ = new_kw_rest_args(p, 0);
}
;
@@ -3743,7 +3805,7 @@ assoc : arg tASSOC arg
| tDSTAR arg
{
void_expr_error(p, $2);
$$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
$$ = cons(new_kw_rest_args(p, 0), $2);
}
;
@@ -3807,7 +3869,7 @@ term : ';' {yyerrok;}
nl : '\n'
{
p->lineno++;
p->lineno += $<num>1;
p->column = 0;
}
;
@@ -4795,6 +4857,7 @@ static int
parser_yylex(parser_state *p)
{
int32_t c;
int nlines = 1;
int space_seen = 0;
int cmd_state;
enum mrb_lex_state_enum last_state;
@@ -4852,6 +4915,7 @@ parser_yylex(parser_state *p)
break;
}
if (p->parsing_heredoc != NULL) {
pylval.num = nlines;
return '\n';
}
while ((c = nextc(p))) {
@@ -4861,13 +4925,13 @@ parser_yylex(parser_state *p)
space_seen = 1;
break;
case '#': /* comment as a whitespace */
pushback(p, '#');
p->lineno++;
goto retry;
skip(p, '\n');
nlines++;
break;
case '.':
if (!peek(p, '.')) {
pushback(p, '.');
p->lineno++;
p->lineno+=nlines; nlines=1;
goto retry;
}
pushback(p, c);
@@ -4875,7 +4939,7 @@ parser_yylex(parser_state *p)
case '&':
if (peek(p, '.')) {
pushback(p, '&');
p->lineno++;
p->lineno+=nlines; nlines=1;
goto retry;
}
pushback(p, c);
@@ -4891,6 +4955,7 @@ parser_yylex(parser_state *p)
normal_newline:
p->cmd_start = TRUE;
p->lstate = EXPR_BEG;
pylval.num = nlines;
return '\n';
case '*':
@@ -4973,7 +5038,7 @@ parser_yylex(parser_state *p)
c = nextc(p);
} while (!(c < 0 || ISSPACE(c)));
if (c != '\n') skip(p, '\n');
p->lineno++;
p->lineno+=nlines; nlines=1;
p->column = 0;
goto retry;
}
@@ -5695,7 +5760,7 @@ parser_yylex(parser_state *p)
case '\\':
c = nextc(p);
if (c == '\n') {
p->lineno++;
p->lineno+=nlines; nlines=1;
p->column = 0;
space_seen = 1;
goto retry; /* skip \\n */
@@ -6140,7 +6205,7 @@ parser_init_cxt(parser_state *p, mrbc_context *cxt)
}
p->capture_errors = cxt->capture_errors;
p->no_optimize = cxt->no_optimize;
p->on_eval = cxt->on_eval;
p->upper = cxt->upper;
if (cxt->partial_hook) {
p->cxt = cxt;
}
@@ -6559,7 +6624,7 @@ dump_args(mrb_state *mrb, node *n, int offset)
static const char*
str_dump(mrb_state *mrb, const char *str, int len)
{
mrb_int ai = mrb_gc_arena_save(mrb);
int ai = mrb_gc_arena_save(mrb);
mrb_value s;
# if INT_MAX > MRB_INT_MAX / 4
/* check maximum length with "\xNN" charactor */
File diff suppressed because it is too large Load Diff
+13 -15
View File
@@ -3,35 +3,33 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
spec.author = 'mruby developers'
spec.summary = 'mruby compiler library'
current_dir = spec.dir
current_build_dir = spec.build_dir
lex_def = "#{current_dir}/core/lex.def"
core_objs = Dir.glob("#{current_dir}/core/*.c").map { |f|
lex_def = "#{dir}/core/lex.def"
core_objs = Dir.glob("#{dir}/core/*.c").map { |f|
next nil if build.cxx_exception_enabled? and f =~ /(codegen).c$/
objfile(f.pathmap("#{current_build_dir}/core/%n"))
objfile(f.pathmap("#{build_dir}/core/%n"))
}.compact
if build.cxx_exception_enabled?
core_objs <<
build.compile_as_cxx("#{current_build_dir}/core/y.tab.c", "#{current_build_dir}/core/y.tab.cxx",
objfile("#{current_build_dir}/y.tab"), ["#{current_dir}/core"]) <<
build.compile_as_cxx("#{current_dir}/core/codegen.c", "#{current_build_dir}/core/codegen.cxx")
build.compile_as_cxx("#{dir}/core/y.tab.c", "#{build_dir}/core/y.tab.cxx",
objfile("#{build_dir}/y.tab"), ["#{dir}/core"]) <<
build.compile_as_cxx("#{dir}/core/codegen.c", "#{build_dir}/core/codegen.cxx")
else
core_objs << objfile("#{current_build_dir}/core/y.tab")
file objfile("#{current_build_dir}/core/y.tab") => "#{current_build_dir}/core/y.tab.c" do |t|
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
core_objs << objfile("#{build_dir}/core/y.tab")
file objfile("#{build_dir}/core/y.tab") => "#{dir}/core/y.tab.c" do |t|
cc.run t.name, t.prerequisites.first, [], ["#{dir}/core"]
end
end
# Parser
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
mkdir_p File.dirname t.name
file "#{dir}/core/y.tab.c" => ["#{dir}/core/parse.y", lex_def] do |t|
yacc.run t.name, t.prerequisites.first
content = File.read(t.name).gsub(/^#line +\d+ +"\K.*$/){$&.relative_path}
File.write(t.name, content)
end
# Lexical analyzer
file lex_def => "#{current_dir}/core/keywords" do |t|
file lex_def => "#{dir}/core/keywords" do |t|
gperf.run t.name, t.prerequisites.first
end
+1 -1
View File
@@ -107,7 +107,7 @@ class Complex < Numeric
[Fixnum, Float].each do |cls|
[:+, :-, :*, :/, :==].each do |op|
cls.instance_eval do
original_operator_name = "__original_operator_#{op}_complex"
original_operator_name = :"__original_operator_#{op}_complex"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Complex
+1 -2
View File
@@ -174,7 +174,7 @@ div_pair(struct float_pair *q, struct float_pair const *a,
static mrb_value
complex_div(mrb_state *mrb, mrb_value self)
{
mrb_value rhs;
mrb_value rhs = mrb_get_arg1(mrb);
struct mrb_complex *a, *b;
struct float_pair ar, ai, br, bi;
struct float_pair br2, bi2;
@@ -183,7 +183,6 @@ complex_div(mrb_state *mrb, mrb_value self)
struct float_pair ai_br, ar_bi;
struct float_pair zr, zi;
mrb_get_args(mrb, "o", &rhs);
a = complex_ptr(mrb, self);
b = complex_ptr(mrb, rhs);
+3 -214
View File
@@ -9,217 +9,6 @@
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
static struct mrb_irep *
get_closure_irep(mrb_state *mrb, int level)
{
struct RProc *proc = mrb->c->ci[-1].proc;
while (level--) {
if (!proc) return NULL;
proc = proc->upper;
}
if (!proc) return NULL;
if (MRB_PROC_CFUNC_P(proc)) {
return NULL;
}
return proc->body.irep;
}
/* search for irep lev above the bottom */
static mrb_irep*
search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
{
int i;
for (i=0; i<top->rlen; i++) {
mrb_irep* tmp = top->reps[i];
if (tmp == bottom) return top;
tmp = search_irep(tmp, bnest-1, lev, bottom);
if (tmp) {
if (bnest == lev) return top;
return tmp;
}
}
return NULL;
}
static uint16_t
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
{
mrb_irep *virep;
int level;
int pos;
for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
if (virep->lv == NULL) {
continue;
}
for (pos = 0; pos < virep->nlocals - 1; pos++) {
if (vsym == virep->lv[pos].name) {
return (pos+1)<<8 | (level+bnest);
}
}
}
return 0;
}
static int
irep_argc(mrb_irep *irep)
{
mrb_code c;
c = irep->iseq[0];
if (c == OP_ENTER) {
mrb_aspec ax = PEEK_W(irep->iseq+1);
/* extra 1 means a slot for block */
return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
}
return 0;
}
static mrb_bool
potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
{
if (v >= nlocals) return FALSE;
/* skip arguments */
if (v < argc+1) return FALSE;
return TRUE;
}
extern uint8_t mrb_insn_size[];
extern uint8_t mrb_insn_size1[];
extern uint8_t mrb_insn_size2[];
extern uint8_t mrb_insn_size3[];
static void
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
{
int i;
uint32_t a;
uint16_t b;
uint8_t c;
mrb_code insn;
int argc = irep_argc(irep);
mrb_code *iseq = (mrb_code *)irep->iseq;
mrb_assert((irep->flags & MRB_ISEQ_NO_FREE) == 0);
for (i = 0; i < irep->ilen; ) {
insn = iseq[i];
switch(insn){
case OP_EPUSH:
a = PEEK_B(iseq+i+1);
patch_irep(mrb, irep->reps[a], bnest + 1, top);
break;
case OP_LAMBDA:
case OP_BLOCK:
a = PEEK_B(iseq+i+1);
b = PEEK_B(iseq+i+2);
patch_irep(mrb, irep->reps[b], bnest + 1, top);
break;
case OP_SEND:
b = PEEK_B(iseq+i+2);
c = PEEK_B(iseq+i+3);
if (c != 0) {
break;
}
else {
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
if (arg != 0) {
/* must replace */
iseq[i] = OP_GETUPVAR;
iseq[i+2] = arg >> 8;
iseq[i+3] = arg & 0xff;
}
}
break;
case OP_MOVE:
a = PEEK_B(iseq+i+1);
b = PEEK_B(iseq+i+2);
/* src part */
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
if (arg != 0) {
/* must replace */
iseq[i] = insn = OP_GETUPVAR;
iseq[i+2] = arg >> 8;
iseq[i+3] = arg & 0xff;
}
}
/* dst part */
if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
if (arg != 0) {
/* must replace */
iseq[i] = insn = OP_SETUPVAR;
iseq[i+1] = (mrb_code)b;
iseq[i+2] = arg >> 8;
iseq[i+3] = arg & 0xff;
}
}
break;
case OP_GETUPVAR:
a = PEEK_B(iseq+i+1);
b = PEEK_B(iseq+i+2);
c = PEEK_B(iseq+i+3);
{
int lev = c+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
if (arg != 0) {
/* must replace */
iseq[i] = OP_GETUPVAR;
iseq[i+2] = arg >> 8;
iseq[i+3] = arg & 0xff;
}
}
}
break;
case OP_SETUPVAR:
a = PEEK_B(iseq+i+1);
b = PEEK_B(iseq+i+2);
c = PEEK_B(iseq+i+3);
{
int lev = c+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
if (arg != 0) {
/* must replace */
iseq[i] = OP_SETUPVAR;
iseq[i+1] = a;
iseq[i+2] = arg >> 8;
iseq[i+3] = arg & 0xff;
}
}
}
break;
case OP_EXT1:
insn = PEEK_B(iseq+i+1);
i += mrb_insn_size1[insn]+1;
continue;
case OP_EXT2:
insn = PEEK_B(iseq+i+1);
i += mrb_insn_size2[insn]+1;
continue;
case OP_EXT3:
insn = PEEK_B(iseq+i+1);
i += mrb_insn_size3[insn]+1;
continue;
}
i+=mrb_insn_size[insn];
}
}
void mrb_codedump_all(mrb_state*, struct RProc*);
static struct RProc*
@@ -243,7 +32,8 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
mrbc_filename(mrb, cxt, file ? file : "(eval)");
cxt->capture_errors = TRUE;
cxt->no_optimize = TRUE;
cxt->on_eval = TRUE;
ci = (mrb->c->ci > mrb->c->cibase) ? mrb->c->ci - 1 : mrb->c->cibase;
cxt->upper = ci->proc && MRB_PROC_CFUNC_P(ci->proc) ? NULL : ci->proc;
p = mrb_parse_nstring(mrb, s, len, cxt);
@@ -298,7 +88,7 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
e->mid = ci->mid;
e->stack = ci[1].stackent;
e->cxt = mrb->c;
MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals);
MRB_ENV_SET_LEN(e, ci->proc->body.irep->nlocals);
bidx = ci->argc;
if (ci->argc < 0) bidx = 2;
else bidx += 1;
@@ -311,7 +101,6 @@ create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding,
}
proc->upper = ci->proc;
mrb->c->ci->target_class = target_class;
patch_irep(mrb, proc->body.irep, 0, proc->body.irep);
/* mrb_codedump_all(mrb, proc); */
mrb_parser_free(p);
+21
View File
@@ -130,3 +130,24 @@ Proc.new { foo }
EOS
}
end
assert('Calling the same method as the variable name') do
hoge = Object.new
def hoge.fuga
"Hit!"
end
assert_equal("Hit!") { fuga = "Miss!"; eval "hoge.fuga" }
assert_equal("Hit!") { fuga = "Miss!"; -> { eval "hoge.fuga" }.call }
assert_equal("Hit!") { -> { fuga = "Miss!"; eval "hoge.fuga" }.call }
assert_equal("Hit!") { fuga = "Miss!"; eval("-> { hoge.fuga }").call }
end
assert('Access numbered parameter from eval') do
hoge = Object.new
def hoge.fuga(a, &b)
b.call(a)
end
assert_equal(6) {
hoge.fuga(3) { _1 + eval("_1") }
}
end
+1 -2
View File
@@ -291,8 +291,7 @@ mrb_fiber_alive_p(mrb_state *mrb, mrb_value self)
static mrb_value
fiber_eq(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_get_args(mrb, "o", &other);
mrb_value other = mrb_get_arg1(mrb);
if (!mrb_fiber_p(other)) {
return mrb_false_value();
+3 -4
View File
@@ -8,8 +8,7 @@ istruct_test_initialize(mrb_state *mrb, mrb_value self)
{
char *string = (char*)mrb_istruct_ptr(self);
mrb_int size = mrb_istruct_size();
mrb_value object;
mrb_get_args(mrb, "o", &object);
mrb_value object = mrb_get_arg1(mrb);
if (mrb_fixnum_p(object)) {
strncpy(string, "fixnum", size-1);
@@ -45,8 +44,8 @@ istruct_test_length(mrb_state *mrb, mrb_value self)
static mrb_value
istruct_test_test_receive(mrb_state *mrb, mrb_value self)
{
mrb_value object;
mrb_get_args(mrb, "o", &object);
mrb_value object = mrb_get_arg1(mrb);
if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
{
mrb_raise(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
+3 -3
View File
@@ -18,7 +18,7 @@ extern "C" {
#if defined(MRB_WITHOUT_IO_PREAD_PWRITE)
# undef MRB_WITH_IO_PREAD_PWRITE
#elif !defined(MRB_WITH_IO_PREAD_PWRITE)
# if defined(__unix__)
# if defined(__unix__) || defined(__MACH__)
# define MRB_WITH_IO_PREAD_PWRITE
# endif
#endif
@@ -50,8 +50,8 @@ struct mrb_io {
#define MRB_O_SHARE_DELETE 0x1000
#define MRB_O_TMPFILE 0x2000
#define MRB_O_NOATIME 0x4000
#define MRB_O_DSYNC 0x00008000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
#define MRB_O_RSYNC 0x00010000 /* Ignored with MRB_INT16 and MRB_WITHOUT_FLOAT */
#define MRB_O_DSYNC 0x00008000
#define MRB_O_RSYNC 0x00010000
#define MRB_O_RDONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_RDONLY))
#define MRB_O_WRONLY_P(f) ((mrb_bool)(((f) & MRB_O_ACCMODE) == MRB_O_WRONLY))
+7 -28
View File
@@ -89,7 +89,7 @@ flock(int fd, int operation) {
}
#endif
mrb_value
static mrb_value
mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
@@ -265,7 +265,7 @@ mrb_file_realpath(mrb_state *mrb, mrb_value klass)
return result;
}
mrb_value
static mrb_value
mrb_file__getwd(mrb_state *mrb, mrb_value klass)
{
mrb_value path;
@@ -401,7 +401,7 @@ mrb_file_mtime(mrb_state *mrb, mrb_value self)
return mrb_funcall(mrb, obj, "at", 1, mrb_fixnum_value(st.st_mtime));
}
mrb_value
static mrb_value
mrb_file_flock(mrb_state *mrb, mrb_value self)
{
#if defined(sun)
@@ -458,7 +458,7 @@ mrb_file_size(mrb_state *mrb, mrb_value self)
}
static int
mrb_ftruncate(int fd, int64_t length)
mrb_ftruncate(int fd, mrb_int length)
{
#ifndef _WIN32
return ftruncate(fd, (off_t)length);
@@ -491,32 +491,11 @@ static mrb_value
mrb_file_truncate(mrb_state *mrb, mrb_value self)
{
int fd;
int64_t length;
mrb_value lenv;
mrb_int length;
mrb_value lenv = mrb_get_arg1(mrb);
fd = mrb_io_fileno(mrb, self);
mrb_get_args(mrb, "o", &lenv);
switch (mrb_type(lenv)) {
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
{
mrb_float lenf = mrb_float(lenv);
if (lenf > INT64_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "length too large");
}
length = (int64_t)lenf;
}
break;
#endif
case MRB_TT_FIXNUM:
default:
{
mrb_int leni = mrb_int(mrb, lenv);
length = (int64_t)leni;
}
break;
}
length = mrb_int(mrb, lenv);
if (mrb_ftruncate(fd, length) != 0) {
mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
}
+18 -35
View File
@@ -85,7 +85,7 @@ mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
* File.directory?(".")
*/
mrb_value
static mrb_value
mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
{
#ifndef S_ISDIR
@@ -93,9 +93,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
#endif
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
@@ -112,7 +110,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
* Returns <code>true</code> if the named file is a pipe.
*/
mrb_value
static mrb_value
mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
@@ -124,9 +122,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
# endif
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
@@ -145,7 +141,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
* Returns <code>true</code> if the named file is a symbolic link.
*/
mrb_value
static mrb_value
mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
@@ -167,9 +163,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
#ifdef S_ISLNK
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_lstat(mrb, obj, &st) == -1)
return mrb_false_value();
@@ -188,7 +182,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
* Returns <code>true</code> if the named file is a socket.
*/
mrb_value
static mrb_value
mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
@@ -210,9 +204,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
#ifdef S_ISSOCK
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
@@ -232,13 +224,12 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
* Return <code>true</code> if the named file exists.
*/
mrb_value
static mrb_value
mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
{
struct stat st;
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
@@ -253,7 +244,7 @@ mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
* regular file.
*/
mrb_value
static mrb_value
mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
{
#ifndef S_ISREG
@@ -261,9 +252,7 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
#endif
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
@@ -281,13 +270,11 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
* a zero size.
*/
mrb_value
static mrb_value
mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
{
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
@@ -306,13 +293,11 @@ mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
* _file_name_ can be an IO object.
*/
mrb_value
static mrb_value
mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
{
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
mrb_sys_fail(mrb, "mrb_stat");
@@ -328,13 +313,11 @@ mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
* file otherwise.
*/
mrb_value
static mrb_value
mrb_filetest_s_size_p(mrb_state *mrb, mrb_value klass)
{
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
mrb_value obj = mrb_get_arg1(mrb);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_nil_value();
+67 -41
View File
@@ -341,7 +341,7 @@ option_to_fd(mrb_state *mrb, mrb_value hash, const char *key)
}
#ifdef _WIN32
mrb_value
static mrb_value
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
{
mrb_value cmd, io;
@@ -439,14 +439,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
return io;
}
#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
mrb_value
static mrb_value
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
{
mrb_raise(mrb, E_NOTIMP_ERROR, "IO#popen is not supported on the platform");
return mrb_false_value();
}
#else
mrb_value
static mrb_value
mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
{
mrb_value cmd, io, result;
@@ -596,16 +596,15 @@ mrb_dup(mrb_state *mrb, int fd, mrb_bool *failed)
return new_fd;
}
mrb_value
static mrb_value
mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
{
mrb_value orig;
mrb_value orig = mrb_get_arg1(mrb);
mrb_value buf;
struct mrb_io *fptr_copy;
struct mrb_io *fptr_orig;
mrb_bool failed = TRUE;
mrb_get_args(mrb, "o", &orig);
fptr_orig = io_get_open_fptr(mrb, orig);
fptr_copy = (struct mrb_io *)DATA_PTR(copy);
if (fptr_orig == fptr_copy) return copy;
@@ -645,7 +644,44 @@ mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
return copy;
}
mrb_value
static void
check_file_descriptor(mrb_state *mrb, mrb_int fd)
{
struct stat sb;
int fdi = (int)fd;
#if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
if (fdi != fd) {
goto badfd;
}
#endif
#ifdef _WIN32
{
DWORD err;
int len = sizeof(err);
if (getsockopt(fdi, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0) {
return;
}
}
if (fdi < 0 || fdi > _getmaxstdio()) {
goto badfd;
}
#endif /* _WIN32 */
if (fstat(fdi, &sb) != 0) {
goto badfd;
}
return;
badfd:
mrb_sys_fail(mrb, "bad file descriptor");
}
static mrb_value
mrb_io_initialize(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr;
@@ -656,6 +692,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
mode = opt = mrb_nil_value();
mrb_get_args(mrb, "i|oo", &fd, &mode, &opt);
check_file_descriptor(mrb, fd);
if (mrb_nil_p(mode)) {
mode = mrb_str_new_cstr(mrb, "r");
}
@@ -747,7 +784,7 @@ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet)
}
}
mrb_value
static mrb_value
mrb_io_check_readable(mrb_state *mrb, mrb_value self)
{
struct mrb_io *fptr = io_get_open_fptr(mrb, self);
@@ -757,7 +794,7 @@ mrb_io_check_readable(mrb_state *mrb, mrb_value self)
return mrb_nil_value();
}
mrb_value
static mrb_value
mrb_io_isatty(mrb_state *mrb, mrb_value self)
{
struct mrb_io *fptr;
@@ -768,7 +805,7 @@ mrb_io_isatty(mrb_state *mrb, mrb_value self)
return mrb_true_value();
}
mrb_value
static mrb_value
mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
{
struct RClass *c = mrb_class_ptr(klass);
@@ -781,7 +818,7 @@ mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
return mrb_io_initialize(mrb, obj);
}
mrb_value
static mrb_value
mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
{
mrb_int fd;
@@ -792,7 +829,7 @@ mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
return mrb_fixnum_value(0);
}
int
static int
mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
{
int fd, retry = FALSE;
@@ -827,7 +864,7 @@ reopen:
return fd;
}
mrb_value
static mrb_value
mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
{
mrb_value path = mrb_nil_value();
@@ -857,7 +894,7 @@ mrb_sysread_dummy(int fd, void *buf, fsize_t nbytes, off_t offset)
return (mrb_io_read_write_size)read(fd, buf, nbytes);
}
mrb_value
static mrb_value
mrb_io_sysread(mrb_state *mrb, mrb_value io)
{
mrb_value buf = mrb_nil_value();
@@ -911,7 +948,7 @@ mrb_io_sysread_common(mrb_state *mrb,
return buf;
}
mrb_value
static mrb_value
mrb_io_sysseek(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr;
@@ -971,7 +1008,7 @@ mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset)
return (mrb_io_read_write_size)write(fd, buf, nbytes);
}
mrb_value
static mrb_value
mrb_io_syswrite(mrb_state *mrb, mrb_value io)
{
mrb_value buf;
@@ -981,7 +1018,7 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0);
}
mrb_value
static mrb_value
mrb_io_close(mrb_state *mrb, mrb_value self)
{
struct mrb_io *fptr;
@@ -990,7 +1027,7 @@ mrb_io_close(mrb_state *mrb, mrb_value self)
return mrb_nil_value();
}
mrb_value
static mrb_value
mrb_io_close_write(mrb_state *mrb, mrb_value self)
{
struct mrb_io *fptr;
@@ -1001,7 +1038,7 @@ mrb_io_close_write(mrb_state *mrb, mrb_value self)
return mrb_nil_value();
}
mrb_value
static mrb_value
mrb_io_closed(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr;
@@ -1013,7 +1050,7 @@ mrb_io_closed(mrb_state *mrb, mrb_value io)
return mrb_true_value();
}
mrb_value
static mrb_value
mrb_io_pid(mrb_state *mrb, mrb_value io)
{
struct mrb_io *fptr;
@@ -1147,6 +1184,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
for (i = 0; i < RARRAY_LEN(read); i++) {
read_io = RARRAY_PTR(read)[i];
fptr = io_get_open_fptr(mrb, read_io);
if (fptr->fd >= FD_SETSIZE) continue;
FD_SET(fptr->fd, rp);
if (mrb_io_read_data_pending(mrb, read_io)) {
pending++;
@@ -1169,6 +1207,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
FD_ZERO(wp);
for (i = 0; i < RARRAY_LEN(write); i++) {
fptr = io_get_open_fptr(mrb, RARRAY_PTR(write)[i]);
if (fptr->fd >= FD_SETSIZE) continue;
FD_SET(fptr->fd, wp);
if (max < fptr->fd)
max = fptr->fd;
@@ -1188,6 +1227,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
FD_ZERO(ep);
for (i = 0; i < RARRAY_LEN(except); i++) {
fptr = io_get_open_fptr(mrb, RARRAY_PTR(except)[i]);
if (fptr->fd >= FD_SETSIZE) continue;
FD_SET(fptr->fd, ep);
if (max < fptr->fd)
max = fptr->fd;
@@ -1276,7 +1316,7 @@ mrb_io_fileno_m(mrb_state *mrb, mrb_value io)
return mrb_fixnum_value(fd);
}
mrb_value
static mrb_value
mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
{
#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
@@ -1300,7 +1340,7 @@ mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
#endif
}
mrb_value
static mrb_value
mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
{
#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
@@ -1336,7 +1376,7 @@ mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
#endif
}
mrb_value
static mrb_value
mrb_io_set_sync(mrb_state *mrb, mrb_value self)
{
struct mrb_io *fptr;
@@ -1348,7 +1388,7 @@ mrb_io_set_sync(mrb_state *mrb, mrb_value self)
return mrb_bool_value(b);
}
mrb_value
static mrb_value
mrb_io_sync(mrb_state *mrb, mrb_value self)
{
struct mrb_io *fptr;
@@ -1363,22 +1403,7 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
static off_t
value2off(mrb_state *mrb, mrb_value offv)
{
switch (mrb_type(offv)) {
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
{
mrb_float tmp = mrb_float(offv);
if (tmp < INT64_MIN || tmp > INT64_MAX) {
/* fall through to use convert by `mrb_int()` (and raise error if out of range) */
} else {
return (off_t)tmp;
}
}
/* fall through */
#endif /* MRB_WITHOUT_FLOAT */
default:
return (off_t)mrb_int(mrb, offv);
}
return (off_t)mrb_int(mrb, offv);
}
/*
@@ -1452,7 +1477,8 @@ mrb_io_readchar(mrb_state *mrb, mrb_value self)
#endif
mrb_get_args(mrb, "S", &buf);
mrb_assert(RSTRING_PTR(buf) > 0);
mrb_assert(RSTRING_LEN(buf) > 0);
mrb_assert(RSTRING_PTR(buf) != NULL);
mrb_str_modify(mrb, RSTRING(buf));
#ifdef MRB_UTF8_STRING
c = RSTRING_PTR(buf)[0];
+18 -12
View File
@@ -110,18 +110,22 @@ assert('File.join') do
end
assert('File.realpath') do
if File::ALT_SEPARATOR
readme_path = File._getwd + File::ALT_SEPARATOR + "README.md"
assert_equal readme_path, File.realpath("README.md")
else
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
begin
dir1 = File.realpath($mrbtest_io_rfname)
dir2 = File.realpath("./#{dir}//./../#{$mrbtest_io_symlinkname}")
assert_equal dir1, dir2
ensure
MRubyIOTestUtil.rmdir dir
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
begin
sep = File::ALT_SEPARATOR || File::SEPARATOR
relative_path = "#{File.basename(dir)}#{sep}realpath_test"
path = "#{File._getwd}#{sep}#{relative_path}"
File.open(path, "w"){}
assert_equal path, File.realpath(relative_path)
unless MRubyIOTestUtil.win?
path1 = File.realpath($mrbtest_io_rfname)
path2 = File.realpath($mrbtest_io_symlinkname)
assert_equal path1, path2
end
ensure
File.delete path rescue nil
MRubyIOTestUtil.rmdir dir
end
assert_raise(ArgumentError) { File.realpath("TO\0DO") }
@@ -129,7 +133,9 @@ end
assert("File.readlink") do
begin
assert_equal $mrbtest_io_rfname, File.readlink($mrbtest_io_symlinkname)
exp = File.basename($mrbtest_io_rfname)
act = File.readlink($mrbtest_io_symlinkname)
assert_equal exp, act
rescue NotImplementedError => e
skip e.message
end
+4
View File
@@ -24,6 +24,10 @@ def assert_io_open(meth)
end
end
io2.close unless meth == :open
assert_raise(RuntimeError) { IO.__send__(meth, 1023) } # For Windows
assert_raise(RuntimeError) { IO.__send__(meth, 1 << 26) }
assert_raise(RuntimeError) { IO.__send__(meth, 1 << 32) } if (1 << 32).kind_of?(Integer)
end
end
+48 -89
View File
@@ -54,6 +54,7 @@ mkdtemp(char *temp)
#include <unistd.h>
#include <sys/un.h>
#include <fcntl.h>
#include <libgen.h>
#endif
#include <sys/stat.h>
@@ -66,88 +67,53 @@ mkdtemp(char *temp)
#include "mruby/variable.h"
#include <mruby/ext/io.h>
int wd_save;
int socket_available_p;
#if !defined(_WIN32) && !defined(_WIN64)
static int mrb_io_socket_available()
{
int fd, retval = 0;
struct sockaddr_un sun0;
char socketname[] = "tmp.mruby-io-socket-ok.XXXXXXXX";
if (!(fd = mkstemp(socketname))) {
goto sock_test_out;
}
unlink(socketname);
close(fd);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
goto sock_test_out;
}
sun0.sun_family = AF_UNIX;
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
if (bind(fd, (struct sockaddr *)&sun0, sizeof(sun0)) == 0) {
retval = 1;
}
sock_test_out:
unlink(socketname);
close(fd);
return retval;
}
#endif
static mrb_value
mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
{
char rfname[] = "tmp.mruby-io-test-r.XXXXXXXX";
char wfname[] = "tmp.mruby-io-test-w.XXXXXXXX";
char symlinkname[] = "tmp.mruby-io-test-l.XXXXXXXX";
char socketname[] = "tmp.mruby-io-test-s.XXXXXXXX";
#define GVNAME(n) "$mrbtest_io_" #n "name"
enum {IDX_READ, IDX_WRITE, IDX_LINK, IDX_SOCKET, IDX_COUNT};
const char *gvnames[] = {GVNAME(rf), GVNAME(wf), GVNAME(symlink), GVNAME(socket)};
char *fnames[IDX_COUNT];
int fds[IDX_COUNT];
char msg[] = "mruby io test\n";
mode_t mask;
int fd0, fd1;
FILE *fp;
int i;
#if !defined(_WIN32) && !defined(_WIN64)
int fd2, fd3;
struct sockaddr_un sun0;
if(!(socket_available_p = mrb_io_socket_available())) {
char *tmpdir;
wd_save = open(".", O_DIRECTORY);
tmpdir = getenv("TMPDIR");
if (tmpdir) chdir(tmpdir);
else chdir("/tmp");
}
#endif
mask = umask(077);
fd0 = mkstemp(rfname);
fd1 = mkstemp(wfname);
if (fd0 == -1 || fd1 == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
return mrb_nil_value();
}
close(fd0);
close(fd1);
#if !defined(_WIN32) && !defined(_WIN64)
fd2 = mkstemp(symlinkname);
fd3 = mkstemp(socketname);
if (fd2 == -1 || fd3 == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
return mrb_nil_value();
}
#endif
umask(mask);
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_str_new_cstr(mrb, rfname));
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_str_new_cstr(mrb, wfname));
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_str_new_cstr(mrb, symlinkname));
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_str_new_cstr(mrb, socketname));
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_str_new_cstr(mrb, msg));
fp = fopen(rfname, "wb");
mask = umask(077);
for (i = 0; i < IDX_COUNT; i++) {
mrb_value fname = mrb_str_new_capa(mrb, 0);
#if !defined(_WIN32) && !defined(_WIN64)
/*
* Workaround for not being able to bind a socket to some file systems
* (e.g. vboxsf, NFS). [#4981]
*/
char *tmpdir = getenv("TMPDIR");
if (tmpdir && strlen(tmpdir) > 0) {
mrb_str_cat_cstr(mrb, fname, tmpdir);
if (*(RSTRING_END(fname)-1) != '/') mrb_str_cat_lit(mrb, fname, "/");
} else {
mrb_str_cat_lit(mrb, fname, "/tmp/");
}
#endif
mrb_str_cat_cstr(mrb, fname, gvnames[i]+1);
mrb_str_cat_cstr(mrb, fname, ".XXXXXXXX");
fnames[i] = RSTRING_PTR(fname);
fds[i] = mkstemp(fnames[i]);
if (fds[i] == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't create temporary file");
}
close(fds[i]);
mrb_gv_set(mrb, mrb_intern_cstr(mrb, gvnames[i]), fname);
}
umask(mask);
fp = fopen(fnames[IDX_READ], "wb");
if (fp == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
return mrb_nil_value();
@@ -155,7 +121,7 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
fputs(msg, fp);
fclose(fp);
fp = fopen(wfname, "wb");
fp = fopen(fnames[IDX_WRITE], "wb");
if (fp == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
return mrb_nil_value();
@@ -163,29 +129,29 @@ mrb_io_test_io_setup(mrb_state *mrb, mrb_value self)
fclose(fp);
#if !defined(_WIN32) && !defined(_WIN64)
unlink(symlinkname);
close(fd2);
if (symlink(rfname, symlinkname) == -1) {
unlink(fnames[IDX_LINK]);
if (symlink(basename(fnames[IDX_READ]), fnames[IDX_LINK]) == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
}
unlink(socketname);
close(fd3);
fd3 = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd3 == -1) {
unlink(fnames[IDX_SOCKET]);
fds[IDX_SOCKET] = socket(AF_UNIX, SOCK_STREAM, 0);
if (fds[IDX_SOCKET] == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket");
}
sun0.sun_family = AF_UNIX;
strncpy(sun0.sun_path, socketname, sizeof(sun0.sun_path));
if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
strncpy(sun0.sun_path, fnames[IDX_SOCKET], sizeof(sun0.sun_path)-1);
sun0.sun_path[sizeof(sun0.sun_path)-1] = 0;
if (bind(fds[IDX_SOCKET], (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "can't bind AF_UNIX socket to %s: %d",
sun0.sun_path,
errno);
}
close(fd3);
close(fds[IDX_SOCKET]);
#endif
return mrb_true_value();
#undef GVNAME
}
static mrb_value
@@ -215,13 +181,6 @@ mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"), mrb_nil_value());
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_msg"), mrb_nil_value());
#if !defined(_WIN32) && !defined(_WIN64)
if(!socket_available_p) {
fchdir(wd_save);
close(wd_save);
}
#endif
return mrb_nil_value();
}
@@ -251,7 +210,7 @@ mrb_io_test_rmdir(mrb_state *mrb, mrb_value klass)
return mrb_true_value();
}
mrb_value
static mrb_value
mrb_io_win_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
+6 -8
View File
@@ -128,9 +128,8 @@ mrb_f_integer(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_float(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
mrb_value arg = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &arg);
return mrb_Float(mrb, arg);
}
#endif
@@ -149,9 +148,9 @@ mrb_f_float(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_string(mrb_state *mrb, mrb_value self)
{
mrb_value arg, tmp;
mrb_value arg = mrb_get_arg1(mrb);
mrb_value tmp;
mrb_get_args(mrb, "o", &arg);
tmp = mrb_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s");
return tmp;
}
@@ -168,9 +167,9 @@ mrb_f_string(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_array(mrb_state *mrb, mrb_value self)
{
mrb_value arg, tmp;
mrb_value arg = mrb_get_arg1(mrb);
mrb_value tmp;
mrb_get_args(mrb, "o", &arg);
tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a");
if (mrb_nil_p(tmp)) {
return mrb_ary_new_from_values(mrb, 1, &arg);
@@ -196,9 +195,8 @@ mrb_f_array(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_f_hash(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
mrb_value arg = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &arg);
if (mrb_nil_p(arg) || (mrb_array_p(arg) && RARRAY_LEN(arg) == 0)) {
return mrb_hash_new(mrb);
}
+14 -16
View File
@@ -146,24 +146,23 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
while (proc) {
if (MRB_PROC_CFUNC_P(proc)) break;
irep = proc->body.irep;
if (!irep->lv) break;
for (i = 0; i + 1 < irep->nlocals; ++i) {
if (irep->lv[i].name) {
mrb_sym sym = irep->lv[i].name;
const char *name = mrb_sym_name(mrb, sym);
switch (name[0]) {
case '*': case '&':
break;
default:
mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value());
break;
if (irep->lv) {
for (i = 0; i + 1 < irep->nlocals; ++i) {
if (irep->lv[i].name) {
mrb_sym sym = irep->lv[i].name;
const char *name = mrb_sym_name(mrb, sym);
switch (name[0]) {
case '*': case '&':
break;
default:
mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value());
break;
}
}
}
}
if (!MRB_PROC_ENV_P(proc)) break;
if (MRB_PROC_SCOPE_P(proc)) break;
proc = proc->upper;
//if (MRB_PROC_SCOPE_P(proc)) break;
if (!proc->c) break;
}
return mrb_hash_keys(mrb, vars);
@@ -671,8 +670,7 @@ mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
ary = mrb_ary_new(mrb);
proc = mrb->c->ci[-1].proc; /* callee proc */
mrb_assert(!MRB_PROC_CFUNC_P(proc));
while (proc) {
while (proc && !MRB_PROC_CFUNC_P(proc)) {
if (MRB_PROC_SCOPE_P(proc)) {
struct RClass *c2 = MRB_PROC_TARGET_CLASS(proc);
+9
View File
@@ -114,6 +114,15 @@ assert('Kernel.local_variables', '15.3.1.2.7') do
# Kernel#local_variables: 15.3.1.3.28
local_variables.sort
}.call(-1, -2)
a = Object.new
def a.hoge(vars, *, **)
Proc.new {
x, y = 1, 2
local_variables.sort
}
end
assert_equal([:vars, :x, :y]) { a.hoge(0).call }
end
assert('Kernel#define_singleton_method') do
+4 -5
View File
@@ -33,9 +33,8 @@ unbound_method_bind(mrb_state *mrb, mrb_value self)
mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_name"));
mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_proc"));
mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "_klass"));
mrb_value recv;
mrb_value recv = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &recv);
bind_check(mrb, recv, owner);
me = method_object_alloc(mrb, mrb_class_get(mrb, "Method"));
mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "_owner"), owner);
@@ -51,11 +50,11 @@ unbound_method_bind(mrb_state *mrb, mrb_value self)
static mrb_value
method_eql(mrb_state *mrb, mrb_value self)
{
mrb_value other, receiver, orig_proc, other_proc;
mrb_value other = mrb_get_arg1(mrb);
mrb_value receiver, orig_proc, other_proc;
struct RClass *owner, *klass;
struct RProc *orig_rproc, *other_rproc;
mrb_get_args(mrb, "o", &other);
if (!mrb_obj_is_instance_of(mrb, other, mrb_class(mrb, self)))
return mrb_false_value();
@@ -110,7 +109,7 @@ method_eql(mrb_state *mrb, mrb_value self)
static mrb_value
mcall(mrb_state *mrb, mrb_value recv, mrb_value proc, mrb_value name, struct RClass *owner,
int argc, mrb_value *argv, mrb_value block)
mrb_int argc, mrb_value *argv, mrb_value block)
{
mrb_value ret;
mrb_sym orig_mid = mrb->c->ci->mid;
+3 -12
View File
@@ -101,18 +101,9 @@ mrb_obj_instance_exec(mrb_state *mrb, mrb_value self)
struct RClass *c;
mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
switch (mrb_type(self)) {
case MRB_TT_SYMBOL:
case MRB_TT_FIXNUM:
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
#endif
c = NULL;
break;
default:
c = mrb_class_ptr(mrb_singleton_class(mrb, self));
break;
c = mrb_singleton_class_ptr(mrb, self);
if (mrb->c->ci->acc < 0) {
return mrb_yield_with_class(mrb, blk, argc, argv, self, c);
}
mrb->c->ci->target_class = c;
return mrb_yield_cont(mrb, blk, self, argc, argv);
@@ -89,7 +89,6 @@ os_count_objects(mrb_state *mrb, mrb_value self)
COUNT_TYPE(T_STRING);
COUNT_TYPE(T_RANGE);
COUNT_TYPE(T_EXCEPTION);
COUNT_TYPE(T_FILE);
COUNT_TYPE(T_ENV);
COUNT_TYPE(T_DATA);
COUNT_TYPE(T_FIBER);
+112 -13
View File
@@ -3,11 +3,6 @@
*/
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error pack/unpack conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include "mruby/error.h"
#include "mruby/array.h"
#include "mruby/class.h"
@@ -217,6 +212,59 @@ pack_l(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int fl
return 4;
}
#ifndef MRB_INT64
static void
u32tostr(char *buf, size_t len, uint32_t n)
{
#ifdef MRB_DISABLE_STDIO
char *bufend = buf + len;
char *p = bufend - 1;
if (len < 1) {
return;
}
*p -- = '\0';
len --;
if (n > 0) {
for (; len > 0 && n > 0; len --, n /= 10) {
*p -- = '0' + (n % 10);
}
p ++;
}
else if (len > 0) {
*p = '0';
len --;
}
memmove(buf, p, bufend - p);
#else
snprintf(buf, len, "%" PRIu32, n);
#endif /* MRB_DISABLE_STDIO */
}
static void
i32tostr(char *buf, size_t len, int32_t n)
{
#ifdef MRB_DISABLE_STDIO
if (len < 1) {
return;
}
if (n < 0) {
*buf ++ = '-';
len --;
n = -n;
}
u32tostr(buf, len, (uint32_t)n);
#else
snprintf(buf, len, "%" PRId32, n);
#endif /* MRB_DISABLE_STDIO */
}
#endif /* MRB_INT64 */
static int
unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
{
@@ -241,16 +289,16 @@ unpack_l(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un
int32_t sl = ul;
#ifndef MRB_INT64
if (!FIXABLE(sl)) {
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRId32, sl);
mrb_raise(mrb, E_RANGE_ERROR, msg);
i32tostr(msg, sizeof(msg), sl);
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
}
#endif
n = sl;
} else {
#ifndef MRB_INT64
if (!POSFIXABLE(ul)) {
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRIu32, ul);
mrb_raise(mrb, E_RANGE_ERROR, msg);
u32tostr(msg, sizeof(msg), ul);
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
}
#endif
n = ul;
@@ -288,6 +336,57 @@ pack_q(mrb_state *mrb, mrb_value o, mrb_value str, mrb_int sidx, unsigned int fl
return 8;
}
static void
u64tostr(char *buf, size_t len, uint64_t n)
{
#ifdef MRB_DISABLE_STDIO
char *bufend = buf + len;
char *p = bufend - 1;
if (len < 1) {
return;
}
*p -- = '\0';
len --;
if (n > 0) {
for (; len > 0 && n > 0; len --, n /= 10) {
*p -- = '0' + (n % 10);
}
p ++;
}
else if (len > 0) {
*p = '0';
len --;
}
memmove(buf, p, bufend - p);
#else
snprintf(buf, len, "%" PRIu64, n);
#endif /* MRB_DISABLE_STDIO */
}
static void
i64tostr(char *buf, size_t len, int64_t n)
{
#ifdef MRB_DISABLE_STDIO
if (len < 1) {
return;
}
if (n < 0) {
*buf ++ = '-';
len --;
n = -n;
}
u64tostr(buf, len, (uint64_t)n);
#else
snprintf(buf, len, "%" PRId64, n);
#endif /* MRB_DISABLE_STDIO */
}
static int
unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, unsigned int flags)
{
@@ -311,14 +410,14 @@ unpack_q(mrb_state *mrb, const unsigned char *src, int srclen, mrb_value ary, un
if (flags & PACK_FLAG_SIGNED) {
int64_t sll = ull;
if (!FIXABLE(sll)) {
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRId64, sll);
mrb_raise(mrb, E_RANGE_ERROR, msg);
i64tostr(msg, sizeof(msg), sll);
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
}
n = sll;
} else {
if (!POSFIXABLE(ull)) {
snprintf(msg, sizeof(msg), "cannot unpack to Fixnum: %" PRIu64, ull);
mrb_raise(mrb, E_RANGE_ERROR, msg);
u64tostr(msg, sizeof(msg), ull);
mrb_raisef(mrb, E_RANGE_ERROR, "cannot unpack to Fixnum: %s", msg);
}
n = ull;
}
+1 -2
View File
@@ -45,9 +45,8 @@ printstr(mrb_state *mrb, mrb_value obj)
mrb_value
mrb_printstr(mrb_state *mrb, mrb_value self)
{
mrb_value argv;
mrb_value argv = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &argv);
printstr(mrb, argv);
return argv;
+2 -2
View File
@@ -6,7 +6,7 @@
#include <mruby/debug.h>
static mrb_value
mrb_proc_lambda(mrb_state *mrb, mrb_value self)
mrb_proc_lambda_p(mrb_state *mrb, mrb_value self)
{
struct RProc *p = mrb_proc_ptr(self);
return mrb_bool_value(MRB_PROC_STRICT_P(p));
@@ -169,7 +169,7 @@ void
mrb_mruby_proc_ext_gem_init(mrb_state* mrb)
{
struct RClass *p = mrb->proc_class;
mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda, MRB_ARGS_NONE());
mrb_define_method(mrb, p, "lambda?", mrb_proc_lambda_p, MRB_ARGS_NONE());
mrb_define_method(mrb, p, "source_location", mrb_proc_source_location, MRB_ARGS_NONE());
mrb_define_method(mrb, p, "to_s", mrb_proc_inspect, MRB_ARGS_NONE());
mrb_define_method(mrb, p, "inspect", mrb_proc_inspect, MRB_ARGS_NONE());
+1 -3
View File
@@ -34,12 +34,10 @@ r_lt(mrb_state *mrb, mrb_value a, mrb_value b)
static mrb_value
range_cover(mrb_state *mrb, mrb_value range)
{
mrb_value val;
struct RRange *r = mrb_range_ptr(mrb, range);
mrb_value val = mrb_get_arg1(mrb);
mrb_value beg, end;
mrb_get_args(mrb, "o", &val);
beg = RANGE_BEG(r);
end = RANGE_END(r);
+1 -3
View File
@@ -91,8 +91,8 @@ module Kernel
end
[:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op|
original_operator_name = :"__original_operator_#{op}_rational"
Fixnum.instance_eval do
original_operator_name = "__original_operator_#{op}_rational"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Rational
@@ -103,7 +103,6 @@ module Kernel
end
end
Float.instance_eval do
original_operator_name = "__original_operator_#{op}_rational"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Rational
@@ -114,4 +113,3 @@ module Kernel
end if Object.const_defined?(:Float)
end
end
+9 -9
View File
@@ -91,9 +91,9 @@ rational_s_new(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "ii", &numerator, &denominator);
#else
#define DROP_PRECISION(cond, num, denom) \
#define DROP_PRECISION(f, num, denom) \
do { \
while (cond) { \
while (f < (mrb_float)MRB_INT_MIN || f > (mrb_float)MRB_INT_MAX) { \
num /= 2; \
denom /= 2; \
} \
@@ -111,8 +111,8 @@ rational_s_new(mrb_state *mrb, mrb_value self)
else {
mrb_float denomf = mrb_to_flo(mrb, denomv);
DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numerator, denomf);
denominator = denomf;
DROP_PRECISION(denomf, numerator, denomf);
denominator = (mrb_int)denomf;
}
}
else {
@@ -124,12 +124,12 @@ rational_s_new(mrb_state *mrb, mrb_value self)
else {
mrb_float denomf = mrb_to_flo(mrb, denomv);
DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numf, denomf);
denominator = denomf;
DROP_PRECISION(denomf, numf, denomf);
denominator = (mrb_int)denomf;
}
DROP_PRECISION(numf < MRB_INT_MIN || numf > MRB_INT_MAX, numf, denominator);
numerator = numf;
DROP_PRECISION(numf, numf, denominator);
numerator = (mrb_int)numf;
}
#endif
@@ -152,7 +152,7 @@ rational_to_i(mrb_state *mrb, mrb_value self)
{
struct mrb_rational *p = rational_ptr(mrb, self);
if (p->denominator == 0) {
mrb_raise(mrb, mrb_exc_get(mrb, "StandardError"), "divided by 0");
mrb_raise(mrb, mrb->eStandardError_class, "divided by 0");
}
return mrb_fixnum_value(p->numerator / p->denominator);
}
+1 -1
View File
@@ -30,7 +30,7 @@
#ifdef _WIN32
#include <windows.h>
#define sleep(x) Sleep(x * 1000)
#define usleep(x) Sleep((DWORD)((x)<1000) ? 1 : ((x)/1000))
#define usleep(x) Sleep((DWORD)(((x)<1000) ? 1 : ((x)/1000)))
#else
#include <unistd.h>
#include <sys/time.h>
+62 -28
View File
@@ -5,11 +5,6 @@
*/
#include <mruby.h>
#ifdef MRB_DISABLE_STDIO
# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
#endif
#include <limits.h>
#include <string.h>
#include <mruby/string.h>
@@ -521,6 +516,50 @@ mrb_f_sprintf(mrb_state *mrb, mrb_value obj)
}
}
static int
mrb_int2str(char *buf, size_t len, mrb_int n)
{
#ifdef MRB_DISABLE_STDIO
char *bufend = buf + len;
char *p = bufend - 1;
if (len < 1) return -1;
*p -- = '\0';
len --;
if (n < 0) {
if (len < 1) return -1;
*p -- = '-';
len --;
n = -n;
}
if (n > 0) {
for (; n > 0; len --, n /= 10) {
if (len < 1) return -1;
*p -- = '0' + (n % 10);
}
p ++;
}
else if (len > 0) {
*p = '0';
len --;
}
else {
return -1;
}
memmove(buf, p, bufend - p);
return bufend - p - 1;
#else
return snprintf(buf, len, "%" MRB_PRId, n);
#endif /* MRB_DISABLE_STDIO */
}
mrb_value
mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fmt)
{
@@ -711,7 +750,12 @@ retry:
}
else if (mrb_fixnum_p(val)) {
mrb_int n = mrb_fixnum(val);
#ifndef MRB_UTF8_STRING
char buf[1];
buf[0] = (char)n&0xff;
tmp = mrb_str_new(mrb, buf, 1);
#else
if (n < 0x80) {
char buf[1];
@@ -722,6 +766,7 @@ retry:
tmp = mrb_funcall(mrb, val, "chr", 0);
mrb_check_type(mrb, tmp, MRB_TT_STRING);
}
#endif
}
else {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
@@ -797,7 +842,7 @@ retry:
case 'B':
case 'u': {
mrb_value val = GETARG();
char nbuf[68], *s;
char nbuf[69], *s;
const char *prefix = NULL;
int sign = 0, dots = 0;
char sc = 0;
@@ -869,7 +914,7 @@ retry:
width--;
}
mrb_assert(base == 10);
snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
mrb_int2str(nbuf, sizeof(nbuf)-1, v);
s = nbuf;
if (v < 0) s++; /* skip minus sign */
}
@@ -877,24 +922,12 @@ retry:
s = nbuf;
if (v < 0) {
dots = 1;
val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
}
switch (base) {
case 2:
if (v < 0) {
val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
}
else {
val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
}
strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1);
break;
case 8:
snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v);
break;
case 16:
snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIx, v);
break;
else {
val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
}
strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-2);
if (v < 0) {
char d;
@@ -1008,7 +1041,7 @@ retry:
mrb_value val = GETARG();
double fval;
mrb_int need = 6;
char fbuf[32];
char fbuf[64];
fval = mrb_float(mrb_Float(mrb, val));
if (!isfinite(fval)) {
@@ -1049,7 +1082,6 @@ retry:
break;
}
fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
need = 0;
if (*p != 'e' && *p != 'E') {
int i;
@@ -1071,7 +1103,8 @@ retry:
need += 20;
CHECK(need);
n = snprintf(&buf[blen], need, fbuf, fval);
fmt_setup(fbuf, sizeof(fbuf), *p, flags, width, prec);
n = mrb_float_to_cstr(mrb, &buf[blen], need, fbuf, fval);
if (n < 0 || n >= need) {
mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
}
@@ -1113,12 +1146,13 @@ fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec)
if (flags & FSPACE) *buf++ = ' ';
if (flags & FWIDTH) {
n = snprintf(buf, end - buf, "%d", (int)width);
n = mrb_int2str(buf, end - buf, width);
buf += n;
}
if (flags & FPREC) {
n = snprintf(buf, end - buf, ".%d", (int)prec);
*buf ++ = '.';
n = mrb_int2str(buf, end - buf, prec);
buf += n;
}
+5 -23
View File
@@ -8,6 +8,11 @@ assert('String#%') do
assert_equal 15, ("%b" % (1<<14)).size
skip unless Object.const_defined?(:Float)
assert_equal "1.0", "%3.1f" % 1.01
assert_equal " 123456789.12", "% 4.2f" % 123456789.123456789
assert_equal "123456789.12", "%-4.2f" % 123456789.123456789
assert_equal "+123456789.12", "%+4.2f" % 123456789.123456789
assert_equal "123456789.12", "%04.2f" % 123456789.123456789
assert_equal "00000000123456789.12", "%020.2f" % 123456789.123456789
end
assert('String#% with inf') do
@@ -68,29 +73,6 @@ assert('String#% with nan') do
assert_equal " NaN", "% 5f" % nan
end
assert("String#% with invalid chr") do
begin
class Fixnum
alias_method :chr_, :chr if method_defined?(:chr)
def chr
nil
end
end
assert_raise TypeError do
"%c" % 0x80
end
ensure
class Fixnum
if method_defined?(:chr_)
alias_method :chr, :chr_
remove_method :chr_
end
end
end
end
assert("String#% %b") do
assert_equal("..10115", "%0b5" % -5)
end
+4 -5
View File
@@ -164,9 +164,8 @@ mrb_str_swapcase(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_str_concat_m(mrb_state *mrb, mrb_value self)
{
mrb_value str;
mrb_value str = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &str);
if (mrb_fixnum_p(str) || mrb_float_p(str))
#ifdef MRB_UTF8_STRING
str = int_chr_utf8(mrb, str);
@@ -335,7 +334,7 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
len = i - start_pos;
if (len > UINT16_MAX) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65536)");
mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65535)");
}
if (pat1 == NULL && ret) {
goto nomem;
@@ -343,9 +342,9 @@ tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_patte
pat1->type = TR_IN_ORDER;
pat1->flag_reverse = flag_reverse;
pat1->flag_on_heap = !ret_uninit;
pat1->n = len;
pat1->n = (uint16_t)len;
pat1->next = NULL;
pat1->val.start_pos = start_pos;
pat1->val.start_pos = (uint16_t)start_pos;
}
if (ret == NULL || ret_uninit) {
+5 -11
View File
@@ -154,9 +154,8 @@ mrb_struct_set_m(mrb_state *mrb, mrb_value obj)
{
mrb_int i = mrb_fixnum(mrb_proc_cfunc_env_get(mrb, 0));
mrb_value *ptr;
mrb_value val;
mrb_value val = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &val);
mrb_struct_modify(mrb, obj);
ptr = RSTRUCT_PTR(obj);
if (ptr == NULL || i >= RSTRUCT_LEN(obj)) {
@@ -356,9 +355,7 @@ mrb_struct_initialize(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_struct_init_copy(mrb_state *mrb, mrb_value copy)
{
mrb_value s;
mrb_get_args(mrb, "o", &s);
mrb_value s = mrb_get_arg1(mrb);
if (mrb_obj_equal(mrb, copy, s)) return copy;
if (!mrb_obj_is_instance_of(mrb, s, mrb_obj_class(mrb, copy))) {
@@ -428,9 +425,8 @@ struct_aref_int(mrb_state *mrb, mrb_value s, mrb_int i)
static mrb_value
mrb_struct_aref(mrb_state *mrb, mrb_value s)
{
mrb_value idx;
mrb_value idx = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &idx);
if (mrb_string_p(idx)) {
mrb_value sym = mrb_check_intern_str(mrb, idx);
@@ -545,11 +541,10 @@ mrb_struct_aset(mrb_state *mrb, mrb_value s)
static mrb_value
mrb_struct_equal(mrb_state *mrb, mrb_value s)
{
mrb_value s2;
mrb_value s2 = mrb_get_arg1(mrb);
mrb_value *ptr, *ptr2;
mrb_int i, len;
mrb_get_args(mrb, "o", &s2);
if (mrb_obj_equal(mrb, s, s2)) {
return mrb_true_value();
}
@@ -582,11 +577,10 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s)
static mrb_value
mrb_struct_eql(mrb_state *mrb, mrb_value s)
{
mrb_value s2;
mrb_value s2 = mrb_get_arg1(mrb);
mrb_value *ptr, *ptr2;
mrb_int i, len;
mrb_get_args(mrb, "o", &s2);
if (mrb_obj_equal(mrb, s, s2)) {
return mrb_true_value();
}
+1
View File
@@ -26,6 +26,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
file assert_lib => assert_c
file assert_c => [assert_rb, build.mrbcfile] do |t|
mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
mrbc.run f, assert_rb, 'mrbtest_assert_irep'
end
+9 -11
View File
@@ -13,6 +13,7 @@
#include <mruby/data.h>
#include <mruby/numeric.h>
#include <mruby/time.h>
#include <mruby/string.h>
#ifdef MRB_DISABLE_STDIO
#include <string.h>
@@ -514,11 +515,10 @@ time_get_ptr(mrb_state *mrb, mrb_value time)
static mrb_value
mrb_time_eq(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
struct mrb_time *tm1, *tm2;
mrb_bool eq_p;
mrb_get_args(mrb, "o", &other);
tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
eq_p = tm1 && tm2 && tm1->sec == tm2->sec && tm1->usec == tm2->usec;
@@ -529,10 +529,9 @@ mrb_time_eq(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_time_cmp(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
struct mrb_time *tm1, *tm2;
mrb_get_args(mrb, "o", &other);
tm1 = DATA_GET_PTR(mrb, self, &mrb_time_type, struct mrb_time);
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
if (!tm1 || !tm2) return mrb_nil_value();
@@ -555,11 +554,10 @@ mrb_time_cmp(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_time_plus(mrb_state *mrb, mrb_value self)
{
mrb_value o;
mrb_value o = mrb_get_arg1(mrb);
struct mrb_time *tm;
time_t sec, usec;
mrb_get_args(mrb, "o", &o);
tm = time_get_ptr(mrb, self);
sec = mrb_to_time_t(mrb, o, &usec);
return mrb_time_make_time(mrb, mrb_obj_class(mrb, self), tm->sec+sec, tm->usec+usec, tm->timezone);
@@ -568,10 +566,9 @@ mrb_time_plus(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_time_minus(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
struct mrb_time *tm, *tm2;
mrb_get_args(mrb, "o", &other);
tm = time_get_ptr(mrb, self);
tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
if (tm2) {
@@ -769,10 +766,9 @@ mrb_time_initialize(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
{
mrb_value src;
mrb_value src = mrb_get_arg1(mrb);
struct mrb_time *t1, *t2;
mrb_get_args(mrb, "o", &src);
if (mrb_obj_equal(mrb, copy, src)) return copy;
if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
@@ -954,7 +950,9 @@ mrb_time_to_s(mrb_state *mrb, mrb_value self)
struct mrb_time *tm = time_get_ptr(mrb, self);
mrb_bool utc = tm->timezone == MRB_TIMEZONE_UTC;
size_t len = (utc ? time_to_s_utc : time_to_s_local)(mrb, tm, buf, sizeof(buf));
return mrb_str_new(mrb, buf, len);
mrb_value str = mrb_str_new(mrb, buf, len);
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
void
+10
View File
@@ -1,3 +1,13 @@
class BasicObject
def !=(other)
if self == other
false
else
true
end
end
end
class Module
# 15.2.2.4.12
def attr_accessor(*names)
+3 -3
View File
@@ -140,7 +140,7 @@ class Hash
def each_value(&block)
return to_enum :each_value unless block
self.keys.each{|k| block.call(self[k])}
self.values.each{|v| block.call(v)}
self
end
@@ -192,11 +192,11 @@ class Hash
recur_list[self.object_id] = true
ary=[]
keys=self.keys
vals=self.values
size=keys.size
i=0
while i<size
k=keys[i]
ary<<(k._inspect(recur_list) + "=>" + self[k]._inspect(recur_list))
ary<<(keys[i]._inspect(recur_list) + "=>" + vals[i]._inspect(recur_list))
i+=1
end
"{"+ary.join(", ")+"}"
+25 -11
View File
@@ -732,6 +732,10 @@ mrb_ary_splice(mrb_state *mrb, mrb_value ary, mrb_int head, mrb_int len, mrb_val
argv = ARY_PTR(r);
}
}
else if (mrb_undef_p(rpl)) {
argc = 0;
argv = NULL;
}
else {
argc = 1;
argv = &rpl;
@@ -804,6 +808,13 @@ ary_subseq(mrb_state *mrb, struct RArray *a, mrb_int beg, mrb_int len)
return mrb_obj_value(b);
}
mrb_value
mrb_ary_subseq(mrb_state *mrb, mrb_value ary, mrb_int beg, mrb_int len)
{
struct RArray *a = mrb_ary_ptr(ary);
return ary_subseq(mrb, a, beg, len);
}
static mrb_int
aget_index(mrb_state *mrb, mrb_value index)
{
@@ -855,10 +866,12 @@ static mrb_value
mrb_ary_aget(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
mrb_int i, len, alen;
mrb_int i;
mrb_int len, alen;
mrb_value index;
if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
if (mrb_get_argc(mrb) == 1) {
index = mrb_get_arg1(mrb);
switch (mrb_type(index)) {
/* a[n..m] */
case MRB_TT_RANGE:
@@ -875,6 +888,7 @@ mrb_ary_aget(mrb_state *mrb, mrb_value self)
}
}
mrb_get_args(mrb, "oi", &index, &len);
i = aget_index(mrb, index);
alen = ARY_LEN(a);
if (i < 0) i += alen;
@@ -928,7 +942,10 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self)
mrb_int i, len;
mrb_ary_modify(mrb, mrb_ary_ptr(self));
if (mrb_get_args(mrb, "oo|o", &v1, &v2, &v3) == 2) {
if (mrb_get_argc(mrb) == 2) {
mrb_value *vs = mrb_get_argv(mrb);
v1 = vs[0]; v2 = vs[1];
/* a[n..m] = v */
switch (mrb_range_beg_len(mrb, v1, &i, &len, RARRAY_LEN(self), FALSE)) {
case MRB_RANGE_TYPE_MISMATCH:
@@ -944,6 +961,7 @@ mrb_ary_aset(mrb_state *mrb, mrb_value self)
return v2;
}
mrb_get_args(mrb, "ooo", &v1, &v2, &v3);
/* a[n,m] = v */
mrb_ary_splice(mrb, self, aget_index(mrb, v1), aget_index(mrb, v2), v3);
return v3;
@@ -1027,10 +1045,9 @@ mrb_ary_last(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_ary_index_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
mrb_int i;
mrb_get_args(mrb, "o", &obj);
for (i = 0; i < RARRAY_LEN(self); i++) {
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
return mrb_fixnum_value(i);
@@ -1042,10 +1059,9 @@ mrb_ary_index_m(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
{
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
mrb_int i, len;
mrb_get_args(mrb, "o", &obj);
for (i = RARRAY_LEN(self) - 1; i >= 0; i--) {
if (mrb_equal(mrb, RARRAY_PTR(self)[i], obj)) {
return mrb_fixnum_value(i);
@@ -1219,9 +1235,8 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
static mrb_value
mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
{
mrb_value ary2;
mrb_value ary2 = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &ary2);
if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_true_value();
if (!mrb_array_p(ary2)) {
return mrb_false_value();
@@ -1234,9 +1249,8 @@ mrb_ary_eq(mrb_state *mrb, mrb_value ary1)
static mrb_value
mrb_ary_cmp(mrb_state *mrb, mrb_value ary1)
{
mrb_value ary2;
mrb_value ary2 = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &ary2);
if (mrb_obj_equal(mrb, ary1, ary2)) return mrb_fixnum_value(0);
if (!mrb_array_p(ary2)) {
return mrb_nil_value();
+47 -31
View File
@@ -549,6 +549,23 @@ mrb_get_argv(mrb_state *mrb)
return array_argv;
}
MRB_API mrb_value
mrb_get_arg1(mrb_state *mrb)
{
mrb_int argc = mrb->c->ci->argc;
mrb_value *array_argv = mrb->c->stack + 1;
if (argc < 0) {
struct RArray *a = mrb_ary_ptr(*array_argv);
argc = ARY_LEN(a);
array_argv = ARY_PTR(a);
}
if (argc != 1) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
return array_argv[0];
}
void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
/*
@@ -1212,10 +1229,9 @@ mrb_mod_ancestors(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_mod_extend_object(mrb_state *mrb, mrb_value mod)
{
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
mrb_check_type(mrb, mod, MRB_TT_MODULE);
mrb_get_args(mrb, "o", &obj);
mrb_include_module(mrb, mrb_class_ptr(mrb_singleton_class(mrb, obj)), mrb_class_ptr(mod));
return mod;
}
@@ -1242,33 +1258,45 @@ mrb_mod_dummy_visibility(mrb_state *mrb, mrb_value mod)
return mod;
}
MRB_API mrb_value
mrb_singleton_class(mrb_state *mrb, mrb_value v)
/* returns mrb_class_ptr(mrb_singleton_class()) */
/* except that it return NULL for immediate values */
MRB_API struct RClass*
mrb_singleton_class_ptr(mrb_state *mrb, mrb_value v)
{
struct RBasic *obj;
switch (mrb_type(v)) {
case MRB_TT_FALSE:
if (mrb_nil_p(v))
return mrb_obj_value(mrb->nil_class);
return mrb_obj_value(mrb->false_class);
return mrb->nil_class;
return mrb->false_class;
case MRB_TT_TRUE:
return mrb_obj_value(mrb->true_class);
return mrb->true_class;
case MRB_TT_CPTR:
return mrb_obj_value(mrb->object_class);
return mrb->object_class;
case MRB_TT_SYMBOL:
case MRB_TT_FIXNUM:
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
#endif
mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
return mrb_nil_value(); /* not reached */
return NULL;
default:
break;
}
obj = mrb_basic_ptr(v);
prepare_singleton_class(mrb, obj);
return mrb_obj_value(obj->c);
return obj->c;
}
MRB_API mrb_value
mrb_singleton_class(mrb_state *mrb, mrb_value v)
{
struct RClass *c = mrb_singleton_class_ptr(mrb, v);
if (c == NULL) {
mrb_raise(mrb, E_TYPE_ERROR, "can't define singleton");
}
return mrb_obj_value(c);
}
MRB_API void
@@ -1481,9 +1509,8 @@ static mrb_value
attr_writer(mrb_state *mrb, mrb_value obj)
{
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
mrb_value val;
mrb_value val = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &val);
mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
return val;
}
@@ -1651,21 +1678,11 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv)
mrb_value
mrb_obj_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
mrb_value arg = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &arg);
return mrb_bool_value(mrb_obj_equal(mrb, self, arg));
}
static mrb_value
mrb_obj_not_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
mrb_get_args(mrb, "o", &arg);
return mrb_bool_value(!mrb_equal(mrb, self, arg));
}
MRB_API mrb_bool
mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
{
@@ -1716,7 +1733,10 @@ mrb_class_real(struct RClass* cl)
MRB_API const char*
mrb_class_name(mrb_state *mrb, struct RClass* c)
{
mrb_value name = class_name_str(mrb, c);
mrb_value name;
if (c == NULL) return NULL;
name = class_name_str(mrb, c);
return RSTRING_PTR(name);
}
@@ -1960,13 +1980,11 @@ mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
static mrb_value
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
{
mrb_value path;
mrb_value path = mrb_get_arg1(mrb);
mrb_sym id;
char *ptr;
mrb_int off, end, len;
mrb_get_args(mrb, "o", &path);
if (mrb_symbol_p(path)) {
/* const get with symbol */
id = mrb_symbol(path);
@@ -2119,10 +2137,9 @@ top_define_method(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
{
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
mrb_bool eqq;
mrb_get_args(mrb, "o", &obj);
eqq = mrb_obj_is_kind_of(mrb, obj, mrb_class_ptr(mod));
return mrb_bool_value(eqq);
@@ -2257,7 +2274,6 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, bob, "initialize", mrb_bob_init, 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, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(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 */
+4
View File
@@ -130,6 +130,10 @@ codedump(mrb_state *mrb, mrb_irep *irep)
printf("OP_LOADI\tR%d\t-%d\t", a, b);
print_lv_a(mrb, irep, a);
break;
CASE(OP_LOADI16, BS):
printf("OP_LOADI16\tR%d\t%d\t", a, (int)(int16_t)b);
print_lv_a(mrb, irep, a);
break;
CASE(OP_LOADI__1, B):
printf("OP_LOADI__1\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
+8 -5
View File
@@ -204,11 +204,14 @@ mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d)
if (!d) { return; }
for (i = 0; i < d->flen; ++i) {
mrb_assert(d->files[i]);
mrb_free(mrb, d->files[i]->lines.ptr);
mrb_free(mrb, d->files[i]);
if (d->files) {
for (i = 0; i < d->flen; ++i) {
if (d->files[i]) {
mrb_free(mrb, d->files[i]->lines.ptr);
mrb_free(mrb, d->files[i]);
}
}
mrb_free(mrb, d->files);
}
mrb_free(mrb, d->files);
mrb_free(mrb, d);
}
+3 -65
View File
@@ -13,9 +13,6 @@
#include <mruby/numeric.h>
#include <mruby/debug.h>
#define FLAG_BYTEORDER_NATIVE 2
#define FLAG_BYTEORDER_NONATIVE 0
#ifndef MRB_WITHOUT_FLOAT
#ifdef MRB_USE_FLOAT
#define MRB_FLOAT_FMT "%.9g"
@@ -709,22 +706,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8
uint16_t crc;
uint32_t offset;
switch (flags & DUMP_ENDIAN_NAT) {
endian_big:
case DUMP_ENDIAN_BIG:
memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
break;
endian_little:
case DUMP_ENDIAN_LIL:
memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident));
break;
case DUMP_ENDIAN_NAT:
if (bigendian_p()) goto endian_big;
goto endian_little;
break;
}
memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
@@ -764,21 +746,6 @@ lv_defined_p(mrb_irep *irep)
return FALSE;
}
static uint8_t
dump_flags(uint8_t flags, uint8_t native)
{
if (native == FLAG_BYTEORDER_NATIVE) {
if ((flags & DUMP_ENDIAN_NAT) == 0) {
return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT;
}
return flags;
}
if ((flags & DUMP_ENDIAN_NAT) == 0) {
return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG;
}
return flags;
}
static int
dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
{
@@ -870,7 +837,7 @@ error_exit:
int
mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
{
return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size);
return dump_irep(mrb, irep, flags, bin, bin_size);
}
#ifndef MRB_DISABLE_STDIO
@@ -886,7 +853,7 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
return MRB_DUMP_INVALID_ARGUMENT;
}
result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size);
result = dump_irep(mrb, irep, flags, &bin, &bin_size);
if (result == MRB_DUMP_OK) {
if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
result = MRB_DUMP_WRITE_FAULT;
@@ -897,20 +864,6 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
return result;
}
static mrb_bool
dump_bigendian_p(uint8_t flags)
{
switch (flags & DUMP_ENDIAN_NAT) {
case DUMP_ENDIAN_BIG:
return TRUE;
case DUMP_ENDIAN_LIL:
return FALSE;
default:
case DUMP_ENDIAN_NAT:
return bigendian_p();
}
}
int
mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname)
{
@@ -921,23 +874,8 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, con
if (fp == NULL || initname == NULL || initname[0] == '\0') {
return MRB_DUMP_INVALID_ARGUMENT;
}
flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE);
result = dump_irep(mrb, irep, flags, &bin, &bin_size);
if (result == MRB_DUMP_OK) {
if (!dump_bigendian_p(flags)) {
if (fprintf(fp, "/* dumped in little endian order.\n"
" use `mrbc -E` option for big endian CPU. */\n") < 0) {
mrb_free(mrb, bin);
return MRB_DUMP_WRITE_FAULT;
}
}
else {
if (fprintf(fp, "/* dumped in big endian order.\n"
" use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) {
mrb_free(mrb, bin);
return MRB_DUMP_WRITE_FAULT;
}
}
if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
mrb_free(mrb, bin);
return MRB_DUMP_WRITE_FAULT;
+58 -7
View File
@@ -160,9 +160,8 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
static mrb_value
exc_set_backtrace(mrb_state *mrb, mrb_value exc)
{
mrb_value backtrace;
mrb_value backtrace = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &backtrace);
set_backtrace(mrb, exc, backtrace);
return backtrace;
}
@@ -185,6 +184,16 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc)
}
}
static mrb_noreturn void
exc_throw(mrb_state *mrb, mrb_value exc)
{
if (!mrb->jmp) {
mrb_p(mrb, exc);
abort();
}
MRB_THROW(mrb->jmp);
}
MRB_API mrb_noreturn void
mrb_exc_raise(mrb_state *mrb, mrb_value exc)
{
@@ -197,11 +206,7 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc)
}
mrb_exc_set(mrb, exc);
}
if (!mrb->jmp) {
mrb_p(mrb, exc);
abort();
}
MRB_THROW(mrb->jmp);
exc_throw(mrb, exc);
}
MRB_API mrb_noreturn void
@@ -550,6 +555,52 @@ mrb_argnum_error(mrb_state *mrb, mrb_int argc, int min, int max)
#undef FMT
}
void mrb_core_init_printabort(void);
int
mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque)
{
struct mrb_jmpbuf *prev_jmp = mrb->jmp;
struct mrb_jmpbuf c_jmp;
int err = 1;
MRB_TRY(&c_jmp) {
mrb->jmp = &c_jmp;
body(mrb, opaque);
err = 0;
} MRB_CATCH(&c_jmp) {
if (mrb->exc) {
mrb_p(mrb, mrb_obj_value(mrb->exc));
mrb->exc = NULL;
}
else {
mrb_core_init_printabort();
}
} MRB_END_EXC(&c_jmp);
mrb->jmp = prev_jmp;
return err;
}
mrb_noreturn void
mrb_core_init_abort(mrb_state *mrb)
{
mrb->exc = NULL;
exc_throw(mrb, mrb_nil_value());
}
mrb_noreturn void
mrb_raise_nomemory(mrb_state *mrb)
{
if (mrb->nomem_err) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
}
else {
mrb_core_init_abort(mrb);
}
}
void
mrb_init_exception(mrb_state *mrb)
{
+13 -5
View File
@@ -132,7 +132,6 @@ mrb_obj_id(mrb_value obj)
case MRB_TT_HASH:
case MRB_TT_RANGE:
case MRB_TT_EXCEPTION:
case MRB_TT_FILE:
case MRB_TT_DATA:
case MRB_TT_ISTRUCT:
default:
@@ -140,7 +139,13 @@ mrb_obj_id(mrb_value obj)
}
}
#if defined(MRB_NAN_BOXING) && defined(MRB_64BIT)
#define mrb_xxx_boxing_cptr_value mrb_nan_boxing_cptr_value
#endif
#ifdef MRB_WORD_BOXING
#define mrb_xxx_boxing_cptr_value mrb_word_boxing_cptr_value
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value
mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f)
@@ -164,17 +169,20 @@ mrb_word_boxing_float_pool(mrb_state *mrb, mrb_float f)
return mrb_obj_value(nf);
}
#endif /* MRB_WITHOUT_FLOAT */
#endif /* MRB_WORD_BOXING */
#if defined(MRB_WORD_BOXING) || (defined(MRB_NAN_BOXING) && defined(MRB_64BIT))
MRB_API mrb_value
mrb_word_boxing_cptr_value(mrb_state *mrb, void *p)
mrb_xxx_boxing_cptr_value(mrb_state *mrb, void *p)
{
mrb_value v;
struct RCptr *cptr = (struct RCptr*)mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
v.value.p = mrb_obj_alloc(mrb, MRB_TT_CPTR, mrb->object_class);
v.value.vp->p = p;
SET_OBJ_VALUE(v, cptr);
cptr->p = p;
return v;
}
#endif /* MRB_WORD_BOXING */
#endif
#if defined _MSC_VER && _MSC_VER < 1900
+98 -21
View File
@@ -37,9 +37,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <mruby.h>
#include <mruby/string.h>
struct fmt_args;
typedef void output_func(struct fmt_args *f, const char *s, size_t l);
struct fmt_args {
mrb_state *mrb;
mrb_value str;
output_func *output;
void *opaque;
};
struct mrb_cstr {
char *buf;
size_t len;
};
#define MAX(a,b) ((a)>(b) ? (a) : (b))
@@ -54,15 +64,44 @@ struct fmt_args {
#define PAD_POS (1U<<(' '-' '))
#define MARK_POS (1U<<('+'-' '))
#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS)
static output_func strcat_value;
static output_func strcat_cstr;
static void
strcat_value(struct fmt_args *f, const char *s, size_t l)
{
mrb_value str = *(mrb_value*)f->opaque;
mrb_str_cat(f->mrb, str, s, l);
}
static void
strcat_cstr(struct fmt_args *f, const char *s, size_t l)
{
struct mrb_cstr *cstr = (struct mrb_cstr*)f->opaque;
if (l > cstr->len) {
mrb_state *mrb = f->mrb;
mrb_raise(mrb, E_ARGUMENT_ERROR, "string buffer too small");
}
memcpy(cstr->buf, s, l);
cstr->buf += l;
cstr->len -= l;
}
static void
out(struct fmt_args *f, const char *s, size_t l)
{
mrb_str_cat(f->mrb, f->str, s, l);
f->output(f, s, l);
}
#define PAD_SIZE 256
static void
pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint8_t fl)
pad(struct fmt_args *f, char c, ptrdiff_t w, ptrdiff_t l, uint32_t fl)
{
char pad[PAD_SIZE];
if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
@@ -92,7 +131,7 @@ typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)
#endif
static int
fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
fmt_fp(struct fmt_args *f, long double y, ptrdiff_t w, ptrdiff_t p, uint32_t fl, int t)
{
uint32_t big[(LDBL_MANT_DIG+28)/29 + 1 // mantissa expansion
+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
@@ -117,11 +156,11 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
if (!isfinite(y)) {
const char *ss = (t&32)?"inf":"INF";
if (y!=y) ss=(t&32)?"nan":"NAN";
pad(f, ' ', 0, 3+pl, fl&~ZERO_PAD);
pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
out(f, prefix, pl);
out(f, ss, 3);
pad(f, ' ', 0, 3+pl, fl^LEFT_ADJ);
return 3+(int)pl;
pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
return (int)MAX(w, 3+pl);
}
y = frexp((double)y, &e2) * 2;
@@ -169,14 +208,14 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
else
l = (s-buf) + (ebuf-estr);
pad(f, ' ', 0, pl+l, fl);
pad(f, ' ', w, pl+l, fl);
out(f, prefix, pl);
pad(f, '0', 0, pl+l, fl^ZERO_PAD);
pad(f, '0', w, pl+l, fl^ZERO_PAD);
out(f, buf, s-buf);
pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
out(f, estr, ebuf-estr);
pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
return (int)pl+(int)l;
pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
return (int)MAX(w, pl+l);
}
if (p<0) p=6;
@@ -288,9 +327,9 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
l += ebuf-estr;
}
pad(f, ' ', 0, pl+l, fl);
pad(f, ' ', w, pl+l, fl);
out(f, prefix, pl);
pad(f, '0', 0, pl+l, fl^ZERO_PAD);
pad(f, '0', w, pl+l, fl^ZERO_PAD);
if ((t|32)=='f') {
if (a>r) a=r;
@@ -325,21 +364,33 @@ fmt_fp(struct fmt_args *f, long double y, ptrdiff_t p, uint8_t fl, int t)
out(f, estr, ebuf-estr);
}
pad(f, ' ', 0, pl+l, fl^LEFT_ADJ);
pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
return (int)pl+(int)l;
return (int)MAX(w, pl+l);
}
static int
fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
{
ptrdiff_t p;
ptrdiff_t w, p;
uint32_t fl;
if (*fmt != '%') {
return -1;
}
++fmt;
/* Read modifier flags */
for (fl=0; (unsigned)*fmt-' '<32 && (FLAGMASK&(1U<<(*fmt-' '))); fmt++)
fl |= 1U<<(*fmt-' ');
/* - and 0 flags are mutually exclusive */
if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
for (w = 0; ISDIGIT(*fmt); ++fmt) {
w = 10 * w + (*fmt - '0');
}
if (*fmt == '.') {
++fmt;
for (p = 0; ISDIGIT(*fmt); ++fmt) {
@@ -353,29 +404,49 @@ fmt_core(struct fmt_args *f, const char *fmt, mrb_float flo)
switch (*fmt) {
case 'e': case 'f': case 'g': case 'a':
case 'E': case 'F': case 'G': case 'A':
return fmt_fp(f, flo, p, 0, *fmt);
return fmt_fp(f, flo, w, p, fl, *fmt);
default:
return -1;
}
}
mrb_value
MRB_API mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
{
struct fmt_args f;
mrb_value str = mrb_str_new_capa(mrb, 24);
f.mrb = mrb;
f.str = mrb_str_new_capa(mrb, 24);
f.output = strcat_value;
f.opaque = (void*)&str;
if (fmt_core(&f, fmt, mrb_float(flo)) < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
}
return f.str;
return str;
}
MRB_API int
mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
{
struct fmt_args f;
struct mrb_cstr cstr;
cstr.buf = buf;
cstr.len = len - 1; /* reserve NUL terminator */
f.mrb = mrb;
f.output = strcat_cstr;
f.opaque = (void*)&cstr;
if (fmt_core(&f, fmt, fval) < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid format string");
}
*cstr.buf = '\0';
return (int)(cstr.buf - buf);
}
#else /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#include <mruby.h>
#include <stdio.h>
mrb_value
MRB_API mrb_value
mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
{
char buf[25];
@@ -383,5 +454,11 @@ mrb_float_to_str(mrb_state *mrb, mrb_value flo, const char *fmt)
snprintf(buf, sizeof(buf), fmt, mrb_float(flo));
return mrb_str_new_cstr(mrb, buf);
}
MRB_API int
mrb_float_to_cstr(mrb_state *mrb, char *buf, size_t len, const char *fmt, mrb_float fval)
{
return snprintf(buf, len, fmt, fval);
}
#endif /* MRB_DISABLE_STDIO || _WIN32 || _WIN64 */
#endif
+15 -280
View File
@@ -201,6 +201,8 @@ gettimeofday_time(void)
#define objects(p) ((RVALUE *)p->objects)
mrb_noreturn void mrb_raise_nomemory(mrb_state *mrb);
MRB_API void*
mrb_realloc_simple(mrb_state *mrb, void *p, size_t len)
{
@@ -224,12 +226,12 @@ mrb_realloc(mrb_state *mrb, void *p, size_t len)
if (len == 0) return p2;
if (p2 == NULL) {
if (mrb->gc.out_of_memory) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
mrb_raise_nomemory(mrb);
/* mrb_panic(mrb); */
}
else {
mrb->gc.out_of_memory = TRUE;
mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
mrb_raise_nomemory(mrb);
}
}
else {
@@ -714,10 +716,10 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
struct REnv *e = (struct REnv*)obj;
mrb_int i, len;
if (MRB_ENV_STACK_SHARED_P(e) && e->cxt && e->cxt->fib) {
if (MRB_ENV_ONSTACK_P(e) && e->cxt && e->cxt->fib) {
mrb_gc_mark(mrb, (struct RBasic*)e->cxt->fib);
}
len = MRB_ENV_STACK_LEN(e);
len = MRB_ENV_LEN(e);
for (i=0; i<len; i++) {
mrb_gc_mark_value(mrb, e->stack[i]);
}
@@ -818,7 +820,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
{
struct REnv *e = (struct REnv*)obj;
if (MRB_ENV_STACK_SHARED_P(e)) {
if (MRB_ENV_ONSTACK_P(e)) {
/* cannot be freed */
e->stack = NULL;
break;
@@ -840,7 +842,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
while (ce <= ci) {
struct REnv *e = ci->env;
if (e && !mrb_object_dead_p(mrb, (struct RBasic*)e) &&
e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
e->tt == MRB_TT_ENV && MRB_ENV_ONSTACK_P(e)) {
mrb_env_unshare(mrb, e);
}
ci--;
@@ -958,13 +960,12 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
}
}
/* rough estimation of number of GC marks (non recursive) */
static size_t
gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
{
size_t children = 0;
gc_mark_children(mrb, gc, obj);
switch (obj->tt) {
case MRB_TT_ICLASS:
children++;
@@ -989,7 +990,7 @@ gc_gray_mark(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
break;
case MRB_TT_ENV:
children += MRB_ENV_STACK_LEN(obj);
children += MRB_ENV_LEN(obj);
break;
case MRB_TT_FIBER:
@@ -1062,7 +1063,9 @@ incremental_marking_phase(mrb_state *mrb, mrb_gc *gc, size_t limit)
size_t tried_marks = 0;
while (gc->gray_list && tried_marks < limit) {
tried_marks += gc_gray_mark(mrb, gc, gc->gray_list);
struct RBasic *obj = gc->gray_list;
gc_mark_children(mrb, gc, obj);
tried_marks += gc_gray_counts(mrb, gc, obj);
}
return tried_marks;
@@ -1294,6 +1297,7 @@ mrb_full_gc(mrb_state *mrb)
{
mrb_gc *gc = &mrb->gc;
if (!mrb->c) return;
if (gc->disabled || gc->iterating) return;
GC_INVOKE_TIME_REPORT("mrb_full_gc()");
@@ -1632,272 +1636,3 @@ mrb_init_gc(mrb_state *mrb)
#endif
#endif
}
#ifdef GC_TEST
#ifdef GC_DEBUG
void
test_mrb_field_write_barrier(void)
{
mrb_state *mrb = mrb_open();
struct RBasic *obj, *value;
mrb_gc *gc = &mrb->gc;
puts("test_mrb_field_write_barrier");
gc->generational = FALSE;
obj = mrb_basic_ptr(mrb_ary_new(mrb));
value = mrb_basic_ptr(mrb_str_new_lit(mrb, "value"));
paint_black(obj);
paint_partial_white(gc, value);
puts(" in MRB_GC_STATE_MARK");
gc->state = MRB_GC_STATE_MARK;
mrb_field_write_barrier(mrb, obj, value);
mrb_assert(is_gray(value));
puts(" in MRB_GC_STATE_SWEEP");
paint_partial_white(gc, value);
gc->state = MRB_GC_STATE_SWEEP;
mrb_field_write_barrier(mrb, obj, value);
mrb_assert(obj->color & gc->current_white_part);
mrb_assert(value->color & gc->current_white_part);
puts(" fail with black");
gc->state = MRB_GC_STATE_MARK;
paint_white(obj);
paint_partial_white(gc, value);
mrb_field_write_barrier(mrb, obj, value);
mrb_assert(obj->color & gc->current_white_part);
puts(" fail with gray");
gc->state = MRB_GC_STATE_MARK;
paint_black(obj);
paint_gray(value);
mrb_field_write_barrier(mrb, obj, value);
mrb_assert(is_gray(value));
{
puts("test_mrb_field_write_barrier_value");
obj = mrb_basic_ptr(mrb_ary_new(mrb));
mrb_value value = mrb_str_new_lit(mrb, "value");
paint_black(obj);
paint_partial_white(gc, mrb_basic_ptr(value));
gc->state = MRB_GC_STATE_MARK;
mrb_field_write_barrier_value(mrb, obj, value);
mrb_assert(is_gray(mrb_basic_ptr(value)));
}
mrb_close(mrb);
}
void
test_mrb_write_barrier(void)
{
mrb_state *mrb = mrb_open();
struct RBasic *obj;
mrb_gc *gc = &mrb->gc;
puts("test_mrb_write_barrier");
obj = mrb_basic_ptr(mrb_ary_new(mrb));
paint_black(obj);
puts(" in MRB_GC_STATE_MARK");
gc->state = MRB_GC_STATE_MARK;
mrb_write_barrier(mrb, obj);
mrb_assert(is_gray(obj));
mrb_assert(gc->atomic_gray_list == obj);
puts(" fail with gray");
paint_gray(obj);
mrb_write_barrier(mrb, obj);
mrb_assert(is_gray(obj));
mrb_close(mrb);
}
void
test_add_gray_list(void)
{
mrb_state *mrb = mrb_open();
struct RBasic *obj1, *obj2;
mrb_gc *gc = &mrb->gc;
puts("test_add_gray_list");
change_gen_gc_mode(mrb, gc, FALSE);
mrb_assert(gc->gray_list == NULL);
obj1 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
add_gray_list(mrb, gc, obj1);
mrb_assert(gc->gray_list == obj1);
mrb_assert(is_gray(obj1));
obj2 = mrb_basic_ptr(mrb_str_new_lit(mrb, "test"));
add_gray_list(mrb, gc, obj2);
mrb_assert(gc->gray_list == obj2);
mrb_assert(gc->gray_list->gcnext == obj1);
mrb_assert(is_gray(obj2));
mrb_close(mrb);
}
void
test_gc_gray_mark(void)
{
mrb_state *mrb = mrb_open();
mrb_value obj_v, value_v;
struct RBasic *obj;
size_t gray_num = 0;
mrb_gc *gc = &mrb->gc;
puts("test_gc_gray_mark");
puts(" in MRB_TT_CLASS");
obj = (struct RBasic*)mrb->object_class;
paint_gray(obj);
gray_num = gc_gray_mark(mrb, gc, obj);
mrb_assert(is_black(obj));
mrb_assert(gray_num > 1);
puts(" in MRB_TT_ARRAY");
obj_v = mrb_ary_new(mrb);
value_v = mrb_str_new_lit(mrb, "test");
paint_gray(mrb_basic_ptr(obj_v));
paint_partial_white(gc, mrb_basic_ptr(value_v));
mrb_ary_push(mrb, obj_v, value_v);
gray_num = gc_gray_mark(mrb, gc, mrb_basic_ptr(obj_v));
mrb_assert(is_black(mrb_basic_ptr(obj_v)));
mrb_assert(is_gray(mrb_basic_ptr(value_v)));
mrb_assert(gray_num == 1);
mrb_close(mrb);
}
void
test_incremental_gc(void)
{
mrb_state *mrb = mrb_open();
size_t max = ~0, live = 0, total = 0, freed = 0;
RVALUE *free;
mrb_heap_page *page;
mrb_gc *gc = &mrb->gc;
puts("test_incremental_gc");
change_gen_gc_mode(mrb, gc, FALSE);
puts(" in mrb_full_gc");
mrb_full_gc(mrb);
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
puts(" in MRB_GC_STATE_ROOT");
incremental_gc(mrb, gc, max);
mrb_assert(gc->state == MRB_GC_STATE_MARK);
puts(" in MRB_GC_STATE_MARK");
incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
puts(" in MRB_GC_STATE_SWEEP");
page = gc->heaps;
while (page) {
RVALUE *p = objects(page);
RVALUE *e = p + MRB_HEAP_PAGE_SIZE;
while (p<e) {
if (is_black(&p->as.basic)) {
live++;
}
if (is_gray(&p->as.basic) && !is_dead(gc, &p->as.basic)) {
printf("%p\n", &p->as.basic);
}
p++;
}
page = page->next;
total += MRB_HEAP_PAGE_SIZE;
}
mrb_assert(gc->gray_list == NULL);
incremental_gc(mrb, gc, max);
mrb_assert(gc->state == MRB_GC_STATE_SWEEP);
incremental_gc(mrb, gc, max);
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
free = (RVALUE*)gc->heaps->freelist;
while (free) {
freed++;
free = (RVALUE*)free->as.free.next;
}
mrb_assert(gc->live == live);
mrb_assert(gc->live == total-freed);
puts("test_incremental_gc(gen)");
incremental_gc_until(mrb, gc, MRB_GC_STATE_SWEEP);
change_gen_gc_mode(mrb, gc, TRUE);
mrb_assert(gc->full == FALSE);
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
puts(" in minor");
mrb_assert(is_minor_gc(gc));
mrb_assert(gc->majorgc_old_threshold > 0);
gc->majorgc_old_threshold = 0;
mrb_incremental_gc(mrb);
mrb_assert(gc->full == TRUE);
mrb_assert(gc->state == MRB_GC_STATE_ROOT);
puts(" in major");
mrb_assert(is_major_gc(gc));
do {
mrb_incremental_gc(mrb);
} while (gc->state != MRB_GC_STATE_ROOT);
mrb_assert(gc->full == FALSE);
mrb_close(mrb);
}
void
test_incremental_sweep_phase(void)
{
mrb_state *mrb = mrb_open();
mrb_gc *gc = &mrb->gc;
puts("test_incremental_sweep_phase");
add_heap(mrb, gc);
gc->sweeps = gc->heaps;
mrb_assert(gc->heaps->next->next == NULL);
mrb_assert(gc->free_heaps->next->next == NULL);
incremental_sweep_phase(mrb, gc, MRB_HEAP_PAGE_SIZE * 3);
mrb_assert(gc->heaps->next == NULL);
mrb_assert(gc->heaps == gc->free_heaps);
mrb_close(mrb);
}
static mrb_value
gc_test(mrb_state *mrb, mrb_value self)
{
test_mrb_field_write_barrier();
test_mrb_write_barrier();
test_add_gray_list();
test_gc_gray_mark();
test_incremental_gc();
test_incremental_sweep_phase();
return mrb_nil_value();
}
#endif /* GC_DEBUG */
#endif /* GC_TEST */
+12 -19
View File
@@ -73,7 +73,7 @@ ht_hash_func(mrb_state *mrb, htable *t, mrb_value key)
default:
hv = mrb_funcall(mrb, key, "hash", 0);
h = (size_t)t ^ (size_t)mrb_fixnum(hv);
h = (size_t)tt ^ (size_t)mrb_fixnum(hv);
break;
}
if (index && (index != t->index || capa != index->capa)) {
@@ -365,7 +365,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
if (!seg->next && i >= t->last_len) {
seg->e[i].key = key;
seg->e[i].val = val;
t->last_len = i+1;
t->last_len = (uint16_t)i+1;
t->size++;
return;
}
@@ -373,7 +373,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
deleted++;
continue;
}
if (ht_hash_equal(mrb, t, k, key)) {
if (ht_hash_equal(mrb, t, key, k)) {
seg->e[i].val = val;
return;
}
@@ -407,7 +407,7 @@ ht_put(mrb_state *mrb, htable *t, mrb_value key, mrb_value val)
}
seg->e[i].key = key;
seg->e[i].val = val;
t->last_len = i+1;
t->last_len = (uint16_t)i+1;
if (t->index == NULL && t->size > MRB_HT_INIT_SIZE*4) {
ht_index(mrb, t);
}
@@ -454,7 +454,7 @@ ht_get(mrb_state *mrb, htable *t, mrb_value key, mrb_value *vp)
return FALSE;
}
if (mrb_undef_p(k)) continue;
if (ht_hash_equal(mrb, t, k, key)) {
if (ht_hash_equal(mrb, t, key, k)) {
if (vp) *vp = seg->e[i].val;
return TRUE;
}
@@ -641,12 +641,11 @@ static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key);
static mrb_value
mrb_hash_init_copy(mrb_state *mrb, mrb_value self)
{
mrb_value orig;
mrb_value orig = mrb_get_arg1(mrb);
struct RHash* copy;
htable *orig_h;
mrb_value ifnone, vret;
mrb_get_args(mrb, "o", &orig);
if (mrb_obj_equal(mrb, self, orig)) return self;
if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
@@ -828,9 +827,8 @@ mrb_hash_init(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_aget(mrb_state *mrb, mrb_value self)
{
mrb_value key;
mrb_value key = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &key);
return mrb_hash_get(mrb, self, key);
}
@@ -913,9 +911,8 @@ mrb_hash_default(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
{
mrb_value ifnone;
mrb_value ifnone = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
RHASH(hash)->flags &= ~MRB_HASH_PROC_DEFAULT;
@@ -969,9 +966,8 @@ mrb_hash_default_proc(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
{
mrb_value ifnone;
mrb_value ifnone = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
mrb_iv_set(mrb, hash, mrb_intern_lit(mrb, "ifnone"), ifnone);
if (!mrb_nil_p(ifnone)) {
@@ -1003,9 +999,8 @@ mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
static mrb_value
mrb_hash_delete(mrb_state *mrb, mrb_value self)
{
mrb_value key;
mrb_value key = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &key);
mrb_hash_modify(mrb, self);
return mrb_hash_delete_key(mrb, self, key);
}
@@ -1288,10 +1283,9 @@ mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key)
static mrb_value
mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
{
mrb_value key;
mrb_value key = mrb_get_arg1(mrb);
mrb_bool key_p;
mrb_get_args(mrb, "o", &key);
key_p = mrb_hash_key_p(mrb, hash, key);
return mrb_bool_value(key_p);
}
@@ -1331,10 +1325,9 @@ hash_has_value_i(mrb_state *mrb, mrb_value key, mrb_value val, void *p)
static mrb_value
mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
{
mrb_value val;
mrb_value val = mrb_get_arg1(mrb);
struct has_v_arg arg;
mrb_get_args(mrb, "o", &val);
arg.found = FALSE;
arg.val = val;
ht_foreach(mrb, RHASH_TBL(hash), hash_has_value_i, &arg);
+6 -9
View File
@@ -71,9 +71,8 @@ mrb_obj_inspect(mrb_state *mrb, mrb_value obj)
static mrb_value
mrb_equal_m(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
mrb_value arg = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &arg);
return mrb_bool_value(mrb_equal(mrb, self, arg));
}
@@ -161,7 +160,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
/* use saved block arg position */
bidx = MRB_ENV_BIDX(e);
/* bidx may be useless (e.g. define_method) */
if (bidx >= MRB_ENV_STACK_LEN(e))
if (bidx >= MRB_ENV_LEN(e))
return mrb_false_value();
bp = &e->stack[bidx];
}
@@ -325,7 +324,7 @@ mrb_obj_clone(mrb_state *mrb, mrb_value self)
mrb_value clone;
if (mrb_immediate_p(self)) {
mrb_raisef(mrb, E_TYPE_ERROR, "can't clone %v", self);
return self;
}
if (mrb_sclass_p(self)) {
mrb_raise(mrb, E_TYPE_ERROR, "can't clone singleton class");
@@ -366,7 +365,7 @@ mrb_obj_dup(mrb_state *mrb, mrb_value obj)
mrb_value dup;
if (mrb_immediate_p(obj)) {
mrb_raisef(mrb, E_TYPE_ERROR, "can't dup %v", obj);
return obj;
}
if (mrb_sclass_p(obj)) {
mrb_raise(mrb, E_TYPE_ERROR, "can't dup singleton class");
@@ -471,9 +470,8 @@ mrb_obj_hash(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
{
mrb_value orig;
mrb_value orig = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &orig);
if (mrb_obj_equal(mrb, self, orig)) return self;
if ((mrb_type(self) != mrb_type(orig)) || (mrb_obj_class(mrb, self) != mrb_obj_class(mrb, orig))) {
mrb_raise(mrb, E_TYPE_ERROR, "initialize_copy should take same class object");
@@ -744,12 +742,11 @@ obj_respond_to(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_obj_ceqq(mrb_state *mrb, mrb_value self)
{
mrb_value v;
mrb_value v = mrb_get_arg1(mrb);
mrb_int i, len;
mrb_sym eqq = mrb_intern_lit(mrb, "===");
mrb_value ary = mrb_ary_splat(mrb, self);
mrb_get_args(mrb, "o", &v);
len = RARRAY_LEN(ary);
for (i=0; i<len; i++) {
mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v);
+56 -30
View File
@@ -14,14 +14,12 @@
#include <mruby/string.h>
#include <mruby/debug.h>
#include <mruby/error.h>
#include <mruby/data.h>
#if SIZE_MAX < UINT32_MAX
# error size_t must be at least 32 bits wide
#endif
#define FLAG_BYTEORDER_BIG 2
#define FLAG_BYTEORDER_LIL 4
#define FLAG_BYTEORDER_NATIVE 8
#define FLAG_SRC_MALLOC 1
#define FLAG_SRC_STATIC 0
@@ -58,6 +56,14 @@ str_to_double(mrb_state *mrb, const char *p, size_t len)
mrb_value mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, int badcheck);
static void
tempirep_free(mrb_state *mrb, void *p)
{
if (p) mrb_irep_decref(mrb, (mrb_irep *)p);
}
static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free };
static mrb_irep*
read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
{
@@ -66,8 +72,11 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
ptrdiff_t diff;
uint16_t tt, pool_data_len, snl;
int plen;
int ai = mrb_gc_arena_save(mrb);
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
mrb_irep *irep = mrb_add_irep(mrb);
int ai = mrb_gc_arena_save(mrb);
irep_obj->data = irep;
/* skip record size */
src += sizeof(uint32_t);
@@ -94,8 +103,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) {
return NULL;
}
if ((flags & FLAG_SRC_MALLOC) == 0 &&
(flags & FLAG_BYTEORDER_NATIVE)) {
if ((flags & FLAG_SRC_MALLOC) == 0) {
irep->iseq = (mrb_code*)src;
src += sizeof(mrb_code) * irep->ilen;
irep->flags |= MRB_ISEQ_NO_FREE;
@@ -188,36 +196,47 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag
}
}
irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen);
irep->reps = (mrb_irep**)mrb_calloc(mrb, irep->rlen, sizeof(mrb_irep*));
diff = src - bin;
mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
*len = (size_t)diff;
irep_obj->data = NULL;
return irep;
}
static mrb_irep*
read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags)
{
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
int ai = mrb_gc_arena_save(mrb);
mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags);
int i;
mrb_gc_arena_restore(mrb, ai);
if (irep == NULL) {
return NULL;
}
irep_obj->data = irep;
bin += *len;
for (i=0; i<irep->rlen; i++) {
size_t rlen;
irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags);
mrb_gc_arena_restore(mrb, ai);
if (irep->reps[i] == NULL) {
return NULL;
}
bin += rlen;
*len += rlen;
}
irep_obj->data = NULL;
return irep;
}
@@ -241,21 +260,21 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; }
irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info));
irep->debug_info = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info));
irep->debug_info->pc_count = (uint32_t)irep->ilen;
record_size = (size_t)bin_to_uint32(bin);
bin += sizeof(uint32_t);
irep->debug_info->flen = bin_to_uint16(bin);
irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen);
irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*));
bin += sizeof(uint16_t);
for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
mrb_irep_debug_info_file *file;
uint16_t filename_idx;
file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file));
file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file));
irep->debug_info->files[f_idx] = file;
file->start_pos = bin_to_uint32(bin);
@@ -285,8 +304,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t *
case mrb_debug_line_flat_map: {
uint32_t l;
file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc(
mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count));
file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc(
mrb, (size_t)(file->line_entry_count), sizeof(mrb_irep_debug_info_line));
for (l = 0; l < file->line_entry_count; ++l) {
file->lines.flat_map[l].start_pos = bin_to_uint32(bin);
bin += sizeof(uint32_t);
@@ -333,6 +352,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
int result;
uint16_t filenames_len;
mrb_sym *filenames;
mrb_value filenames_obj;
bin = start;
header = (struct rite_section_debug_header *)bin;
@@ -340,7 +360,8 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
filenames_len = bin_to_uint16(bin);
bin += sizeof(uint16_t);
filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len);
filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len);
filenames = (mrb_sym*)RSTRING_PTR(filenames_obj);
for (i = 0; i < filenames_len; ++i) {
uint16_t f_len = bin_to_uint16(bin);
bin += sizeof(uint16_t);
@@ -364,7 +385,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t
}
debug_exit:
mrb_free(mrb, filenames);
mrb_str_resize(mrb, filenames_obj, 0);
return result;
}
@@ -422,6 +443,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
int result;
uint32_t syms_len;
mrb_sym *syms;
mrb_value syms_obj;
mrb_sym (*intern_func)(mrb_state*, const char*, size_t) =
(flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static;
@@ -431,7 +453,8 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
syms_len = bin_to_uint32(bin);
bin += sizeof(uint32_t);
syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len);
syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len);
syms = (mrb_sym*)RSTRING_PTR(syms_obj);
for (i = 0; i < syms_len; ++i) {
uint16_t const str_len = bin_to_uint16(bin);
bin += sizeof(uint16_t);
@@ -451,7 +474,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl
}
lv_exit:
mrb_free(mrb, syms);
mrb_str_resize(mrb, syms_obj, 0);
return result;
}
@@ -464,19 +487,7 @@ read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint16_
return MRB_DUMP_READ_FAULT;
}
if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) {
if (bigendian_p())
*flags |= FLAG_BYTEORDER_NATIVE;
else
*flags |= FLAG_BYTEORDER_BIG;
}
else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) {
if (bigendian_p())
*flags |= FLAG_BYTEORDER_LIL;
else
*flags |= FLAG_BYTEORDER_NATIVE;
}
else {
if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) != 0) {
return MRB_DUMP_INVALID_FILE_HEADER;
}
@@ -500,6 +511,7 @@ static mrb_irep*
read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
{
int result;
struct RData *irep_obj = NULL;
mrb_irep *irep = NULL;
const struct rite_section_header *section_header;
uint16_t crc;
@@ -520,12 +532,15 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
return NULL;
}
irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
bin += sizeof(struct rite_binary_header);
do {
section_header = (const struct rite_section_header *)bin;
if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) {
irep = read_section_irep(mrb, bin, flags);
if (!irep) return NULL;
irep_obj->data = irep;
}
else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) {
if (!irep) return NULL; /* corrupted data */
@@ -544,6 +559,8 @@ read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags)
bin += bin_to_uint32(section_header->section_size);
} while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0);
irep_obj->data = NULL;
return irep;
}
@@ -595,7 +612,16 @@ load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c)
MRB_API mrb_value
mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c)
{
return load_irep(mrb, mrb_read_irep(mrb, bin), c);
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
mrb_irep *irep = mrb_read_irep(mrb, bin);
mrb_value ret;
irep_obj->data = irep;
mrb_irep_incref(mrb, irep);
ret = load_irep(mrb, irep, c);
irep_obj->data = NULL;
mrb_irep_decref(mrb, irep);
return ret;
}
MRB_API mrb_value
+50 -70
View File
@@ -67,12 +67,11 @@ mrb_int_value(mrb_state *mrb, mrb_float f)
static mrb_value
integral_pow(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
#ifndef MRB_WITHOUT_FLOAT
mrb_float d;
#endif
mrb_get_args(mrb, "o", &y);
if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) {
/* try ipow() */
mrb_int base = mrb_fixnum(x);
@@ -116,9 +115,8 @@ static mrb_value
integral_idiv(mrb_state *mrb, mrb_value x)
{
#ifdef MRB_WITHOUT_FLOAT
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
if (!mrb_fixnum_p(y)) {
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
}
@@ -154,9 +152,8 @@ static mrb_value
integral_div(mrb_state *mrb, mrb_value x)
{
#ifdef MRB_WITHOUT_FLOAT
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
if (!mrb_fixnum_p(y)) {
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
}
@@ -210,26 +207,30 @@ static mrb_value
flo_to_s(mrb_state *mrb, mrb_value flt)
{
mrb_float f = mrb_float(flt);
mrb_value str;
if (isinf(f)) {
return f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
: mrb_str_new_lit(mrb, "Infinity");
str = f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
: mrb_str_new_lit(mrb, "Infinity");
goto exit;
}
else if (isnan(f)) {
return mrb_str_new_lit(mrb, "NaN");
str = mrb_str_new_lit(mrb, "NaN");
goto exit;
}
else {
char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
mrb_value str = mrb_float_to_str(mrb, flt, fmt);
mrb_int len;
char *begp, *p, *endp;
str = mrb_float_to_str(mrb, flt, fmt);
insert_dot_zero:
begp = RSTRING_PTR(str);
len = RSTRING_LEN(str);
for (p = begp, endp = p + len; p < endp; ++p) {
if (*p == '.') {
return str;
goto exit;
}
else if (*p == 'e') {
ptrdiff_t e_pos = p - begp;
@@ -237,7 +238,7 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
p = RSTRING_PTR(str) + e_pos;
memmove(p + 2, p, len - e_pos);
memcpy(p, ".0", 2);
return str;
goto exit;
}
}
@@ -247,8 +248,12 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
goto insert_dot_zero;
}
return str;
goto exit;
}
exit:
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
/* 15.2.9.3.2 */
@@ -263,9 +268,8 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
static mrb_value
flo_minus(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
}
@@ -281,9 +285,8 @@ flo_minus(mrb_state *mrb, mrb_value x)
static mrb_value
flo_mul(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
}
@@ -343,11 +346,9 @@ flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp)
static mrb_value
flo_mod(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_float mod;
mrb_get_args(mrb, "o", &y);
flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod);
return mrb_float_value(mrb, mod);
}
@@ -368,9 +369,8 @@ flo_mod(mrb_state *mrb, mrb_value x)
static mrb_value
fix_eql(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
if (!mrb_fixnum_p(y)) return mrb_false_value();
return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
}
@@ -379,9 +379,8 @@ fix_eql(mrb_state *mrb, mrb_value x)
static mrb_value
flo_eql(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
if (!mrb_float_p(y)) return mrb_false_value();
return mrb_bool_value(mrb_float(x) == mrb_float(y));
}
@@ -402,8 +401,7 @@ flo_eql(mrb_state *mrb, mrb_value x)
static mrb_value
flo_eq(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_get_args(mrb, "o", &y);
mrb_value y = mrb_get_arg1(mrb);
switch (mrb_type(y)) {
case MRB_TT_FIXNUM:
@@ -421,7 +419,6 @@ value_int64(mrb_state *mrb, mrb_value x)
switch (mrb_type(x)) {
case MRB_TT_FIXNUM:
return (int64_t)mrb_fixnum(x);
break;
case MRB_TT_FLOAT:
return (int64_t)mrb_float(x);
default:
@@ -452,9 +449,8 @@ flo_rev(mrb_state *mrb, mrb_value x)
static mrb_value
flo_and(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
int64_t v1, v2;
mrb_get_args(mrb, "o", &y);
v1 = (int64_t)mrb_float(x);
v2 = value_int64(mrb, y);
@@ -464,9 +460,8 @@ flo_and(mrb_state *mrb, mrb_value x)
static mrb_value
flo_or(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
int64_t v1, v2;
mrb_get_args(mrb, "o", &y);
v1 = (int64_t)mrb_float(x);
v2 = value_int64(mrb, y);
@@ -476,9 +471,8 @@ flo_or(mrb_state *mrb, mrb_value x)
static mrb_value
flo_xor(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
int64_t v1, v2;
mrb_get_args(mrb, "o", &y);
v1 = (int64_t)mrb_float(x);
v2 = value_int64(mrb, y);
@@ -839,9 +833,8 @@ mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
static mrb_value
fix_mul(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
return fixnum_mul(mrb, x, y);
}
@@ -886,10 +879,9 @@ fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp)
static mrb_value
fix_mod(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_int a, b;
mrb_get_args(mrb, "o", &y);
a = mrb_fixnum(x);
if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) {
mrb_int mod;
@@ -928,9 +920,7 @@ fix_mod(mrb_state *mrb, mrb_value x)
static mrb_value
fix_divmod(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_get_args(mrb, "o", &y);
mrb_value y = mrb_get_arg1(mrb);
if (mrb_fixnum_p(y)) {
mrb_int div, mod;
@@ -967,12 +957,10 @@ fix_divmod(mrb_state *mrb, mrb_value x)
static mrb_value
flo_divmod(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_float div, mod;
mrb_value a, b;
mrb_get_args(mrb, "o", &y);
flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
a = mrb_int_value(mrb, div);
b = mrb_float_value(mrb, mod);
@@ -995,9 +983,8 @@ flo_divmod(mrb_state *mrb, mrb_value x)
static mrb_value
fix_equal(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
switch (mrb_type(y)) {
case MRB_TT_FIXNUM:
return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
@@ -1054,9 +1041,8 @@ static mrb_value flo_xor(mrb_state *mrb, mrb_value x);
static mrb_value
fix_and(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
bit_op(x, y, and, &);
}
@@ -1071,9 +1057,8 @@ fix_and(mrb_state *mrb, mrb_value x)
static mrb_value
fix_or(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
bit_op(x, y, or, |);
}
@@ -1088,9 +1073,8 @@ fix_or(mrb_state *mrb, mrb_value x)
static mrb_value
fix_xor(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
bit_op(x, y, or, ^);
}
@@ -1312,9 +1296,8 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
static mrb_value
fix_plus(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &other);
return fixnum_plus(mrb, self, other);
}
@@ -1370,9 +1353,8 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
static mrb_value
fix_minus(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &other);
return fixnum_minus(mrb, self, other);
}
@@ -1383,6 +1365,7 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
char buf[MRB_INT_BIT+1];
char *b = buf + sizeof buf;
mrb_int val = mrb_fixnum(x);
mrb_value str;
if (base < 2 || 36 < base) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
@@ -1403,7 +1386,9 @@ mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
} while (val /= base);
}
return mrb_str_new(mrb, b, buf + sizeof(buf) - b);
str = mrb_str_new(mrb, b, buf + sizeof(buf) - b);
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
/* 15.2.8.3.25 */
@@ -1474,21 +1459,21 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
/* 15.2.9.3.6 */
/*
* call-seq:
* self.f <=> other.f => -1, 0, +1
* self.f <=> other.f => -1, 0, +1, or nil
* < => -1
* = => 0
* > => +1
* Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
* less than, equal to, or greater than <i>numeric</i>. This is the
* basis for the tests in <code>Comparable</code>.
* basis for the tests in <code>Comparable</code>. When the operands are
* not comparable, it returns nil instead of raising an exception.
*/
static mrb_value
integral_cmp(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_int n;
mrb_get_args(mrb, "o", &other);
n = cmpnum(mrb, self, other);
if (n == -2) return mrb_nil_value();
return mrb_fixnum_value(n);
@@ -1503,10 +1488,9 @@ cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2)
static mrb_value
integral_lt(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_int n;
mrb_get_args(mrb, "o", &other);
n = cmpnum(mrb, self, other);
if (n == -2) cmperr(mrb, self, other);
if (n < 0) return mrb_true_value();
@@ -1516,10 +1500,9 @@ integral_lt(mrb_state *mrb, mrb_value self)
static mrb_value
integral_le(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_int n;
mrb_get_args(mrb, "o", &other);
n = cmpnum(mrb, self, other);
if (n == -2) cmperr(mrb, self, other);
if (n <= 0) return mrb_true_value();
@@ -1529,10 +1512,9 @@ integral_le(mrb_state *mrb, mrb_value self)
static mrb_value
integral_gt(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_int n;
mrb_get_args(mrb, "o", &other);
n = cmpnum(mrb, self, other);
if (n == -2) cmperr(mrb, self, other);
if (n > 0) return mrb_true_value();
@@ -1542,10 +1524,9 @@ integral_gt(mrb_state *mrb, mrb_value self)
static mrb_value
integral_ge(mrb_state *mrb, mrb_value self)
{
mrb_value other;
mrb_value other = mrb_get_arg1(mrb);
mrb_int n;
mrb_get_args(mrb, "o", &other);
n = cmpnum(mrb, self, other);
if (n == -2) cmperr(mrb, self, other);
if (n >= 0) return mrb_true_value();
@@ -1597,9 +1578,8 @@ num_infinite_p(mrb_state *mrb, mrb_value self)
static mrb_value
flo_plus(mrb_state *mrb, mrb_value x)
{
mrb_value y;
mrb_value y = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &y);
return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
}
#endif
+23 -5
View File
@@ -47,6 +47,17 @@ mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
mrb_value result;
if (mrb_obj_eq(mrb, obj1, obj2)) return TRUE;
#ifndef MRB_WITHOUT_FLOAT
/* value mixing with integer and float */
if (mrb_fixnum_p(obj1)) {
if (mrb_float_p(obj2) && (mrb_float)mrb_fixnum(obj1) == mrb_float(obj2))
return TRUE;
}
else if (mrb_float_p(obj1)) {
if (mrb_fixnum_p(obj2) && mrb_float(obj1) == (mrb_float)mrb_fixnum(obj2))
return TRUE;
}
#endif
result = mrb_funcall(mrb, obj1, "==", 1, obj2);
if (mrb_test(result)) return TRUE;
return FALSE;
@@ -83,13 +94,17 @@ mrb_true(mrb_state *mrb, mrb_value obj)
static mrb_value
nil_to_s(mrb_state *mrb, mrb_value obj)
{
return mrb_str_new_frozen(mrb, 0, 0);
mrb_value str = mrb_str_new_frozen(mrb, 0, 0);
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
static mrb_value
nil_inspect(mrb_state *mrb, mrb_value obj)
{
return mrb_str_new_lit_frozen(mrb, "nil");
mrb_value str = mrb_str_new_lit_frozen(mrb, "nil");
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
/***********************************************************************
@@ -150,7 +165,9 @@ true_xor(mrb_state *mrb, mrb_value obj)
static mrb_value
true_to_s(mrb_state *mrb, mrb_value obj)
{
return mrb_str_new_lit_frozen(mrb, "true");
mrb_value str = mrb_str_new_lit_frozen(mrb, "true");
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
/* 15.2.5.3.4 */
@@ -257,7 +274,9 @@ false_or(mrb_state *mrb, mrb_value obj)
static mrb_value
false_to_s(mrb_state *mrb, mrb_value obj)
{
return mrb_str_new_lit_frozen(mrb, "false");
mrb_value str = mrb_str_new_lit_frozen(mrb, "false");
RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
return str;
}
void
@@ -358,7 +377,6 @@ static const struct types {
{MRB_TT_STRING, "String"},
{MRB_TT_RANGE, "Range"},
/* {MRB_TT_BIGNUM, "Bignum"}, */
{MRB_TT_FILE, "File"},
{MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */
/* {MRB_TT_VARMAP, "Varmap"}, */ /* internal use: dynamic variables */
/* {MRB_TT_NODE, "Node"}, */ /* internal use: syntax tree node */
+27 -3
View File
@@ -7,24 +7,48 @@
#include <mruby.h>
#include <mruby/string.h>
#include <mruby/variable.h>
#include <mruby/error.h>
#include <string.h>
#ifndef MRB_DISABLE_STDIO
static void
printcstr(const char *str, size_t len, FILE *stream)
{
if (str) {
fwrite(str, len, 1, stream);
putc('\n', stream);
}
}
static void
printstr(mrb_value obj, FILE *stream)
{
if (mrb_string_p(obj)) {
fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stream);
putc('\n', stream);
printcstr(RSTRING_PTR(obj), RSTRING_LEN(obj), stream);
}
}
#else
# define printcstr(str, len, stream) (void)0
# define printstr(obj, stream) (void)0
#endif
void
mrb_core_init_printabort(void)
{
static const char *str = "Failed mruby core initialization";
printcstr(str, strlen(str), stdout);
}
MRB_API void
mrb_p(mrb_state *mrb, mrb_value obj)
{
printstr(mrb_inspect(mrb, obj), stdout);
if (mrb_type(obj) == MRB_TT_EXCEPTION && mrb_obj_ptr(obj) == mrb->nomem_err) {
static const char *str = "Out of memory";
printcstr(str, strlen(str), stdout);
}
else {
printstr(mrb_inspect(mrb, obj), stdout);
}
}
MRB_API void
+26 -7
View File
@@ -8,6 +8,7 @@
#include <mruby/class.h>
#include <mruby/proc.h>
#include <mruby/opcode.h>
#include <mruby/data.h>
static const mrb_code call_iseq[] = {
OP_CALL,
@@ -46,7 +47,7 @@ env_new(mrb_state *mrb, mrb_int nlocals)
int bidx;
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL);
MRB_ENV_SET_STACK_LEN(e, nlocals);
MRB_ENV_SET_LEN(e, nlocals);
bidx = ci->argc;
if (ci->argc < 0) bidx = 2;
else bidx += 1;
@@ -121,8 +122,15 @@ mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const
p->e.env = e = env_new(mrb, argc);
p->flags |= MRB_PROC_ENVSET;
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)e);
MRB_ENV_UNSHARE_STACK(e);
MRB_ENV_CLOSE(e);
/* NOTE: Prevents keeping invalid addresses when NoMemoryError is raised from `mrb_malloc()`. */
e->stack = NULL;
MRB_ENV_SET_LEN(e, 0);
e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc);
MRB_ENV_SET_LEN(e, argc);
if (argv) {
for (i = 0; i < argc; ++i) {
e->stack[i] = argv[i];
@@ -155,9 +163,9 @@ mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
if (!e) {
mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv.");
}
if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) {
if (idx < 0 || MRB_ENV_LEN(e) <= idx) {
mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %i (expected: 0 <= index < %i)",
idx, MRB_ENV_STACK_LEN(e));
idx, MRB_ENV_LEN(e));
}
return e->stack[idx];
@@ -203,9 +211,8 @@ mrb_proc_s_new(mrb_state *mrb, mrb_value proc_class)
static mrb_value
mrb_proc_init_copy(mrb_state *mrb, mrb_value self)
{
mrb_value proc;
mrb_value proc = mrb_get_arg1(mrb);
mrb_get_args(mrb, "o", &proc);
if (!mrb_proc_p(proc)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "not a proc");
}
@@ -286,14 +293,25 @@ mrb_proc_arity(const struct RProc *p)
return arity;
}
static void
tempirep_free(mrb_state *mrb, void *p)
{
if (p) mrb_irep_free(mrb, (mrb_irep *)p);
}
static const mrb_data_type tempirep_type = { "temporary irep", tempirep_free };
void
mrb_init_proc(mrb_state *mrb)
{
struct RProc *p;
mrb_method_t m;
mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
struct RData *irep_obj = mrb_data_object_alloc(mrb, mrb->object_class, NULL, &tempirep_type);
mrb_irep *call_irep;
static const mrb_irep mrb_irep_zero = { 0 };
call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep));
irep_obj->data = call_irep;
*call_irep = mrb_irep_zero;
call_irep->flags = MRB_ISEQ_NO_FREE;
call_irep->iseq = call_iseq;
@@ -305,6 +323,7 @@ mrb_init_proc(mrb_state *mrb)
mrb_define_method(mrb, mrb->proc_class, "arity", proc_arity, MRB_ARGS_NONE());
p = mrb_proc_new(mrb, call_irep);
irep_obj->data = NULL;
MRB_METHOD_FROM_PROC(m, p);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "call"), m);
mrb_define_method_raw(mrb, mrb->proc_class, mrb_intern_lit(mrb, "[]"), m);
+4 -12
View File
@@ -182,11 +182,9 @@ range_eq(mrb_state *mrb, mrb_value range)
{
struct RRange *rr;
struct RRange *ro;
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
mrb_bool v1, v2;
mrb_get_args(mrb, "o", &obj);
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
if (!mrb_obj_is_instance_of(mrb, obj, mrb_obj_class(mrb, range))) { /* same class? */
return mrb_false_value();
@@ -211,13 +209,11 @@ range_eq(mrb_state *mrb, mrb_value range)
static mrb_value
range_include(mrb_state *mrb, mrb_value range)
{
mrb_value val;
mrb_value val = mrb_get_arg1(mrb);
struct RRange *r = mrb_range_ptr(mrb, range);
mrb_value beg, end;
mrb_bool include_p;
mrb_get_args(mrb, "o", &val);
beg = RANGE_BEG(r);
end = RANGE_END(r);
include_p = r_le(mrb, beg, val) && /* beg <= val */
@@ -289,11 +285,9 @@ range_inspect(mrb_state *mrb, mrb_value range)
static mrb_value
range_eql(mrb_state *mrb, mrb_value range)
{
mrb_value obj;
mrb_value obj = mrb_get_arg1(mrb);
struct RRange *r, *o;
mrb_get_args(mrb, "o", &obj);
if (mrb_obj_equal(mrb, range, obj)) return mrb_true_value();
if (!mrb_obj_is_kind_of(mrb, obj, mrb->range_class)) return mrb_false_value();
if (!mrb_range_p(obj)) return mrb_false_value();
@@ -312,11 +306,9 @@ range_eql(mrb_state *mrb, mrb_value range)
static mrb_value
range_initialize_copy(mrb_state *mrb, mrb_value copy)
{
mrb_value src;
mrb_value src = mrb_get_arg1(mrb);
struct RRange *r;
mrb_get_args(mrb, "o", &src);
if (mrb_obj_equal(mrb, copy, src)) return copy;
if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+34 -11
View File
@@ -19,11 +19,25 @@ void mrb_init_mrbgems(mrb_state*);
void mrb_gc_init(mrb_state*, mrb_gc *gc);
void mrb_gc_destroy(mrb_state*, mrb_gc *gc);
int mrb_core_init_protect(mrb_state *mrb, void (*body)(mrb_state *, void *), void *opaque);
static void
init_gc_and_core(mrb_state *mrb, void *opaque)
{
static const struct mrb_context mrb_context_zero = { 0 };
mrb_gc_init(mrb, &mrb->gc);
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
*mrb->c = mrb_context_zero;
mrb->root_c = mrb->c;
mrb_init_core(mrb);
}
MRB_API mrb_state*
mrb_open_core(mrb_allocf f, void *ud)
{
static const mrb_state mrb_state_zero = { 0 };
static const struct mrb_context mrb_context_zero = { 0 };
mrb_state *mrb;
if (f == NULL) f = mrb_default_allocf;
@@ -35,12 +49,10 @@ mrb_open_core(mrb_allocf f, void *ud)
mrb->allocf = f;
mrb->atexit_stack_len = 0;
mrb_gc_init(mrb, &mrb->gc);
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
*mrb->c = mrb_context_zero;
mrb->root_c = mrb->c;
mrb_init_core(mrb);
if (mrb_core_init_protect(mrb, init_gc_and_core, NULL)) {
mrb_close(mrb);
return NULL;
}
return mrb;
}
@@ -65,6 +77,12 @@ mrb_open(void)
return mrb;
}
static void
init_mrbgems(mrb_state *mrb, void *opaque)
{
mrb_init_mrbgems(mrb);
}
MRB_API mrb_state*
mrb_open_allocf(mrb_allocf f, void *ud)
{
@@ -75,7 +93,10 @@ mrb_open_allocf(mrb_allocf f, void *ud)
}
#ifndef DISABLE_GEMS
mrb_init_mrbgems(mrb);
if (mrb_core_init_protect(mrb, init_mrbgems, NULL)) {
mrb_close(mrb);
return NULL;
}
mrb_gc_arena_restore(mrb, 0);
#endif
return mrb;
@@ -131,9 +152,11 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep)
}
mrb_free(mrb, irep->pool);
mrb_free(mrb, irep->syms);
for (i=0; i<irep->rlen; i++) {
if (irep->reps[i])
mrb_irep_decref(mrb, irep->reps[i]);
if (irep->reps) {
for (i=0; i<irep->rlen; i++) {
if (irep->reps[i])
mrb_irep_decref(mrb, irep->reps[i]);
}
}
mrb_free(mrb, irep->reps);
mrb_free(mrb, irep->lv);
+25 -22
View File
@@ -1061,10 +1061,9 @@ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2)
static mrb_value
mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
{
mrb_value str2;
mrb_value str2 = mrb_get_arg1(mrb);
mrb_int result;
mrb_get_args(mrb, "o", &str2);
if (!mrb_string_p(str2)) {
return mrb_nil_value();
}
@@ -1106,9 +1105,7 @@ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
static mrb_value
mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
{
mrb_value str2;
mrb_get_args(mrb, "o", &str2);
mrb_value str2 = mrb_get_arg1(mrb);
return mrb_bool_value(mrb_str_equal(mrb, str1, str2));
}
@@ -1791,10 +1788,9 @@ mrb_str_empty_p(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_str_eql(mrb_state *mrb, mrb_value self)
{
mrb_value str2;
mrb_value str2 = mrb_get_arg1(mrb);
mrb_bool eql_p;
mrb_get_args(mrb, "o", &str2);
eql_p = (mrb_string_p(str2)) && str_eql(mrb, self, str2);
return mrb_bool_value(eql_p);
@@ -2759,7 +2755,7 @@ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
MRB_API mrb_value
mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
{
return mrb_str_cat(mrb, str, ptr, strlen(ptr));
return mrb_str_cat(mrb, str, ptr, ptr ? strlen(ptr) : 0);
}
MRB_API mrb_value
@@ -2889,25 +2885,32 @@ mrb_str_setbyte(mrb_state *mrb, mrb_value str)
static mrb_value
mrb_str_byteslice(mrb_state *mrb, mrb_value str)
{
mrb_value a1, a2;
mrb_value a1;
mrb_int str_len = RSTRING_LEN(str), beg, len;
mrb_bool empty = TRUE;
if (mrb_get_args(mrb, "o|o", &a1, &a2) == 2) {
beg = mrb_fixnum(mrb_to_int(mrb, a1));
len = mrb_fixnum(mrb_to_int(mrb, a2));
}
else if (mrb_range_p(a1)) {
if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
return mrb_nil_value();
len = mrb_get_argc(mrb);
switch (len) {
case 2:
mrb_get_args(mrb, "ii", &beg, &len);
break;
case 1:
a1 = mrb_get_arg1(mrb);
if (mrb_range_p(a1)) {
if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
return mrb_nil_value();
}
}
else {
beg = mrb_fixnum(mrb_to_int(mrb, a1));
len = 1;
empty = FALSE;
}
break;
default:
mrb_argnum_error(mrb, len, 1, 2);
break;
}
else {
beg = mrb_fixnum(mrb_to_int(mrb, a1));
len = 1;
empty = FALSE;
}
if (mrb_str_beg_len(str_len, &beg, &len) && (empty || len != 0)) {
return mrb_str_byte_subseq(mrb, str, beg, len);
}
+8 -7
View File
@@ -172,11 +172,13 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
if (sym > 0) return sym;
/* registering a new symbol */
sym = ++mrb->symidx;
sym = mrb->symidx + 1;
if (mrb->symcapa < sym) {
if (mrb->symcapa == 0) mrb->symcapa = 100;
else mrb->symcapa = (size_t)(mrb->symcapa * 6 / 5);
mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(mrb->symcapa+1));
size_t symcapa = mrb->symcapa;
if (symcapa == 0) symcapa = 100;
else symcapa = (size_t)(symcapa * 6 / 5);
mrb->symtbl = (symbol_name*)mrb_realloc(mrb, mrb->symtbl, sizeof(symbol_name)*(symcapa+1));
mrb->symcapa = symcapa;
}
sname = &mrb->symtbl[sym];
sname->len = (uint16_t)len;
@@ -201,7 +203,7 @@ sym_intern(mrb_state *mrb, const char *name, size_t len, mrb_bool lit)
else {
sname->prev = 0;
}
mrb->symhash[hash] = sym;
mrb->symhash[hash] = mrb->symidx = sym;
return sym<<SYMBOL_NORMAL_SHIFT;
}
@@ -562,10 +564,9 @@ mrb_sym_dump(mrb_state *mrb, mrb_sym sym)
static mrb_value
sym_cmp(mrb_state *mrb, mrb_value s1)
{
mrb_value s2;
mrb_value s2 = mrb_get_arg1(mrb);
mrb_sym sym1, sym2;
mrb_get_args(mrb, "o", &s2);
if (!mrb_symbol_p(s2)) return mrb_nil_value();
sym1 = mrb_symbol(s1);
sym2 = mrb_symbol(s2);
+44 -48
View File
@@ -152,7 +152,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize
struct REnv *e = ci->env;
mrb_value *st;
if (e && MRB_ENV_STACK_SHARED_P(e) &&
if (e && MRB_ENV_ONSTACK_P(e) &&
(st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
ptrdiff_t off = e->stack - oldbase;
@@ -162,7 +162,7 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase, size_t oldsize
if (ci->proc && MRB_PROC_ENV_P(ci->proc) && ci->env != MRB_PROC_ENV(ci->proc)) {
e = MRB_PROC_ENV(ci->proc);
if (e && MRB_ENV_STACK_SHARED_P(e) &&
if (e && MRB_ENV_ONSTACK_P(e) &&
(st = e->stack) && oldbase <= st && st < oldbase+oldsize) {
ptrdiff_t off = e->stack - oldbase;
@@ -297,10 +297,10 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e)
{
if (e == NULL) return;
else {
size_t len = (size_t)MRB_ENV_STACK_LEN(e);
size_t len = (size_t)MRB_ENV_LEN(e);
mrb_value *p;
if (!MRB_ENV_STACK_SHARED_P(e)) return;
if (!MRB_ENV_ONSTACK_P(e)) return;
if (e->cxt != mrb->c) return;
if (e == mrb->c->cibase->env) return; /* for mirb */
p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len);
@@ -308,7 +308,7 @@ mrb_env_unshare(mrb_state *mrb, struct REnv *e)
stack_copy(p, e->stack, len);
}
e->stack = p;
MRB_ENV_UNSHARE_STACK(e);
MRB_ENV_CLOSE(e);
mrb_write_barrier(mrb, (struct RBasic *)e);
}
}
@@ -324,6 +324,7 @@ cipop(mrb_state *mrb)
}
void mrb_exc_set(mrb_state *mrb, mrb_value exc);
static mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
static void
ecall(mrb_state *mrb)
@@ -335,10 +336,12 @@ ecall(mrb_state *mrb)
struct REnv *env;
ptrdiff_t cioff;
int ai = mrb_gc_arena_save(mrb);
uint16_t i = --c->eidx;
uint16_t i;
int nregs;
if (i<0) return;
if (c->eidx == 0) return;
i = --c->eidx;
/* restrict total call depth of ecall() */
if (++mrb->ecall_nest > MRB_ECALL_DEPTH_MAX) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
@@ -624,7 +627,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
ci->argc--;
}
else { /* variable length arguments */
mrb_ary_shift(mrb, regs[0]);
regs[0] = mrb_ary_subseq(mrb, regs[0], 1, RARRAY_LEN(regs[0]) - 1);
}
if (MRB_METHOD_CFUNC_P(m)) {
@@ -648,8 +651,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
}
ci = mrb->c->ci;
if (ci->acc == CI_ACC_DIRECT) {
ci->target_class = c;
return mrb_yield_cont(mrb, blk, self, 1, &self);
return mrb_yield_with_class(mrb, blk, 1, &self, self, c);
}
ci->target_class = c;
p = mrb_proc_ptr(blk);
@@ -724,26 +726,11 @@ mrb_value
mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
{
mrb_value a, b;
mrb_value cv;
struct RClass *c;
if (mrb_get_args(mrb, "|S&", &a, &b) == 1) {
mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented");
}
switch (mrb_type(self)) {
case MRB_TT_SYMBOL:
case MRB_TT_FIXNUM:
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
#endif
c = 0;
break;
default:
cv = mrb_singleton_class(mrb, self);
c = mrb_class_ptr(cv);
break;
}
return eval_under(mrb, self, b, c);
return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self));
}
MRB_API mrb_value
@@ -767,16 +754,25 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
ci = cipush(mrb);
ci->mid = mid;
ci->proc = p;
ci->stackent = mrb->c->stack;
ci->argc = (int)argc;
ci->target_class = c;
ci->acc = CI_ACC_SKIP;
n = MRB_PROC_CFUNC_P(p) ? (int)(argc+2) : p->body.irep->nregs;
mrb->c->stack = mrb->c->stack + n;
ci->stackent = mrb->c->stack;
mrb->c->stack += n;
if (argc >= CALL_MAXARGS) {
ci->argc = -1;
n = 3;
}
else {
ci->argc = (int)argc;
n = argc + 2;
}
mrb_stack_extend(mrb, n);
mrb->c->stack[0] = self;
if (argc > 0) {
if (ci->argc < 0) {
mrb->c->stack[1] = mrb_ary_new_from_values(mrb, argc, argv);
argc = 1;
}
else if (argc > 0) {
stack_copy(mrb->c->stack+1, argv, argc);
}
mrb->c->stack[argc+1] = mrb_nil_value();
@@ -1062,6 +1058,11 @@ RETRY_TRY_BLOCK:
NEXT;
}
CASE(OP_LOADI16, BS) {
SET_INT_VALUE(regs[a], (mrb_int)(int16_t)b);
NEXT;
}
CASE(OP_LOADSYM, BB) {
SET_SYM_VALUE(regs[a], syms[b]);
NEXT;
@@ -1099,13 +1100,13 @@ RETRY_TRY_BLOCK:
}
CASE(OP_GETSV, BB) {
mrb_value val = mrb_vm_special_get(mrb, b);
mrb_value val = mrb_vm_special_get(mrb, syms[b]);
regs[a] = val;
NEXT;
}
CASE(OP_SETSV, BB) {
mrb_vm_special_set(mrb, b, regs[a]);
mrb_vm_special_set(mrb, syms[b], regs[a]);
NEXT;
}
@@ -1168,7 +1169,7 @@ RETRY_TRY_BLOCK:
mrb_value *regs_a = regs + a;
struct REnv *e = uvenv(mrb, c);
if (e && b < MRB_ENV_STACK_LEN(e)) {
if (e && b < MRB_ENV_LEN(e)) {
*regs_a = e->stack[b];
}
else {
@@ -1183,7 +1184,7 @@ RETRY_TRY_BLOCK:
if (e) {
mrb_value *regs_a = regs + a;
if (b < MRB_ENV_STACK_LEN(e)) {
if (b < MRB_ENV_LEN(e)) {
e->stack[b] = *regs_a;
mrb_write_barrier(mrb, (struct RBasic*)e);
}
@@ -1496,12 +1497,7 @@ RETRY_TRY_BLOCK:
ci->target_class = MRB_PROC_TARGET_CLASS(m);
ci->proc = m;
if (MRB_PROC_ENV_P(m)) {
struct REnv *e = MRB_PROC_ENV(m);
ci->mid = e->mid;
if (!e->stack) {
e->stack = mrb->c->stack;
}
ci->mid = MRB_PROC_ENV(m)->mid;
}
/* prepare stack */
@@ -1697,7 +1693,7 @@ RETRY_TRY_BLOCK:
else {
struct REnv *e = uvenv(mrb, lv-1);
if (!e) goto L_NOSUPER;
if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1)
if (MRB_ENV_LEN(e) <= m1+r+m2+kd+1)
goto L_NOSUPER;
stack = e->stack + 1;
}
@@ -2023,7 +2019,7 @@ RETRY_TRY_BLOCK:
if (MRB_PROC_ENV_P(dst)) {
struct REnv *e = MRB_PROC_ENV(dst);
if (!MRB_ENV_STACK_SHARED_P(e) || (e->cxt && e->cxt != mrb->c)) {
if (!MRB_ENV_ONSTACK_P(e) || (e->cxt && e->cxt != mrb->c)) {
localjump_error(mrb, LOCALJUMP_ERROR_RETURN);
goto L_RAISE;
}
@@ -2078,7 +2074,7 @@ RETRY_TRY_BLOCK:
mrb_exc_set(mrb, exc);
goto L_RAISE;
}
if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_STACK_SHARED_P(MRB_PROC_ENV(proc))) {
if (!MRB_PROC_ENV_P(proc) || !MRB_ENV_ONSTACK_P(MRB_PROC_ENV(proc))) {
goto L_BREAK_ERROR;
}
else {
@@ -2178,8 +2174,8 @@ RETRY_TRY_BLOCK:
if (lv == 0) stack = regs + 1;
else {
struct REnv *e = uvenv(mrb, lv-1);
if (!e || (!MRB_ENV_STACK_SHARED_P(e) && e->mid == 0) ||
MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) {
if (!e || (!MRB_ENV_ONSTACK_P(e) && e->mid == 0) ||
MRB_ENV_LEN(e) <= m1+r+m2+1) {
localjump_error(mrb, LOCALJUMP_ERROR_YIELD);
goto L_RAISE;
}
@@ -2824,7 +2820,7 @@ RETRY_TRY_BLOCK:
MRB_END_EXC(&c_jmp);
}
MRB_API mrb_value
static mrb_value
mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
{
if (mrb->c->ci->argc < 0) {
+1 -1
View File
@@ -7,7 +7,7 @@ MRuby.each_target do
# loader all gems
self.libmruby_objs << objfile("#{build_dir}/mrbgems/gem_init")
file objfile("#{build_dir}/mrbgems/gem_init") => ["#{build_dir}/mrbgems/gem_init.c", "#{build_dir}/LEGAL"]
file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__] do |t|
file "#{build_dir}/mrbgems/gem_init.c" => [MRUBY_CONFIG, __FILE__, *Dir.glob("#{build_dir}/mrbgems/mruby-*/*.c")] do |t|
mkdir_p "#{build_dir}/mrbgems"
open(t.name, 'w') do |f|
gem_func_gems = gems.select { |g| g.generate_functions }
+5 -4
View File
@@ -56,7 +56,9 @@ def assertion_string(err, str, iso=nil, e=nil, bt=nil)
msg = "#{err}#{str}"
msg += " [#{iso}]" if iso && !iso.empty?
msg += " => #{e}" if e && !e.to_s.empty?
msg += " (#{GEMNAME == 'mruby-test' ? 'core' : "mrbgems: #{GEMNAME}"})"
if Object.const_defined?(:GEMNAME)
msg += " (#{GEMNAME == 'mruby-test' ? 'core' : "mrbgems: #{GEMNAME}"})"
end
if $mrbtest_assert
$mrbtest_assert.each do |idx, assert_msg, diff|
msg += "\n - Assertion[#{idx}]"
@@ -64,7 +66,7 @@ def assertion_string(err, str, iso=nil, e=nil, bt=nil)
msg += "\n#{diff}" if diff && !diff.empty?
end
end
msg += "\nbacktrace:\n #{bt.join("\n ")}" if bt
msg += "\nbacktrace:\n #{bt.join("\n ")}" if bt && !bt.empty?
msg
end
@@ -122,8 +124,7 @@ def assert(str = 'assert', iso = '')
$mrbtest_child_noassert[-2] += 1
t_print('?')
rescue Exception => e
bt = e.backtrace if $mrbtest_verbose
$asserts.push(assertion_string("#{e.class}: ", str, iso, e, bt))
$asserts.push(assertion_string("#{e.class}: ", str, iso, e, e.backtrace))
$kill_test += 1
t_print('X')
ensure
+8 -26
View File
@@ -1,16 +1,16 @@
##
# ensure Test
assert('ensure - context - yield') do
class EnsureYieldBreak
attr_reader :ensure_context
def try
yield
ensure
@ensure_context = self
end
class EnsureYieldBreak
attr_reader :ensure_context
def try
yield
ensure
@ensure_context = self
end
end
assert('ensure - context - yield') do
yielder = EnsureYieldBreak.new
yielder.try do
end
@@ -18,15 +18,6 @@ assert('ensure - context - yield') do
end
assert('ensure - context - yield and break') do
class EnsureYieldBreak
attr_reader :ensure_context
def try
yield
ensure
@ensure_context = self
end
end
yielder = EnsureYieldBreak.new
yielder.try do
break
@@ -35,15 +26,6 @@ assert('ensure - context - yield and break') do
end
assert('ensure - context - yield and return') do
class EnsureYieldBreak
attr_reader :ensure_context
def try
yield
ensure
@ensure_context = self
end
end
yielder = EnsureYieldBreak.new
lambda do
yielder.try do
+15 -24
View File
@@ -29,7 +29,7 @@ assert('Kernel.block_given?', '15.3.1.2.2') do
end
end
# Kernel.eval is provided by the mruby-gem mrbgem. '15.3.1.2.3'
# Kernel.eval is provided by the mruby-eval mrbgem. '15.3.1.2.3'
assert('Kernel.iterator?', '15.3.1.2.5') do
assert_false Kernel.iterator?
@@ -59,20 +59,11 @@ assert('Kernel.loop', '15.3.1.2.8') do
assert_equal 100, i
end
assert('Kernel.p', '15.3.1.2.9') do
# TODO search for a way to test p to stdio
assert_true true
end
# Kernel.p is provided by the mruby-print mrbgem. '15.3.1.2.9'
assert('Kernel.print', '15.3.1.2.10') do
# TODO search for a way to test print to stdio
assert_true true
end
# Kernel.print is provided by the mruby-print mrbgem. '15.3.1.2.10'
assert('Kernel.puts', '15.3.1.2.11') do
# TODO search for a way to test puts to stdio
assert_true true
end
# Kernel.puts is provided by the mruby-print mrbgem. '15.3.1.2.11'
assert('Kernel.raise', '15.3.1.2.12') do
assert_raise RuntimeError do
@@ -100,6 +91,10 @@ assert('Kernel#__send__', '15.3.1.3.4') do
assert_true __send__(:respond_to?, :nil?)
# test without argument and without block
assert_equal String, __send__(:to_s).class
args = [:respond_to?, :nil?]
assert_true __send__(*args)
assert_equal [:respond_to?, :nil?], args
end
assert('Kernel#block_given?', '15.3.1.3.6') do
@@ -121,6 +116,13 @@ assert('Kernel#block_given?', '15.3.1.3.6') do
"block"
end
end
def bg_try_in_block
-> { block_given? }[]
end
assert_false bg_try_in_block
assert_true bg_try_in_block{}
end
assert('Kernel#class', '15.3.1.3.7') do
@@ -197,17 +199,6 @@ assert('Kernel#dup', '15.3.1.3.9') do
a.set(2)
c = a.dup
immutables = [ 1, :foo, true, false, nil ]
error_count = 0
immutables.each do |i|
begin
i.dup
rescue TypeError
error_count += 1
end
end
assert_equal immutables.size, error_count
assert_equal 2, a.get
assert_equal 1, b.get
assert_equal 2, c.get